btrfs: Add raid56 support for updating
authorZhao Lei <zhaolei@cn.fujitsu.com>
Wed, 19 Aug 2015 07:54:15 +0000 (15:54 +0800)
committerChris Mason <clm@fb.com>
Mon, 31 Aug 2015 18:45:48 +0000 (11:45 -0700)
 num_tolerated_disk_barrier_failures in btrfs_balance

Code for updating fs_info->num_tolerated_disk_barrier_failures in
btrfs_balance() lacks raid56 support.

Reason:
 Above code was wroten in 2012-08-01, together with
 btrfs_calc_num_tolerated_disk_barrier_failures()'s first version.

 Then, btrfs_calc_num_tolerated_disk_barrier_failures() got updated
 later to support raid56, but code in btrfs_balance() was not
 updated together.

Fix:
 Merge above similar code to a common function:
 btrfs_get_num_tolerated_disk_barrier_failures()
 and make it support both case.

 It can fix this bug with a bonus of cleanup, and make these code
 never in above no-sync state from now on.

Suggested-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/volumes.c

index 51192d94c90cdaaf51015883b83c0fda64984340..0b658d0230f02911142a6557c1daca92c6fe6775 100644 (file)
@@ -3440,6 +3440,26 @@ static int barrier_all_devices(struct btrfs_fs_info *info)
        return 0;
 }
 
+int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags)
+{
+       if ((flags & (BTRFS_BLOCK_GROUP_DUP |
+                     BTRFS_BLOCK_GROUP_RAID0 |
+                     BTRFS_AVAIL_ALLOC_BIT_SINGLE)) ||
+           ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0))
+               return 0;
+
+       if (flags & (BTRFS_BLOCK_GROUP_RAID1 |
+                    BTRFS_BLOCK_GROUP_RAID5 |
+                    BTRFS_BLOCK_GROUP_RAID10))
+               return 1;
+
+       if (flags & BTRFS_BLOCK_GROUP_RAID6)
+               return 2;
+
+       pr_warn("BTRFS: unknown raid type: %llu\n", flags);
+       return 0;
+}
+
 int btrfs_calc_num_tolerated_disk_barrier_failures(
        struct btrfs_fs_info *fs_info)
 {
@@ -3482,28 +3502,11 @@ int btrfs_calc_num_tolerated_disk_barrier_failures(
                        if (space.total_bytes == 0 || space.used_bytes == 0)
                                continue;
                        flags = space.flags;
-                       /*
-                        * return
-                        * 0: if dup, single or RAID0 is configured for
-                        *    any of metadata, system or data, else
-                        * 1: if RAID5 is configured, or if RAID1 or
-                        *    RAID10 is configured and only two mirrors
-                        *    are used, else
-                        * 2: if RAID6 is configured
-                        */
-                       if (num_tolerated_disk_barrier_failures > 0 &&
-                           ((flags & (BTRFS_BLOCK_GROUP_DUP |
-                                      BTRFS_BLOCK_GROUP_RAID0)) ||
-                            ((flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0)))
-                               num_tolerated_disk_barrier_failures = 0;
-                       else if (num_tolerated_disk_barrier_failures > 1 &&
-                                (flags & (BTRFS_BLOCK_GROUP_RAID1 |
-                                          BTRFS_BLOCK_GROUP_RAID5 |
-                                          BTRFS_BLOCK_GROUP_RAID10)))
-                               num_tolerated_disk_barrier_failures = 1;
-                       else if (num_tolerated_disk_barrier_failures > 2 &&
-                                (flags & BTRFS_BLOCK_GROUP_RAID6))
-                               num_tolerated_disk_barrier_failures = 2;
+
+                       num_tolerated_disk_barrier_failures = min(
+                               num_tolerated_disk_barrier_failures,
+                               btrfs_get_num_tolerated_disk_barrier_failures(
+                                       flags));
                }
                up_read(&sinfo->groups_sem);
        }
index d4cbfeeeedd42050d3b2cd61707f80781d258328..bdfb479ea85955112305d0c30a17af9c7647daed 100644 (file)
@@ -139,6 +139,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
                                     u64 objectid);
 int btree_lock_page_hook(struct page *page, void *data,
                                void (*flush_fn)(void *));
+int btrfs_get_num_tolerated_disk_barrier_failures(u64 flags);
 int btrfs_calc_num_tolerated_disk_barrier_failures(
        struct btrfs_fs_info *fs_info);
 int __init btrfs_end_io_wq_init(void);
index 69520dfa8960d0dd3539a260bec8c22d57f680e1..644e070b3bd24657e676556a68f042becead03bb 100644 (file)
@@ -3585,23 +3585,10 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
        } while (read_seqretry(&fs_info->profiles_lock, seq));
 
        if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
-               int num_tolerated_disk_barrier_failures;
-               u64 target = bctl->sys.target;
-
-               num_tolerated_disk_barrier_failures =
-                       btrfs_calc_num_tolerated_disk_barrier_failures(fs_info);
-               if (num_tolerated_disk_barrier_failures > 0 &&
-                   (target &
-                    (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID0 |
-                     BTRFS_AVAIL_ALLOC_BIT_SINGLE)))
-                       num_tolerated_disk_barrier_failures = 0;
-               else if (num_tolerated_disk_barrier_failures > 1 &&
-                        (target &
-                         (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID10)))
-                       num_tolerated_disk_barrier_failures = 1;
-
-               fs_info->num_tolerated_disk_barrier_failures =
-                       num_tolerated_disk_barrier_failures;
+               fs_info->num_tolerated_disk_barrier_failures = min(
+                       btrfs_calc_num_tolerated_disk_barrier_failures(fs_info),
+                       btrfs_get_num_tolerated_disk_barrier_failures(
+                               bctl->sys.target));
        }
 
        ret = insert_balance_item(fs_info->tree_root, bctl);