]> git.neil.brown.name Git - LaFS.git/commitdiff
Fix lafs_iget_fs for subset filesystems.
authorNeilBrown <neilb@suse.de>
Sun, 3 Oct 2010 09:33:16 +0000 (20:33 +1100)
committerNeilBrown <neilb@suse.de>
Sun, 10 Oct 2010 23:33:56 +0000 (10:33 +1100)
This requires spliting code out from the s_get function so
we can just get a super_block given the parent inode.

Signed-off-by: NeilBrown <neilb@suse.de>
inode.c
lafs.h
super.c

diff --git a/inode.c b/inode.c
index 15d5276c9478f19a00e75d07c831658b94a97ace..857ea60bcd1f1cdeff38252c162b7f35ed6bed4c 100644 (file)
--- a/inode.c
+++ b/inode.c
@@ -212,25 +212,28 @@ lafs_iget_fs(struct fs *fs, int fsnum, int inum, int async)
        if (fsnum) {
                /* Need to locate or load the superblock for this
                 * subordinate filesystem
-                * FIXME
                 */
                struct inode *filesys;
+               struct super_block *sb2;
 
-               printk("get filesys %d\n", fsnum);
-               BUG();
                filesys = lafs_iget(sb, fsnum, async);
                if (IS_ERR(filesys))
                        return filesys;
-               if (filesys->i_sb == sb) {
-                       /* No mounted fs here.
-                        * Need to mount one FIXME
-                        */
-                       BUG();
+               if (LAFSI(filesys)->type != TypeInodeFile) {
+                       iput(filesys);
                        return ERR_PTR(-ENOENT);
                }
-               printk("get inode %d\n", inum);
-               rv = lafs_iget(filesys->i_sb, inum, async);
-               iput(filesys);
+               /* FIXME can get_subset_sb be async at all?? */
+               sb2 = lafs_get_subset_sb(filesys);
+               if (IS_ERR(sb2)) {
+                       iput(filesys);
+                       return ERR_PTR(PTR_ERR(sb2));
+               }
+               rv = lafs_iget(sb2, inum, async);
+               if (IS_ERR(rv))
+                       deactivate_locked_super(sb2);
+               else
+                       up_write(&sb2->s_umount);
        } else {
                rv = lafs_iget(sb, inum, async);
                atomic_inc(&sb->s_active);
diff --git a/lafs.h b/lafs.h
index 397330e8659f6f7c6a3ad0ab5a8fb21af58442cb..e52a1680d02d9b645ecb447ba6ae1d8f8a35de8d 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -696,6 +696,7 @@ int lafs_cluster_empty(struct fs *fs, int cnum);
 /* super.c */
 int lafs_write_state(struct fs *fs);
 void lafs_destroy_inode(struct inode *inode);
+struct super_block *lafs_get_subset_sb(struct inode *ino);
 
 /* checkpoint.c */
 void lafs_checkpoint_lock(struct fs *fs);
diff --git a/super.c b/super.c
index af8b2c7d3490b813f6a550ff8f1e758e88bfc3eb..bdfbe1c08af23fb1fb14c582b9a51e5f3fb73bf9 100644 (file)
--- a/super.c
+++ b/super.c
@@ -953,6 +953,72 @@ static int set_subset(struct super_block *sb, void *data)
        return 0;
 }
 
+static struct file_system_type lafs_subset_fs_type;
+struct super_block *lafs_get_subset_sb(struct inode *ino)
+{
+       /* ino must be a TypeInodeFile inode in the prime filesystem. */
+       struct fs *fs = fs_from_inode(ino);
+       struct super_block *sb;
+       struct sb_key *k = kmalloc(sizeof(*k), GFP_KERNEL);
+
+       if (!k)
+               return ERR_PTR(-ENOMEM);
+
+       k->fs = fs;
+       k->root = ino;
+       sb = sget(&lafs_subset_fs_type, test_subset, set_subset, k);
+       if (IS_ERR(sb)) {
+               kfree(k);
+       } else if (sb->s_root) {
+               /* already allocated */
+               kfree(k);
+       } else {
+               struct inode *rootdir, *imapfile;
+               int err = 0;
+
+               igrab(ino);
+               sb->s_blocksize = fs->blocksize;
+               sb->s_blocksize_bits = fs->blocksize_bits;
+               sb->s_bdi = fs->prime_sb->s_bdi;
+               sb->s_op = &lafs_sops;
+               sb->s_export_op = &lafs_export_ops;
+               sb->s_time_gran = 2;
+               rootdir = lafs_iget(sb, 2, SYNC);
+               if (IS_ERR(rootdir) && PTR_ERR(rootdir) == -ENOENT) {
+                       rootdir = lafs_new_inode(fs, sb, NULL,
+                                                TypeDir, 2, 0755, NULL);
+                       /* FIXME could the inode get written before we set
+                        * the link count ??*/
+                       rootdir->i_nlink = 2;
+               }
+               if (IS_ERR(rootdir))
+                       err = PTR_ERR(rootdir);
+               else {
+                       sb->s_root = d_alloc_root(rootdir);
+                       imapfile = lafs_iget(sb, 1, SYNC);
+                       if (IS_ERR(imapfile) && PTR_ERR(imapfile) == -ENOENT)
+                               imapfile = lafs_new_inode(fs, sb, NULL,
+                                                         TypeInodeMap, 1, 0, NULL);
+
+                       if (IS_ERR(imapfile))
+                               err = PTR_ERR(imapfile);
+                       else
+                               iput(imapfile);
+               }
+
+               if (!err) {
+                       sb->s_op = fs->prime_sb->s_op;
+                       sb->s_flags |= MS_ACTIVE;
+                       atomic_inc(&fs->prime_sb->s_active);
+                       igrab(ino);
+               } else {
+                       deactivate_locked_super(sb);
+                       sb = ERR_PTR(err);
+               }
+       }
+       return sb;
+}
+
 static int
 lafs_get_subset(struct file_system_type *fs_type,
                int flags, const char *dev_name, void *data,
@@ -975,7 +1041,6 @@ lafs_get_subset(struct file_system_type *fs_type,
        struct super_block *sb;
        struct inode *ino;
        struct fs *fs;
-       struct sb_key *k;
 
        err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
        if (err)
@@ -1051,49 +1116,14 @@ lafs_get_subset(struct file_system_type *fs_type,
                if (err)
                        goto out_unlock;
        }
+       err = 0;
        /* We have a TypeInodeFile so we can make a superblock */
-       k = kmalloc(sizeof(*k), GFP_KERNEL);
-       k->fs = fs;
-       k->root = ino;
-       sb = sget(fs_type, test_subset, set_subset, k);
-       if (IS_ERR(sb)) {
-               kfree(k);
+       sb = lafs_get_subset_sb(ino);
+       iput(ino);
+
+       if (IS_ERR(sb))
                err = PTR_ERR(sb);
-       } else if (sb->s_root) {
-               /* already allocated */
-               kfree(k);
-       } else {
-               struct inode *rootdir, *imapfile;
-               err = 0;
-               igrab(ino);
-               sb->s_blocksize = fs->blocksize;
-               sb->s_blocksize_bits = fs->blocksize_bits;
-               sb->s_bdi = fs->prime_sb->s_bdi;
-               sb->s_op = &lafs_sops;
-               sb->s_export_op = &lafs_export_ops;
-               sb->s_time_gran = 2;
-               rootdir = lafs_iget(sb, 2, SYNC);
-               if (IS_ERR(rootdir) && PTR_ERR(rootdir) == -ENOENT) {
-                       rootdir = lafs_new_inode(fs, sb, NULL,
-                                                TypeDir, 2, 0755, NULL);
-                       /* FIXME could the inode get written before we set
-                        * the link count ??*/
-                       rootdir->i_nlink = 2;
-               }
-               sb->s_root = d_alloc_root(rootdir);
-               imapfile = lafs_iget(sb, 1, SYNC);
-               if (IS_ERR(imapfile) && PTR_ERR(imapfile) == -ENOENT)
-                       imapfile = lafs_new_inode(fs, sb, NULL,
-                                                 TypeInodeMap, 1, 0, NULL);
-
-               if (!IS_ERR(imapfile))
-                       iput(imapfile);
-
-               sb->s_op = fs->prime_sb->s_op;
-               sb->s_flags |= MS_ACTIVE;
-               atomic_inc(&fs->prime_sb->s_active);
-       }
-       if (!err)
+       else
                simple_set_mnt(mnt, sb);
 out_unlock:
        mutex_unlock(&ino->i_mutex);
@@ -1127,7 +1157,7 @@ struct file_system_type lafs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
-struct file_system_type lafs_subset_fs_type = {
+static struct file_system_type lafs_subset_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "lafs_subset",
        .get_sb         = lafs_get_subset,