diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2016-04-08 18:57:46 -0800 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2017-01-18 21:39:01 -0900 |
commit | b6d1d22adc830e78c68e23b3b7aa59439cf5c7d1 (patch) | |
tree | bda1e02845b025b9492fa17859738c368ec4b09a | |
parent | 3f7f1f1e782a41bf013311204aad9bed04460b2e (diff) |
bcache: fix bch_btree_node_iter_fix()
-rw-r--r-- | drivers/md/bcache/bset.c | 24 | ||||
-rw-r--r-- | drivers/md/bcache/bset.h | 2 | ||||
-rw-r--r-- | drivers/md/bcache/btree_iter.c | 23 | ||||
-rw-r--r-- | drivers/md/bcache/btree_iter.h | 3 | ||||
-rw-r--r-- | drivers/md/bcache/btree_update.c | 19 |
5 files changed, 38 insertions, 33 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c index 7569c4470755..c590320facaa 100644 --- a/drivers/md/bcache/bset.c +++ b/drivers/md/bcache/bset.c @@ -874,7 +874,8 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b, */ struct bkey_packed *bch_bset_insert(struct btree_keys *b, struct btree_node_iter *iter, - struct bkey_i *insert) + struct bkey_i *insert, + bool *overwrote) { struct bkey_format *f = &b->format; struct bset_tree *t = bset_tree_last(b); @@ -911,14 +912,18 @@ struct bkey_packed *bch_bset_insert(struct btree_keys *b, /* prev is in the tree, if we merge we're done */ if (prev && bch_bkey_try_merge_inline(b, iter, prev, - bkey_to_packed(insert), true)) - return NULL; + bkey_to_packed(insert), true)) { + *overwrote = true; + return prev; + } if (where != bset_bkey_last(i) && bch_bkey_try_merge_inline(b, iter, bkey_to_packed(insert), - where, false)) - return NULL; + where, false)) { + *overwrote = true; + return where; + } /* * Can we overwrite the current key, instead of doing a memmove()? @@ -968,8 +973,9 @@ struct bkey_packed *bch_bset_insert(struct btree_keys *b, btree_keys_account_key_add(&b->nr, src); bch_bset_fix_lookup_table(b, t, where); - bch_verify_btree_nr_keys(b); + bch_verify_btree_nr_keys(b); + *overwrote = false; return where; overwrite: if (!bkey_deleted(where)) @@ -982,9 +988,11 @@ overwrite: if (!bkey_deleted(src)) btree_keys_account_key_add(&b->nr, src); - return NULL; + + bch_verify_btree_nr_keys(b); + *overwrote = true; + return where; } -EXPORT_SYMBOL(bch_bset_insert); /* Lookup */ diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h index 7fa94acd6005..a38f20df2d10 100644 --- a/drivers/md/bcache/bset.h +++ b/drivers/md/bcache/bset.h @@ -326,7 +326,7 @@ void bch_bset_fix_invalidated_key(struct btree_keys *, struct bkey_packed *); struct bkey_packed *bch_bset_insert(struct btree_keys *, struct btree_node_iter *, - struct bkey_i *); + struct bkey_i *, bool *); static inline void btree_keys_account_key(struct btree_nr_keys *n, struct bkey_packed *k, diff --git a/drivers/md/bcache/btree_iter.c b/drivers/md/bcache/btree_iter.c index ad37ce80cc50..8b2636541959 100644 --- a/drivers/md/bcache/btree_iter.c +++ b/drivers/md/bcache/btree_iter.c @@ -166,15 +166,18 @@ static bool btree_iter_cmp(struct btree_iter *iter, void bch_btree_node_iter_fix(struct btree_iter *iter, struct btree_keys *b, struct btree_node_iter *node_iter, - struct bkey_packed *where) + struct bkey_packed *where, + bool overwrote) { struct bkey_format *f = &b->format; struct bset *i = bset_tree_last(b)->data; const struct bkey_packed *end = bset_bkey_last(i); struct btree_node_iter_set *set; - unsigned shift = where->u64s; + unsigned shift = overwrote ? 0 : where->u64s; unsigned offset = __btree_node_key_to_offset(b, where); unsigned old_end = __btree_node_key_to_offset(b, end) - shift; + bool iter_pos_before_new = btree_iter_cmp(iter, iter->pos, + bkey_unpack_key(f, where).p); BUG_ON(node_iter->used > MAX_BSETS); @@ -184,18 +187,18 @@ void bch_btree_node_iter_fix(struct btree_iter *iter, if (set->end == old_end) { set->end += shift; - if (set->k > offset || - (set->k == offset && - !btree_iter_cmp(iter, iter->pos, - bkey_unpack_key(f, where).p))) - set->k += shift; - bch_btree_node_iter_sort(node_iter, b); + if (set->k >= offset) { + if (iter_pos_before_new) + set->k = offset; + else + set->k += shift; + bch_btree_node_iter_sort(node_iter, b); + } return; } /* didn't find the bset in the iterator - might have to readd it: */ - - if (btree_iter_cmp(iter, iter->pos, bkey_unpack_key(f, where).p)) + if (iter_pos_before_new) bch_btree_node_iter_push(node_iter, b, where, end); } diff --git a/drivers/md/bcache/btree_iter.h b/drivers/md/bcache/btree_iter.h index f084735dac31..1d0186af5000 100644 --- a/drivers/md/bcache/btree_iter.h +++ b/drivers/md/bcache/btree_iter.h @@ -111,7 +111,8 @@ __next_linked_btree_node(struct btree_iter *iter, struct btree *b, ((_linked) = __next_linked_btree_node(_iter, _b, _linked));) void bch_btree_node_iter_fix(struct btree_iter *, struct btree_keys *, - struct btree_node_iter *, struct bkey_packed *); + struct btree_node_iter *, struct bkey_packed *, + bool overwrote); bool bch_btree_iter_upgrade(struct btree_iter *); int bch_btree_iter_unlock(struct btree_iter *); diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c index 215be17b62b9..c71285b6d223 100644 --- a/drivers/md/bcache/btree_update.c +++ b/drivers/md/bcache/btree_update.c @@ -657,6 +657,7 @@ void bch_btree_bset_insert(struct btree_iter *iter, { struct btree_iter *linked; struct bkey_packed *where; + bool overwrote; EBUG_ON(bkey_deleted(&insert->k) && bkey_val_u64s(&insert->k)); EBUG_ON(insert->k.u64s > bch_btree_keys_u64s_remaining(iter->c, b)); @@ -670,22 +671,14 @@ void bch_btree_bset_insert(struct btree_iter *iter, * though. */ - where = bch_bset_insert(&b->keys, node_iter, insert); + where = bch_bset_insert(&b->keys, node_iter, insert, &overwrote); - if (where) { - bch_btree_node_iter_fix(iter, &b->keys, node_iter, where); + bch_btree_node_iter_fix(iter, &b->keys, node_iter, where, overwrote); - for_each_linked_btree_node(iter, b, linked) - bch_btree_node_iter_fix(linked, &b->keys, + for_each_linked_btree_node(iter, b, linked) + bch_btree_node_iter_fix(linked, &b->keys, &linked->node_iters[b->level], - where); - } else { - bch_btree_node_iter_sort(node_iter, &b->keys); - - for_each_linked_btree_node(iter, b, linked) - bch_btree_node_iter_sort(&linked->node_iters[b->level], - &b->keys); - } + where, overwrote); bch_btree_node_iter_verify(node_iter, &b->keys); |