1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Lustre filesystem abstraction routines
6 * Copyright (C) 2004 Cluster File Systems, Inc.
8 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
24 #define DEBUG_SUBSYSTEM S_FILTER
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>
40 #include <linux/lustre_snap.h>
41 #include <linux/lustre_smfs.h>
43 static struct inode* fsfilt_smfs_create_indirect(struct inode *inode,
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;
59 cache_inode = I2CI(inode);
63 cache_parent = I2CI(parent);
67 pre_smfs_inode(inode, cache_inode);
68 pre_smfs_inode(inode, cache_parent);
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);
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,
84 static struct inode* fsfilt_smfs_get_indirect(struct inode *inode,
87 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
88 struct inode *cache_inode = NULL;
89 struct inode *cache_ind_inode = NULL;
90 struct inode *ind_inode = NULL;
96 cache_inode = I2CI(inode);
100 pre_smfs_inode(inode, cache_inode);
102 if (snap_fsfilt->fs_get_indirect)
103 cache_ind_inode = snap_fsfilt->fs_get_indirect(cache_inode,
105 post_smfs_inode(inode, cache_inode);
107 if (cache_ind_inode && !IS_ERR(cache_ind_inode)){
108 /*FIXME: get indirect inode set_cow flags*/
109 ind_inode = smfs_get_inode(inode->i_sb, cache_ind_inode->i_ino,
115 static int fsfilt_smfs_set_indirect(struct inode *inode, int index,
116 ino_t ind_ino, ino_t parent_ino)
118 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
119 struct inode *cache_inode = NULL;
123 if (snap_fsfilt == NULL)
126 cache_inode = I2CI(inode);
130 pre_smfs_inode(inode, cache_inode);
131 if (snap_fsfilt->fs_set_indirect)
132 rc = snap_fsfilt->fs_set_indirect(cache_inode, index,
133 ind_ino, parent_ino);
134 post_smfs_inode(inode, cache_inode);
139 static int fsfilt_smfs_snap_feature(struct super_block *sb, int feature,
142 struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
143 struct super_block *csb = S2CSB(sb);
146 if (snap_fsfilt == NULL)
151 if (snap_fsfilt->fs_snap_feature)
152 rc = snap_fsfilt->fs_snap_feature(csb, feature, op);
157 static int fsfilt_smfs_is_redirector(struct inode *inode)
159 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
160 struct inode *cache_inode = NULL;
164 if (snap_fsfilt == NULL)
167 cache_inode = I2CI(inode);
171 pre_smfs_inode(inode, cache_inode);
172 if (snap_fsfilt->fs_is_redirector)
173 rc = snap_fsfilt->fs_is_redirector(cache_inode);
174 post_smfs_inode(inode, cache_inode);
178 static int fsfilt_smfs_is_indirect(struct inode *inode)
180 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
181 struct inode *cache_inode = NULL;
185 if (snap_fsfilt == NULL)
188 cache_inode = I2CI(inode);
192 pre_smfs_inode(inode, cache_inode);
193 if (snap_fsfilt->fs_is_indirect)
194 rc = snap_fsfilt->fs_is_indirect(cache_inode);
195 post_smfs_inode(inode, cache_inode);
199 static ino_t fsfilt_smfs_get_indirect_ino(struct super_block *sb, ino_t ino,
202 struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
203 struct super_block *csb = S2CSB(sb);
207 if (snap_fsfilt == NULL)
210 if (snap_fsfilt->fs_get_indirect_ino)
211 rc = snap_fsfilt->fs_get_indirect_ino(csb, ino, index);
216 static int fsfilt_smfs_destroy_indirect(struct inode *inode, int index,
217 struct inode *next_ind)
219 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
220 struct inode *cache_inode = NULL;
221 struct inode *cache_next = NULL;
225 if (snap_fsfilt == NULL)
228 cache_inode = I2CI(inode);
232 cache_next = I2CI(next_ind);
236 pre_smfs_inode(inode, cache_inode);
237 pre_smfs_inode(next_ind, cache_next);
239 if (snap_fsfilt->fs_destroy_indirect)
240 rc = snap_fsfilt->fs_destroy_indirect(cache_inode, index,
242 post_smfs_inode(inode, cache_inode);
243 post_smfs_inode(next_ind, cache_next);
247 static int fsfilt_smfs_restore_indirect(struct inode *inode, int index)
249 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
250 struct inode *cache_inode = NULL;
254 if (snap_fsfilt == NULL)
257 cache_inode = I2CI(inode);
261 pre_smfs_inode(inode, cache_inode);
263 if (snap_fsfilt->fs_restore_indirect)
264 rc = snap_fsfilt->fs_restore_indirect(cache_inode, index);
266 post_smfs_inode(inode, cache_inode);
270 static int fsfilt_smfs_iterate(struct super_block *sb,
271 int (*repeat)(struct inode *inode, void *priv),
272 struct inode **start, void *priv, int flag)
274 struct fsfilt_operations *snap_fsfilt = S2SNAPI(sb)->snap_cache_fsfilt;
275 struct super_block *csb = S2CSB(sb);
279 /*FIXME start == NULL, later*/
280 LASSERT(start == NULL);
282 if (snap_fsfilt == NULL)
285 if (snap_fsfilt->fs_iterate)
286 rc = snap_fsfilt->fs_iterate(csb, repeat, start, priv, flag);
291 static int fsfilt_smfs_copy_block(struct inode *dst, struct inode *src, int blk)
293 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(dst);
294 struct inode *cache_dst = NULL;
295 struct inode *cache_src = NULL;
299 if (snap_fsfilt == NULL)
302 cache_dst = I2CI(dst);
306 cache_src = I2CI(src);
310 pre_smfs_inode(dst, cache_dst);
311 pre_smfs_inode(src, cache_src);
313 if (snap_fsfilt->fs_copy_block)
314 rc = snap_fsfilt->fs_copy_block(cache_dst, cache_src, blk);
316 post_smfs_inode(dst, cache_dst);
317 post_smfs_inode(src, cache_src);
322 static int fsfilt_smfs_set_snap_info(struct inode *inode,
323 void* key, __u32 keylen, void *val,
327 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
328 struct inode *cache_inode = NULL;
331 if (snap_fsfilt == NULL)
334 cache_inode = I2CI(inode);
338 pre_smfs_inode(inode, cache_inode);
340 if (snap_fsfilt->fs_set_snap_info)
341 rc = snap_fsfilt->fs_set_snap_info(cache_inode, key,
342 keylen, val, vallen);
343 post_smfs_inode(inode, cache_inode);
348 static int fsfilt_smfs_get_snap_info(struct inode *inode, void *key,
349 __u32 keylen, void *val, __u32 *vallen)
351 struct fsfilt_operations *snap_fsfilt = I2SNAPCOPS(inode);
352 struct inode *cache_inode = NULL;
355 if (snap_fsfilt == NULL)
358 cache_inode = I2CI(inode);
362 if (snap_fsfilt->fs_get_snap_info)
363 rc = snap_fsfilt->fs_get_snap_info(cache_inode, key,
364 keylen, val, vallen);
369 static int fsfilt_smfs_read_dotsnap_dir_page(struct file *file, char *buf,
370 size_t count, loff_t *off)
372 struct inode *inode = file->f_dentry->d_inode;
373 struct fsfilt_operations *snap_cops = I2SNAPCOPS(inode);
374 struct snap_table *stbl = S2SNAPI(inode->i_sb)->sntbl;
375 int i = 0, size = 0, off_count = 0, buf_off = 0, rc = 0;
378 /*Get the offset of dir ent*/
379 while (size < *off && off_count < stbl->sntbl_count) {
380 char *name = stbl->sntbl_items[i].sn_name;
381 size +=snap_cops->fs_dir_ent_size(name);
384 for (i = off_count; i < stbl->sntbl_count; i++) {
385 char *name = stbl->sntbl_items[i].sn_name;
386 rc = snap_cops->fs_set_dir_ent(inode->i_sb, name, buf, buf_off,
393 if (buf_off >= count)
402 struct fsfilt_operations fsfilt_smfs_snap_ops = {
403 .fs_type = "smfs_snap",
404 .fs_owner = THIS_MODULE,
405 .fs_create_indirect = fsfilt_smfs_create_indirect,
406 .fs_get_indirect = fsfilt_smfs_get_indirect,
407 .fs_set_indirect = fsfilt_smfs_set_indirect,
408 .fs_snap_feature = fsfilt_smfs_snap_feature,
409 .fs_is_redirector = fsfilt_smfs_is_redirector,
410 .fs_is_indirect = fsfilt_smfs_is_indirect,
411 .fs_get_indirect_ino = fsfilt_smfs_get_indirect_ino,
412 .fs_destroy_indirect = fsfilt_smfs_destroy_indirect,
413 .fs_restore_indirect = fsfilt_smfs_restore_indirect,
414 .fs_iterate = fsfilt_smfs_iterate,
415 .fs_copy_block = fsfilt_smfs_copy_block,
416 .fs_set_snap_info = fsfilt_smfs_set_snap_info,
417 .fs_get_snap_info = fsfilt_smfs_get_snap_info,
418 .fs_read_dotsnap_dir_page = fsfilt_smfs_read_dotsnap_dir_page,
422 static int __init fsfilt_smfs_snap_init(void)
426 rc = fsfilt_register_ops(&fsfilt_smfs_snap_ops);
430 static void __exit fsfilt_smfs_snap_exit(void)
432 fsfilt_unregister_ops(&fsfilt_smfs_snap_ops);
435 module_init(fsfilt_smfs_snap_init);
436 module_exit(fsfilt_smfs_snap_exit);
438 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
439 MODULE_DESCRIPTION("Lustre SMFS SNAP Filesystem Helper v0.1");
440 MODULE_LICENSE("GPL");