Btrfs: check duplicate backrefs for both data and metadata
[linux-2.6-block.git] / fs / btrfs / super.c
index 6dfae5b28f5939e4dad06410d5c8948eb3574b27..3427db28f6fe941e7e35d87b786da3df0e83a743 100644 (file)
@@ -52,7 +52,6 @@
 #include "export.h"
 #include "compression.h"
 
-
 static struct super_operations btrfs_super_ops;
 
 static void btrfs_put_super(struct super_block *sb)
@@ -67,8 +66,8 @@ static void btrfs_put_super(struct super_block *sb)
 enum {
        Opt_degraded, Opt_subvol, Opt_device, Opt_nodatasum, Opt_nodatacow,
        Opt_max_extent, Opt_max_inline, Opt_alloc_start, Opt_nobarrier,
-       Opt_ssd, Opt_thread_pool, Opt_noacl,  Opt_compress, Opt_notreelog,
-       Opt_ratio, Opt_flushoncommit, Opt_err,
+       Opt_ssd, Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl,
+       Opt_compress, Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -84,6 +83,8 @@ static match_table_t tokens = {
        {Opt_thread_pool, "thread_pool=%d"},
        {Opt_compress, "compress"},
        {Opt_ssd, "ssd"},
+       {Opt_ssd_spread, "ssd_spread"},
+       {Opt_nossd, "nossd"},
        {Opt_noacl, "noacl"},
        {Opt_notreelog, "notreelog"},
        {Opt_flushoncommit, "flushoncommit"},
@@ -174,6 +175,19 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        printk(KERN_INFO "btrfs: use ssd allocation scheme\n");
                        btrfs_set_opt(info->mount_opt, SSD);
                        break;
+               case Opt_ssd_spread:
+                       printk(KERN_INFO "btrfs: use spread ssd "
+                              "allocation scheme\n");
+                       btrfs_set_opt(info->mount_opt, SSD);
+                       btrfs_set_opt(info->mount_opt, SSD_SPREAD);
+                       break;
+               case Opt_nossd:
+                       printk(KERN_INFO "btrfs: not using ssd allocation "
+                              "scheme\n");
+                       btrfs_set_opt(info->mount_opt, NOSSD);
+                       btrfs_clear_opt(info->mount_opt, SSD);
+                       btrfs_clear_opt(info->mount_opt, SSD_SPREAD);
+                       break;
                case Opt_nobarrier:
                        printk(KERN_INFO "btrfs: turning off barriers\n");
                        btrfs_set_opt(info->mount_opt, NOBARRIER);
@@ -322,7 +336,7 @@ static int btrfs_fill_super(struct super_block *sb,
        struct dentry *root_dentry;
        struct btrfs_super_block *disk_super;
        struct btrfs_root *tree_root;
-       struct btrfs_inode *bi;
+       struct btrfs_key key;
        int err;
 
        sb->s_maxbytes = MAX_LFS_FILESIZE;
@@ -341,23 +355,15 @@ static int btrfs_fill_super(struct super_block *sb,
        }
        sb->s_fs_info = tree_root;
        disk_super = &tree_root->fs_info->super_copy;
-       inode = btrfs_iget_locked(sb, BTRFS_FIRST_FREE_OBJECTID,
-                                 tree_root->fs_info->fs_root);
-       bi = BTRFS_I(inode);
-       bi->location.objectid = inode->i_ino;
-       bi->location.offset = 0;
-       bi->root = tree_root->fs_info->fs_root;
 
-       btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
-
-       if (!inode) {
-               err = -ENOMEM;
+       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);
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto fail_close;
        }
-       if (inode->i_state & I_NEW) {
-               btrfs_read_locked_inode(inode);
-               unlock_new_inode(inode);
-       }
 
        root_dentry = d_alloc_root(inode);
        if (!root_dentry) {
@@ -433,12 +439,16 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
        if (btrfs_test_opt(root, COMPRESS))
                seq_puts(seq, ",compress");
-       if (btrfs_test_opt(root, SSD))
+       if (btrfs_test_opt(root, NOSSD))
+               seq_puts(seq, ",nossd");
+       if (btrfs_test_opt(root, SSD_SPREAD))
+               seq_puts(seq, ",ssd_spread");
+       else if (btrfs_test_opt(root, SSD))
                seq_puts(seq, ",ssd");
        if (btrfs_test_opt(root, NOTREELOG))
-               seq_puts(seq, ",no-treelog");
+               seq_puts(seq, ",notreelog");
        if (btrfs_test_opt(root, FLUSHONCOMMIT))
-               seq_puts(seq, ",flush-on-commit");
+               seq_puts(seq, ",flushoncommit");
        if (!(root->fs_info->sb->s_flags & MS_POSIXACL))
                seq_puts(seq, ",noacl");
        return 0;
@@ -584,7 +594,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                if (btrfs_super_log_root(&root->fs_info->super_copy) != 0)
                        return -EINVAL;
 
-               ret = btrfs_cleanup_reloc_trees(root);
+               /* recover relocation */
+               ret = btrfs_recover_relocation(root);
                WARN_ON(ret);
 
                ret = btrfs_cleanup_fs_roots(root->fs_info);