diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-07-21 19:05:06 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-03-06 15:27:04 -0500 |
commit | f5c4fdcf94802ca3ee6a572b8952741c221ed0bb (patch) | |
tree | 397b461595a2b5ab0e7950ea8ac0e82f4406ad07 | |
parent | c5941502b2750dd8f138faa8e7f23ee1910bea5d (diff) |
bcache: lift restrictions on 0 size extents
-rw-r--r-- | fs/bcachefs/bset.c | 100 | ||||
-rw-r--r-- | fs/bcachefs/bset.h | 52 | ||||
-rw-r--r-- | fs/bcachefs/btree_gc.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.h | 9 | ||||
-rw-r--r-- | fs/bcachefs/btree_iter.c | 8 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_interior.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/extents.c | 243 |
9 files changed, 96 insertions, 333 deletions
diff --git a/fs/bcachefs/bset.c b/fs/bcachefs/bset.c index 92046ae4915c..95a2c52cfd8c 100644 --- a/fs/bcachefs/bset.c +++ b/fs/bcachefs/bset.c @@ -120,20 +120,6 @@ void bch2_dump_btree_node_iter(struct btree *b, #ifdef CONFIG_BCACHEFS_DEBUG -static bool keys_out_of_order(struct btree *b, - const struct bkey_packed *prev, - const struct bkey_packed *next, - bool is_extents) -{ - struct bkey nextu = bkey_unpack_key(b, next); - - return bkey_cmp_left_packed_byval(b, prev, bkey_start_pos(&nextu)) > 0 || - ((is_extents - ? !bkey_deleted(next) - : !bkey_deleted(prev)) && - !bkey_cmp_packed(b, prev, next)); -} - void __bch2_verify_btree_nr_keys(struct btree *b) { struct bset_tree *t; @@ -159,7 +145,7 @@ static void bch2_btree_node_iter_next_check(struct btree_node_iter *iter, bkey_unpack_key(b, k); if (n && - keys_out_of_order(b, k, n, iter->is_extents)) { + __btree_node_iter_cmp(b, k, n) > 0) { struct bkey ku = bkey_unpack_key(b, k); struct bkey nu = bkey_unpack_key(b, n); char buf1[80], buf2[80]; @@ -189,7 +175,7 @@ void bch2_btree_node_iter_verify(struct btree_node_iter *iter, btree_bkey_last(b, t)); BUG_ON(prev && - btree_node_iter_cmp(iter, b, *prev, *set) > 0); + btree_node_iter_cmp(b, *prev, *set) > 0); prev = set; } @@ -200,65 +186,40 @@ void bch2_btree_node_iter_verify(struct btree_node_iter *iter, if (bch2_btree_node_iter_bset_pos(iter, b, t) == btree_bkey_last(b, t) && (k = bch2_bkey_prev_all(b, t, btree_bkey_last(b, t)))) - BUG_ON(__btree_node_iter_cmp(iter->is_extents, b, - k, first) > 0); + BUG_ON(__btree_node_iter_cmp(b, k, first) > 0); } void bch2_verify_key_order(struct btree *b, - struct btree_node_iter *iter, - struct bkey_packed *where) + struct btree_node_iter *_iter, + struct bkey_packed *where) { + struct btree_node_iter iter = *_iter; struct bset_tree *t = bch2_bkey_to_bset(b, where); - struct bkey_packed *k, *prev; + struct bkey_packed *k; struct bkey uk, uw = bkey_unpack_key(b, where); k = bch2_bkey_prev_all(b, t, where); - if (k && - keys_out_of_order(b, k, where, iter->is_extents)) { - char buf1[100], buf2[100]; - - bch2_dump_btree_node(b); - uk = bkey_unpack_key(b, k); - bch2_bkey_to_text(buf1, sizeof(buf1), &uk); - bch2_bkey_to_text(buf2, sizeof(buf2), &uw); - panic("out of order with prev:\n%s\n%s\n", - buf1, buf2); - } + BUG_ON(k && + __btree_node_iter_cmp(b, k, where) > 0); k = bkey_next(where); BUG_ON(k != btree_bkey_last(b, t) && - keys_out_of_order(b, where, k, iter->is_extents)); + __btree_node_iter_cmp(b, where, k) > 0); - for_each_bset(b, t) { - if (where >= btree_bkey_first(b, t) || - where < btree_bkey_last(b, t)) - continue; - - k = bch2_btree_node_iter_bset_pos(iter, b, t); - - if (k == btree_bkey_last(b, t)) - k = bch2_bkey_prev_all(b, t, k); + if (btree_node_is_extents(b)) { + do { + k = bch2_btree_node_iter_prev_all(&iter, b); + } while (k && bkey_deleted(k)); - while (bkey_cmp_left_packed_byval(b, k, bkey_start_pos(&uw)) > 0 && - (prev = bch2_bkey_prev_all(b, t, k))) - k = prev; + BUG_ON(k && (uk = bkey_unpack_key(b, k), + bkey_cmp(uk.p, bkey_start_pos(&uw)) > 0)); - for (; - k != btree_bkey_last(b, t); - k = bkey_next(k)) { - uk = bkey_unpack_key(b, k); + iter = *_iter; + bch2_btree_node_iter_advance(&iter, b); + k = bch2_btree_node_iter_peek(&iter, b); - if (iter->is_extents) { - BUG_ON(!(bkey_cmp(uw.p, bkey_start_pos(&uk)) <= 0 || - bkey_cmp(uk.p, bkey_start_pos(&uw)) <= 0)); - } else { - BUG_ON(!bkey_cmp(uw.p, uk.p) && - !bkey_deleted(&uk)); - } - - if (bkey_cmp(uw.p, bkey_start_pos(&uk)) <= 0) - break; - } + BUG_ON(k && (uk = bkey_unpack_key(b, k), + bkey_cmp(uw.p, bkey_start_pos(&uk)) > 0)); } } @@ -1264,7 +1225,6 @@ void bch2_bset_insert(struct btree *b, bch2_bset_fix_lookup_table(b, t, where, clobber_u64s, src->u64s); - bch2_verify_key_order(b, iter, where); bch2_verify_btree_nr_keys(b); } @@ -1470,7 +1430,7 @@ void bch2_btree_node_iter_push(struct btree_node_iter *iter, noinline __flatten __attribute__((cold)) static void btree_node_iter_init_pack_failed(struct btree_node_iter *iter, struct btree *b, struct bpos search, - bool strictly_greater, bool is_extents) + bool strictly_greater) { struct bset_tree *t; @@ -1527,7 +1487,7 @@ static void btree_node_iter_init_pack_failed(struct btree_node_iter *iter, */ void bch2_btree_node_iter_init(struct btree_node_iter *iter, struct btree *b, struct bpos search, - bool strictly_greater, bool is_extents) + bool strictly_greater) { struct bset_tree *t; struct bkey_packed p, *packed_search = NULL; @@ -1535,7 +1495,7 @@ void bch2_btree_node_iter_init(struct btree_node_iter *iter, EBUG_ON(bkey_cmp(search, b->data->min_key) < 0); bset_aux_tree_verify(b); - __bch2_btree_node_iter_init(iter, is_extents); + memset(iter, 0, sizeof(*iter)); switch (bch2_bkey_pack_pos_lossy(&p, search, b)) { case BKEY_PACK_POS_EXACT: @@ -1546,7 +1506,7 @@ void bch2_btree_node_iter_init(struct btree_node_iter *iter, break; case BKEY_PACK_POS_FAIL: btree_node_iter_init_pack_failed(iter, b, search, - strictly_greater, is_extents); + strictly_greater); return; } @@ -1561,12 +1521,11 @@ void bch2_btree_node_iter_init(struct btree_node_iter *iter, } void bch2_btree_node_iter_init_from_start(struct btree_node_iter *iter, - struct btree *b, - bool is_extents) + struct btree *b) { struct bset_tree *t; - __bch2_btree_node_iter_init(iter, is_extents); + memset(iter, 0, sizeof(*iter)); for_each_bset(b, t) __bch2_btree_node_iter_push(iter, b, @@ -1594,7 +1553,7 @@ static inline bool btree_node_iter_sort_two(struct btree_node_iter *iter, { bool ret; - if ((ret = (btree_node_iter_cmp(iter, b, + if ((ret = (btree_node_iter_cmp(b, iter->data[first], iter->data[first + 1]) > 0))) swap(iter->data[first], iter->data[first + 1]); @@ -1696,8 +1655,7 @@ struct bkey_packed *bch2_btree_node_iter_prev_all(struct btree_node_iter *iter, k = bch2_bkey_prev_all(b, t, bch2_btree_node_iter_bset_pos(iter, b, t)); if (k && - (!prev || __btree_node_iter_cmp(iter->is_extents, b, - k, prev) > 0)) { + (!prev || __btree_node_iter_cmp(b, k, prev) > 0)) { prev = k; prev_t = t; } diff --git a/fs/bcachefs/bset.h b/fs/bcachefs/bset.h index cc4ea5d87e4b..6ebfebf78ae0 100644 --- a/fs/bcachefs/bset.h +++ b/fs/bcachefs/bset.h @@ -421,27 +421,18 @@ static inline enum bch_extent_overlap bch2_extent_overlap(const struct bkey *k, /* Btree key iteration */ struct btree_node_iter { - u8 is_extents; - struct btree_node_iter_set { u16 k, end; } data[MAX_BSETS]; }; -static inline void __bch2_btree_node_iter_init(struct btree_node_iter *iter, - bool is_extents) -{ - iter->is_extents = is_extents; - memset(iter->data, 0, sizeof(iter->data)); -} - void bch2_btree_node_iter_push(struct btree_node_iter *, struct btree *, const struct bkey_packed *, const struct bkey_packed *); void bch2_btree_node_iter_init(struct btree_node_iter *, struct btree *, - struct bpos, bool, bool); + struct bpos, bool); void bch2_btree_node_iter_init_from_start(struct btree_node_iter *, - struct btree *, bool); + struct btree *); struct bkey_packed *bch2_btree_node_iter_bset_pos(struct btree_node_iter *, struct btree *, struct bset_tree *); @@ -468,30 +459,20 @@ static inline bool bch2_btree_node_iter_end(struct btree_node_iter *iter) return __btree_node_iter_set_end(iter, 0); } -static inline int __btree_node_iter_cmp(bool is_extents, - struct btree *b, - struct bkey_packed *l, - struct bkey_packed *r) +static inline int __btree_node_iter_cmp(struct btree *b, + const struct bkey_packed *l, + const struct bkey_packed *r) { - /* - * For non extents, when keys compare equal the deleted keys have to - * come first - so that bch2_btree_node_iter_next_check() can detect - * duplicate nondeleted keys (and possibly other reasons?) - * - * For extents, bkey_deleted() is used as a proxy for k->size == 0, so - * deleted keys have to sort last. - */ - return bkey_cmp_packed(b, l, r) ?: is_extents - ? (int) bkey_deleted(l) - (int) bkey_deleted(r) - : (int) bkey_deleted(r) - (int) bkey_deleted(l); + /* When keys compare equal deleted keys come first */ + return bkey_cmp_packed(b, l, r) ?: + (int) bkey_deleted(r) - (int) bkey_deleted(l); } -static inline int btree_node_iter_cmp(struct btree_node_iter *iter, - struct btree *b, +static inline int btree_node_iter_cmp(struct btree *b, struct btree_node_iter_set l, struct btree_node_iter_set r) { - return __btree_node_iter_cmp(iter->is_extents, b, + return __btree_node_iter_cmp(b, __btree_node_offset_to_key(b, l.k), __btree_node_offset_to_key(b, r.k)); } @@ -559,21 +540,12 @@ struct bkey_packed *bch2_btree_node_iter_prev_all(struct btree_node_iter *, struct bkey_packed *bch2_btree_node_iter_prev(struct btree_node_iter *, struct btree *); -/* - * Iterates over all _live_ keys - skipping deleted (and potentially - * overlapping) keys - */ -#define for_each_btree_node_key(b, k, iter, _is_extents) \ - for (bch2_btree_node_iter_init_from_start((iter), (b), (_is_extents));\ - ((k) = bch2_btree_node_iter_peek(iter, b)); \ - bch2_btree_node_iter_advance(iter, b)) - struct bkey_s_c bch2_btree_node_iter_peek_unpack(struct btree_node_iter *, struct btree *, struct bkey *); -#define for_each_btree_node_key_unpack(b, k, iter, _is_extents, unpacked)\ - for (bch2_btree_node_iter_init_from_start((iter), (b), (_is_extents));\ +#define for_each_btree_node_key_unpack(b, k, iter, unpacked) \ + for (bch2_btree_node_iter_init_from_start((iter), (b)); \ (k = bch2_btree_node_iter_peek_unpack((iter), (b), (unpacked))).k;\ bch2_btree_node_iter_advance(iter, b)) diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index f2e9c10e4efe..de47a7eb6449 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -214,7 +214,6 @@ static unsigned btree_gc_mark_node(struct bch_fs *c, struct btree *b) if (btree_node_has_ptrs(b)) for_each_btree_node_key_unpack(b, k, &iter, - btree_node_is_extents(b), &unpacked) { bch2_bkey_debugcheck(c, b, k); stale = max(stale, bch2_gc_mark_key(c, type, k, 0)); @@ -1012,7 +1011,6 @@ static int bch2_initial_gc_btree(struct bch_fs *c, enum btree_id id) struct bkey_s_c k; for_each_btree_node_key_unpack(b, k, &node_iter, - btree_node_is_extents(b), &unpacked) { ret = bch2_btree_mark_key_initial(c, btree_node_type(b), k); diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 0525c3b87f95..b72673294308 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -21,7 +21,7 @@ /* btree_node_iter_large: */ #define btree_node_iter_cmp_heap(h, _l, _r) \ - __btree_node_iter_cmp((iter)->is_extents, b, \ + __btree_node_iter_cmp(b, \ __btree_node_offset_to_key(b, (_l).k), \ __btree_node_offset_to_key(b, (_r).k)) @@ -783,8 +783,7 @@ void bch2_btree_sort_into(struct bch_fs *c, bch2_bset_set_no_aux_tree(dst, dst->set); - bch2_btree_node_iter_init_from_start(&src_iter, src, - btree_node_is_extents(src)); + bch2_btree_node_iter_init_from_start(&src_iter, src); if (btree_node_ops(src)->key_normalize || btree_node_ops(src)->key_merge) @@ -1154,7 +1153,7 @@ int bch2_btree_node_read_done(struct bch_fs *c, struct btree *b, bool have_retry int ret, retry_read = 0, write = READ; iter = mempool_alloc(&c->fill_iter, GFP_NOIO); - __bch2_btree_node_iter_large_init(iter, btree_node_is_extents(b)); + iter->used = 0; if (bch2_meta_read_fault("btree")) btree_err(BTREE_ERR_MUST_RETRY, c, b, NULL, diff --git a/fs/bcachefs/btree_io.h b/fs/bcachefs/btree_io.h index 01df817d3eeb..5b007ed5b376 100644 --- a/fs/bcachefs/btree_io.h +++ b/fs/bcachefs/btree_io.h @@ -145,20 +145,11 @@ ssize_t bch2_dirty_btree_nodes_print(struct bch_fs *, char *); /* Sorting */ struct btree_node_iter_large { - u8 is_extents; u16 used; struct btree_node_iter_set data[MAX_BSETS]; }; -static inline void -__bch2_btree_node_iter_large_init(struct btree_node_iter_large *iter, - bool is_extents) -{ - iter->used = 0; - iter->is_extents = is_extents; -} - void bch2_btree_node_iter_large_advance(struct btree_node_iter_large *, struct btree *); diff --git a/fs/bcachefs/btree_iter.c b/fs/bcachefs/btree_iter.c index c05014b0a9d8..735433b4f633 100644 --- a/fs/bcachefs/btree_iter.c +++ b/fs/bcachefs/btree_iter.c @@ -428,8 +428,7 @@ iter_current_key_not_modified: k = bch2_bkey_prev_all(b, t, bch2_btree_node_iter_bset_pos(node_iter, b, t)); if (k && - __btree_node_iter_cmp(node_iter, b, - k, where) > 0) { + __btree_node_iter_cmp(b, k, where) > 0) { struct btree_node_iter_set *set; unsigned offset = __btree_node_key_to_offset(b, bkey_next(k)); @@ -474,6 +473,8 @@ void bch2_btree_node_iter_fix(struct btree_iter *iter, &linked->l[b->level].iter, t, where, clobber_u64s, new_u64s); + bch2_verify_key_order(b, node_iter, where); + /* interior node iterators are... special... */ if (!b->level) bch2_btree_iter_verify(iter, b); @@ -594,8 +595,7 @@ static inline void __btree_iter_init(struct btree_iter *iter, struct btree_iter_level *l = &iter->l[b->level]; bch2_btree_node_iter_init(&l->iter, b, iter->pos, - iter->flags & BTREE_ITER_IS_EXTENTS, - btree_node_is_extents(b)); + iter->flags & BTREE_ITER_IS_EXTENTS); /* Skip to first non whiteout: */ if (b->level) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index f42239dab71c..4268722c5dbc 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -32,7 +32,7 @@ static void btree_node_interior_verify(struct btree *b) BUG_ON(!b->level); - bch2_btree_node_iter_init(&iter, b, b->key.k.p, false, false); + bch2_btree_node_iter_init(&iter, b, b->key.k.p, false); #if 1 BUG_ON(!(k = bch2_btree_node_iter_peek(&iter, b)) || bkey_cmp_left_packed(b, k, &b->key.k.p)); @@ -1320,7 +1320,7 @@ static void btree_split_insert_keys(struct btree_update *as, struct btree *b, BUG_ON(btree_node_type(b) != BKEY_TYPE_BTREE); - bch2_btree_node_iter_init(&node_iter, b, k->k.p, false, false); + bch2_btree_node_iter_init(&node_iter, b, k->k.p, false); while (!bch2_keylist_empty(keys)) { k = bch2_keylist_front(keys); diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 007aa5ef4091..852310de94d6 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -96,7 +96,9 @@ overwrite: bch2_bset_insert(b, node_iter, k, insert, clobber_u64s); if (k->u64s != clobber_u64s || bkey_whiteout(&insert->k)) bch2_btree_node_iter_fix(iter, b, node_iter, t, k, - clobber_u64s, k->u64s); + clobber_u64s, k->u64s); + else + bch2_verify_key_order(b, node_iter, k); return true; } diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index b7d969b1a1c7..be7623b08b28 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -847,30 +847,34 @@ void bch2_key_resize(struct bkey *k, * that we have to unpack the key, modify the unpacked key - then this * copies/repacks the unpacked to the original as necessary. */ -static bool __extent_save(struct btree *b, struct btree_node_iter *iter, - struct bkey_packed *dst, struct bkey *src) +static bool __extent_save(struct btree *b, struct bkey_packed *dst, + struct bkey *src) { struct bkey_format *f = &b->format; struct bkey_i *dst_unpacked; - bool ret; if ((dst_unpacked = packed_to_bkey(dst))) { dst_unpacked->k = *src; - ret = true; + return true; } else { - ret = bch2_bkey_pack_key(dst, src, f); + return bch2_bkey_pack_key(dst, src, f); } +} - if (ret && iter) - bch2_verify_key_order(b, iter, dst); - - return ret; +static void extent_save(struct btree *b, struct bkey_packed *dst, + struct bkey *src) +{ + BUG_ON(!__extent_save(b, dst, src)); } -static void extent_save(struct btree *b, struct btree_node_iter *iter, - struct bkey_packed *dst, struct bkey *src) +static bool extent_i_save(struct btree *b, struct bkey_packed *dst, + struct bkey_i *src) { - BUG_ON(!__extent_save(b, iter, dst, src)); + if (!__extent_save(b, dst, &src->k)) + return false; + + memcpy(bkeyp_val(&b->format, dst), &src->v, bkey_val_bytes(&src->k)); + return true; } /* @@ -999,7 +1003,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c, sort_key_next(iter, b, _r); } else { __bch2_cut_front(l.k->p, r); - extent_save(b, NULL, rk, r.k); + extent_save(b, rk, r.k); } extent_sort_sift(iter, b, _r - iter->data); @@ -1013,7 +1017,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c, bch2_cut_back(bkey_start_pos(r.k), &tmp.k.k); __bch2_cut_front(r.k->p, l); - extent_save(b, NULL, lk, l.k); + extent_save(b, lk, l.k); extent_sort_sift(iter, b, 0); @@ -1021,7 +1025,7 @@ struct btree_nr_keys bch2_extent_sort_fix_overlapping(struct bch_fs *c, bkey_to_packed(&tmp.k)); } else { bch2_cut_back(bkey_start_pos(r.k), l.k); - extent_save(b, NULL, lk, l.k); + extent_save(b, lk, l.k); } } @@ -1161,7 +1165,7 @@ static void extent_bset_insert(struct bch_fs *c, struct btree_iter *iter, bch2_bset_insert(l->b, &l->iter, where, insert, clobber_u64s); bch2_btree_node_iter_fix(iter, l->b, &l->iter, t, where, - clobber_u64s, where->u64s); + clobber_u64s, where->u64s); return; drop_deleted_keys: bch2_bset_delete(l->b, where, clobber_u64s); @@ -1317,21 +1321,21 @@ extent_squash(struct extent_insert_state *s, struct bkey_i *insert, struct btree_iter_level *l = &iter->l[0]; struct btree *b = l->b; struct btree_node_iter *node_iter = &l->iter; - enum btree_insert_ret ret; switch (overlap) { case BCH_EXTENT_OVERLAP_FRONT: /* insert overlaps with start of k: */ bch2_cut_subtract_front(s, insert->k.p, k); BUG_ON(bkey_deleted(k.k)); - extent_save(b, node_iter, _k, k.k); + extent_save(b, _k, k.k); + bch2_verify_key_order(b, node_iter, _k); break; case BCH_EXTENT_OVERLAP_BACK: /* insert overlaps with end of k: */ bch2_cut_subtract_back(s, bkey_start_pos(&insert->k), k); BUG_ON(bkey_deleted(k.k)); - extent_save(b, node_iter, _k, k.k); + extent_save(b, _k, k.k); /* * As the auxiliary tree is indexed by the end of the @@ -1340,47 +1344,18 @@ extent_squash(struct extent_insert_state *s, struct bkey_i *insert, */ bch2_bset_fix_invalidated_key(b, t, _k); bch2_btree_node_iter_fix(iter, b, node_iter, t, - _k, _k->u64s, _k->u64s); + _k, _k->u64s, _k->u64s); break; case BCH_EXTENT_OVERLAP_ALL: { - struct bpos orig_pos = k.k->p; - /* The insert key completely covers k, invalidate k */ if (!bkey_whiteout(k.k)) btree_keys_account_key_drop(&b->nr, t - b->set, _k); bch2_drop_subtract(s, k); - k.k->p = bkey_start_pos(&insert->k); - if (!__extent_save(b, node_iter, _k, k.k)) { - /* - * Couldn't repack: we aren't necessarily able - * to repack if the new key is outside the range - * of the old extent, so we have to split - * @insert: - */ - k.k->p = orig_pos; - extent_save(b, node_iter, _k, k.k); - - ret = extent_insert_advance_pos(s, k.s_c); - if (ret != BTREE_INSERT_OK) - return ret; - - extent_insert_committed(s); - /* - * We split and inserted upto at k.k->p - that - * has to coincide with iter->pos, so that we - * don't have anything more we have to insert - * until we recheck our journal reservation: - */ - EBUG_ON(bkey_cmp(s->committed, k.k->p)); - } else { - bch2_bset_fix_invalidated_key(b, t, _k); - bch2_btree_node_iter_fix(iter, b, node_iter, t, - _k, _k->u64s, _k->u64s); - } - + extent_save(b, _k, k.k); + bch2_verify_key_order(b, node_iter, _k); break; } case BCH_EXTENT_OVERLAP_MIDDLE: { @@ -1407,7 +1382,8 @@ extent_squash(struct extent_insert_state *s, struct bkey_i *insert, bch2_cut_subtract_front(s, insert->k.p, k); BUG_ON(bkey_deleted(k.k)); - extent_save(b, node_iter, _k, k.k); + extent_save(b, _k, k.k); + bch2_verify_key_order(b, node_iter, _k); bch2_add_sectors(s, bkey_i_to_s_c(&split.k), bkey_start_offset(&split.k.k), @@ -1448,6 +1424,11 @@ bch2_delete_fixup_extent(struct extent_insert_state *s) EBUG_ON(bkey_cmp(iter->pos, bkey_start_pos(&insert->k))); EBUG_ON(bkey_cmp(iter->pos, k.k->p) >= 0); + if (!k.k->size) { + bch2_btree_node_iter_advance(node_iter, b); + continue; + } + if (bkey_cmp(bkey_start_pos(k.k), insert->k.p) >= 0) break; @@ -1616,6 +1597,11 @@ bch2_insert_fixup_extent(struct btree_insert *trans, EBUG_ON(bkey_cmp(iter->pos, bkey_start_pos(&insert->k->k))); EBUG_ON(bkey_cmp(iter->pos, k.k->p) >= 0); + if (!k.k->size) { + bch2_btree_node_iter_advance(node_iter, b); + continue; + } + if (bkey_cmp(bkey_start_pos(k.k), insert->k->k.p) >= 0) break; @@ -1625,18 +1611,11 @@ bch2_insert_fixup_extent(struct btree_insert *trans, if (ret != BTREE_INSERT_OK) goto stop; - if (!k.k->size) - goto squash; - - /* - * Only call advance pos & call hook for nonzero size extents: - */ ret = extent_insert_advance_pos(&s, k.s_c); if (ret != BTREE_INSERT_OK) goto stop; - if (k.k->size && - (k.k->needs_whiteout || bset_written(b, bset(b, t)))) + if (k.k->needs_whiteout || bset_written(b, bset(b, t))) insert->k->k.needs_whiteout = true; if (overlap == BCH_EXTENT_OVERLAP_ALL && @@ -1645,7 +1624,7 @@ bch2_insert_fixup_extent(struct btree_insert *trans, unreserve_whiteout(b, t, _k); _k->needs_whiteout = false; } -squash: + ret = extent_squash(&s, insert->k, t, _k, k, overlap); if (ret != BTREE_INSERT_OK) goto stop; @@ -2157,130 +2136,6 @@ static enum merge_result bch2_extent_merge(struct bch_fs *c, return BCH_MERGE_MERGE; } -static void extent_i_save(struct btree *b, struct bkey_packed *dst, - struct bkey_i *src) -{ - struct bkey_format *f = &b->format; - struct bkey_i *dst_unpacked; - - BUG_ON(bkeyp_val_u64s(f, dst) != bkey_val_u64s(&src->k)); - - /* - * We don't want the bch2_verify_key_order() call in extent_save(), - * because we may be out of order with deleted keys that are about to be - * removed by extent_bset_insert() - */ - - if ((dst_unpacked = packed_to_bkey(dst))) - bkey_copy(dst_unpacked, src); - else - BUG_ON(!bch2_bkey_pack(dst, src, f)); -} - -static bool extent_merge_one_overlapping(struct btree_iter *iter, - struct bpos new_pos, - struct bset_tree *t, - struct bkey_packed *k, struct bkey uk, - bool check, bool could_pack) -{ - struct btree_iter_level *l = &iter->l[0]; - - BUG_ON(!bkey_deleted(k)); - - if (check) { - return !bkey_packed(k) || could_pack; - } else { - uk.p = new_pos; - extent_save(l->b, &l->iter, k, &uk); - bch2_bset_fix_invalidated_key(l->b, t, k); - bch2_btree_node_iter_fix(iter, l->b, &l->iter, t, - k, k->u64s, k->u64s); - return true; - } -} - -static bool extent_merge_do_overlapping(struct btree_iter *iter, - struct bkey *m, bool back_merge) -{ - struct btree_iter_level *l = &iter->l[0]; - struct btree *b = l->b; - struct btree_node_iter *node_iter = &l->iter; - struct bset_tree *t; - struct bkey_packed *k; - struct bkey uk; - struct bpos new_pos = back_merge ? m->p : bkey_start_pos(m); - bool could_pack = bkey_pack_pos((void *) &uk, new_pos, b); - bool check = true; - - /* - * @m is the new merged extent: - * - * The merge took place in the last bset; we know there can't be any 0 - * size extents overlapping with m there because if so they would have - * been between the two extents we merged. - * - * But in the other bsets, we have to check for and fix such extents: - */ -do_fixup: - for_each_bset(b, t) { - if (t == bset_tree_last(b)) - break; - - /* - * if we don't find this bset in the iterator we already got to - * the end of that bset, so start searching from the end. - */ - k = bch2_btree_node_iter_bset_pos(node_iter, b, t); - - if (k == btree_bkey_last(b, t)) - k = bch2_bkey_prev_all(b, t, k); - if (!k) - continue; - - if (back_merge) { - /* - * Back merge: 0 size extents will be before the key - * that was just inserted (and thus the iterator - * position) - walk backwards to find them - */ - for (; - k && - (uk = bkey_unpack_key(b, k), - bkey_cmp(uk.p, bkey_start_pos(m)) > 0); - k = bch2_bkey_prev_all(b, t, k)) { - if (bkey_cmp(uk.p, m->p) >= 0) - continue; - - if (!extent_merge_one_overlapping(iter, new_pos, - t, k, uk, check, could_pack)) - return false; - } - } else { - /* Front merge - walk forwards */ - for (; - k != btree_bkey_last(b, t) && - (uk = bkey_unpack_key(b, k), - bkey_cmp(uk.p, m->p) < 0); - k = bkey_next(k)) { - if (bkey_cmp(uk.p, - bkey_start_pos(m)) <= 0) - continue; - - if (!extent_merge_one_overlapping(iter, new_pos, - t, k, uk, check, could_pack)) - return false; - } - } - } - - if (check) { - check = false; - goto do_fixup; - } - - return true; -} - /* * When merging an extent that we're inserting into a btree node, the new merged * extent could overlap with an existing 0 size extent - if we don't fix that, @@ -2297,13 +2152,11 @@ static bool bch2_extent_merge_inline(struct bch_fs *c, { struct btree *b = iter->l[0].b; struct btree_node_iter *node_iter = &iter->l[0].iter; - const struct bkey_format *f = &b->format; struct bset_tree *t = bset_tree_last(b); struct bkey_packed *m; BKEY_PADDED(k) li; BKEY_PADDED(k) ri; struct bkey_i *mi; - struct bkey tmp; /* * We need to save copies of both l and r, because we might get a @@ -2322,15 +2175,9 @@ static bool bch2_extent_merge_inline(struct bch_fs *c, case BCH_MERGE_NOMERGE: return false; case BCH_MERGE_PARTIAL: - if (bkey_packed(m) && !bch2_bkey_pack_key((void *) &tmp, &mi->k, f)) + if (!extent_i_save(b, m, mi)) return false; - if (!extent_merge_do_overlapping(iter, &li.k.k, back_merge)) - return false; - - extent_i_save(b, m, mi); - bch2_bset_fix_invalidated_key(b, t, m); - /* * Update iterator to reflect what we just inserted - otherwise, * the iter_fix() call is going to put us _before_ the key we @@ -2339,6 +2186,7 @@ static bool bch2_extent_merge_inline(struct bch_fs *c, if (back_merge) bch2_btree_iter_set_pos_same_leaf(iter, li.k.k.p); + bch2_bset_fix_invalidated_key(b, t, m); bch2_btree_node_iter_fix(iter, b, node_iter, t, m, m->u64s, m->u64s); @@ -2348,15 +2196,10 @@ static bool bch2_extent_merge_inline(struct bch_fs *c, bkey_copy(packed_to_bkey(r), &ri.k); return false; case BCH_MERGE_MERGE: - if (bkey_packed(m) && !bch2_bkey_pack_key((void *) &tmp, &li.k.k, f)) + if (!extent_i_save(b, m, &li.k)) return false; - if (!extent_merge_do_overlapping(iter, &li.k.k, back_merge)) - return false; - - extent_i_save(b, m, &li.k); bch2_bset_fix_invalidated_key(b, t, m); - bch2_btree_node_iter_fix(iter, b, node_iter, t, m, m->u64s, m->u64s); return true; |