summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-05-07 22:05:05 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-01-18 12:05:14 -0500
commit7b7c8ff48eb0e9942bf6f58bd4941241ea76cc23 (patch)
tree5b62bdf9692617042d0c9db7359821dc74f4b298
parentc3fe35500f7161f67bad9c5eb0ddd027a99e7ec7 (diff)
bcachefs: Fix bch2_dev_in_target
wasn't updated for nested disk groups
-rw-r--r--fs/bcachefs/alloc.c15
-rw-r--r--fs/bcachefs/disk_groups.c30
-rw-r--r--fs/bcachefs/disk_groups.h28
-rw-r--r--fs/bcachefs/extents.c12
-rw-r--r--fs/bcachefs/rebalance.c4
5 files changed, 44 insertions, 45 deletions
diff --git a/fs/bcachefs/alloc.c b/fs/bcachefs/alloc.c
index b0bcdf2e0cfc..54cfac1fc9e2 100644
--- a/fs/bcachefs/alloc.c
+++ b/fs/bcachefs/alloc.c
@@ -1398,12 +1398,10 @@ static void writepoint_drop_ptrs(struct bch_fs *c,
{
int i;
- for (i = wp->first_ptr - 1; i >= 0; --i) {
- struct bch_dev *ca = bch_dev_bkey_exists(c, wp->ptrs[i]->ptr.dev);
-
- if (dev_in_target(ca, target) == in_target)
+ for (i = wp->first_ptr - 1; i >= 0; --i)
+ if (bch2_dev_in_target(c, wp->ptrs[i]->ptr.dev,
+ target) == in_target)
writepoint_drop_ptr(c, wp, i);
- }
}
static void verify_not_stale(struct bch_fs *c, const struct write_point *wp)
@@ -1564,7 +1562,7 @@ struct write_point *bch2_alloc_sectors_start(struct bch_fs *c,
/* does writepoint have ptrs we don't want to use? */
if (target)
writepoint_for_each_ptr(wp, ob, i)
- if (!dev_idx_in_target(c, ob->ptr.dev, target)) {
+ if (!bch2_dev_in_target(c, ob->ptr.dev, target)) {
swap(wp->ptrs[i], wp->ptrs[wp->first_ptr]);
wp->first_ptr++;
}
@@ -1599,7 +1597,8 @@ alloc_done:
* one in the target we want:
*/
if (cache_idx >= 0) {
- if (!dev_in_target(ca, target)) {
+ if (!bch2_dev_in_target(c, wp->ptrs[i]->ptr.dev,
+ target)) {
writepoint_drop_ptr(c, wp, i);
} else {
writepoint_drop_ptr(c, wp, cache_idx);
@@ -1630,7 +1629,7 @@ alloc_done:
if (ca->mi.durability &&
ca->mi.durability <= nr_ptrs_effective - nr_replicas &&
- !dev_idx_in_target(c, ob->ptr.dev, target)) {
+ !bch2_dev_in_target(c, ob->ptr.dev, target)) {
swap(wp->ptrs[i], wp->ptrs[wp->first_ptr]);
wp->first_ptr++;
nr_ptrs_effective -= ca->mi.durability;
diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c
index 24e8a45970c1..0687e8d224cd 100644
--- a/fs/bcachefs/disk_groups.c
+++ b/fs/bcachefs/disk_groups.c
@@ -196,6 +196,36 @@ const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *c, unsigned targe
}
}
+bool bch2_dev_in_target(struct bch_fs *c, unsigned dev, unsigned target)
+{
+ struct target t = target_decode(target);
+
+ switch (t.type) {
+ case TARGET_NULL:
+ return false;
+ case TARGET_DEV:
+ return dev == t.dev;
+ case TARGET_GROUP: {
+ struct bch_disk_groups_cpu *g;
+ const struct bch_devs_mask *m;
+ bool ret;
+
+ rcu_read_lock();
+ g = rcu_dereference(c->disk_groups);
+ m = t.group < g->nr && !g->entries[t.group].deleted
+ ? &g->entries[t.group].devs
+ : NULL;
+
+ ret = m ? test_bit(dev, m->d) : false;
+ rcu_read_unlock();
+
+ return ret;
+ }
+ default:
+ BUG();
+ }
+}
+
static int __bch2_disk_group_find(struct bch_sb_field_disk_groups *groups,
unsigned parent,
const char *name, unsigned namelen)
diff --git a/fs/bcachefs/disk_groups.h b/fs/bcachefs/disk_groups.h
index 3f006a4ffa6e..d202eb3a9de6 100644
--- a/fs/bcachefs/disk_groups.h
+++ b/fs/bcachefs/disk_groups.h
@@ -54,34 +54,8 @@ static inline struct target target_decode(unsigned target)
return (struct target) { .type = TARGET_NULL };
}
-static inline bool dev_in_target(struct bch_dev *ca, unsigned target)
-{
- struct target t = target_decode(target);
-
- switch (t.type) {
- case TARGET_NULL:
- return false;
- case TARGET_DEV:
- return ca->dev_idx == t.dev;
- case TARGET_GROUP:
- return ca->mi.group && ca->mi.group - 1 == t.group;
- default:
- BUG();
- }
-}
-
-static inline bool dev_idx_in_target(struct bch_fs *c, unsigned dev, unsigned target)
-{
- bool ret;
-
- rcu_read_lock();
- ret = dev_in_target(rcu_dereference(c->devs[dev]), target);
- rcu_read_unlock();
-
- return ret;
-}
-
const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *, unsigned);
+bool bch2_dev_in_target(struct bch_fs *, unsigned, unsigned);
int bch2_disk_path_find(struct bch_sb_handle *, const char *);
int bch2_disk_path_find_or_create(struct bch_sb_handle *, const char *);
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index b00e89037e37..b414fd43f772 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -160,13 +160,11 @@ bch2_extent_has_target(struct bch_fs *c, struct bkey_s_c_extent e, unsigned targ
{
const struct bch_extent_ptr *ptr;
- extent_for_each_ptr(e, ptr) {
- struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
-
- if (dev_in_target(ca, target) &&
- (!ptr->cached || !ptr_stale(ca, ptr)))
+ extent_for_each_ptr(e, ptr)
+ if (bch2_dev_in_target(c, ptr->dev, target) &&
+ (!ptr->cached ||
+ !ptr_stale(bch_dev_bkey_exists(c, ptr->dev), ptr)))
return ptr;
- }
return NULL;
}
@@ -2025,7 +2023,7 @@ void bch2_extent_mark_replicas_cached(struct bch_fs *c,
int n = bch2_extent_ptr_durability(c, ptr);
if (n && n <= extra &&
- !dev_in_target(c->devs[ptr->dev], target)) {
+ !bch2_dev_in_target(c, ptr->dev, target)) {
ptr->cached = true;
extra -= n;
}
diff --git a/fs/bcachefs/rebalance.c b/fs/bcachefs/rebalance.c
index 7dd376fa500f..7be9113ca6bd 100644
--- a/fs/bcachefs/rebalance.c
+++ b/fs/bcachefs/rebalance.c
@@ -22,10 +22,8 @@ static inline bool rebalance_ptr_pred(struct bch_fs *c,
struct bch_extent_crc_unpacked crc,
struct bch_io_opts *io_opts)
{
- struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev);
-
if (io_opts->background_target &&
- !dev_in_target(ca, io_opts->background_target) &&
+ !bch2_dev_in_target(c, ptr->dev, io_opts->background_target) &&
!ptr->cached)
return true;