]> git.neil.brown.name Git - LaFS.git/blob - snapshot.c
README update
[LaFS.git] / snapshot.c
1
2 /*
3  * fs/lafs/super.c
4  * Copyright (C) 2005-2009
5  * Neil Brown <neilb@suse.de>
6  * Released under the GPL, version 2
7  */
8
9 #include        "lafs.h"
10 #include        <linux/namei.h>
11 #include        <linux/crc32.h>
12 #include        <linux/slab.h>
13
14 /*
15  * Mounting a snapshot is very different from mounting a new
16  * filesystem.
17  * The 'dev' passed is really a path to the mountpoint of the
18  * original - or atleast a file within the original.
19  * We find that filesystem, make sure it is a LaFS, find the
20  * named snapshot, and mount it read_only
21  */
22
23 struct options {
24         char  *snapshot;
25 };
26
27 static int parse_opts(struct options *op, const char *dev_name, char *data)
28 {
29         /* dev_name must start with '/',
30          * data must have snapshot=....
31          */
32         char *p;
33
34         if (dev_name[0] != '/')
35                 return -EINVAL;
36         op->snapshot = NULL;
37         while ((p = strsep(&data, ",")) != NULL) {
38                 if (!*p)
39                         continue;
40                 if (strncmp(p, "snapshot=", 9) == 0) {
41                         op->snapshot = p+9;
42                 } else {
43                         printk(KERN_ERR
44                                "LaFS: Unrecognised mount option \"%s\"\n", p);
45                         return -EINVAL;
46                 }
47         }
48         if (op->snapshot == NULL || op->snapshot[0] == 0) {
49                 printk(KERN_ERR
50                        "LaFS: No snaphot name given.\n");
51                 return -EINVAL;
52         }
53         return 0;
54 }
55
56 /* s_fs_info for snapshots contains the snapshot number as well */
57 struct snap_key {
58         struct sb_key k;
59         int ssnum;
60 };
61
62 static int snap_test(struct super_block *sb, void *data)
63 {
64         struct snap_key *ptn = data;
65         struct snap_key *sk = container_of(sb->s_fs_info, struct snap_key, k);
66         return sk->k.fs == ptn->k.fs && sk->ssnum == ptn->ssnum;
67 }
68
69 static int snap_set(struct super_block *sb, void *data)
70 {
71         struct snap_key *sk = data;
72         sb->s_fs_info = &sk->k;
73         return set_anon_super(sb, NULL);
74 }
75
76 static int
77 lafs_snap_get_sb(struct file_system_type *fstype,
78                  int flags, const char *dev_name, void *data,
79                  struct vfsmount *mnt)
80 {
81         /* The 'dev_name' is a path to an object in the
82          * parent filesystem (typically the mountpoint).
83          * "data" contains 'snapshot=name' giving the name
84          * of the snapshot to be found and mounted
85          */
86         char *cdata = data;
87         struct nameidata nd;
88         int err;
89         struct super_block *sb;
90         struct fs *fs;
91         int s;
92         struct la_inode *lai;
93         struct page *p;
94         struct options op;
95         struct snap_key *sk;
96
97         err = parse_opts(&op, dev_name, cdata);
98         if (err)
99                 return err;
100
101         p = alloc_page(GFP_KERNEL);
102         if (!p)
103                 return -ENOMEM;
104
105         err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
106         if (err) {
107                 put_page(p);
108                 return err;
109         }
110         sb = nd.path.dentry->d_sb;
111         err = -EINVAL;
112         if (sb->s_type != &lafs_fs_type)
113                 goto fail;
114         fs = fs_from_sb(sb);
115
116         for (s = 1; s < fs->maxsnapshot; s++) {
117                 int nlen;
118
119                 if (fs->ss[s].root_addr == 0)
120                         continue;
121                 if (fs->ss[s].root) {
122                         struct lafs_inode *li = LAFSI(fs->ss[s].root);
123                         if (li->md.fs.name &&
124                             strcmp(li->md.fs.name, op.snapshot) == 0)
125                                 /* found it */
126                                 break;
127                 }
128                 err = lafs_load_page(fs, p, fs->ss[s].root_addr, 1);
129                 if (err)
130                         continue;
131                 lai = (struct la_inode *)page_address(p);
132                 nlen = le16_to_cpu(lai->metadata_size) -
133                         offsetof(struct la_inode, metadata[0].fs.name);
134                 printk("ss %d is %.*s\n", s, nlen, lai->metadata[0].fs.name);
135                 if (strncmp(lai->metadata[0].fs.name, op.snapshot, nlen) != 0)
136                         continue;
137                 /* FIXME more checks? */
138                 /* Found it */
139                 break;
140         }
141         if (s == fs->maxsnapshot) {
142                 err = -ENOENT;
143                 goto fail;
144         }
145         /* Ok, we have the right snapshot... now we need a superblock */
146         sk = kzalloc(sizeof(*sk), GFP_KERNEL);
147         if (!sk) {
148                 err = -ENOMEM;
149                 goto fail;
150         }
151         sk->k.fs = fs;
152         sk->ssnum = s;
153         
154         sb = sget(&lafs_snap_fs_type, snap_test, snap_set, NULL);
155         if (IS_ERR(sb)) {
156                 kfree(sk);
157                 err = PTR_ERR(sb);
158                 goto fail;
159         }
160         if (sb->s_root) {
161                 /* already existed */
162                 kfree(sk);
163         } else {
164                 struct inode *rootino, *rootdir;
165                 struct datablock *b;
166                 sb->s_flags = flags | MS_RDONLY;
167
168                 atomic_inc(&fs->prime_sb->s_active);
169
170                 rootino = iget_locked(sb, 0);
171                 fs->ss[s].root = sk->k.root = rootino;
172                 LAFSI(rootino)->filesys = rootino;
173                 b = lafs_get_block(rootino, 0, NULL, GFP_KERNEL,
174                                    MKREF(snap));
175                 b->b.physaddr = fs->ss[s].root_addr;
176                 set_bit(B_PhysValid, &b->b.flags);
177                 LAFS_BUG(test_bit(B_Valid, &b->b.flags), &b->b);
178                 printk("ss root at %llu\n", b->b.physaddr);
179                 err = lafs_load_block(&b->b, NULL);
180                 if (!err)
181                         err = lafs_wait_block(&b->b);
182                 if (!err)
183                         err = lafs_import_inode(fs->ss[s].root, b);
184                 putdref(b, MKREF(snap));
185                 unlock_new_inode(rootino);
186                 if (err) {
187                         deactivate_locked_super(sb);
188                         goto fail;
189                 }
190                 rootdir = lafs_iget(rootino, 2, SYNC);
191                 sb->s_root = d_alloc_root(rootdir);
192                 sb->s_op = fs->prime_sb->s_op;
193                 sb->s_flags |= MS_ACTIVE;
194         }
195         up_write(&sb->s_umount);
196         path_put(&nd.path);
197         put_page(p);
198         simple_set_mnt(mnt, sb);
199         return 0;
200
201 fail:
202         put_page(p);
203         path_put(&nd.path);
204         return err;
205 }
206
207 static void lafs_snap_kill_sb(struct super_block *sb)
208 {
209         struct fs *fs = fs_from_sb(sb);
210
211         printk("Generic_shutdown_super being called....\n");
212         kill_anon_super(sb);
213         kfree(sb->s_fs_info);
214         printk("Generic_shutdown_super called\n");
215         deactivate_super(fs->prime_sb);
216 }
217
218 struct file_system_type lafs_snap_fs_type = {
219         .owner          = THIS_MODULE,
220         .name           = "lafs_snap",
221         .get_sb         = lafs_snap_get_sb,
222         .kill_sb        = lafs_snap_kill_sb,
223 };
224