From 9a39783371f14fb16ce4339b0396c546c66e7e4b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sun, 3 Oct 2010 20:33:16 +1100 Subject: [PATCH] Fix lafs_iget_fs for subset filesystems. 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 --- inode.c | 25 ++++++------ lafs.h | 1 + super.c | 116 +++++++++++++++++++++++++++++++++++--------------------- 3 files changed, 88 insertions(+), 54 deletions(-) diff --git a/inode.c b/inode.c index 15d5276..857ea60 100644 --- 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 397330e..e52a168 100644 --- 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 af8b2c7..bdfbe1c 100644 --- 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, -- 2.39.5