summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-12-16 14:18:33 -0500
committerKent Overstreet <kent.overstreet@gmail.com>2020-12-16 15:29:51 -0500
commit10e0294af802bf23016633f8b9d0dec38ec0d8ad (patch)
treebe8aa58f982cee5c354d34a97fb99c29112a19cd
parent4d925ccec837a72eb3b0ff3543cab2885c0d5e2a (diff)
bcachefs: Check for duplicate device ptrs in bch2_bkey_ptrs_invalid()
This is something we clearly should be checking for, but weren't - oops. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/extents.c8
-rw-r--r--fs/bcachefs/replicas.c5
-rw-r--r--fs/bcachefs/util.h5
3 files changed, 13 insertions, 5 deletions
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index 7fae6a4ba26f..828ccf07da61 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -1046,11 +1046,13 @@ static const char *extent_ptr_invalid(const struct bch_fs *c,
const char *bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k)
{
struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
+ struct bch_devs_list devs;
const union bch_extent_entry *entry;
struct bch_extent_crc_unpacked crc;
unsigned size_ondisk = k.k->size;
const char *reason;
unsigned nonce = UINT_MAX;
+ unsigned i;
if (k.k->type == KEY_TYPE_btree_ptr)
size_ondisk = c->opts.btree_node_size;
@@ -1101,6 +1103,12 @@ const char *bch2_bkey_ptrs_invalid(const struct bch_fs *c, struct bkey_s_c k)
}
}
+ devs = bch2_bkey_devs(k);
+ bubble_sort(devs.devs, devs.nr, u8_cmp);
+ for (i = 0; i + 1 < devs.nr; i++)
+ if (devs.devs[i] == devs.devs[i + 1])
+ return "multiple ptrs to same device";
+
return NULL;
}
diff --git a/fs/bcachefs/replicas.c b/fs/bcachefs/replicas.c
index 00a197b65e0b..d37d173f3ba6 100644
--- a/fs/bcachefs/replicas.c
+++ b/fs/bcachefs/replicas.c
@@ -11,11 +11,6 @@ static int bch2_cpu_replicas_to_sb_replicas(struct bch_fs *,
/* Replicas tracking - in memory: */
-static inline int u8_cmp(u8 l, u8 r)
-{
- return cmp_int(l, r);
-}
-
static void verify_replicas_entry(struct bch_replicas_entry *e)
{
#ifdef CONFIG_BCACHEFS_DEBUG
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index 6e5335440b4b..c69b05deec41 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.h
@@ -747,4 +747,9 @@ u64 *bch2_acc_percpu_u64s(u64 __percpu *, unsigned);
#define cmp_int(l, r) ((l > r) - (l < r))
+static inline int u8_cmp(u8 l, u8 r)
+{
+ return cmp_int(l, r);
+}
+
#endif /* _BCACHEFS_UTIL_H */