Whamcloud - gitweb
Update snapfs: 1) some fix on clonefs read in lustre
[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 inode *inode, 
326                                      void* key, __u32 keylen, void *val, 
327                                      __u32 *vallen)
328 {
329
330         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
331         struct inode *cache_inode = NULL;
332         int                      rc = -EIO;
333                 
334         if (snap_fsfilt == NULL)
335                 RETURN(rc);
336         
337         cache_inode = I2CI(inode);
338         if (!cache_inode)
339                 RETURN(rc);
340
341         pre_smfs_inode(inode, cache_inode);
342         
343         if (snap_fsfilt->fs_set_snap_info)
344                 rc = snap_fsfilt->fs_set_snap_info(cache_inode, key, 
345                                                    keylen, val, vallen);
346         post_smfs_inode(inode, cache_inode);
347         
348         RETURN(rc);
349 }
350
351 static int fsfilt_smfs_get_snap_info(struct inode *inode, void *key, 
352                                      __u32 keylen, void *val, __u32 *vallen)
353 {
354         struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
355         struct inode *cache_inode = NULL;
356         int                      rc = -EIO;
357         
358         if (snap_fsfilt == NULL)
359                 RETURN(rc);
360         
361         cache_inode = I2CI(inode);
362         if (!cache_inode)
363                 RETURN(rc);
364         
365         if (snap_fsfilt->fs_get_snap_info)
366                 rc = snap_fsfilt->fs_get_snap_info(cache_inode, key, 
367                                                    keylen, val, vallen);
368         
369         RETURN(rc);
370 }
371 struct fsfilt_operations fsfilt_smfs_snap_ops = {
372         .fs_type                = "smfs_snap",
373         .fs_owner               = THIS_MODULE,
374         .fs_create_indirect     = fsfilt_smfs_create_indirect,
375         .fs_get_indirect        = fsfilt_smfs_get_indirect,
376         .fs_set_indirect        = fsfilt_smfs_set_indirect,
377         .fs_snap_feature        = fsfilt_smfs_snap_feature,
378         .fs_is_redirector       = fsfilt_smfs_is_redirector,
379         .fs_is_indirect         = fsfilt_smfs_is_indirect,
380         .fs_get_indirect_ino    = fsfilt_smfs_get_indirect_ino,
381         .fs_destroy_indirect    = fsfilt_smfs_destroy_indirect,
382         .fs_restore_indirect    = fsfilt_smfs_restore_indirect,
383         .fs_iterate             = fsfilt_smfs_iterate,
384         .fs_copy_block          = fsfilt_smfs_copy_block,
385         .fs_set_snap_info       = fsfilt_smfs_set_snap_info,
386         .fs_get_snap_info       = fsfilt_smfs_get_snap_info,
387 };
388
389
390 static int __init fsfilt_smfs_snap_init(void)
391 {
392         int rc;
393
394         rc = fsfilt_register_ops(&fsfilt_smfs_snap_ops);
395         return rc;
396 }
397
398 static void __exit fsfilt_smfs_snap_exit(void)
399 {
400         fsfilt_unregister_ops(&fsfilt_smfs_snap_ops);
401 }
402
403 module_init(fsfilt_smfs_snap_init);
404 module_exit(fsfilt_smfs_snap_exit);
405
406 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
407 MODULE_DESCRIPTION("Lustre SMFS SNAP Filesystem Helper v0.1");
408 MODULE_LICENSE("GPL");