summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-07-21 19:05:06 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2018-03-06 15:27:04 -0500
commitf5c4fdcf94802ca3ee6a572b8952741c221ed0bb (patch)
tree397b461595a2b5ab0e7950ea8ac0e82f4406ad07
parentc5941502b2750dd8f138faa8e7f23ee1910bea5d (diff)
bcache: lift restrictions on 0 size extents
-rw-r--r--fs/bcachefs/bset.c100
-rw-r--r--fs/bcachefs/bset.h52
-rw-r--r--fs/bcachefs/btree_gc.c2
-rw-r--r--fs/bcachefs/btree_io.c7
-rw-r--r--fs/bcachefs/btree_io.h9
-rw-r--r--fs/bcachefs/btree_iter.c8
-rw-r--r--fs/bcachefs/btree_update_interior.c4
-rw-r--r--fs/bcachefs/btree_update_leaf.c4
-rw-r--r--fs/bcachefs/extents.c243
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;