diff mbox

[v2] btrfs: Add raid56 support for updating num_tolerated_disk_barrier_failures in btrfs_balance()

Message ID 5aaaa5a35953dc4a02b8bfe7e7d426b64831994f.1437382947.git.zhaolei@cn.fujitsu.com (mailing list archive)
State New, archived
Headers show

Commit Message

Zhaolei July 20, 2015, 9:04 a.m. UTC
From: Zhao Lei <zhaolei@cn.fujitsu.com>

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.

Changelog v1-v2:
 1: Use a common function instead of adding extra argument to
    btrfs_calc_num_tolerated_disk_barrier_failures(), which is quite
    usefully used by many more functions, Suggested-by:
    Anand Jain <anand.jain@oracle.com>

Suggested-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Zhao Lei <zhaolei@cn.fujitsu.com>
---
 fs/btrfs/disk-io.c | 47 +++++++++++++++++++++++++----------------------
 fs/btrfs/disk-io.h |  1 +
 fs/btrfs/volumes.c | 21 ++++-----------------
 3 files changed, 30 insertions(+), 39 deletions(-)
diff mbox

Patch

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b6600c7..1e5dcfd 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -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);
 	}
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index d4cbfee..bdfb479 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -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);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index fbe7c10..a4392ad 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3573,23 +3573,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);