+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;
+}
+