From: Kent Overstreet Date: Wed, 19 May 2021 03:17:03 +0000 (-0400) Subject: bcachefs: Split extents if necessary in bch2_trans_update() X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=d6462f494dcf57422f36f9c4704c2c128354f6c4;p=linux.git bcachefs: Split extents if necessary in bch2_trans_update() Currently, we handle multiple overlapping extents in the same transaction commit by doing fixups in bch2_trans_update() - this patch extents that to split updates when necessary. The next patch that changes the reflink code to not fragment extents when making them indirect will require this. Signed-off-by: Kent Overstreet --- diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index fbe6a17ffd8a9..cc844ca81bccb 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -1099,9 +1099,30 @@ int bch2_trans_update(struct btree_trans *trans, struct btree_iter *iter, if (i < trans->updates + trans->nr_updates && i->btree_id == n.btree_id && bkey_cmp(n.k->k.p, bkey_start_pos(&i->k->k)) > 0) { - /* We don't handle splitting extents here: */ - BUG_ON(bkey_cmp(bkey_start_pos(&n.k->k), - bkey_start_pos(&i->k->k)) > 0); + if (bkey_cmp(bkey_start_pos(&n.k->k), + bkey_start_pos(&i->k->k)) > 0) { + struct btree_insert_entry split = *i; + int ret; + + BUG_ON(trans->nr_updates + 1 >= BTREE_ITER_MAX); + + split.k = bch2_trans_kmalloc(trans, bkey_bytes(&i->k->k)); + ret = PTR_ERR_OR_ZERO(split.k); + if (ret) + return ret; + + bkey_copy(split.k, i->k); + bch2_cut_back(bkey_start_pos(&n.k->k), split.k); + + split.iter = bch2_trans_get_iter(trans, split.btree_id, + bkey_start_pos(&split.k->k), + BTREE_ITER_INTENT); + split.iter->flags |= BTREE_ITER_KEEP_UNTIL_COMMIT; + bch2_trans_iter_put(trans, split.iter); + array_insert_item(trans->updates, trans->nr_updates, + i - trans->updates, split); + i++; + } /* * When we have an extent that overwrites the start of another diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index 9fc858a0a4962..5a45e738bc804 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -342,9 +342,8 @@ int bch2_extent_update(struct btree_trans *trans, bch2_trans_iter_put(trans, inode_iter); } - bch2_trans_update(trans, iter, k, 0); - - ret = bch2_trans_commit(trans, disk_res, journal_seq, + ret = bch2_trans_update(trans, iter, k, 0) ?: + bch2_trans_commit(trans, disk_res, journal_seq, BTREE_INSERT_NOCHECK_RW| BTREE_INSERT_NOFAIL); if (ret) diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c index 405a194d10e5d..ec8532b39a49a 100644 --- a/fs/bcachefs/reflink.c +++ b/fs/bcachefs/reflink.c @@ -155,7 +155,9 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, *refcount = 0; memcpy(refcount + 1, &orig->v, bkey_val_bytes(&orig->k)); - bch2_trans_update(trans, reflink_iter, r_v, 0); + ret = bch2_trans_update(trans, reflink_iter, r_v, 0); + if (ret) + goto err; r_p = bch2_trans_kmalloc(trans, sizeof(*r_p)); if (IS_ERR(r_p)) { @@ -168,7 +170,7 @@ static int bch2_make_extent_indirect(struct btree_trans *trans, set_bkey_val_bytes(&r_p->k, sizeof(r_p->v)); r_p->v.idx = cpu_to_le64(bkey_start_offset(&r_v->k)); - bch2_trans_update(trans, extent_iter, &r_p->k_i, 0); + ret = bch2_trans_update(trans, extent_iter, &r_p->k_i, 0); err: if (!IS_ERR(reflink_iter)) c->reflink_hint = reflink_iter->pos.offset;