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.
9 * Author: Peter J. Braam <braam@mountainviewdata.com>
11 #define DEBUG_SUBSYSTEM S_SNAP
13 #include <linux/module.h>
14 #include <linux/kmod.h>
15 #include <linux/init.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"
28 unsigned int snap_debug_failcode = 0;
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);
35 extern int snap_get_index_from_name (int tableno, char *name);
38 extern struct snapshot_operations ext3_snap_operations;
39 extern struct journal_ops snap_ext3_journal_ops;
41 static void put_filesystem(struct file_system_type *fs)
44 __MOD_DEC_USE_COUNT(fs->owner);
47 static struct vfsmount* get_vfsmount(struct super_block *sb)
49 struct vfsmount *rootmnt, *mnt, *ret = NULL;
50 struct list_head *end, *list;
52 rootmnt = mntget(current->fs->rootmnt);
53 end = list = &rootmnt->mnt_list;
55 mnt = list_entry(list, struct vfsmount, mnt_list);
56 if (mnt->mnt_sb == sb) {
61 } while (end != list);
62 mntput(current->fs->rootmnt);
66 void get_snap_current_mnt(struct super_block *sb)
70 mnt = get_vfsmount(sb);
74 void put_snap_current_mnt(struct super_block *sb)
78 mnt = get_vfsmount(sb);
83 /* In get_opt we get options in opt, value in opt_value
84 * we must remember to free opt and opt_value*/
85 static char * snapfs_options(char *options, char **cache_type,
86 char **cow_type, char **snaptable)
88 struct option *opt_value;
91 while (!(get_opt(&opt_value, &pos))) {
92 if (!strcmp(opt_value->opt, "cache_type")) {
93 if (cache_type != NULL)
94 *cache_type = opt_value->value;
95 } else if (!strcmp(opt_value->opt, "cow_type")) {
97 *cow_type = opt_value->value;
98 } else if (!strcmp(opt_value->opt, "snap_table")) {
99 if (snaptable != NULL)
100 *snaptable = opt_value->value;
105 if (!*cache_type && cache_type)
106 *cache_type = "ext3";
107 if (!*cow_type && cow_type)
109 if (!*snaptable && snaptable)
113 int snapfs_remount(struct super_block * sb, int *flags, char *data)
115 struct super_operations *sops;
116 struct snap_cache *cache = NULL;
117 char *snapno = NULL, *pos = NULL;
118 char *cache_data = NULL;
122 CDEBUG(D_SUPER, "remount opts: %s\n", data ? (char *)data : "(none)");
124 if ((err = init_option(data))) {
127 cache = snap_find_cache(sb->s_dev);
129 CERROR("cannot find cache on remount\n");
130 GOTO(out_err, err = -ENODEV);
133 /* If an option has not yet been set, we allow it to be set on
134 * remount. If an option already has a value, we pass NULL for
135 * the option pointer, which means that the snapfs option
136 * will be parsed but discarded.
138 cache_data = snapfs_options(data, NULL, NULL, &snapno);
140 CDEBUG(D_SUPER, "cache_data at %p is: %s\n", cache_data, cache_data);
141 sops = filter_c2csops(cache->cache_filter);
142 if (sops->remount_fs)
143 err = sops->remount_fs(sb, flags, pos);
149 * snapfs super block read.
151 * Allocate a struct snap_cache, determine the underlying fs type,
152 * read the underlying fs superblock, save the underlying fs ops,
153 * and then replace them with snapfs ops.
155 * Remove the snapfs options before passing to underlying fs.
159 struct super_block *sb,
163 struct file_system_type *fstype;
164 struct snap_cache *cache = NULL;
165 char *cache_type = NULL, *cow_type = NULL;
166 char *snapno = NULL, *cache_data = NULL;
172 cache_data = snapfs_options(data, &cache_type, &cow_type, &snapno);
173 /* set up the cache */
174 cache = snap_init_cache();
176 CERROR("snapfs_read_super: failure allocating cache.\n");
177 GOTO(out_err, rc = -EINVAL);
179 /*get cache and cache filter type */
180 fstype = get_fs_type((const char *)cache_type);
182 if ( !fstype || !fstype->read_super) {
183 CERROR("Unrecognized cache type %s \n", cache_type);
184 GOTO(out_err, rc = -EINVAL);
186 cache->cache_filter = filter_get_filter_fs((const char *)cache_type);
187 if (!cache->cache_filter) {
188 CERROR("Unrecognized cache type %s \n", cache_type);
189 GOTO(out_err, rc = -EINVAL);
193 * Read the underlying file system superblock - ext2, ext3, reiser.
194 * This performs the underlying mount operation. The snapfs options
195 * have been removed from 'cache_data'.
197 * Note: It's assumed that sb is always returned.
199 if (fstype->read_super(sb, cache_data, silent) != sb) {
200 CERROR("snapfs: cache mount failure.\n");
201 GOTO(out_err, rc = -EINVAL);
204 * We now know the dev of the cache: hash the cache.
206 * 'cache' is the struct snap_cache allocated for this
209 snap_cache_add(cache, sb->s_dev);
211 tableno = simple_strtoul(snapno, NULL, 0);
212 cache->cache_snap_tableno = tableno;
213 CDEBUG(D_SUPER, "get tableno %d\n", cache->cache_snap_tableno);
216 * make sure we have our own super operations
218 * Initialize or re-initialize the cache->cache_ops shared
219 * struct snap_ops structure set based on the underlying
222 filter_setup_super_ops(cache->cache_filter, sb->s_op,
223 ¤tfs_super_ops);
224 sb->s_op = filter_c2usops(cache->cache_filter);
226 * Save pointers in the snap_cache structure to the
227 * snapfs and underlying file system superblocks.
229 cache->cache_sb = sb; /* Underlying file system superblock. */
231 /* set up snapshot ops, handle COMPAT_FEATUREs */
234 else if (strcmp (cache_type,"ext3") == 0 || !cache_type){
235 cache->cache_type = FILTER_FS_EXT3;
236 filter_setup_snapshot_ops(cache->cache_filter,
237 &ext3_snap_operations);
238 filter_setup_journal_ops(cache->cache_filter,
239 &snap_ext3_journal_ops);
240 if( !EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_SNAPFS) ){
241 if( strcmp(cow_type, "block")==0 ){
242 sb->u.ext3_sb.s_es->s_feature_compat |=
243 cpu_to_le32(EXT3_FEATURE_COMPAT_BLOCKCOW);
246 sb->u.ext3_sb.s_last_cowed_pri_ino = 0;
247 sb->u.ext3_sb.s_first_cowed_pri_ino = 0;
249 /* now get our own directory operations */
250 if ( sb->s_root && sb->s_root->d_inode ) {
251 filter_setup_dir_ops(cache->cache_filter,
253 ¤tfs_dir_iops, ¤tfs_dir_fops);
254 sb->s_root->d_inode->i_op =filter_c2udiops(cache->cache_filter);
256 CDEBUG(D_SUPER, "lookup at %p\n",
257 sb->s_root->d_inode->i_op->lookup);
258 /* XXX is this needed ?? ext3 do not have dentry operations*/
259 filter_setup_dentry_ops(cache->cache_filter,
261 ¤tfs_dentry_ops);
262 sb->s_root->d_op = filter_c2udops(cache->cache_filter);
263 init_filter_data(sb->s_root->d_inode, 0);
266 * Save a pointer to the snap_cache structure in the
267 * "snap_current" superblock.
269 (struct snap_cache *) sb->u.generic_sbp = cache;
271 snapfs_read_snaptable(cache, tableno);
273 CDEBUG(D_SUPER, "sb %lx, sb->u.generic_sbp: %lx\n",
274 (ulong) sb, (ulong) sb->u.generic_sbp);
277 /* Inc in get_fs_type, Dec in put_fs_type*/
279 put_filesystem(fstype);
285 static DECLARE_FSTYPE_DEV(snapfs_current_type,
286 "snap_current", snapfs_read_super);
288 /* Find the options for the clone. These consist of a cache device
289 and an index in the snaptable associated with that device.
291 static char *clonefs_options(char *options, char **devstr, char **namestr)
293 struct option *opt_value = NULL;
296 while (!(get_opt(&opt_value, &pos))) {
297 if (!strcmp(opt_value->opt, "dev")) {
299 *devstr = opt_value->value;
300 } else if (!strcmp(opt_value->opt, "name")) {
302 *namestr = opt_value->value;
309 static int snap_cache_lookup_ino_cb(struct snap_cache *cache, void *in, unsigned long *out)
311 ino_t ino = *((unsigned long*)in);
314 struct super_block *sb = cache->cache_sb;
315 kdev_t dev = sb->s_dev;
317 if (MAJOR(dev) != LOOP_MAJOR)
319 if (sb->s_bdev->bd_op && sb->s_bdev->bd_op->ioctl) {
320 struct inode *inode = sb->s_bdev->bd_inode;
321 struct loop_info loop_info;
323 sb->s_bdev->bd_op->ioctl(inode, NULL, LOOP_GET_INFO,
324 (unsigned long)&loop_info);
326 if(loop_info.lo_inode == ino) {
334 static int snapfs_path2dev(char *dev_path, kdev_t *dev)
336 struct dentry *dentry;
340 if (path_init(dev_path, LOOKUP_FOLLOW, &nd)) {
341 error = path_walk(dev_path, &nd);
349 if (!dentry->d_inode || is_bad_inode(dentry->d_inode) ||
350 (!S_ISBLK(dentry->d_inode->i_mode) &&
351 !S_ISREG(dentry->d_inode->i_mode))){
355 if (S_ISBLK(dentry->d_inode->i_mode)) {
356 *dev = kdev_t_to_nr(dentry->d_inode->i_rdev);
358 /*here we must walk through all the snap cache to
359 *find the loop device */
362 if (snap_cache_process(snap_cache_lookup_ino_cb,
363 &dentry->d_inode->i_ino,
364 (unsigned long*)&tmp))
372 extern struct super_operations clone_super_ops;
374 * We always need to remove the snapfs options before passing
379 struct super_block *sb,
383 struct snap_clone_info *clone_sb;
384 struct snap_cache *snap_cache = NULL;
385 struct inode *root_inode = NULL;
386 char *devstr = NULL, *namestr = NULL;
395 CDEBUG(D_SUPER, "mount opts: %s\n", data ? (char *)data : "(none)");
398 /* read and validate options */
399 cache_data = clonefs_options(data, &devstr, &namestr);
401 CERROR("clonefs: invalid mount option %s\n", (char*)data);
402 GOTO(out_err, err=-EINVAL);
404 if (!namestr || !devstr) {
405 CERROR("snapfs: mount options name and dev mandatory\n");
406 GOTO(out_err, err=-EINVAL);
409 err = snapfs_path2dev(devstr, &dev);
411 CERROR("snap: incorrect device option %s\n", devstr);
412 GOTO(out_err, err=-EINVAL);
415 snap_cache = snap_find_cache(dev);
417 CERROR("snap: incorrect device option %s\n", devstr);
418 GOTO(out_err, err=-EINVAL);
421 index = snap_get_index_from_name (snap_cache->cache_snap_tableno,
423 CDEBUG(D_SUPER, "tableno %d, name %s, get index %d\n",
424 snap_cache->cache_snap_tableno, namestr, index);
427 CERROR("No valid index for name %s passed to mount\n",namestr);
428 GOTO(out_err, err=-EINVAL);
432 * Force clone fs to be read-only.
434 * XXX - Is there a way to change the mount options too so
435 * the fs is listed as RO by mount?
437 sb->s_flags |= MS_RDONLY;
439 /* set up the super block */
440 clone_sb = (struct snap_clone_info *)&sb->u.generic_sbp;
441 list_add(&clone_sb->clone_list_entry, &snap_cache->cache_clone_list);
442 clone_sb->clone_cache = snap_cache;
443 clone_sb->clone_index = index;
444 sb->s_op = &clone_super_ops;
446 root_ino = snap_cache->cache_sb->s_root->d_inode->i_ino;
447 root_inode = iget(sb, root_ino);
449 CDEBUG(D_SUPER, "readinode %p, root ino %ld, root inode at %p\n",
450 sb->s_op->read_inode, root_ino, root_inode);
452 sb->s_root = d_alloc_root(root_inode);
455 list_del(&clone_sb->clone_list_entry);
456 GOTO(out_err, err=-EINVAL);
458 dget(snap_cache->cache_sb->s_root);
460 CDEBUG(D_SUPER, "sb %lx, &sb->u.generic_sbp: %lx\n",
461 (ulong) sb, (ulong) &sb->u.generic_sbp);
463 get_snap_current_mnt(snap_cache->cache_sb);
471 static DECLARE_FSTYPE(snapfs_clone_type, "snap_clone", clone_read_super, 0);
473 int init_snapfs(void)
477 snap_init_cache_hash();
478 init_filter_info_cache();
480 status = register_filesystem(&snapfs_current_type);
482 CERROR("snapfs: failed in register current filesystem!\n");
485 status = register_filesystem(&snapfs_clone_type);
487 unregister_filesystem(&snapfs_current_type);
488 CERROR("snapfs: failed in register clone filesystem!\n");
496 int cleanup_snapfs(void)
502 cleanup_filter_info_cache();
503 err = unregister_filesystem(&snapfs_clone_type);
505 CERROR("snapfs: failed to unregister clone filesystem\n");
507 err = unregister_filesystem(&snapfs_current_type);
509 CERROR("snapfs: failed to unregister filesystem\n");