Whamcloud - gitweb
268db4b77fcbcd74cff648522de1871cfb7ab518
[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        #if 0 
76         if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ 
77                 /*FIXME: get indirect inode set_cow flags*/ 
78                 ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino, 
79                                            inode, 0);
80         }   
81         #endif 
82         RETURN(ind_inode);
83 }
84
85 static struct inode*  fsfilt_smfs_get_indirect(struct inode *inode, 
86                                                int *table, int slot)
87 {
88         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
89         struct inode *cache_inode = NULL;
90         struct inode *cache_ind_inode = NULL;
91         struct inode *ind_inode = NULL;
92         ENTRY;
93
94         if (!snap_fsfilt)
95                 RETURN(NULL);
96
97         cache_inode = I2CI(inode);
98         if (!cache_inode)
99                 RETURN(NULL);
100
101         pre_smfs_inode(inode, cache_inode);
102
103         if (snap_fsfilt->fs_get_indirect)
104                 cache_ind_inode = snap_fsfilt->fs_get_indirect(cache_inode, 
105                                                                table, slot);
106         post_smfs_inode(inode, cache_inode);
107 #if 0      
108         if (cache_ind_inode && !IS_ERR(cache_ind_inode)){ 
109                 /*FIXME: get indirect inode set_cow flags*/ 
110                 ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
111                                            inode, slot);
112         }    
113 #endif
114         RETURN(ind_inode);
115 }
116
117 static int fsfilt_smfs_set_indirect(struct inode *inode, int index,
118                                     ino_t ind_ino, ino_t parent_ino)
119 {
120         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
121         struct inode *cache_inode = NULL;
122         int    rc = -EIO;
123         ENTRY;
124
125         if (snap_fsfilt == NULL)
126                 RETURN(rc);
127
128         cache_inode = I2CI(inode);
129         if (!cache_inode)
130                 RETURN(rc);
131
132         pre_smfs_inode(inode, cache_inode);
133         if (snap_fsfilt->fs_set_indirect)
134                 rc = snap_fsfilt->fs_set_indirect(cache_inode, index,
135                                                   ind_ino, parent_ino);
136         post_smfs_inode(inode, cache_inode);
137         
138         RETURN(rc);
139 }
140
141 static int fsfilt_smfs_snap_feature(struct super_block *sb, int feature, 
142                                     int op)
143 {
144         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
145         struct super_block       *csb = S2CSB(sb);
146         int                      rc = -EIO;
147         
148         if (snap_fsfilt == NULL)
149                 RETURN(rc);
150         if (!csb)
151                 RETURN(rc);
152         
153         if (snap_fsfilt->fs_snap_feature)
154                 rc = snap_fsfilt->fs_snap_feature(csb, feature, op);  
155         
156         RETURN(rc); 
157 }
158
159 static int fsfilt_smfs_is_redirector(struct inode *inode)
160 {
161         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
162         struct inode *cache_inode = NULL;
163         int    rc = -EIO;
164         ENTRY;
165
166         if (snap_fsfilt == NULL)
167                 RETURN(rc);
168
169         cache_inode = I2CI(inode);
170         if (!cache_inode)
171                 RETURN(rc);
172
173         pre_smfs_inode(inode, cache_inode);
174         if (snap_fsfilt->fs_is_redirector)
175                 rc = snap_fsfilt->fs_is_redirector(cache_inode);
176         post_smfs_inode(inode, cache_inode);
177         
178         RETURN(rc);
179 }
180 static int fsfilt_smfs_is_indirect(struct inode *inode)
181 {
182         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
183         struct inode *cache_inode = NULL;
184         int    rc = -EIO;
185         ENTRY;
186
187         if (snap_fsfilt == NULL)
188                 RETURN(rc);
189
190         cache_inode = I2CI(inode);
191         if (!cache_inode)
192                 RETURN(rc);
193
194         pre_smfs_inode(inode, cache_inode);
195         if (snap_fsfilt->fs_is_indirect)
196                 rc = snap_fsfilt->fs_is_indirect(cache_inode);
197         post_smfs_inode(inode, cache_inode);
198         
199         RETURN(rc);
200 }
201 static ino_t fsfilt_smfs_get_indirect_ino(struct super_block *sb, ino_t ino, 
202                                           int index)
203 {
204         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
205         struct super_block       *csb = S2CSB(sb);
206         int    rc = -EIO;
207         ENTRY;
208
209         if (snap_fsfilt == NULL)
210                 RETURN(rc);
211
212         if (snap_fsfilt->fs_get_indirect_ino)
213                 rc = snap_fsfilt->fs_get_indirect_ino(csb, ino, index);
214          
215         RETURN(rc);
216 }
217
218 static int fsfilt_smfs_destroy_indirect(struct inode *inode, int index,
219                                         struct inode *next_ind)
220 {
221         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
222         struct inode *cache_inode = NULL;
223         struct inode *cache_next = NULL;
224         int    rc = -EIO;
225         ENTRY;
226
227         if (snap_fsfilt == NULL)
228                 RETURN(rc);
229
230         cache_inode = I2CI(inode);
231         if (!cache_inode)
232                 RETURN(rc);
233
234         cache_next = I2CI(next_ind);
235         if (!cache_next)
236                 RETURN(rc);
237
238         pre_smfs_inode(inode, cache_inode);
239         pre_smfs_inode(next_ind, cache_next);
240
241         if (snap_fsfilt->fs_destroy_indirect)
242                 rc = snap_fsfilt->fs_destroy_indirect(cache_inode, index, 
243                                                       cache_next);
244         post_smfs_inode(inode, cache_inode);
245         post_smfs_inode(next_ind, cache_next);
246         
247         RETURN(rc);
248 }
249 static int fsfilt_smfs_restore_indirect(struct inode *inode, int index)
250 {
251         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
252         struct inode *cache_inode = NULL;
253         int    rc = -EIO;
254         ENTRY;
255
256         if (snap_fsfilt == NULL)
257                 RETURN(rc);
258
259         cache_inode = I2CI(inode);
260         if (!cache_inode)
261                 RETURN(rc);
262
263         pre_smfs_inode(inode, cache_inode);
264         
265         if (snap_fsfilt->fs_restore_indirect)
266                 rc = snap_fsfilt->fs_restore_indirect(cache_inode, index);
267         
268         post_smfs_inode(inode, cache_inode);
269         
270         RETURN(rc);
271 }
272 static int fsfilt_smfs_iterate(struct super_block *sb,
273                                int (*repeat)(struct inode *inode, void *priv),
274                                struct inode **start, void *priv, int flag)
275 {
276         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
277         struct super_block       *csb = S2CSB(sb);
278         int                      rc = -EIO;
279         ENTRY;
280
281         /*FIXME start == NULL, later*/
282         LASSERT(start == NULL);
283  
284         if (snap_fsfilt == NULL)
285                 RETURN(rc);
286          
287         if (snap_fsfilt->fs_iterate)
288                 rc = snap_fsfilt->fs_iterate(csb, repeat, start, priv, flag);
289
290         RETURN(rc);
291 }
292
293 static int fsfilt_smfs_copy_block(struct inode *dst, struct inode *src, int blk)
294 {
295         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(dst);
296         struct inode *cache_dst = NULL;
297         struct inode *cache_src = NULL;
298         int    rc = -EIO;
299         ENTRY;
300
301         if (snap_fsfilt == NULL)
302                 RETURN(rc);
303          
304         cache_dst = I2CI(dst);
305         if (!cache_dst)
306                 RETURN(rc);
307        
308         cache_src = I2CI(src);
309         if (!cache_src)
310                 RETURN(rc);
311
312         pre_smfs_inode(dst, cache_dst);
313         pre_smfs_inode(src, cache_src);
314         
315         if (snap_fsfilt->fs_copy_block)
316                 rc = snap_fsfilt->fs_copy_block(cache_dst, cache_src, blk);
317
318         post_smfs_inode(dst, cache_dst);
319         post_smfs_inode(src, cache_src);
320          
321         RETURN(rc); 
322 }
323
324 static int fsfilt_smfs_set_snap_info(struct inode *inode, 
325                                      void* key, __u32 keylen, void *val, 
326                                      __u32 *vallen)
327 {
328
329         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
330         struct inode *cache_inode = NULL;
331         int                      rc = -EIO;
332                 
333         if (snap_fsfilt == NULL)
334                 RETURN(rc);
335         
336         cache_inode = I2CI(inode);
337         if (!cache_inode)
338                 RETURN(rc);
339
340         pre_smfs_inode(inode, cache_inode);
341         
342         if (snap_fsfilt->fs_set_snap_info)
343                 rc = snap_fsfilt->fs_set_snap_info(cache_inode, key, 
344                                                    keylen, val, vallen);
345         post_smfs_inode(inode, cache_inode);
346         
347         RETURN(rc);
348 }
349
350 static int fsfilt_smfs_get_snap_info(struct inode *inode, void *key, 
351                                      __u32 keylen, void *val, __u32 *vallen)
352 {
353         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
354         struct inode *cache_inode = NULL;
355         int                      rc = -EIO;
356         
357         if (snap_fsfilt == NULL)
358                 RETURN(rc);
359         
360         cache_inode = I2CI(inode);
361         if (!cache_inode)
362                 RETURN(rc);
363         
364         if (snap_fsfilt->fs_get_snap_info)
365                 rc = snap_fsfilt->fs_get_snap_info(cache_inode, key, 
366                                                    keylen, val, vallen);
367         
368         RETURN(rc);
369 }
370
371 static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
372                                              size_t count, loff_t *off)
373 {
374 #if 0
375         struct inode *inode = file->f_dentry->d_inode;
376         struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
377         int    i = 0, size = 0, off_count = 0, buf_off = 0, rc = 0;
378         ENTRY;
379         /*Get the offset of dir ent*/
380         //struct snap_table *stbl = S2SNAPI(inode->i_sb)->sni_table;
381         while (size < *off && off_count < stbl->sntbl_count) {
382                 char *name = stbl->sntbl_items[i].sn_name;
383                 size +=snap_cops->fs_dir_ent_size(name);
384                 off_count ++;
385         }
386         for (i = off_count; i < stbl->sntbl_count; i++) {
387                 char *name = stbl->sntbl_items[i].sn_name;
388                 rc = snap_cops->fs_set_dir_ent(inode->i_sb, name, buf, buf_off, 
389                                                rc, count);
390                 if (rc < 0)
391                         break;
392
393                 buf_off += rc;
394
395                 if (buf_off >= count) 
396                         break;
397         }
398         if (rc > 0) 
399                 rc = 0; 
400 #else
401 #warning "still not implement read .snap dir page for fsfilt Wangdi"
402 #endif
403         RETURN(0); 
404 }
405
406 struct fsfilt_operations fsfilt_smfs_snap_ops = {
407         .fs_type                = "smfs_snap",
408         .fs_owner               = THIS_MODULE,
409         .fs_create_indirect     = fsfilt_smfs_create_indirect,
410         .fs_get_indirect        = fsfilt_smfs_get_indirect,
411         .fs_set_indirect        = fsfilt_smfs_set_indirect,
412         .fs_snap_feature        = fsfilt_smfs_snap_feature,
413         .fs_is_redirector       = fsfilt_smfs_is_redirector,
414         .fs_is_indirect         = fsfilt_smfs_is_indirect,
415         .fs_get_indirect_ino    = fsfilt_smfs_get_indirect_ino,
416         .fs_destroy_indirect    = fsfilt_smfs_destroy_indirect,
417         .fs_restore_indirect    = fsfilt_smfs_restore_indirect,
418         .fs_iterate             = fsfilt_smfs_iterate,
419         .fs_copy_block          = fsfilt_smfs_copy_block,
420         .fs_set_snap_info       = fsfilt_smfs_set_snap_info,
421         .fs_get_snap_info       = fsfilt_smfs_get_snap_info,
422         .fs_read_dotsnap_dir_page = fsfilt_smfs_read_dotsnap_dir_page,
423 };
424
425
426 static int __init fsfilt_smfs_snap_init(void)
427 {
428         int rc;
429
430         rc = fsfilt_register_ops(&fsfilt_smfs_snap_ops);
431         return rc;
432 }
433
434 static void __exit fsfilt_smfs_snap_exit(void)
435 {
436         fsfilt_unregister_ops(&fsfilt_smfs_snap_ops);
437 }
438
439 module_init(fsfilt_smfs_snap_init);
440 module_exit(fsfilt_smfs_snap_exit);
441
442 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
443 MODULE_DESCRIPTION("Lustre SMFS SNAP Filesystem Helper v0.1");
444 MODULE_LICENSE("GPL");