diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2020-08-06 15:22:24 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2020-08-25 13:09:38 -0400 |
commit | f7160b419df8870185e7000c562c0ec3fffde63c (patch) | |
tree | 70e827e10711b965210c2b33f66f69b039d5fea6 | |
parent | 08033673ba0173d5dbe4d37068f2ee09b1b44c9b (diff) |
bcachefs: Fix a couple null ptr derefs when no disk groups exist
Normally successfully parsing a target means disk groups should exist,
but we don't want a BUG() or null ptr deref if we end up with an invalid
target.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r-- | fs/bcachefs/disk_groups.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/io.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/super.c | 7 |
3 files changed, 8 insertions, 7 deletions
diff --git a/fs/bcachefs/disk_groups.c b/fs/bcachefs/disk_groups.c index b6e3152312ba..c52b6faac9b4 100644 --- a/fs/bcachefs/disk_groups.c +++ b/fs/bcachefs/disk_groups.c @@ -183,7 +183,7 @@ const struct bch_devs_mask *bch2_target_to_mask(struct bch_fs *c, unsigned targe case TARGET_GROUP: { struct bch_disk_groups_cpu *g = rcu_dereference(c->disk_groups); - return t.group < g->nr && !g->entries[t.group].deleted + return g && t.group < g->nr && !g->entries[t.group].deleted ? &g->entries[t.group].devs : NULL; } @@ -208,7 +208,7 @@ bool bch2_dev_in_target(struct bch_fs *c, unsigned dev, unsigned target) rcu_read_lock(); g = rcu_dereference(c->disk_groups); - m = t.group < g->nr && !g->entries[t.group].deleted + m = g && t.group < g->nr && !g->entries[t.group].deleted ? &g->entries[t.group].devs : NULL; diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index 92d2ec5662a5..5c9c3cf54edd 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -54,7 +54,9 @@ static bool bch2_target_congested(struct bch_fs *c, u16 target) return false; rcu_read_lock(); - devs = bch2_target_to_mask(c, target); + devs = bch2_target_to_mask(c, target) ?: + &c->rw_devs[BCH_DATA_user]; + for_each_set_bit(d, devs->d, BCH_SB_MEMBERS_MAX) { ca = rcu_dereference(c->devs[d]); if (!ca) diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index d30800d76fdc..94288fc92ec4 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -169,10 +169,9 @@ int bch2_congested(void *data, int bdi_bits) } } } else { - unsigned target = READ_ONCE(c->opts.foreground_target); - const struct bch_devs_mask *devs = target - ? bch2_target_to_mask(c, target) - : &c->rw_devs[BCH_DATA_user]; + const struct bch_devs_mask *devs = + bch2_target_to_mask(c, c->opts.foreground_target) ?: + &c->rw_devs[BCH_DATA_user]; for_each_member_device_rcu(ca, c, i, devs) { bdi = ca->disk_sb.bdev->bd_bdi; |