btrfs: make open_ctree() return int
[linux-2.6-block.git] / fs / btrfs / super.c
index 200f63bc6675eca20cf1b55c9ced534efccaf63b..56e007fd670262c00a6934375b9da164c0eff0e4 100644 (file)
@@ -40,7 +40,6 @@
 #include <linux/magic.h>
 #include <linux/slab.h>
 #include <linux/cleancache.h>
-#include <linux/mnt_namespace.h>
 #include <linux/ratelimit.h>
 #include "compat.h"
 #include "delayed-inode.h"
@@ -148,13 +147,13 @@ void __btrfs_std_error(struct btrfs_fs_info *fs_info, const char *function,
 
 static void btrfs_put_super(struct super_block *sb)
 {
-       struct btrfs_root *root = btrfs_sb(sb);
-       int ret;
-
-       ret = close_ctree(root);
-       sb->s_fs_info = NULL;
-
-       (void)ret; /* FIXME: need to fix VFS to return error? */
+       (void)close_ctree(btrfs_sb(sb));
+       /* FIXME: need to fix VFS to return error? */
+       /* AV: return it _where_?  ->put_super() can be triggered by any number
+        * of async events, up to and including delivery of SIGKILL to the
+        * last process that kept it busy.  Or segfault in the aforementioned
+        * process...  Whom would you report that to?
+        */
 }
 
 enum {
@@ -590,6 +589,7 @@ static int btrfs_fill_super(struct super_block *sb,
        struct inode *inode;
        struct dentry *root_dentry;
        struct btrfs_root *tree_root;
+       struct btrfs_fs_info *fs_info;
        struct btrfs_key key;
        int err;
 
@@ -604,18 +604,19 @@ static int btrfs_fill_super(struct super_block *sb,
        sb->s_flags |= MS_POSIXACL;
 #endif
 
-       tree_root = open_ctree(sb, fs_devices, (char *)data);
-
-       if (IS_ERR(tree_root)) {
+       err = open_ctree(sb, fs_devices, (char *)data);
+       if (err) {
                printk("btrfs: open_ctree failed\n");
-               return PTR_ERR(tree_root);
+               return err;
        }
+       tree_root = sb->s_fs_info;
+       fs_info = tree_root->fs_info;
        sb->s_fs_info = tree_root;
 
        key.objectid = BTRFS_FIRST_FREE_OBJECTID;
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
-       inode = btrfs_iget(sb, &key, tree_root->fs_info->fs_root, NULL);
+       inode = btrfs_iget(sb, &key, fs_info->fs_root, NULL);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                goto fail_close;
@@ -636,6 +637,7 @@ static int btrfs_fill_super(struct super_block *sb,
 
 fail_close:
        close_ctree(tree_root);
+       free_fs_info(fs_info);
        return err;
 }
 
@@ -662,9 +664,9 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
        return ret;
 }
 
-static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
+static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
 {
-       struct btrfs_root *root = btrfs_sb(vfs->mnt_sb);
+       struct btrfs_root *root = btrfs_sb(dentry->d_sb);
        struct btrfs_fs_info *info = root->fs_info;
        char *compress_type;
 
@@ -731,20 +733,15 @@ static int btrfs_test_super(struct super_block *s, void *data)
        struct btrfs_root *test_root = data;
        struct btrfs_root *root = btrfs_sb(s);
 
-       /*
-        * If this super block is going away, return false as it
-        * can't match as an existing super block.
-        */
-       if (!atomic_read(&s->s_active))
-               return 0;
        return root->fs_info->fs_devices == test_root->fs_info->fs_devices;
 }
 
 static int btrfs_set_super(struct super_block *s, void *data)
 {
-       s->s_fs_info = data;
-
-       return set_anon_super(s, data);
+       int err = set_anon_super(s, data);
+       if (!err)
+               s->s_fs_info = data;
+       return err;
 }
 
 /*
@@ -904,12 +901,11 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        if (!fs_info)
                return ERR_PTR(-ENOMEM);
 
-       fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       fs_info->tree_root = btrfs_alloc_root(fs_info);
        if (!fs_info->tree_root) {
                error = -ENOMEM;
                goto error_fs_info;
        }
-       fs_info->tree_root->fs_info = fs_info;
        fs_info->fs_devices = fs_devices;
 
        fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
@@ -1220,11 +1216,21 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)
        return 0;
 }
 
+static void btrfs_kill_super(struct super_block *sb)
+{
+       struct btrfs_fs_info *fs_info = NULL;
+       if (sb->s_root)
+               fs_info = btrfs_sb(sb)->fs_info;
+       kill_anon_super(sb);
+       if (fs_info)
+               free_fs_info(fs_info);
+}
+
 static struct file_system_type btrfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "btrfs",
        .mount          = btrfs_mount,
-       .kill_sb        = kill_anon_super,
+       .kill_sb        = btrfs_kill_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };