struct dentry *de;
int err;
int d;
- struct sb_key *k = kmalloc(sizeof(*k), GFP_KERNEL);
+ struct sb_key *k = fs->prime_sb->s_fs_info;
fs->rolled = 0;
fs->ss[0].root = root = iget_locked(fs->prime_sb, 0);
k->root = root;
- k->fs = fs;
- fs->prime_sb->s_fs_info = k;
err = -ENOMEM;
b = lafs_get_block(root, 0, NULL, GFP_KERNEL, MKREF(mount));
return newstate;
}
+/* we identify lafs superblocks by the filesystem uuid. This means
+ * that block-level snapshots cannot be mounted. You should use
+ * fs-level snapshots instead.
+ */
+static int sb_test(struct super_block *sb, void *data)
+{
+ struct sb_key *ptn = data;
+ struct sb_key *sk = sb->s_fs_info;
+ return memcmp(ptn->fs->state->uuid,
+ sk->fs->state->uuid, 16) == 0;
+}
+
+static int sb_set(struct super_block *sb, void *data)
+{
+ struct sb_key *ptn = data;
+ sb->s_fs_info = ptn;
+ return set_anon_super(sb, NULL);
+}
+
+
static int
lafs_load(struct fs *fs, struct options *op, int newest)
{
struct lafs_state *st;
int i;
int err;
+ struct sb_key *k;
st = fs->state = op->devlist[newest].stateblock;
op->devlist[newest].stateblock = NULL;
err = lafs_segtrack_init(fs->segtrack);
fs->ss = kzalloc(sizeof(struct snapshot)*fs->maxsnapshot, GFP_KERNEL);
- if (!fs->ss || !fs->scan.free_usages || err)
+ if (!fs->ss || !fs->scan.free_usages || err) {
+ if (!err)
+ err = -ENOMEM;
goto abort;
+ }
fs->checkpointcluster = le64_to_cpu(st->checkpointcluster);
for (i = 0; i < fs->maxsnapshot; i++) {
* guessed better
*/
+ err = -ENOMEM;
fs->devs = kzalloc(sizeof(struct fs_dev)*fs->devices, GFP_KERNEL);
if (!fs->devs)
goto abort;
- fs->prime_sb = sget(&lafs_fs_type, NULL, set_anon_super, NULL);
- if (!fs->prime_sb)
+ k = kzalloc(sizeof(*k), GFP_KERNEL);
+ k->fs = fs;
+ fs->prime_sb = sget(&lafs_fs_type, sb_test, sb_set, k);
+ if (IS_ERR(fs->prime_sb)) {
+ kfree(k);
+ err = PTR_ERR(fs->prime_sb);
goto abort;
+ }
+ if (fs->prime_sb->s_root) {
+ /* filesystem with this uuid already exists */
+ kfree(k);
+ deactivate_locked_super(fs->prime_sb);
+ fs->prime_sb = NULL;
+ err = -EBUSY;
+ goto abort;
+ }
fs->prime_sb->s_blocksize = 1 << op->blockbits;
fs->prime_sb->s_blocksize_bits = op->blockbits;
fs->prime_sb->s_op = &lafs_sops;