Whamcloud - gitweb
port snapfs to 2.4
[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/jbd.h>
20 #include <linux/ext3_fs.h>
21 #include <linux/snap.h>
22 #include <linux/errno.h>
23 #include "snapfs_internal.h" 
24
25
26 #ifdef SNAP_DEBUG
27 unsigned int snap_debug_failcode = 0;
28 #endif
29
30 extern struct snap_cache *snap_init_cache(void);
31 extern inline void snap_cache_add(struct snap_cache *, kdev_t);
32 extern inline void snap_init_cache_hash(void);
33
34 extern int snap_get_index_from_name (int tableno, char *name);
35
36
37 extern struct snapshot_operations ext3_snap_operations;
38 extern struct journal_ops snap_ext3_journal_ops;
39                                                                                                                                                                                                      
40 static void put_filesystem(struct file_system_type *fs)
41 {
42         if (fs->owner)
43                 __MOD_DEC_USE_COUNT(fs->owner);
44 }
45
46
47 /* returns an allocated string, copied out from data if opt is found */
48 static char *read_opt(const char *opt, char *data)
49 {
50         char *value;
51         char *retval;
52
53         CDEBUG(D_SUPER, "option: %s, data %s\n", opt, data);
54         if ( strncmp(opt, data, strlen(opt)) )
55                 return NULL;
56
57         if ( (value = strchr(data, '=')) == NULL )
58                 return NULL;
59
60         value++;
61         SNAP_ALLOC(retval, strlen(value) + 1);
62         if ( !retval ) {
63                 CERROR("snapfs: Out of memory!\n");
64                 return NULL;
65         }
66
67         strcpy(retval, value);
68         CDEBUG(D_SUPER, "Assigned option: %s, value %s\n", opt, retval);
69         return retval;
70 }
71
72 static inline void store_opt(char **dst, char *opt)
73 {
74         if (dst) {
75                 if (*dst)
76                         SNAP_FREE(*dst, strlen(*dst) + 1);
77                 *dst = opt;
78         } else
79                 SNAP_FREE(opt, strlen(opt) + 1);
80 }
81
82 /* Find the options for snapfs in "options", saving them into the
83  * passed pointers.  If the pointer is null, the option is discarded.
84  * Copy out all non-snapfs options into cache_data (to be passed
85  * to the read_super operation of the cache).  The return value will
86  * be a pointer to the end of the cache_data.
87  */
88 static char *snapfs_options(char *options, char *cache_data,
89                             char **cache_type, char **cow_type,
90                             char **snaptable)
91 {
92         char *this_char;
93         char *cache_data_end = cache_data;
94
95         /* set the defaults here */
96         if (cache_type && !*cache_type) {
97                 SNAP_ALLOC(*cache_type, strlen("ext3") + 1);
98                 strcpy(*cache_type, "ext3");
99         }
100         if (cow_type && !*cow_type) {
101                 SNAP_ALLOC(*cow_type, strlen("block") + 1);
102                 strcpy(*cow_type, "block");
103         }
104         if (snaptable && !*snaptable) {
105                 SNAP_ALLOC(*snaptable, strlen("-1")+1);
106                 strcpy(*snaptable, "-1");
107         }
108
109         if (!options || !cache_data)
110                 return cache_data_end;
111
112         CDEBUG(D_SUPER, "parsing options\n");
113         for (this_char = strtok (options, ",");
114              this_char != NULL;
115              this_char = strtok (NULL, ",")) {
116                 char *opt;
117                 CDEBUG(D_SUPER, "this_char %s\n", this_char);
118
119                 if ( (opt = read_opt("cache_type", this_char)) ) {
120                         store_opt(cache_type, opt);
121                         continue;
122                 }
123                 if ( (opt = read_opt("cow_type", this_char)) ){
124                         store_opt(cow_type, opt);
125                         continue;
126                 }
127                 if ( (opt = read_opt("table", this_char)) ) {
128                         store_opt(snaptable, opt);
129                         continue;
130                 }
131
132                 cache_data_end += sprintf(cache_data_end, "%s%s",
133                                           cache_data_end != cache_data ? ",":"",
134                                           this_char);
135         }
136
137         return cache_data_end;
138 }
139
140 int snapfs_remount(struct super_block * sb, int *flags, char *data)
141 {
142         char *cache_data = NULL;
143         char *snapno = NULL;
144         char *cache_data_end;
145         struct snap_cache *cache = NULL;
146         struct super_operations *sops;
147         int err = 0;
148
149         ENTRY;
150         CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
151         if (data) {
152                 /* reserve space for the cache's data */
153                 SNAP_ALLOC(cache_data, PAGE_SIZE);
154                 if ( !cache_data ) 
155                         GOTO(out_err, err = -ENOMEM);
156         }
157
158         cache = snap_find_cache(sb->s_dev);
159         if (!cache) {
160                 CERROR("cannot find cache on remount\n");
161                 GOTO(out_err, err = -ENODEV);
162         }
163
164         /* If an option has not yet been set, we allow it to be set on
165          * remount.  If an option already has a value, we pass NULL for
166          * the option pointer, which means that the snapfs option
167          * will be parsed but discarded.
168          */
169         cache_data_end = snapfs_options(data, cache_data, NULL, NULL, &snapno);
170
171         if (cache_data) {
172                 if (cache_data_end == cache_data) {
173                         SNAP_FREE(cache_data, PAGE_SIZE);
174                         cache_data = NULL;
175                 } else {
176                         CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data,
177                                cache_data);
178                 }
179         }
180
181
182         sops = filter_c2csops(cache->cache_filter);
183         if (sops->remount_fs) {
184                 err = sops->remount_fs(sb, flags, cache_data);
185         }
186
187         EXIT;
188 out_err:
189         if (cache_data)
190                 SNAP_FREE(cache_data, PAGE_SIZE);
191         return err;
192 }
193
194 /* XXXX remount: needed if snapfs was mounted RO at boot time
195    without a snaptable 
196 */ 
197
198
199 /*
200  * snapfs super block read.
201  *
202  * Allocate a struct snap_cache, determine the underlying fs type,
203  * read the underlying fs superblock, save the underlying fs ops,
204  * and then replace them with snapfs ops.
205  *
206  * Remove the snapfs options before passing to underlying fs.
207  */
208 struct super_block *
209 snapfs_read_super (
210         struct super_block *sb,
211         void *data,
212         int silent)
213 {
214         struct file_system_type *fstype;
215         struct snap_cache *cache = NULL;
216         char *cache_data = NULL;
217         char *cache_data_end;
218         char *cache_type = NULL;
219         char *cow_type = NULL;
220         char *snapno = NULL;
221         char *endptr;
222         int tableno;
223
224         ENTRY;
225
226         /* reserve space for the cache's data */
227         SNAP_ALLOC(cache_data, PAGE_SIZE);
228         if ( !cache_data ) {
229                 CERROR("snapfs_read_super: Cannot allocate data page.\n");
230                 GOTO(out_err, 0);
231         }
232
233         CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
234
235         /* read and validate options */
236         cache_data_end = snapfs_options(data, cache_data, &cache_type, &cow_type, &snapno);
237
238         /* Need to free cache_type and snapno when it's not in use */
239
240         /* was there anything for the cache filesystem in the data? */
241         if (cache_data_end == cache_data) {
242                 SNAP_FREE(cache_data, PAGE_SIZE);
243                 cache_data = NULL;
244         } else {
245                 CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data,
246                        cache_data);
247         }
248
249         /* set up the cache */
250         cache = snap_init_cache();
251         if ( !cache ) {
252                 CERROR("snapfs_read_super: failure allocating cache.\n");
253                 GOTO(out_err, 0);
254         }
255
256         fstype = get_fs_type(cache_type);
257         if ( !fstype || !fstype->read_super) {
258                 GOTO(out_err, 0);
259         }
260         
261         cache->cache_filter = filter_get_filter_fs((const char *)cache_type); 
262         
263         if (!cache->cache_filter) {
264                 CERROR("Unrecognized cache type %s \n", cache_type);
265                 GOTO(out_err, 0);
266         }
267
268         /*
269          * Read the underlying file system superblock - ext2, ext3, reiser.
270          * This performs the underlying mount operation. The snapfs options
271          * have been removed from 'cache_data'.
272          *
273          * Note: It's assumed that sb is always returned.
274          */
275         if (fstype->read_super(sb, cache_data, silent) != sb) {
276                 CERROR("snapfs: cache mount failure.\n");
277                 GOTO(out_err, 0);
278         }
279
280         /* this might have been freed above */
281         if (cache_data) {
282                 SNAP_FREE(cache_data, PAGE_SIZE);
283                 cache_data = NULL;
284         }
285
286
287         /*
288          * We now know the dev of the cache: hash the cache.
289          *
290          * 'cache' is the struct snap_cache allocated for this
291          * snapfs mount.
292          */
293         snap_cache_add(cache, sb->s_dev);
294
295         tableno  =  simple_strtoul(snapno, &endptr, 0);
296         cache->cache_snap_tableno = tableno;
297
298
299         CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
300         /*
301          * make sure we have our own super operations
302          *
303          * Initialize or re-initialize the cache->cache_ops shared
304          * struct snap_ops structure set based on the underlying
305          * file system type.
306          */
307         filter_setup_super_ops(cache->cache_filter, sb->s_op,
308                                &currentfs_super_ops);
309         sb->s_op = filter_c2usops(cache->cache_filter); 
310         /*
311          * Save pointers in the snap_cache structure to the
312          * snapfs and underlying file system superblocks.
313          */
314         cache->cache_sb = sb; /* Underlying file system superblock. */
315
316         /* set up snapshot ops, handle COMPAT_FEATUREs */
317         if( 0 ){
318         }
319         else if ( strcmp (cache_type,"ext3") == 0 ){
320                 cache->cache_type = FILTER_FS_EXT3;
321                 filter_setup_snapshot_ops(cache->cache_filter,
322                                         &ext3_snap_operations);
323                 filter_setup_journal_ops(cache->cache_filter,
324                                         &snap_ext3_journal_ops);
325                 if( !EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_SNAPFS) ){
326                         if( strcmp(cow_type, "block")==0 ){
327                                 sb->u.ext3_sb.s_es->s_feature_compat |=
328                                         cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW);
329                         }
330                 }
331                 sb->u.ext3_sb.s_last_cowed_pri_ino = 0;
332                 sb->u.ext3_sb.s_first_cowed_pri_ino = 0;
333         }
334         /* now get our own directory operations */
335         if ( sb->s_root && sb->s_root->d_inode ) {
336                 filter_setup_dir_ops(cache->cache_filter, 
337                                      sb->s_root->d_inode,
338                                      &currentfs_dir_iops, &currentfs_dir_fops);
339                 sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter);
340
341                 CDEBUG(D_SUPER, "lookup at %p\n", 
342                        sb->s_root->d_inode->i_op->lookup);
343                 /* XXX is this needed ?? ext3 do not have dentry operations*/
344                 filter_setup_dentry_ops(cache->cache_filter, 
345                                         sb->s_root->d_op, 
346                                         &currentfs_dentry_ops);
347                 sb->s_root->d_op = filter_c2udops(cache->cache_filter);
348         }
349         /*
350          * Save a pointer to the snap_cache structure in the
351          * "snap_current" superblock.
352          */
353         (struct snap_cache *) sb->u.generic_sbp = cache;
354
355         snapfs_read_snaptable(cache, tableno);
356         
357         CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
358                 (ulong) sb, (ulong) sb->u.generic_sbp);
359
360         /* we can free snapno and cache_type now, because it's not used */
361         if (snapno) {
362                 SNAP_FREE(snapno, strlen(snapno) + 1);
363                 snapno = NULL;
364         }
365         if (cache_type) {
366                 SNAP_FREE(cache_type, strlen(cache_type) + 1);
367                 snapno = NULL;
368         }
369         if (cow_type) {
370                 SNAP_FREE(cow_type, strlen(cow_type) + 1);
371                 cow_type = NULL;
372         }
373         /* Inc in get_fs_type, Dec in put_fs_type*/
374
375         put_filesystem(fstype);
376         
377         return sb;
378
379  out_err:
380         CDEBUG(D_SUPER, "out_err called\n");
381         if (cache)
382                 SNAP_FREE(cache, sizeof(struct snap_cache));
383         if (cache_data)
384                 SNAP_FREE(cache_data, PAGE_SIZE);
385         if (snapno)
386                 SNAP_FREE(snapno, strlen(snapno) + 1);
387         if (cache_type)
388                 SNAP_FREE(cache_type, strlen(cache_type) + 1);
389         if (cow_type)
390                 SNAP_FREE(cow_type, strlen(cow_type) + 1);
391         if (fstype)
392                 put_filesystem(fstype);
393
394         return NULL;
395 }
396
397 static DECLARE_FSTYPE_DEV(snapfs_current_type, "snap_current", snapfs_read_super);
398
399
400 /* Find the options for the clone. These consist of a cache device
401    and an index in the snaptable associated with that device. 
402 */
403 static char *clonefs_options(char *options, char *cache_data,
404                             char **devstr, char **namestr)
405 {
406         char *this_char;
407         char *cache_data_end = cache_data;
408
409         if (!options || !cache_data)
410                 return cache_data_end;
411
412         CDEBUG(D_SUPER, "parsing options\n");
413         for (this_char = strtok (options, ",");
414              this_char != NULL;
415              this_char = strtok (NULL, ",")) {
416                 char *opt;
417                 CDEBUG(D_SUPER, "this_char %s\n", this_char);
418
419                 if ( (opt = read_opt("dev", this_char)) ) {
420                         store_opt(devstr, opt);
421                         continue;
422                 }
423                 if ( (opt = read_opt("name", this_char)) ) {
424                         store_opt(namestr, opt);
425                         continue;
426                 }
427
428                 cache_data_end += sprintf(cache_data_end, "%s%s",
429                                           cache_data_end != cache_data ? ",":"",
430                                           this_char);
431         }
432
433         return cache_data_end;
434 }
435
436 static int snapfs_path2dev(char *dev_path, kdev_t *dev)
437 {
438         struct dentry *dentry;
439         struct nameidata nd;
440         int error = 0;
441         
442         if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
443                 error = path_walk(dev_path, &nd);
444                 if (error)
445                         return error;
446         } else
447                 return -EINVAL;
448
449         dentry = nd.dentry;
450
451         if (!dentry->d_inode || !S_ISBLK(dentry->d_inode->i_mode) || 
452             is_bad_inode(dentry->d_inode) ) {
453                 path_release(&nd);
454                 return -ENODEV;
455         }
456
457         *dev = dentry->d_inode->i_rdev;
458         path_release(&nd);
459         return 0;
460 }
461
462
463 extern struct super_operations clone_super_ops;
464
465 /*
466  * We always need to remove the snapfs options before passing
467  * to bottom FS.
468  */
469 struct super_block *
470 clone_read_super(
471         struct super_block *sb,
472         void *data,
473         int silent)
474 {
475         struct snap_clone_info *clone_sb;
476         struct snap_cache *snap_cache = NULL;
477         int err;
478         char *cache_data = NULL;
479         char *cache_data_end;
480         char *devstr = NULL;
481         kdev_t dev;
482         char *namestr = NULL;
483         //char *endptr;
484         int index;
485         ino_t root_ino;
486         struct inode *root_inode;
487
488         ENTRY;
489
490
491         /* reserve space for the cache's data */
492         SNAP_ALLOC(cache_data, PAGE_SIZE);
493         if ( !cache_data ) {
494                 CERROR("clone_read_super: Cannot allocate data page.\n");
495                 GOTO(out_err, 0);
496         }
497
498         CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
499
500         /* read and validate options */
501         cache_data_end = clonefs_options(data, cache_data, &devstr, &namestr);
502
503         /* was there anything for the cache filesystem in the data? */
504         if (cache_data_end == cache_data) {
505                 SNAP_FREE(cache_data, PAGE_SIZE);
506                 cache_data = NULL;
507         } else {
508                 CERROR("clonefs: invalid mount option %s\n", cache_data);
509                 GOTO(out_err, 0);
510         }
511
512         if (!namestr || !devstr) {
513                 CERROR("snapfs: mount options name and dev mandatory\n");
514                 GOTO(out_err, 0);
515         }
516
517         err = snapfs_path2dev(devstr, &dev);
518         if ( err ) {
519                 CERROR("snap: incorrect device option %s\n", devstr);
520                 GOTO(out_err, 0);
521         }
522         
523         snap_cache = snap_find_cache(dev);
524         if ( !snap_cache ) {
525                 CERROR("snap: incorrect device option %s\n", devstr);
526                 GOTO(out_err, 0);
527         }
528
529         /*index =  simple_strtoul(indexstr, &endptr, 0);
530         if ( indexstr == endptr ) {
531                 printk("No valid index passed to mount\n"); 
532                 EXIT;
533                 goto out_err;
534         }
535         */
536
537         index = snap_get_index_from_name (snap_cache->cache_snap_tableno, 
538                                         namestr);
539         CDEBUG(D_SUPER, "tableno %d, name %s, get index %d\n", 
540                         snap_cache->cache_snap_tableno, namestr, index);
541
542         if(index < 0 ) {
543                 CERROR("No valid index for name %s passed to mount\n",namestr); 
544                 GOTO(out_err, 0);
545         }
546
547         /*
548          * Force clone fs to be read-only.
549          *
550          * XXX - Is there a way to change the mount options too so
551          * the fs is listed as RO by mount?
552          */
553         sb->s_flags |= MS_RDONLY;
554
555         /* set up the super block */
556         clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
557         list_add(&clone_sb->clone_list_entry, &snap_cache->cache_clone_list);
558         clone_sb->clone_cache = snap_cache;
559         clone_sb->clone_index = index;
560         sb->s_op = &clone_super_ops;
561
562         root_ino = snap_cache->cache_sb->s_root->d_inode->i_ino;
563         root_inode = iget(sb, root_ino);
564
565         CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
566                sb->s_op->read_inode, root_ino, root_inode);
567
568         sb->s_root = d_alloc_root(root_inode);
569         if (!sb->s_root) {
570                 list_del(&clone_sb->clone_list_entry);
571                 sb = NULL;
572         }
573
574         dget(snap_cache->cache_sb->s_root);
575
576         if (cache_data)
577                 SNAP_FREE(cache_data, PAGE_SIZE);
578         if (devstr)
579                 SNAP_FREE(devstr, strlen(devstr) + 1);
580         if (namestr)
581                 SNAP_FREE(namestr, strlen(namestr) + 1);
582         CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
583                 (ulong) sb, (ulong) &sb->u.generic_sbp);
584         return sb;
585  out_err:
586         return NULL;
587 }
588
589 static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0);
590
591 int init_snapfs(void)
592 {
593         int status;
594
595         snap_init_cache_hash();
596         init_filter_info_cache();
597
598         status = register_filesystem(&snapfs_clone_type);
599         if (status) {
600                 unregister_filesystem(&snapfs_current_type);
601                 CERROR("snapfs: failed in register clone filesystem!\n");
602         }
603
604         status = register_filesystem(&snapfs_current_type);
605         if (status) {
606                 CERROR("snapfs: failed in register current filesystem!\n");
607         }
608         return status;
609 }
610
611
612
613 int cleanup_snapfs(void)
614 {
615         int err;
616
617         ENTRY;
618
619         cleanup_filter_info_cache();
620         err = unregister_filesystem(&snapfs_clone_type);
621         if ( err ) {
622                 CERROR("snapfs: failed to unregister clone filesystem\n");
623         }
624         err = unregister_filesystem(&snapfs_current_type);
625         if ( err ) {
626                 CERROR("snapfs: failed to unregister filesystem\n");
627         }
628         return 0;
629 }