Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 943c6e99 authored by Zhao Lei's avatar Zhao Lei Committed by Chris Mason
Browse files

btrfs: Add raid56 support for updating


 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: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarZhao Lei <zhaolei@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent 2c458045
Loading
Loading
Loading
Loading
+25 −22
Original line number Diff line number Diff line
@@ -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);
	}
+1 −0
Original line number Diff line number Diff line
@@ -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);
+4 −17
Original line number Diff line number Diff line
@@ -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);