aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-08-21 18:35:15 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:25 -0400
commite42951b0aa50bb67b29da1af1099013c1aeb1d9d (patch)
treed423c9d3eb2c00af621f1ffa42939259f4ce0f49
parent76426098e419c1732efc3f88166f3f3592c215c9 (diff)
bcachefs: Fix bch2_sort_repack_merge()
bch2_bkey_normalize() modifies the value, and we were modifying the original value in the src btree node - but, we're called without a write lock held on the src node. Oops... Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/bkey_sort.c19
-rw-r--r--fs/bcachefs/extents.c4
2 files changed, 10 insertions, 13 deletions
diff --git a/fs/bcachefs/bkey_sort.c b/fs/bcachefs/bkey_sort.c
index 9f5d9b4bf1c9..e32fad5a91ac 100644
--- a/fs/bcachefs/bkey_sort.c
+++ b/fs/bcachefs/bkey_sort.c
@@ -415,25 +415,22 @@ bch2_sort_repack_merge(struct bch_fs *c,
struct bkey_format *out_f,
bool filter_whiteouts)
{
- struct bkey_packed *prev = NULL, *k_packed, *next;
- struct bkey k_unpacked;
+ struct bkey_packed *prev = NULL, *k_packed;
struct bkey_s k;
struct btree_nr_keys nr;
+ BKEY_PADDED(k) tmp;
memset(&nr, 0, sizeof(nr));
- next = bch2_btree_node_iter_next_all(iter, src);
- while ((k_packed = next)) {
- /*
- * The filter might modify the size of @k's value, so advance
- * the iterator first:
- */
- next = bch2_btree_node_iter_next_all(iter, src);
-
+ while ((k_packed = bch2_btree_node_iter_next_all(iter, src))) {
if (filter_whiteouts && bkey_whiteout(k_packed))
continue;
- k = __bkey_disassemble(src, k_packed, &k_unpacked);
+ EBUG_ON(bkeyp_val_u64s(&src->format, k_packed) >
+ BKEY_EXTENT_VAL_U64s_MAX);
+
+ bch2_bkey_unpack(src, &tmp.k, k_packed);
+ k = bkey_i_to_s(&tmp.k);
if (filter_whiteouts &&
bch2_bkey_normalize(c, k))
diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c
index 81ec55526ce9..779ee42350ad 100644
--- a/fs/bcachefs/extents.c
+++ b/fs/bcachefs/extents.c
@@ -1590,9 +1590,9 @@ bool bch2_extent_normalize(struct bch_fs *c, struct bkey_s k)
/* will only happen if all pointers were cached: */
if (!bkey_val_u64s(k.k))
- k.k->type = KEY_TYPE_deleted;
+ k.k->type = KEY_TYPE_discard;
- return false;
+ return bkey_whiteout(k.k);
}
void bch2_bkey_mark_replicas_cached(struct bch_fs *c, struct bkey_s k,