Whamcloud - gitweb
764811d481012e5ceecd998652905cb19a427078
[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 = iget4(inode->i_sb, cache_ind_inode->i_ino, NULL, 0);
109         }    
110         RETURN(ind_inode);
111 }
112
113 static int fsfilt_smfs_set_indirect(struct inode *inode, int index,
114                                     ino_t ind_ino, ino_t parent_ino)
115 {
116         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
117         struct inode *cache_inode = NULL;
118         int    rc = -EIO;
119         ENTRY;
120
121         if (snap_fsfilt == NULL)
122                 RETURN(rc);
123
124         cache_inode = I2CI(inode);
125         if (!cache_inode)
126                 RETURN(rc);
127
128         pre_smfs_inode(inode, cache_inode);
129         if (snap_fsfilt->fs_set_indirect)
130                 rc = snap_fsfilt->fs_set_indirect(cache_inode, index,
131                                                   ind_ino, parent_ino);
132         post_smfs_inode(inode, cache_inode);
133         
134         RETURN(rc);
135 }
136
137 static int fsfilt_smfs_snap_feature(struct super_block *sb, int feature, 
138                                     int op)
139 {
140         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
141         struct super_block       *csb = S2CSB(sb);
142         int                      rc = -EIO;
143         
144         if (snap_fsfilt == NULL)
145                 RETURN(rc);
146         if (!csb)
147                 RETURN(rc);
148         
149         if (snap_fsfilt->fs_snap_feature)
150                 rc = snap_fsfilt->fs_snap_feature(csb, feature, op);  
151         
152         RETURN(rc); 
153 }
154
155 static int fsfilt_smfs_is_redirector(struct inode *inode)
156 {
157         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
158         struct inode *cache_inode = NULL;
159         int    rc = -EIO;
160         ENTRY;
161
162         if (snap_fsfilt == NULL)
163                 RETURN(rc);
164
165         cache_inode = I2CI(inode);
166         if (!cache_inode)
167                 RETURN(rc);
168
169         pre_smfs_inode(inode, cache_inode);
170         if (snap_fsfilt->fs_is_redirector)
171                 rc = snap_fsfilt->fs_is_redirector(cache_inode);
172         post_smfs_inode(inode, cache_inode);
173         
174         RETURN(rc);
175 }
176 static int fsfilt_smfs_is_indirect(struct inode *inode)
177 {
178         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
179         struct inode *cache_inode = NULL;
180         int    rc = -EIO;
181         ENTRY;
182
183         if (snap_fsfilt == NULL)
184                 RETURN(rc);
185
186         cache_inode = I2CI(inode);
187         if (!cache_inode)
188                 RETURN(rc);
189
190         pre_smfs_inode(inode, cache_inode);
191         if (snap_fsfilt->fs_is_indirect)
192                 rc = snap_fsfilt->fs_is_indirect(cache_inode);
193         post_smfs_inode(inode, cache_inode);
194         
195         RETURN(rc);
196 }
197 static ino_t fsfilt_smfs_get_indirect_ino(struct inode *inode, int index)
198 {
199         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
200         struct inode *cache_inode = NULL;
201         int    rc = -EIO;
202         ENTRY;
203
204         if (snap_fsfilt == NULL)
205                 RETURN(rc);
206
207         cache_inode = I2CI(inode);
208         if (!cache_inode)
209                 RETURN(rc);
210
211         pre_smfs_inode(inode, cache_inode);
212         if (snap_fsfilt->fs_get_indirect_ino)
213                 rc = snap_fsfilt->fs_get_indirect_ino(cache_inode, index);
214         post_smfs_inode(inode, cache_inode);
215         
216         RETURN(rc);
217 }
218
219 static int fsfilt_smfs_destroy_indirect(struct inode *inode, int index,
220                                         struct inode *next_ind)
221 {
222         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
223         struct inode *cache_inode = NULL;
224         struct inode *cache_next = NULL;
225         int    rc = -EIO;
226         ENTRY;
227
228         if (snap_fsfilt == NULL)
229                 RETURN(rc);
230
231         cache_inode = I2CI(inode);
232         if (!cache_inode)
233                 RETURN(rc);
234
235         cache_next = I2CI(next_ind);
236         if (!cache_next)
237                 RETURN(rc);
238
239         pre_smfs_inode(inode, cache_inode);
240         pre_smfs_inode(next_ind, cache_next);
241
242         if (snap_fsfilt->fs_destroy_indirect)
243                 rc = snap_fsfilt->fs_destroy_indirect(cache_inode, index, 
244                                                       cache_next);
245         post_smfs_inode(inode, cache_inode);
246         post_smfs_inode(next_ind, cache_next);
247         
248         RETURN(rc);
249 }
250 static int fsfilt_smfs_restore_indirect(struct inode *inode, int index)
251 {
252         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
253         struct inode *cache_inode = NULL;
254         int    rc = -EIO;
255         ENTRY;
256
257         if (snap_fsfilt == NULL)
258                 RETURN(rc);
259
260         cache_inode = I2CI(inode);
261         if (!cache_inode)
262                 RETURN(rc);
263
264         pre_smfs_inode(inode, cache_inode);
265         
266         if (snap_fsfilt->fs_restore_indirect)
267                 rc = snap_fsfilt->fs_restore_indirect(cache_inode, index);
268         
269         post_smfs_inode(inode, cache_inode);
270         
271         RETURN(rc);
272 }
273 static int fsfilt_smfs_iterate(struct super_block *sb,
274                                int (*repeat)(struct inode *inode, void *priv),
275                                struct inode **start, void *priv, int flag)
276 {
277         struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
278         struct super_block       *csb = S2CSB(sb);
279         int                      rc = -EIO;
280         ENTRY;
281
282         /*FIXME start == NULL, later*/
283         LASSERT(start == NULL);
284  
285         if (snap_fsfilt == NULL)
286                 RETURN(rc);
287          
288         if (snap_fsfilt->fs_iterate)
289                 rc = snap_fsfilt->fs_iterate(csb, repeat, start, priv, flag);
290
291         RETURN(rc);
292 }
293
294 static int fsfilt_smfs_copy_block(struct inode *dst, struct inode *src, int blk)
295 {
296         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(dst);
297         struct inode *cache_dst = NULL;
298         struct inode *cache_src = NULL;
299         int    rc = -EIO;
300         ENTRY;
301
302         if (snap_fsfilt == NULL)
303                 RETURN(rc);
304          
305         cache_dst = I2CI(dst);
306         if (!cache_dst)
307                 RETURN(rc);
308        
309         cache_src = I2CI(src);
310         if (!cache_src)
311                 RETURN(rc);
312
313         pre_smfs_inode(dst, cache_dst);
314         pre_smfs_inode(src, cache_src);
315         
316         if (snap_fsfilt->fs_copy_block)
317                 rc = snap_fsfilt->fs_copy_block(cache_dst, cache_src, blk);
318
319         post_smfs_inode(dst, cache_dst);
320         post_smfs_inode(src, cache_src);
321          
322         RETURN(rc); 
323 }
324
325 static int fsfilt_smfs_set_snap_info(struct super_block *sb,struct inode *inode, 
326                                      void* key, __u32 keylen, void *val, 
327                                      __u32 *vallen)
328 {
329         struct super_block     *csb = NULL;
330         struct inode           *cache_inode = NULL;  
331         struct fsfilt_operations *snap_fsfilt = NULL; 
332         int                      rc = -EIO;
333         
334         if (sb) {
335                 csb = S2CSB(sb);
336                 snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
337         } else if (inode) {
338                 cache_inode = I2CI(inode);
339                 snap_fsfilt = I2SNAPCOPS(inode);
340         }
341
342         if (snap_fsfilt == NULL)
343                 RETURN(rc);
344         
345         if (snap_fsfilt->fs_set_snap_info)
346                 rc = snap_fsfilt->fs_set_snap_info(csb, cache_inode, key, 
347                                                    keylen, val, vallen);
348
349         RETURN(rc);
350 }
351
352 static int fsfilt_smfs_get_snap_info(struct super_block *sb, struct inode *inode,
353                                      void *key, __u32 keylen, void *val,
354                                      __u32 *vallen)
355 {
356         struct super_block     *csb = NULL;
357         struct inode           *cache_inode = NULL;  
358         struct fsfilt_operations *snap_fsfilt = NULL; 
359         int                      rc = -EIO;
360         
361         if (sb) {
362                 csb = S2CSB(sb);
363                 snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
364         } else if (inode) {
365                 cache_inode = I2CI(inode);
366                 snap_fsfilt = I2SNAPCOPS(inode);
367         }
368       
369         if (snap_fsfilt == NULL)
370                 RETURN(rc);
371        
372         if (snap_fsfilt->fs_get_snap_info)
373                 rc = snap_fsfilt->fs_get_snap_info(csb, cache_inode, key, 
374                                                    keylen, val, vallen);
375
376         RETURN(rc);
377 }
378 struct fsfilt_operations fsfilt_smfs_snap_ops = {
379         .fs_type                = "smfs_snap",
380         .fs_owner               = THIS_MODULE,
381         .fs_create_indirect     = fsfilt_smfs_create_indirect,
382         .fs_get_indirect        = fsfilt_smfs_get_indirect,
383         .fs_set_indirect        = fsfilt_smfs_set_indirect,
384         .fs_snap_feature        = fsfilt_smfs_snap_feature,
385         .fs_is_redirector       = fsfilt_smfs_is_redirector,
386         .fs_is_indirect         = fsfilt_smfs_is_indirect,
387         .fs_get_indirect_ino    = fsfilt_smfs_get_indirect_ino,
388         .fs_destroy_indirect    = fsfilt_smfs_destroy_indirect,
389         .fs_restore_indirect    = fsfilt_smfs_restore_indirect,
390         .fs_iterate             = fsfilt_smfs_iterate,
391         .fs_copy_block          = fsfilt_smfs_copy_block,
392         .fs_set_snap_info       = fsfilt_smfs_set_snap_info,
393         .fs_get_snap_info       = fsfilt_smfs_get_snap_info,
394 };
395
396
397 static int __init fsfilt_smfs_snap_init(void)
398 {
399         int rc;
400
401         rc = fsfilt_register_ops(&fsfilt_smfs_snap_ops);
402         return rc;
403 }
404
405 static void __exit fsfilt_smfs_snap_exit(void)
406 {
407         fsfilt_unregister_ops(&fsfilt_smfs_snap_ops);
408 }
409
410 module_init(fsfilt_smfs_snap_init);
411 module_exit(fsfilt_smfs_snap_exit);
412
413 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
414 MODULE_DESCRIPTION("Lustre SMFS SNAP Filesystem Helper v0.1");
415 MODULE_LICENSE("GPL");