summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/md/bcache/bset.c24
-rw-r--r--drivers/md/bcache/bset.h2
-rw-r--r--drivers/md/bcache/btree_iter.c23
-rw-r--r--drivers/md/bcache/btree_iter.h3
-rw-r--r--drivers/md/bcache/btree_update.c19
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);