From 6d67de1079993e09e7a867a6936a8163ece98792 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 19 Apr 2025 19:13:40 -0400 Subject: [PATCH] bcachefs: for_each_rw_member_rcu() Signed-off-by: Kent Overstreet --- fs/bcachefs/alloc_background.c | 10 ++++++++-- fs/bcachefs/journal.c | 4 +++- fs/bcachefs/journal_io.c | 5 +---- fs/bcachefs/journal_reclaim.c | 4 +++- fs/bcachefs/movinggc.c | 4 +++- fs/bcachefs/sb-members.h | 3 +++ 6 files changed, 21 insertions(+), 9 deletions(-) diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c index 0494d188605f..195d20220b7d 100644 --- a/fs/bcachefs/alloc_background.c +++ b/fs/bcachefs/alloc_background.c @@ -2575,8 +2575,10 @@ u64 bch2_min_rw_member_capacity(struct bch_fs *c) { u64 ret = U64_MAX; - for_each_rw_member(c, ca) + rcu_read_lock(); + for_each_rw_member_rcu(c, ca) ret = min(ret, ca->mi.nbuckets * ca->mi.bucket_size); + rcu_read_unlock(); return ret; } @@ -2600,8 +2602,12 @@ static bool bch2_dev_has_open_write_point(struct bch_fs *c, struct bch_dev *ca) void bch2_dev_allocator_set_rw(struct bch_fs *c, struct bch_dev *ca, bool rw) { + /* BCH_DATA_free == all rw devs */ + for (unsigned i = 0; i < ARRAY_SIZE(c->rw_devs); i++) - if (rw && (ca->mi.data_allowed & BIT(i))) + if (rw && + (i == BCH_DATA_free || + (ca->mi.data_allowed & BIT(i)))) set_bit(ca->dev_idx, c->rw_devs[i].d); else clear_bit(ca->dev_idx, c->rw_devs[i].d); diff --git a/fs/bcachefs/journal.c b/fs/bcachefs/journal.c index 3694b83af8cc..e1cd6e8e37cf 100644 --- a/fs/bcachefs/journal.c +++ b/fs/bcachefs/journal.c @@ -699,8 +699,10 @@ static unsigned max_dev_latency(struct bch_fs *c) { u64 nsecs = 0; - for_each_rw_member(c, ca) + rcu_read_lock(); + for_each_rw_member_rcu(c, ca) nsecs = max(nsecs, ca->io_latency[WRITE].stats.max_duration); + rcu_read_unlock(); return nsecs_to_jiffies(nsecs); } diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 28fa381cd589..438ad32ba242 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -2055,12 +2055,9 @@ CLOSURE_CALLBACK(bch2_journal_write) struct journal *j = container_of(w, struct journal, buf[w->idx]); struct bch_fs *c = container_of(j, struct bch_fs, journal); struct bch_replicas_padded replicas; - unsigned nr_rw_members = 0; + unsigned nr_rw_members = dev_mask_nr(&c->rw_devs[BCH_DATA_journal]); int ret; - for_each_rw_member(c, ca) - nr_rw_members++; - BUG_ON(BCH_SB_CLEAN(c->disk_sb.sb)); BUG_ON(!w->write_started); BUG_ON(w->write_allocated); diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c index fd7a140c9fd6..dc8169a970dd 100644 --- a/fs/bcachefs/journal_reclaim.c +++ b/fs/bcachefs/journal_reclaim.c @@ -627,7 +627,8 @@ static u64 journal_seq_to_flush(struct journal *j) spin_lock(&j->lock); - for_each_rw_member(c, ca) { + rcu_read_lock(); + for_each_rw_member_rcu(c, ca) { struct journal_device *ja = &ca->journal; unsigned nr_buckets, bucket_to_flush; @@ -641,6 +642,7 @@ static u64 journal_seq_to_flush(struct journal *j) seq_to_flush = max(seq_to_flush, ja->bucket_seq[bucket_to_flush]); } + rcu_read_unlock(); /* Also flush if the pin fifo is more than half full */ seq_to_flush = max_t(s64, seq_to_flush, diff --git a/fs/bcachefs/movinggc.c b/fs/bcachefs/movinggc.c index 96873372b516..e97e87ebe312 100644 --- a/fs/bcachefs/movinggc.c +++ b/fs/bcachefs/movinggc.c @@ -279,7 +279,8 @@ unsigned long bch2_copygc_wait_amount(struct bch_fs *c) { s64 wait = S64_MAX, fragmented_allowed, fragmented; - for_each_rw_member(c, ca) { + rcu_read_lock(); + for_each_rw_member_rcu(c, ca) { struct bch_dev_usage_full usage_full = bch2_dev_usage_full_read(ca); struct bch_dev_usage usage; @@ -296,6 +297,7 @@ unsigned long bch2_copygc_wait_amount(struct bch_fs *c) wait = min(wait, max(0LL, fragmented_allowed - fragmented)); } + rcu_read_unlock(); return wait; } diff --git a/fs/bcachefs/sb-members.h b/fs/bcachefs/sb-members.h index 28c6fc25c32c..c71a1ba61525 100644 --- a/fs/bcachefs/sb-members.h +++ b/fs/bcachefs/sb-members.h @@ -107,6 +107,9 @@ static inline struct bch_dev *__bch2_next_dev(struct bch_fs *c, struct bch_dev * #define for_each_online_member_rcu(_c, _ca) \ for_each_member_device_rcu(_c, _ca, &(_c)->online_devs) +#define for_each_rw_member_rcu(_c, _ca) \ + for_each_member_device_rcu(_c, _ca, &(_c)->rw_devs[BCH_DATA_free]) + static inline void bch2_dev_get(struct bch_dev *ca) { #ifdef CONFIG_BCACHEFS_DEBUG -- 2.50.1