return err;
}
-static int test_subset(struct super_block *sb, void *data)
-{
- struct sb_key *ptn = data;
- struct sb_key *k = sb->s_fs_info;
-
- return ptn->fs == k->fs && ptn->root == k->root;
-}
-
-static int set_subset(struct super_block *sb, void *data)
-{
- sb->s_fs_info = data;
- set_anon_super(sb, NULL);
- return 0;
-}
-
-static struct file_system_type lafs_subset_fs_type;
-struct super_block *lafs_get_subset_sb(struct inode *ino)
+static struct dentry *lafs_get_subset_root(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;
-
- ino->i_private = sb;
-
- 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(ino, 2, SYNC);
- if (IS_ERR(rootdir) && PTR_ERR(rootdir) == -ENOENT) {
- rootdir = lafs_new_inode(fs, ino, 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(ino, 1, SYNC);
- if (IS_ERR(imapfile) && PTR_ERR(imapfile) == -ENOENT)
- imapfile = lafs_new_inode(fs, ino, NULL,
- TypeInodeMap, 1, 0, NULL);
-
- if (IS_ERR(imapfile))
- err = PTR_ERR(imapfile);
- else
- iput(imapfile);
- }
-
- if (!err) {
- struct inode *atime = lafs_iget(ino, 3, SYNC);
- if (!IS_ERR(atime)) {
- if (LAFSI(atime)->type != TypeAccessTime) {
- iput(atime);
- err = -EINVAL;
- } else
- LAFSI(ino)->md.fs.accesstime = atime;
- } else if (PTR_ERR(atime) != -ENOENT)
- err = PTR_ERR(ino);
- }
+ int err = 0;
+ struct inode *rootdir, *imapfile;
+ struct dentry *root;
+
+ sb = fs->prime_sb;
+
+ rootdir = lafs_iget(ino, 2, SYNC);
+ if (IS_ERR(rootdir) && PTR_ERR(rootdir) == -ENOENT) {
+ rootdir = lafs_new_inode(fs, ino, 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 {
+ root = d_alloc_root(rootdir);
+ imapfile = lafs_iget(ino, 1, SYNC);
+ if (IS_ERR(imapfile) && PTR_ERR(imapfile) == -ENOENT)
+ imapfile = lafs_new_inode(fs, ino, 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);
- }
+ if (!err) {
+ struct inode *atime = lafs_iget(ino, 3, SYNC);
+ if (!IS_ERR(atime)) {
+ if (LAFSI(atime)->type != TypeAccessTime) {
+ iput(atime);
+ err = -EINVAL;
+ } else
+ LAFSI(ino)->md.fs.accesstime = atime;
+ } else if (PTR_ERR(atime) != -ENOENT)
+ err = PTR_ERR(ino);
}
- return sb;
+ if (err) {
+ dput(root);
+ return ERR_PTR(err);
+ } else
+ return root;
}
static int
struct super_block *sb;
struct inode *ino;
struct fs *fs;
+ struct dentry *root;
err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd);
if (err)
if (sb->s_type != &lafs_fs_type &&
sb->s_type != &lafs_snap_fs_type)
goto out;
+ /* FIXME test not a subset filesystem */
ino = nd.path.dentry->d_inode;
if (LAFSI(ino)->type != TypeInodeFile &&
LAFSI(ino)->type != TypeDir)
goto out;
fs = fs_from_sb(sb);
mutex_lock(&ino->i_mutex);
+ err = 0;
if (LAFSI(ino)->type == TypeDir) {
struct datablock *inodb;
/* maybe convert this to TypeInodeFile */
if (err)
goto out_unlock;
}
- err = 0;
/* We have a TypeInodeFile so we can make a superblock */
- sb = lafs_get_subset_sb(ino);
+ root = lafs_get_subset_root(ino);
iput(ino);
- if (IS_ERR(sb))
- err = PTR_ERR(sb);
- else
- simple_set_mnt(mnt, sb);
+ if (IS_ERR(root))
+ err = PTR_ERR(root);
+ else {
+ mnt->mnt_sb = fs->prime_sb;
+ atomic_inc(&mnt->mnt_sb->s_active);
+ mnt->mnt_root = root;
+ }
out_unlock:
mutex_unlock(&ino->i_mutex);
out:
return err;
}
-static void lafs_kill_subset(struct super_block *sb)
-{
- struct sb_key *k = sb->s_fs_info;
- if (LAFSI(k->root)->md.fs.accesstime) {
- iput(LAFSI(k->root)->md.fs.accesstime);
- LAFSI(k->root)->md.fs.accesstime = NULL;
- }
- kill_anon_super(sb);
- iput(k->root);
- deactivate_super(k->fs->prime_sb);
- kfree(k);
-}
-
const struct file_operations lafs_subset_file_operations = {
};
.owner = THIS_MODULE,
.name = "lafs_subset",
.get_sb = lafs_get_subset,
- .kill_sb = lafs_kill_subset,
};
static int __init lafs_init(void)