Whamcloud - gitweb
587075bdb13b64ecf7983a7ac8be4e464891fdd4
[fs/lustre-release.git] / lustre / snapfs / super.c
1 /*
2  *  snap_current
3  *
4  *  Copyright (C) 1998 Peter J. Braam
5  *  Copyright (C) 2000 Stelias Computing, Inc.
6  *  Copyright (C) 2000 Red Hat, Inc.
7  *  Copyright (C) 2000 Mountain View Data, Inc.
8  *
9  *  Author: Peter J. Braam <braam@mountainviewdata.com>
10  */
11 #define DEBUG_SUBSYSTEM S_SNAP
12
13 #include <linux/module.h>
14 #include <linux/kmod.h>
15 #include <linux/init.h>
16 #include <linux/fs.h>
17 #include <linux/slab.h>
18 #include <linux/string.h>
19 #include <linux/loop.h>
20 #include <linux/jbd.h>
21 #include <linux/ext3_fs.h>
22 #include <linux/snap.h>
23 #include <linux/errno.h>
24 #include "snapfs_internal.h" 
25
26
27 #ifdef SNAP_DEBUG
28 unsigned int snap_debug_failcode = 0;
29 #endif
30
31 extern struct snap_cache *snap_init_cache(void);
32 extern inline void snap_cache_add(struct snap_cache *, kdev_t);
33 extern inline void snap_init_cache_hash(void);
34
35 extern int snap_get_index_from_name (int tableno, char *name);
36
37
38 extern struct snapshot_operations ext3_snap_operations;
39 extern struct journal_ops snap_ext3_journal_ops;
40                                                                                                                                                                                                      
41 static void put_filesystem(struct file_system_type *fs)
42 {
43         if (fs->owner)
44                 __MOD_DEC_USE_COUNT(fs->owner);
45 }
46
47 /* In get_opt we get options in opt, value in opt_value
48  * we must remember to free opt and opt_value*/
49 static char * snapfs_options(char *options, char **cache_type, 
50                              char **cow_type, char **snaptable)
51 {
52         struct option *opt_value;
53         char *pos;
54         
55         while (!(get_opt(&opt_value, &pos))) {                  
56                 if (!strcmp(opt_value->opt, "cache_type")) {
57                         if (cache_type != NULL)
58                                 *cache_type = opt_value->value;
59                 } else if (!strcmp(opt_value->opt, "cow_type")) {
60                         if (cow_type != NULL)
61                                 *cow_type = opt_value->value;
62                 } else if (!strcmp(opt_value->opt, "snap_table")) {
63                         if (snaptable != NULL)
64                                 *snaptable = opt_value->value;
65                 } else {
66                         break;
67                 }
68         }
69         if (!*cache_type && cache_type) 
70                 *cache_type = "ext3"; 
71         if (!*cow_type && cow_type) 
72                 *cow_type = "block";
73         if (!*snaptable && snaptable)
74                 *snaptable = "0";
75         return pos;
76 }
77 int snapfs_remount(struct super_block * sb, int *flags, char *data)
78 {
79         struct super_operations *sops;
80         struct snap_cache *cache = NULL;
81         char *snapno = NULL, *pos = NULL;
82         char *cache_data = NULL;
83         int err = 0;
84
85         ENTRY;
86         CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
87
88         if ((err = init_option(data))) {
89                 GOTO(out_err, 0);       
90         }
91         cache = snap_find_cache(sb->s_dev);
92         if (!cache) {
93                 CERROR("cannot find cache on remount\n");
94                 GOTO(out_err, err = -ENODEV);
95         }
96
97         /* If an option has not yet been set, we allow it to be set on
98          * remount.  If an option already has a value, we pass NULL for
99          * the option pointer, which means that the snapfs option
100          * will be parsed but discarded.
101          */
102         cache_data = snapfs_options(data, NULL, NULL, &snapno);
103
104         CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data, cache_data); 
105         sops = filter_c2csops(cache->cache_filter);
106         if (sops->remount_fs) 
107                 err = sops->remount_fs(sb, flags, pos);
108 out_err:
109         cleanup_option();
110         RETURN(err);
111 }
112 /*
113  * snapfs super block read.
114  *
115  * Allocate a struct snap_cache, determine the underlying fs type,
116  * read the underlying fs superblock, save the underlying fs ops,
117  * and then replace them with snapfs ops.
118  *
119  * Remove the snapfs options before passing to underlying fs.
120  */
121 struct super_block *
122 snapfs_read_super (
123         struct super_block *sb,
124         void *data,
125         int silent)
126 {
127         struct file_system_type *fstype;
128         struct snap_cache *cache = NULL;
129         char *cache_type = NULL, *cow_type = NULL;
130         char *snapno = NULL, *cache_data = NULL;
131         int tableno, rc = 0;
132
133         ENTRY;
134
135         init_option(data);
136         cache_data = snapfs_options(data, &cache_type, &cow_type, &snapno);
137         /* set up the cache */
138         cache = snap_init_cache();
139         if ( !cache ) {
140                 CERROR("snapfs_read_super: failure allocating cache.\n");
141                 GOTO(out_err, rc = -EINVAL);
142         }
143         /*get cache and cache filter type */    
144         fstype = get_fs_type((const char *)cache_type);
145
146         if ( !fstype || !fstype->read_super) {
147                 CERROR("Unrecognized cache type %s \n", cache_type);
148                 GOTO(out_err, rc = -EINVAL);
149         }
150         cache->cache_filter = filter_get_filter_fs((const char *)cache_type); 
151         if (!cache->cache_filter) {
152                 CERROR("Unrecognized cache type %s \n", cache_type);
153                 GOTO(out_err, rc = -EINVAL);
154         }
155
156         /*
157          * Read the underlying file system superblock - ext2, ext3, reiser.
158          * This performs the underlying mount operation. The snapfs options
159          * have been removed from 'cache_data'.
160          *
161          * Note: It's assumed that sb is always returned.
162          */
163         if (fstype->read_super(sb, cache_data, silent) != sb) {
164                 CERROR("snapfs: cache mount failure.\n");
165                 GOTO(out_err, rc = -EINVAL);
166         }
167         /*
168          * We now know the dev of the cache: hash the cache.
169          *
170          * 'cache' is the struct snap_cache allocated for this
171          * snapfs mount.
172          */
173         snap_cache_add(cache, sb->s_dev);
174
175         tableno = simple_strtoul(snapno, NULL, 0);
176         cache->cache_snap_tableno = tableno;
177         CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
178         
179         /*
180          * make sure we have our own super operations
181          *
182          * Initialize or re-initialize the cache->cache_ops shared
183          * struct snap_ops structure set based on the underlying
184          * file system type.
185          */
186         filter_setup_super_ops(cache->cache_filter, sb->s_op,
187                                &currentfs_super_ops);
188         sb->s_op = filter_c2usops(cache->cache_filter); 
189         /*
190          * Save pointers in the snap_cache structure to the
191          * snapfs and underlying file system superblocks.
192          */
193         cache->cache_sb = sb; /* Underlying file system superblock. */
194
195         /* set up snapshot ops, handle COMPAT_FEATUREs */
196         if( 0 ){
197         }
198         else if (strcmp (cache_type,"ext3") == 0 || !cache_type){
199                 cache->cache_type = FILTER_FS_EXT3;
200                 filter_setup_snapshot_ops(cache->cache_filter,
201                                         &ext3_snap_operations);
202                 filter_setup_journal_ops(cache->cache_filter,
203                                         &snap_ext3_journal_ops);
204                 if( !EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_SNAPFS) ){
205                         if( strcmp(cow_type, "block")==0 ){
206                                 sb->u.ext3_sb.s_es->s_feature_compat |=
207                                         cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW);
208                         }
209                 }
210                 sb->u.ext3_sb.s_last_cowed_pri_ino = 0;
211                 sb->u.ext3_sb.s_first_cowed_pri_ino = 0;
212         }
213         /* now get our own directory operations */
214         if ( sb->s_root && sb->s_root->d_inode ) {
215                 filter_setup_dir_ops(cache->cache_filter, 
216                                      sb->s_root->d_inode,
217                                      &currentfs_dir_iops, &currentfs_dir_fops);
218                 sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter);
219
220                 CDEBUG(D_SUPER, "lookup at %p\n", 
221                        sb->s_root->d_inode->i_op->lookup);
222                 /* XXX is this needed ?? ext3 do not have dentry operations*/
223                 filter_setup_dentry_ops(cache->cache_filter, 
224                                         sb->s_root->d_op, 
225                                         &currentfs_dentry_ops);
226                 sb->s_root->d_op = filter_c2udops(cache->cache_filter);
227                 init_filter_data(sb->s_root->d_inode, 0); 
228         }
229         /*
230          * Save a pointer to the snap_cache structure in the
231          * "snap_current" superblock.
232          */
233         (struct snap_cache *) sb->u.generic_sbp = cache;
234
235         snapfs_read_snaptable(cache, tableno);
236         
237         CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
238                 (ulong) sb, (ulong) sb->u.generic_sbp);
239 out_err:
240         cleanup_option();
241         /* Inc in get_fs_type, Dec in put_fs_type*/
242         if (fstype)
243                 put_filesystem(fstype);
244         if (rc) 
245                 return NULL;
246         return sb; 
247 }
248
249 static DECLARE_FSTYPE_DEV(snapfs_current_type, 
250                           "snap_current", snapfs_read_super);
251
252 /* Find the options for the clone. These consist of a cache device
253    and an index in the snaptable associated with that device. 
254 */
255 static char *clonefs_options(char *options, char **devstr, char **namestr)
256 {
257         struct option *opt_value = NULL;
258         char *pos;
259         
260         while (!(get_opt(&opt_value, &pos))) {                  
261                 if (!strcmp(opt_value->opt, "dev")) {
262                         if (devstr != NULL)
263                                 *devstr = opt_value->value;
264                 } else if (!strcmp(opt_value->opt, "name")) {
265                         if (namestr != NULL)
266                                 *namestr = opt_value->value;
267                 } else {
268                         break;
269                 }
270         }
271         return pos;
272 }
273 static int snap_cache_lookup_ino_cb(struct snap_cache *cache, void *in, unsigned long *out)
274 {
275         ino_t ino = *((unsigned long*)in);
276
277         if (cache) {
278                 struct super_block *sb = cache->cache_sb;
279                 kdev_t dev = sb->s_dev;
280
281                 if (MAJOR(dev) != LOOP_MAJOR) 
282                         return 0;
283                 if (sb->s_bdev->bd_op && sb->s_bdev->bd_op->ioctl) {
284                         struct inode *inode = sb->s_bdev->bd_inode;
285                         struct loop_info loop_info;
286
287                         sb->s_bdev->bd_op->ioctl(inode, NULL, LOOP_GET_INFO, 
288                                                  (unsigned long)&loop_info);
289                         
290                         if(loop_info.lo_inode == ino) {
291                                 *out = sb->s_dev; 
292                                 return 1;
293                         }
294                 }
295         }
296         return 0;       
297 }
298 static int snapfs_path2dev(char *dev_path, kdev_t *dev)
299 {
300         struct dentry *dentry;
301         struct nameidata nd;
302         int error = 0;
303         
304         if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
305                 error = path_walk(dev_path, &nd);
306                 if (error)
307                         return error;
308         } else
309                 return -EINVAL;
310
311         dentry = nd.dentry;
312
313         if (!dentry->d_inode || is_bad_inode(dentry->d_inode) || 
314             (!S_ISBLK(dentry->d_inode->i_mode) && 
315              !S_ISREG(dentry->d_inode->i_mode))){
316                 path_release(&nd);
317                 return -ENODEV;
318         }
319         if (S_ISBLK(dentry->d_inode->i_mode)) {
320                 *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
321         } else {
322                 /*here we must walk through all the snap cache to 
323                  *find the loop device */
324                 kdev_t tmp;
325
326                 if (snap_cache_process(snap_cache_lookup_ino_cb,
327                                        &dentry->d_inode->i_ino, 
328                                        (unsigned long*)&tmp))
329                         return -EINVAL;
330                 *dev = tmp;
331         }
332         path_release(&nd);
333         return 0;
334 }
335
336 extern struct super_operations clone_super_ops;
337 /*
338  * We always need to remove the snapfs options before passing
339  * to bottom FS.
340  */
341 struct super_block *
342 clone_read_super(
343         struct super_block *sb,
344         void *data,
345         int silent)
346 {
347         struct snap_clone_info *clone_sb;
348         struct snap_cache *snap_cache = NULL;
349         struct inode *root_inode = NULL;
350         char *devstr = NULL, *namestr = NULL;
351         char *cache_data;
352         kdev_t dev;
353         int index;
354         ino_t root_ino;
355         int err = 0;
356
357         ENTRY;
358
359         CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
360         
361         init_option(data);
362         /* read and validate options */
363         cache_data = clonefs_options(data, &devstr, &namestr);
364         if (*cache_data) {
365                 CERROR("clonefs: invalid mount option %s\n", (char*)data);
366                 GOTO(out_err, err=-EINVAL);
367         }
368         if (!namestr || !devstr) {
369                 CERROR("snapfs: mount options name and dev mandatory\n");
370                 GOTO(out_err, err=-EINVAL);
371         }
372
373         err = snapfs_path2dev(devstr, &dev);
374         if ( err ) {
375                 CERROR("snap: incorrect device option %s\n", devstr);
376                 GOTO(out_err, err=-EINVAL);
377         }
378         
379         snap_cache = snap_find_cache(dev);
380         if ( !snap_cache ) {
381                 CERROR("snap: incorrect device option %s\n", devstr);
382                 GOTO(out_err, err=-EINVAL);
383         }
384
385         index = snap_get_index_from_name (snap_cache->cache_snap_tableno, 
386                                         namestr);
387         CDEBUG(D_SUPER, "tableno %d, name %s, get index %d\n", 
388                         snap_cache->cache_snap_tableno, namestr, index);
389
390         if(index < 0 ) {
391                 CERROR("No valid index for name %s passed to mount\n",namestr); 
392                 GOTO(out_err, err=-EINVAL);
393         }
394
395         /*
396          * Force clone fs to be read-only.
397          *
398          * XXX - Is there a way to change the mount options too so
399          * the fs is listed as RO by mount?
400          */
401         sb->s_flags |= MS_RDONLY;
402
403         /* set up the super block */
404         clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
405         list_add(&clone_sb->clone_list_entry, &snap_cache->cache_clone_list);
406         clone_sb->clone_cache = snap_cache;
407         clone_sb->clone_index = index;
408         sb->s_op = &clone_super_ops;
409
410         root_ino = snap_cache->cache_sb->s_root->d_inode->i_ino;
411         root_inode = iget(sb, root_ino);
412
413         CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
414                sb->s_op->read_inode, root_ino, root_inode);
415
416         sb->s_root = d_alloc_root(root_inode);
417         
418         if (!sb->s_root) {
419                 list_del(&clone_sb->clone_list_entry);
420                 GOTO(out_err, err=-EINVAL);
421         }
422         dget(snap_cache->cache_sb->s_root);
423
424         CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
425                 (ulong) sb, (ulong) &sb->u.generic_sbp);
426  out_err:
427         cleanup_option();
428         if (err)
429                 return NULL;
430         return sb;
431 }
432
433 static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0);
434
435 int init_snapfs(void)
436 {
437         int status;
438
439         snap_init_cache_hash();
440         init_filter_info_cache();
441
442         status = register_filesystem(&snapfs_current_type);
443         if (status) {
444                 CERROR("snapfs: failed in register current filesystem!\n");
445         }
446
447         status = register_filesystem(&snapfs_clone_type);
448         if (status) {
449                 unregister_filesystem(&snapfs_current_type);
450                 CERROR("snapfs: failed in register clone filesystem!\n");
451         }
452
453         return status;
454 }
455
456
457
458 int cleanup_snapfs(void)
459 {
460         int err;
461
462         ENTRY;
463
464         cleanup_filter_info_cache();
465         err = unregister_filesystem(&snapfs_clone_type);
466         if ( err ) {
467                 CERROR("snapfs: failed to unregister clone filesystem\n");
468         }
469         err = unregister_filesystem(&snapfs_current_type);
470         if ( err ) {
471                 CERROR("snapfs: failed to unregister filesystem\n");
472         }
473         return 0;
474 }