summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2022-12-05 14:06:15 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2022-12-07 11:11:59 -0500
commit41cf178a5d5dde96544e6e060774f7209a8385a7 (patch)
tree2d37eec70d8910e820dc201e404c400a2d847ed9
parent6f01cbb6db10fc7758ce3901fd01960d688346aa (diff)
bcachefs: Fix alloc key compat code
The format for bch_alloc_v4 allows for adding new fields, but bch2_alloc_to_v4_mut() was buggy - it was allocating a buffer sized based on the current key, not including new fields being added. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/alloc_background.c77
-rw-r--r--fs/bcachefs/alloc_background.h2
2 files changed, 44 insertions, 35 deletions
diff --git a/fs/bcachefs/alloc_background.c b/fs/bcachefs/alloc_background.c
index 39d8d31722da..474ef290f39f 100644
--- a/fs/bcachefs/alloc_background.c
+++ b/fs/bcachefs/alloc_background.c
@@ -386,7 +386,6 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
{
struct bch_alloc_v4 _a;
const struct bch_alloc_v4 *a = bch2_alloc_to_v4(k, &_a);
- const struct bch_backpointer *bps;
unsigned i;
prt_newline(out);
@@ -413,33 +412,41 @@ void bch2_alloc_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c
prt_newline(out);
prt_printf(out, "io_time[WRITE] %llu", a->io_time[WRITE]);
prt_newline(out);
- prt_printf(out, "backpointers: %llu", BCH_ALLOC_V4_NR_BACKPOINTERS(a));
- printbuf_indent_add(out, 2);
- bps = alloc_v4_backpointers_c(a);
- for (i = 0; i < BCH_ALLOC_V4_NR_BACKPOINTERS(a); i++) {
+ if (k.k->type == KEY_TYPE_alloc_v4) {
+ struct bkey_s_c_alloc_v4 a_raw = bkey_s_c_to_alloc_v4(k);
+ const struct bch_backpointer *bps = alloc_v4_backpointers_c(a_raw.v);
+
+ prt_printf(out, "bp_start %llu", BCH_ALLOC_V4_BACKPOINTERS_START(a_raw.v));
prt_newline(out);
- bch2_backpointer_to_text(out, &bps[i]);
+
+ prt_printf(out, "backpointers: %llu", BCH_ALLOC_V4_NR_BACKPOINTERS(a_raw.v));
+ printbuf_indent_add(out, 2);
+
+ for (i = 0; i < BCH_ALLOC_V4_NR_BACKPOINTERS(a_raw.v); i++) {
+ prt_newline(out);
+ bch2_backpointer_to_text(out, &bps[i]);
+ }
+
+ printbuf_indent_sub(out, 2);
}
- printbuf_indent_sub(out, 4);
+ printbuf_indent_sub(out, 2);
}
void __bch2_alloc_to_v4(struct bkey_s_c k, struct bch_alloc_v4 *out)
{
if (k.k->type == KEY_TYPE_alloc_v4) {
- int d;
+ void *src, *dst;
*out = *bkey_s_c_to_alloc_v4(k).v;
- d = (int) BCH_ALLOC_V4_U64s -
- (int) (BCH_ALLOC_V4_BACKPOINTERS_START(out) ?: BCH_ALLOC_V4_U64s_V0);
- if (unlikely(d > 0)) {
- memset((u64 *) out + BCH_ALLOC_V4_BACKPOINTERS_START(out),
- 0,
- d * sizeof(u64));
- SET_BCH_ALLOC_V4_BACKPOINTERS_START(out, BCH_ALLOC_V4_U64s);
- }
+ src = alloc_v4_backpointers(out);
+ SET_BCH_ALLOC_V4_BACKPOINTERS_START(out, BCH_ALLOC_V4_U64s);
+ dst = alloc_v4_backpointers(out);
+
+ if (src < dst)
+ memset(src, 0, dst - src);
} else {
struct bkey_alloc_unpacked u = bch2_alloc_unpack(k);
@@ -465,20 +472,20 @@ static noinline struct bkey_i_alloc_v4 *
__bch2_alloc_to_v4_mut(struct btree_trans *trans, struct bkey_s_c k)
{
struct bkey_i_alloc_v4 *ret;
- unsigned bytes = k.k->type == KEY_TYPE_alloc_v4
- ? bkey_bytes(k.k)
- : sizeof(struct bkey_i_alloc_v4);
-
- /*
- * Reserve space for one more backpointer here:
- * Not sketchy at doing it this way, nope...
- */
- ret = bch2_trans_kmalloc(trans, bytes + sizeof(struct bch_backpointer));
- if (IS_ERR(ret))
- return ret;
-
if (k.k->type == KEY_TYPE_alloc_v4) {
- struct bch_backpointer *src, *dst;
+ struct bkey_s_c_alloc_v4 a = bkey_s_c_to_alloc_v4(k);
+ unsigned bytes = sizeof(struct bkey_i_alloc_v4) +
+ BCH_ALLOC_V4_NR_BACKPOINTERS(a.v) *
+ sizeof(struct bch_backpointer);
+ void *src, *dst;
+
+ /*
+ * Reserve space for one more backpointer here:
+ * Not sketchy at doing it this way, nope...
+ */
+ ret = bch2_trans_kmalloc(trans, bytes + sizeof(struct bch_backpointer));
+ if (IS_ERR(ret))
+ return ret;
bkey_reassemble(&ret->k_i, k);
@@ -488,9 +495,15 @@ __bch2_alloc_to_v4_mut(struct btree_trans *trans, struct bkey_s_c k)
memmove(dst, src, BCH_ALLOC_V4_NR_BACKPOINTERS(&ret->v) *
sizeof(struct bch_backpointer));
- memset(src, 0, dst - src);
+ if (src < dst)
+ memset(src, 0, dst - src);
set_alloc_v4_u64s(ret);
} else {
+ ret = bch2_trans_kmalloc(trans, sizeof(struct bkey_i_alloc_v4) +
+ sizeof(struct bch_backpointer));
+ if (IS_ERR(ret))
+ return ret;
+
bkey_alloc_v4_init(&ret->k_i);
ret->k.p = k.k->p;
bch2_alloc_to_v4(k, &ret->v);
@@ -508,10 +521,8 @@ static inline struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut_inlined(struct btree_
*/
struct bkey_i_alloc_v4 *ret =
bch2_trans_kmalloc_nomemzero(trans, bkey_bytes(k.k) + sizeof(struct bch_backpointer));
- if (!IS_ERR(ret)) {
+ if (!IS_ERR(ret))
bkey_reassemble(&ret->k_i, k);
- memset((void *) ret + bkey_bytes(k.k), 0, sizeof(struct bch_backpointer));
- }
return ret;
}
diff --git a/fs/bcachefs/alloc_background.h b/fs/bcachefs/alloc_background.h
index be48b7d88da5..d67fab0f5dc1 100644
--- a/fs/bcachefs/alloc_background.h
+++ b/fs/bcachefs/alloc_background.h
@@ -112,8 +112,6 @@ struct bkey_i_alloc_v4 *bch2_alloc_to_v4_mut(struct btree_trans *, struct bkey_s
int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
-#define ALLOC_SCAN_BATCH(ca) max_t(size_t, 1, (ca)->mi.nbuckets >> 9)
-
int bch2_alloc_v1_invalid(const struct bch_fs *, struct bkey_s_c, int, struct printbuf *);
int bch2_alloc_v2_invalid(const struct bch_fs *, struct bkey_s_c, int, struct printbuf *);
int bch2_alloc_v3_invalid(const struct bch_fs *, struct bkey_s_c, int, struct printbuf *);