summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2023-05-30 14:51:12 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-06-20 22:55:59 -0400
commit181f332a8e8cfebe12afd68787a6690b8f2064b9 (patch)
treed16fcc5e19c8c67d8b6616f543bd7e28a62d2f9e
parent0e2a3e960eae76d182fac840b73859bbb11ea68e (diff)
bcachefs: don't spin in rebalance when background target is not usable
If a bcachefs filesystem is configured with a background device (disk group), rebalance will relocate data to this device in the background by checking extent keys for whether they currently reside in the specified target. For keys that do not, rebalance performs a read/write cycle to allow the write path to properly relocate data. If the background target is not usable (read-only, for example), however, the write path doesn't actually move data to another device. Instead, rebalance spins indefinitely reading and rewriting the same data over and over to the same device. If the background target is made available again, the rebalance picks this up, relocates the data, and eventually terminates. To avoid this spinning behavior, update the rebalance background target logic to not only check whether the extent is not in the target, but whether the target is actually usable as well. If not, then don't mark the key for rewrite. Signed-off-by: Brian Foster <bfoster@redhat.com>
-rw-r--r--fs/bcachefs/disk_groups.h8
-rw-r--r--fs/bcachefs/rebalance.c3
2 files changed, 10 insertions, 1 deletions
diff --git a/fs/bcachefs/disk_groups.h b/fs/bcachefs/disk_groups.h
index bf39db3868bf..ec12584ceee7 100644
--- a/fs/bcachefs/disk_groups.h
+++ b/fs/bcachefs/disk_groups.h
@@ -68,6 +68,14 @@ static inline struct bch_devs_mask target_rw_devs(struct bch_fs *c,
return devs;
}
+static inline bool bch2_target_accepts_data(struct bch_fs *c,
+ enum bch_data_type data_type,
+ u16 target)
+{
+ struct bch_devs_mask rw_devs = target_rw_devs(c, data_type, target);
+ return !bitmap_empty(rw_devs.d, BCH_SB_MEMBERS_MAX);
+}
+
bool bch2_dev_in_target(struct bch_fs *, unsigned, unsigned);
int bch2_disk_path_find(struct bch_sb_handle *, const char *);
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c
index 66c40999163d..989f37a3b46a 100644
--- a/fs/bcachefs/rebalance.c
+++ b/fs/bcachefs/rebalance.c
@@ -57,7 +57,8 @@ static bool rebalance_pred(struct bch_fs *c, void *arg,
i = 0;
bkey_for_each_ptr(ptrs, ptr) {
if (!ptr->cached &&
- !bch2_dev_in_target(c, ptr->dev, io_opts->background_target))
+ !bch2_dev_in_target(c, ptr->dev, io_opts->background_target) &&
+ bch2_target_accepts_data(c, BCH_DATA_user, io_opts->background_target))
data_opts->rewrite_ptrs |= 1U << i;
i++;
}