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);
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,
struct super_block *sb;
struct inode *ino;
struct fs *fs;
- struct sb_key *k;
err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
if (err)
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);
.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,