diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-08-16 09:58:07 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:25 -0400 |
commit | 3c7f3b7aeb73f2155aec9d00567b70ef55ede465 (patch) | |
tree | b15d0dd40a4213018b9d6c3f9c4fb38fd5f5ff97 | |
parent | 63069bb6bf03ac7a55c53886a1380899df3a176d (diff) |
bcachefs: Refactor bch2_extent_trim_atomic() for reflink
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/buckets.c | 6 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 87 | ||||
-rw-r--r-- | fs/bcachefs/extents.h | 6 | ||||
-rw-r--r-- | fs/bcachefs/fs-io.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/io.c | 11 | ||||
-rw-r--r-- | fs/bcachefs/recovery.c | 10 |
7 files changed, 105 insertions, 31 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index b878f9a9882c..5f94b6e9cf28 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -400,8 +400,7 @@ static inline void btree_insert_entry_checks(struct btree_trans *trans, BUG_ON(i->iter->level); BUG_ON(bkey_cmp(bkey_start_pos(&i->k->k), i->iter->pos)); EBUG_ON((i->iter->flags & BTREE_ITER_IS_EXTENTS) && - !bch2_extent_is_atomic(i->k, i->iter)); - + bkey_cmp(i->k->k.p, i->iter->l[0].b->key.k.p) > 0); EBUG_ON((i->iter->flags & BTREE_ITER_IS_EXTENTS) && !(trans->flags & BTREE_INSERT_ATOMIC)); } @@ -1031,7 +1030,10 @@ retry: /* create the biggest key we can */ bch2_key_resize(&delete.k, max_sectors); bch2_cut_back(end, &delete.k); - bch2_extent_trim_atomic(&delete, iter); + + ret = bch2_extent_trim_atomic(&delete, iter); + if (ret) + break; } bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &delete)); diff --git a/fs/bcachefs/buckets.c b/fs/bcachefs/buckets.c index 569c9e4a55aa..baf9642d21ca 100644 --- a/fs/bcachefs/buckets.c +++ b/fs/bcachefs/buckets.c @@ -1255,9 +1255,6 @@ int bch2_mark_update(struct btree_trans *trans, if (!btree_node_type_needs_gc(iter->btree_id)) return 0; - EBUG_ON(btree_node_is_extents(b) && - !bch2_extent_is_atomic(insert->k, insert->iter)); - if (!(trans->flags & BTREE_INSERT_NOMARK_INSERT)) bch2_mark_key_locked(c, bkey_i_to_s_c(insert->k), 0, insert->k->k.size, @@ -1636,9 +1633,6 @@ int bch2_trans_mark_update(struct btree_trans *trans, if (!btree_node_type_needs_gc(iter->btree_id)) return 0; - EBUG_ON(btree_node_is_extents(b) && - !bch2_extent_is_atomic(insert, iter)); - ret = bch2_trans_mark_key(trans, bkey_i_to_s_c(insert), 0, insert->k.size, BCH_BUCKET_MARK_INSERT); if (ret) diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 0e43e81065b6..11defa3d99a5 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -949,47 +949,104 @@ static unsigned bch2_bkey_nr_alloc_ptrs(struct bkey_s_c k) return ret; } -static inline struct bpos -bch2_extent_atomic_end(struct bkey_i *insert, struct btree_iter *iter) +static int __bch2_extent_atomic_end(struct btree_trans *trans, + struct bkey_s_c k, + unsigned offset, + struct bpos *end, + unsigned *nr_iters, + unsigned max_iters) +{ + int ret = 0; + + switch (k.k->type) { + case KEY_TYPE_extent: + *nr_iters += bch2_bkey_nr_alloc_ptrs(k); + + if (*nr_iters >= max_iters) { + *end = bpos_min(*end, k.k->p); + return 0; + } + + break; + } + + return ret; +} + +int bch2_extent_atomic_end(struct btree_trans *trans, + struct btree_iter *iter, + struct bkey_i *insert, + struct bpos *end) { struct btree *b = iter->l[0].b; struct btree_node_iter node_iter = iter->l[0].iter; struct bkey_packed *_k; - unsigned nr_alloc_ptrs = + unsigned nr_iters = bch2_bkey_nr_alloc_ptrs(bkey_i_to_s_c(insert)); + int ret = 0; BUG_ON(iter->uptodate > BTREE_ITER_NEED_PEEK); BUG_ON(bkey_cmp(bkey_start_pos(&insert->k), b->data->min_key) < 0); - while ((_k = bch2_btree_node_iter_peek_filter(&node_iter, b, + *end = bpos_min(insert->k.p, b->key.k.p); + + ret = __bch2_extent_atomic_end(trans, bkey_i_to_s_c(insert), + 0, end, &nr_iters, 10); + if (ret) + return ret; + + while (nr_iters < 20 && + (_k = bch2_btree_node_iter_peek_filter(&node_iter, b, KEY_TYPE_discard))) { struct bkey unpacked; struct bkey_s_c k = bkey_disassemble(b, _k, &unpacked); + unsigned offset = 0; - if (bkey_cmp(insert->k.p, bkey_start_pos(k.k)) <= 0) + if (bkey_cmp(bkey_start_pos(k.k), *end) >= 0) break; - nr_alloc_ptrs += bch2_bkey_nr_alloc_ptrs(k); + if (bkey_cmp(bkey_start_pos(&insert->k), + bkey_start_pos(k.k)) > 0) + offset = bkey_start_offset(&insert->k) - + bkey_start_offset(k.k); - if (nr_alloc_ptrs > 20) { - BUG_ON(bkey_cmp(k.k->p, bkey_start_pos(&insert->k)) <= 0); - return bpos_min(insert->k.p, k.k->p); - } + ret = __bch2_extent_atomic_end(trans, k, offset, + end, &nr_iters, 20); + if (ret) + return ret; + + if (nr_iters >= 20) + break; bch2_btree_node_iter_advance(&node_iter, b); } - return bpos_min(insert->k.p, b->key.k.p); + return 0; } -void bch2_extent_trim_atomic(struct bkey_i *k, struct btree_iter *iter) +int bch2_extent_trim_atomic(struct bkey_i *k, struct btree_iter *iter) { - bch2_cut_back(bch2_extent_atomic_end(k, iter), &k->k); + struct bpos end; + int ret; + + ret = bch2_extent_atomic_end(iter->trans, iter, k, &end); + if (ret) + return ret; + + bch2_cut_back(end, &k->k); + return 0; } -bool bch2_extent_is_atomic(struct bkey_i *k, struct btree_iter *iter) +int bch2_extent_is_atomic(struct bkey_i *k, struct btree_iter *iter) { - return !bkey_cmp(bch2_extent_atomic_end(k, iter), k->k.p); + struct bpos end; + int ret; + + ret = bch2_extent_atomic_end(iter->trans, iter, k, &end); + if (ret) + return ret; + + return !bkey_cmp(end, k->k.p); } enum btree_insert_ret diff --git a/fs/bcachefs/extents.h b/fs/bcachefs/extents.h index 035d15bbca39..156d8e37045a 100644 --- a/fs/bcachefs/extents.h +++ b/fs/bcachefs/extents.h @@ -425,8 +425,10 @@ enum merge_result bch2_reservation_merge(struct bch_fs *, .key_merge = bch2_reservation_merge, \ } -void bch2_extent_trim_atomic(struct bkey_i *, struct btree_iter *); -bool bch2_extent_is_atomic(struct bkey_i *, struct btree_iter *); +int bch2_extent_atomic_end(struct btree_trans *, struct btree_iter *, + struct bkey_i *, struct bpos *); +int bch2_extent_trim_atomic(struct bkey_i *, struct btree_iter *); +int bch2_extent_is_atomic(struct bkey_i *, struct btree_iter *); enum btree_insert_ret bch2_extent_can_insert(struct btree_trans *, struct btree_insert_entry *, diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 91a34ca5e4e1..ef94aecaa7cb 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -310,7 +310,9 @@ int bch2_extent_update(struct btree_trans *trans, if (ret) return ret; - bch2_extent_trim_atomic(k, extent_iter); + ret = bch2_extent_trim_atomic(k, extent_iter); + if (ret) + return ret; ret = sum_sector_overwrites(trans, extent_iter, k, &allocating, @@ -2634,7 +2636,9 @@ static long bch2_fcollapse(struct bch_inode_info *inode, bch2_cut_front(src->pos, ©.k); copy.k.k.p.offset -= len >> 9; - bch2_extent_trim_atomic(©.k, dst); + ret = bch2_extent_trim_atomic(©.k, dst); + if (ret) + goto bkey_err; BUG_ON(bkey_cmp(dst->pos, bkey_start_pos(©.k.k))); diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index fd1aceea3553..ed84572a9e67 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -274,6 +274,8 @@ int bch2_write_index_default(struct bch_write_op *op) bch2_verify_keylist_sorted(keys); bch2_trans_init(&trans, c, BTREE_ITER_MAX, 256); +retry: + bch2_trans_begin(&trans); iter = bch2_trans_get_iter(&trans, BTREE_ID_EXTENTS, bkey_start_pos(&bch2_keylist_front(keys)->k), @@ -284,7 +286,9 @@ int bch2_write_index_default(struct bch_write_op *op) bkey_copy(&split.k, bch2_keylist_front(keys)); - bch2_extent_trim_atomic(&split.k, iter); + ret = bch2_extent_trim_atomic(&split.k, iter); + if (ret) + break; bch2_trans_update(&trans, BTREE_INSERT_ENTRY(iter, &split.k)); @@ -301,6 +305,11 @@ int bch2_write_index_default(struct bch_write_op *op) bch2_keylist_pop_front(keys); } while (!bch2_keylist_empty(keys)); + if (ret == -EINTR) { + ret = 0; + goto retry; + } + bch2_trans_exit(&trans); return ret; diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index a7fc3fe4284a..3742b241807c 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -247,6 +247,7 @@ static int bch2_extent_replay_key(struct bch_fs *c, struct bkey_i *k) struct disk_reservation disk_res = bch2_disk_reservation_init(c, 0); struct bkey_i *split; + struct bpos atomic_end; bool split_compressed = false; int ret; @@ -273,9 +274,14 @@ retry: if (ret) goto err; + ret = bch2_extent_atomic_end(&trans, split_iter, + k, &atomic_end); + if (ret) + goto err; + if (!split_compressed && bch2_extent_is_compressed(bkey_i_to_s_c(k)) && - !bch2_extent_is_atomic(k, split_iter)) { + bkey_cmp(atomic_end, k->k.p) < 0) { ret = bch2_disk_reservation_add(c, &disk_res, k->k.size * bch2_bkey_nr_dirty_ptrs(bkey_i_to_s_c(k)), @@ -287,7 +293,7 @@ retry: bkey_copy(split, k); bch2_cut_front(split_iter->pos, split); - bch2_extent_trim_atomic(split, split_iter); + bch2_cut_back(atomic_end, &split->k); bch2_trans_update(&trans, BTREE_INSERT_ENTRY(split_iter, split)); bch2_btree_iter_set_pos(iter, split->k.p); |