Whamcloud - gitweb
640d288ed4cd072c43da47c64c231d5770ea2d37
[fs/lustre-release.git] / lustre / lvfs / fsfilt_snap_smfs.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Lustre filesystem abstraction routines
5  *
6  *  Copyright (C) 2004 Cluster File Systems, Inc.
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
10  *   Lustre is free software; you can redistribute it and/or
11  *   modify it under the terms of version 2 of the GNU General Public
12  *   License as published by the Free Software Foundation.
13  *
14  *   Lustre is distributed in the hope that it will be useful,
15  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *   GNU General Public License for more details.
18  *
19  *   You should have received a copy of the GNU General Public License
20  *   along with Lustre; if not, write to the Free Software
21  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23
24 #define DEBUG_SUBSYSTEM S_FILTER
25
26 #include <linux/fs.h>
27 #include <linux/jbd.h>
28 #include <linux/slab.h>
29 #include <linux/pagemap.h>
30 #include <linux/quotaops.h>
31 #include <linux/version.h>
32 #include <linux/kp30.h>
33 #include <linux/lustre_fsfilt.h>
34 #include <linux/lustre_smfs.h>
35 #include <linux/obd.h>
36 #include <linux/obd_class.h>
37 #include <linux/module.h>
38 #include <linux/init.h>
39
40 #include <linux/lustre_snap.h>
41 #include <linux/lustre_smfs.h>
42
43 static struct inode* fsfilt_smfs_create_indirect(struct inode *inode,
44                                                  int index,
45                                                  unsigned int gen,
46                                                  struct inode *parent,
47                                                  int del)
48 {
49         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
50         struct inode *cache_inode = NULL;
51         struct inode *cache_parent = NULL;
52         struct inode *cache_ind_inode = NULL;
53         struct inode *ind_inode = NULL;
54         ENTRY;
55
56         if (!snap_fsfilt)
57                 RETURN(NULL);
58
59         cache_inode = I2CI(inode);
60         if (!cache_inode)
61                 RETURN(NULL);
62
63         cache_parent = I2CI(parent);
64         if (!cache_parent)
65                 RETURN(NULL);
66
67         pre_smfs_inode(inode, cache_inode);
68         pre_smfs_inode(inode, cache_parent);
69
70         if (snap_fsfilt->fs_create_indirect)
71                 cache_ind_inode = snap_fsfilt->fs_create_indirect(cache_inode, 
72                                                index, gen, cache_parent, del);
73         post_smfs_inode(inode, cache_inode);
74         post_smfs_inode(inode, cache_parent);
75         
76         if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ 
77                 /*FIXME: get indirect inode set_cow flags*/ 
78                 ind_inode = iget4(inode->i_sb, cache_ind_inode->i_ino, NULL, 0);
79         }    
80         RETURN(ind_inode);
81 }
82
83 static struct inode*  fsfilt_smfs_get_indirect(struct inode *inode, 
84                                                int *table, int slot)
85 {
86         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
87         struct inode *cache_inode = NULL;
88         struct inode *cache_ind_inode = NULL;
89         struct inode *ind_inode = NULL;
90         ENTRY;
91
92         if (!snap_fsfilt)
93                 RETURN(NULL);
94
95         cache_inode = I2CI(inode);
96         if (!cache_inode)
97                 RETURN(NULL);
98
99         pre_smfs_inode(inode, cache_inode);
100
101         if (snap_fsfilt->fs_get_indirect)
102                 cache_ind_inode = snap_fsfilt->fs_get_indirect(cache_inode, 
103                                                                table, slot);
104         post_smfs_inode(inode, cache_inode);
105       
106         if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ 
107                 /*FIXME: get indirect inode set_cow flags*/ 
108                 ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
109                                            inode, slot);
110         }    
111         RETURN(ind_inode);
112 }
113
114 static int fsfilt_smfs_set_indirect(struct inode *inode, int index,
115                                     ino_t ind_ino, ino_t parent_ino)
116 {
117         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
118         struct inode *cache_inode = NULL;
119         int    rc = -EIO;
120         ENTRY;
121
122         if (snap_fsfilt == NULL)
123                 RETURN(rc);
124
125         cache_inode = I2CI(inode);
126         if (!cache_inode)
127                 RETURN(rc);
128
129         pre_smfs_inode(inode, cache_inode);
130         if (snap_fsfilt->fs_set_indirect)
131                 rc = snap_fsfilt->fs_set_indirect(cache_inode, index,
132                                                   ind_ino, parent_ino);
133         post_smfs_inode(inode, cache_inode);
134         
135         RETURN(rc);
136 }
137
138 static int fsfilt_smfs_snap_feature(struct super_block *sb, int feature, 
139                                     int op)
140 {
141         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
142         struct super_block       *csb = S2CSB(sb);
143         int                      rc = -EIO;
144         
145         if (snap_fsfilt == NULL)
146                 RETURN(rc);
147         if (!csb)
148                 RETURN(rc);
149         
150         if (snap_fsfilt->fs_snap_feature)
151                 rc = snap_fsfilt->fs_snap_feature(csb, feature, op);  
152         
153         RETURN(rc); 
154 }
155
156 static int fsfilt_smfs_is_redirector(struct inode *inode)
157 {
158         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
159         struct inode *cache_inode = NULL;
160         int    rc = -EIO;
161         ENTRY;
162
163         if (snap_fsfilt == NULL)
164                 RETURN(rc);
165
166         cache_inode = I2CI(inode);
167         if (!cache_inode)
168                 RETURN(rc);
169
170         pre_smfs_inode(inode, cache_inode);
171         if (snap_fsfilt->fs_is_redirector)
172                 rc = snap_fsfilt->fs_is_redirector(cache_inode);
173         post_smfs_inode(inode, cache_inode);
174         
175         RETURN(rc);
176 }
177 static int fsfilt_smfs_is_indirect(struct inode *inode)
178 {
179         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
180         struct inode *cache_inode = NULL;
181         int    rc = -EIO;
182         ENTRY;
183
184         if (snap_fsfilt == NULL)
185                 RETURN(rc);
186
187         cache_inode = I2CI(inode);
188         if (!cache_inode)
189                 RETURN(rc);
190
191         pre_smfs_inode(inode, cache_inode);
192         if (snap_fsfilt->fs_is_indirect)
193                 rc = snap_fsfilt->fs_is_indirect(cache_inode);
194         post_smfs_inode(inode, cache_inode);
195         
196         RETURN(rc);
197 }
198 static ino_t fsfilt_smfs_get_indirect_ino(struct super_block *sb, ino_t ino, 
199                                           int index)
200 {
201         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
202         struct super_block       *csb = S2CSB(sb);
203         int    rc = -EIO;
204         ENTRY;
205
206         if (snap_fsfilt == NULL)
207                 RETURN(rc);
208
209         if (snap_fsfilt->fs_get_indirect_ino)
210                 rc = snap_fsfilt->fs_get_indirect_ino(csb, ino, index);
211          
212         RETURN(rc);
213 }
214
215 static int fsfilt_smfs_destroy_indirect(struct inode *inode, int index,
216                                         struct inode *next_ind)
217 {
218         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
219         struct inode *cache_inode = NULL;
220         struct inode *cache_next = NULL;
221         int    rc = -EIO;
222         ENTRY;
223
224         if (snap_fsfilt == NULL)
225                 RETURN(rc);
226
227         cache_inode = I2CI(inode);
228         if (!cache_inode)
229                 RETURN(rc);
230
231         cache_next = I2CI(next_ind);
232         if (!cache_next)
233                 RETURN(rc);
234
235         pre_smfs_inode(inode, cache_inode);
236         pre_smfs_inode(next_ind, cache_next);
237
238         if (snap_fsfilt->fs_destroy_indirect)
239                 rc = snap_fsfilt->fs_destroy_indirect(cache_inode, index, 
240                                                       cache_next);
241         post_smfs_inode(inode, cache_inode);
242         post_smfs_inode(next_ind, cache_next);
243         
244         RETURN(rc);
245 }
246 static int fsfilt_smfs_restore_indirect(struct inode *inode, int index)
247 {
248         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
249         struct inode *cache_inode = NULL;
250         int    rc = -EIO;
251         ENTRY;
252
253         if (snap_fsfilt == NULL)
254                 RETURN(rc);
255
256         cache_inode = I2CI(inode);
257         if (!cache_inode)
258                 RETURN(rc);
259
260         pre_smfs_inode(inode, cache_inode);
261         
262         if (snap_fsfilt->fs_restore_indirect)
263                 rc = snap_fsfilt->fs_restore_indirect(cache_inode, index);
264         
265         post_smfs_inode(inode, cache_inode);
266         
267         RETURN(rc);
268 }
269 static int fsfilt_smfs_iterate(struct super_block *sb,
270                                int (*repeat)(struct inode *inode, void *priv),
271                                struct inode **start, void *priv, int flag)
272 {
273         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
274         struct super_block       *csb = S2CSB(sb);
275         int                      rc = -EIO;
276         ENTRY;
277
278         /*FIXME start == NULL, later*/
279         LASSERT(start == NULL);
280  
281         if (snap_fsfilt == NULL)
282                 RETURN(rc);
283          
284         if (snap_fsfilt->fs_iterate)
285                 rc = snap_fsfilt->fs_iterate(csb, repeat, start, priv, flag);
286
287         RETURN(rc);
288 }
289
290 static int fsfilt_smfs_copy_block(struct inode *dst, struct inode *src, int blk)
291 {
292         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(dst);
293         struct inode *cache_dst = NULL;
294         struct inode *cache_src = NULL;
295         int    rc = -EIO;
296         ENTRY;
297
298         if (snap_fsfilt == NULL)
299                 RETURN(rc);
300          
301         cache_dst = I2CI(dst);
302         if (!cache_dst)
303                 RETURN(rc);
304        
305         cache_src = I2CI(src);
306         if (!cache_src)
307                 RETURN(rc);
308
309         pre_smfs_inode(dst, cache_dst);
310         pre_smfs_inode(src, cache_src);
311         
312         if (snap_fsfilt->fs_copy_block)
313                 rc = snap_fsfilt->fs_copy_block(cache_dst, cache_src, blk);
314
315         post_smfs_inode(dst, cache_dst);
316         post_smfs_inode(src, cache_src);
317          
318         RETURN(rc); 
319 }
320
321 static int fsfilt_smfs_set_snap_info(struct inode *inode, 
322                                      void* key, __u32 keylen, void *val, 
323                                      __u32 *vallen)
324 {
325
326         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
327         struct inode *cache_inode = NULL;
328         int                      rc = -EIO;
329                 
330         if (snap_fsfilt == NULL)
331                 RETURN(rc);
332         
333         cache_inode = I2CI(inode);
334         if (!cache_inode)
335                 RETURN(rc);
336
337         pre_smfs_inode(inode, cache_inode);
338         
339         if (snap_fsfilt->fs_set_snap_info)
340                 rc = snap_fsfilt->fs_set_snap_info(cache_inode, key, 
341                                                    keylen, val, vallen);
342         post_smfs_inode(inode, cache_inode);
343         
344         RETURN(rc);
345 }
346
347 static int fsfilt_smfs_get_snap_info(struct inode *inode, void *key, 
348                                      __u32 keylen, void *val, __u32 *vallen)
349 {
350         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
351         struct inode *cache_inode = NULL;
352         int                      rc = -EIO;
353         
354         if (snap_fsfilt == NULL)
355                 RETURN(rc);
356         
357         cache_inode = I2CI(inode);
358         if (!cache_inode)
359                 RETURN(rc);
360         
361         if (snap_fsfilt->fs_get_snap_info)
362                 rc = snap_fsfilt->fs_get_snap_info(cache_inode, key, 
363                                                    keylen, val, vallen);
364         
365         RETURN(rc);
366 }
367
368 static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
369                                              size_t count, loff_t *off)
370 {
371         struct inode *inode = file->f_dentry->d_inode;
372         struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
373         struct snap_table *stbl = S2SNAPI(inode->i_sb)->sntbl;
374         int    i = 0, size = 0, off_count = 0, buf_off = 0, rc = 0;
375         ENTRY;
376
377         /*Get the offset of dir ent*/
378         while (size < *off && off_count < stbl->sntbl_count) {
379                 char *name = stbl->sntbl_items[i].sn_name;
380                 size +=snap_cops->fs_dir_ent_size(name);
381                 off_count ++;
382         }
383         for (i = off_count; i < stbl->sntbl_count; i++) {
384                 char *name = stbl->sntbl_items[i].sn_name;
385                 rc = snap_cops->fs_set_dir_ent(inode->i_sb, name, buf, buf_off, 
386                                                rc, count);
387                 if (rc < 0)
388                         break;
389
390                 buf_off += rc;
391
392                 if (buf_off >= count) 
393                         break;
394         }
395         if (rc > 0) 
396                 rc = 0; 
397
398         RETURN(rc); 
399 }
400
401 struct fsfilt_operations fsfilt_smfs_snap_ops = {
402         .fs_type                = "smfs_snap",
403         .fs_owner               = THIS_MODULE,
404         .fs_create_indirect     = fsfilt_smfs_create_indirect,
405         .fs_get_indirect        = fsfilt_smfs_get_indirect,
406         .fs_set_indirect        = fsfilt_smfs_set_indirect,
407         .fs_snap_feature        = fsfilt_smfs_snap_feature,
408         .fs_is_redirector       = fsfilt_smfs_is_redirector,
409         .fs_is_indirect         = fsfilt_smfs_is_indirect,
410         .fs_get_indirect_ino    = fsfilt_smfs_get_indirect_ino,
411         .fs_destroy_indirect    = fsfilt_smfs_destroy_indirect,
412         .fs_restore_indirect    = fsfilt_smfs_restore_indirect,
413         .fs_iterate             = fsfilt_smfs_iterate,
414         .fs_copy_block          = fsfilt_smfs_copy_block,
415         .fs_set_snap_info       = fsfilt_smfs_set_snap_info,
416         .fs_get_snap_info       = fsfilt_smfs_get_snap_info,
417         .fs_read_dotsnap_dir_page = fsfilt_smfs_read_dotsnap_dir_page,
418 };
419
420
421 static int __init fsfilt_smfs_snap_init(void)
422 {
423         int rc;
424
425         rc = fsfilt_register_ops(&fsfilt_smfs_snap_ops);
426         return rc;
427 }
428
429 static void __exit fsfilt_smfs_snap_exit(void)
430 {
431         fsfilt_unregister_ops(&fsfilt_smfs_snap_ops);
432 }
433
434 module_init(fsfilt_smfs_snap_init);
435 module_exit(fsfilt_smfs_snap_exit);
436
437 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
438 MODULE_DESCRIPTION("Lustre SMFS SNAP Filesystem Helper v0.1");
439 MODULE_LICENSE("GPL");