diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-09-27 14:44:56 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:10:15 -0400 |
commit | 4220666398de7f5127bab5437b5276b3eb155282 (patch) | |
tree | ef6652e6d8e75ad660ce21a2dc43aeb46fe7c636 /fs/bcachefs/inode.c | |
parent | 7dcf62c06d11195e8caecd7b2236aa5b07e3ef8c (diff) |
bcachefs: Fix bch2_inode_delete_keys()
bch2_inode_delete_keys() was using BTREE_ITER_NOT_EXTENTS, on the
assumption that it would never need to split extents.
But that caused a race with extents being split by other threads -
specifically, the data move path. Extents iterators have the iterator
position pointing to the start of the extent, which avoids the race.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/inode.c')
-rw-r--r-- | fs/bcachefs/inode.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/bcachefs/inode.c b/fs/bcachefs/inode.c index 4a695a8e7a3b..bb3f443d8381 100644 --- a/fs/bcachefs/inode.c +++ b/fs/bcachefs/inode.c @@ -780,6 +780,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, struct btree_iter iter; struct bkey_s_c k; struct bkey_i delete; + struct bpos end = POS(inum.inum, U64_MAX); u32 snapshot; int ret = 0; @@ -788,7 +789,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, * extent iterator: */ bch2_trans_iter_init(trans, &iter, id, POS(inum.inum, 0), - BTREE_ITER_INTENT|BTREE_ITER_NOT_EXTENTS); + BTREE_ITER_INTENT); while (1) { bch2_trans_begin(trans); @@ -799,7 +800,7 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, bch2_btree_iter_set_snapshot(&iter, snapshot); - k = bch2_btree_iter_peek_upto(&iter, POS(inum.inum, U64_MAX)); + k = bch2_btree_iter_peek_upto(&iter, end); ret = bkey_err(k); if (ret) goto err; @@ -810,6 +811,11 @@ static int bch2_inode_delete_keys(struct btree_trans *trans, bkey_init(&delete.k); delete.k.p = iter.pos; + if (iter.flags & BTREE_ITER_IS_EXTENTS) + bch2_key_resize(&delete.k, + bpos_min(end, k.k->p).offset - + iter.pos.offset); + ret = bch2_trans_update(trans, &iter, &delete, 0) ?: bch2_trans_commit(trans, NULL, NULL, BTREE_INSERT_NOFAIL); |