btrfs delete ordered inode handling fix
[deliverable/linux.git] / fs / btrfs / super.c
index 892864906880e0442cd1f8d49eac06426892b864..05029656e42e9c871238175ea692ade0cc031b66 100644 (file)
@@ -65,11 +65,13 @@ static void btrfs_put_super (struct super_block * sb)
 }
 
 enum {
-       Opt_subvol, Opt_nodatasum, Opt_nodatacow, Opt_max_extent,
-       Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd, Opt_err,
+       Opt_degraded, Opt_subvol, Opt_nodatasum, Opt_nodatacow,
+       Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
+       Opt_ssd, Opt_err,
 };
 
 static match_table_t tokens = {
+       {Opt_degraded, "degraded"},
        {Opt_subvol, "subvol=%s"},
        {Opt_nodatasum, "nodatasum"},
        {Opt_nodatacow, "nodatacow"},
@@ -106,9 +108,8 @@ u64 btrfs_parse_size(char *str)
        return res;
 }
 
-static int parse_options (char * options,
-                         struct btrfs_root *root,
-                         char **subvol_name)
+int btrfs_parse_options(char *options, struct btrfs_root *root,
+                       char **subvol_name)
 {
        char * p;
        struct btrfs_fs_info *info = NULL;
@@ -135,6 +136,12 @@ static int parse_options (char * options,
 
                token = match_token(p, tokens, args);
                switch (token) {
+               case Opt_degraded:
+                       if (info) {
+                               printk("btrfs: allowing degraded mounts\n");
+                               btrfs_set_opt(info->mount_opt, DEGRADED);
+                       }
+                       break;
                case Opt_subvol:
                        if (subvol_name) {
                                *subvol_name = match_strdup(&args[0]);
@@ -234,7 +241,7 @@ static int btrfs_fill_super(struct super_block * sb,
        sb->s_xattr = btrfs_xattr_handlers;
        sb->s_time_gran = 1;
 
-       tree_root = open_ctree(sb, fs_devices);
+       tree_root = open_ctree(sb, fs_devices, (char *)data);
 
        if (IS_ERR(tree_root)) {
                printk("btrfs: open_ctree failed\n");
@@ -267,8 +274,6 @@ static int btrfs_fill_super(struct super_block * sb,
                goto fail_close;
        }
 
-       parse_options((char *)data, tree_root, NULL);
-
        /* this does the super kobj at the same time */
        err = btrfs_sysfs_add_super(tree_root->fs_info);
        if (err)
@@ -315,24 +320,12 @@ static void btrfs_write_super(struct super_block *sb)
        sb->s_dirt = 0;
 }
 
-/*
- * This is almost a copy of get_sb_bdev in fs/super.c.
- * We need the local copy to allow direct mounting of
- * subvolumes, but this could be easily integrated back
- * into the generic version.  --hch
- */
-
-/* start copy & paste */
-static int set_bdev_super(struct super_block *s, void *data)
+static int btrfs_test_super(struct super_block *s, void *data)
 {
-       s->s_bdev = data;
-       s->s_dev = s->s_bdev->bd_dev;
-       return 0;
-}
+       struct btrfs_fs_devices *test_fs_devices = data;
+       struct btrfs_root *root = btrfs_sb(s);
 
-static int test_bdev_super(struct super_block *s, void *data)
-{
-       return (void *)s->s_bdev == data;
+       return root->fs_info->fs_devices == test_fs_devices;
 }
 
 int btrfs_get_sb_bdev(struct file_system_type *fs_type,
@@ -353,15 +346,10 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
        if (error)
                return error;
 
-       bdev = fs_devices->lowest_bdev;
-       /*
-        * once the super is inserted into the list by sget, s_umount
-        * will protect the lockfs code from trying to start a snapshot
-        * while we are mounting
-        */
-       down(&bdev->bd_mount_sem);
-       s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
-       up(&bdev->bd_mount_sem);
+       bdev = fs_devices->latest_bdev;
+       btrfs_lock_volumes();
+       s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices);
+       btrfs_unlock_volumes();
        if (IS_ERR(s))
                goto error_s;
 
@@ -373,13 +361,11 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
                        goto error_bdev;
                }
 
-               close_bdev_excl(bdev);
        } else {
                char b[BDEVNAME_SIZE];
 
                s->s_flags = flags;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
-               sb_set_blocksize(s, block_size(bdev));
                error = btrfs_fill_super(s, fs_devices, data,
                                         flags & MS_SILENT ? 1 : 0);
                if (error) {
@@ -388,6 +374,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
                        goto error;
                }
 
+               btrfs_sb(s)->fs_info->bdev_holder = fs_type;
                s->s_flags |= MS_ACTIVE;
        }
 
@@ -429,7 +416,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
        int ret;
        char *subvol_name = NULL;
 
-       parse_options((char *)data, NULL, &subvol_name);
+       btrfs_parse_options((char *)data, NULL, &subvol_name);
        ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, mnt,
                        subvol_name ? subvol_name : "default");
        if (subvol_name)
@@ -457,7 +444,7 @@ static struct file_system_type btrfs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "btrfs",
        .get_sb         = btrfs_get_sb,
-       .kill_sb        = kill_block_super,
+       .kill_sb        = kill_anon_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
 
@@ -500,7 +487,6 @@ static void btrfs_unlockfs(struct super_block *sb)
 
 static struct super_operations btrfs_super_ops = {
        .delete_inode   = btrfs_delete_inode,
-       .put_inode      = btrfs_put_inode,
        .put_super      = btrfs_put_super,
        .write_super    = btrfs_write_super,
        .sync_fs        = btrfs_sync_fs,
This page took 0.034727 seconds and 5 git commands to generate.