From: Zygo Blaxell Date: Mon, 16 Mar 2020 03:55:28 +0000 (-0400) Subject: btrfs: allow balance usage filter to select full block groups X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf7bc89e7ef915d099be5a3dee551a2ff418289b;p=linux btrfs: allow balance usage filter to select full block groups There's a gap in what we can specify with the current balance usage filter. This command doesn't balance all data block groups: 1. btrfs balance start -dusage=0..100 /fs and neither does this one: 2. btrfs balance start -dusage=100 /fs and since commit a105bb88f46b6 in 2013, we can't work around with: 3. btrfs balance start -dusage=101 /fs/that/is/raid1 and there's a related problem when resuming paused balances, e.g. during a mount. Commands #1 and #2 fail as documented in the btrfs-balance man page: usage=, usage= Balances only block groups with usage under the given percentage. Since completely full block groups are not "under" 100%, the filter expression "usage=100" covers any block group with at least 1 unused byte, but not completely full block groups. Command #3 fails because of commit a105bb88f46b6 "Btrfs: fix a regression in balance usage filter" which removed the ability to specify percentage values over 100; however, we don't want to revert that because we do want to guard against integer overflows and other surprises that arise from truly bad user inputs. There are a few ways to fix this. This patch implements one that does not alter any existing behavior: we allow 'usage=101' with the meaning "100% + 1 byte". This leaves "usage=100" referring to any block group that is not completely full, in case anyone relies on that filter behavior, while allowing a method for accepting completely full blocks in the filter. It also allows 'usage=101' to work around the balance recovery issue below. Starting with commit 596410151e "Btrfs: recover balance on mount", btrfs will insert a 'usage=90' filter when resuming a balance if no 'usage' filter was used on the original balance. If the original balance does not use 'convert' or 'usage', then 'usage=90' will be inserted. This can be surprising when pausing balances to let snapshot deletes run, as in this log: BTRFS info (device dm-0): balance: start -dlimit=999 BTRFS info (device dm-0): relocating block group 1776771137536 flags data BTRFS info (device dm-0): found 18 extents, stage: move data extents BTRFS info (device dm-0): found 18 extents, stage: update data pointers BTRFS info (device dm-0): balance: paused BTRFS debug (device dm-0): cleaner removing 2649 BTRFS info (device dm-0): balance: resume -dusage=90,limit=998 BTRFS info (device dm-0): balance: ended with status: 0 We expected to balance 999 block groups, instead we got one, because the resumed balance used a very different filter than the original. If we set 'usage=100', we avoid this behavior on balance resume, but we also fail to balance all but one of the full block groups. To work around this, we need a way to set the BTRFS_BALANCE_ARGS_USAGE flag without losing the ability to select full block groups. Signed-off-by: Zygo Blaxell (cherry picked from commit f8392690b5fb1010484f7fa33b36e37c4a894de2) --- diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 37b54ce2d5366..6a59b9a2cd479 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -4237,7 +4237,7 @@ static int chunk_usage_range_filter(struct btrfs_fs_info *fs_info, u64 chunk_off if (bargs->usage_max == 0) user_thresh_max = 1; else if (bargs->usage_max > 100) - user_thresh_max = cache->length; + user_thresh_max = cache->length + 1; else user_thresh_max = mult_perc(cache->length, bargs->usage_max); @@ -4266,7 +4266,7 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset, if (bargs->usage_min == 0) user_thresh = 1; else if (bargs->usage > 100) - user_thresh = cache->length; + user_thresh = cache->length + 1; else user_thresh = mult_perc(cache->length, bargs->usage);