summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-02-02 23:31:00 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:35:22 -0800
commit0b0830f979701f504e96d10f551c9ce682d18af9 (patch)
treef4009ccc5644d6e5c463218f0e94c2b21d76499e
parentd1c5d6a6eae0ab473ccdd5f2a84232c1e80711e1 (diff)
bcache: fix a bug with extent merging
-rw-r--r--drivers/md/bcache/bset.c27
-rw-r--r--drivers/md/bcache/btree_update.c4
2 files changed, 12 insertions, 19 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 016066899954..161bb5cddc68 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -856,6 +856,8 @@ static void bch_bset_fix_lookup_table(struct btree_keys *b,
*
* Attempts front and back merges (if @b has a method for key merging).
*
+ * NOTE: after calling @insert may be modified and is undefined
+ *
* @iter is used as a hint for where to insert at, but it's not
* fixed/revalidated for the insertion, that's the caller's responsibility
* (because there may be other iterators to fix, it's easier to just do all of
@@ -880,7 +882,6 @@ struct bkey_packed *bch_bset_insert(struct btree_keys *b,
struct bkey_packed *where = bch_btree_node_iter_bset_pos(iter, b, i) ?:
bset_bkey_last(i);
struct bkey_packed packed, *src;
- BKEY_PADDED(k) tmp;
BUG_ON(bset_written(t));
BUG_ON(insert->k.u64s < BKEY_U64s);
@@ -902,6 +903,10 @@ struct bkey_packed *bch_bset_insert(struct btree_keys *b,
verify_insert_pos(b, prev, where, insert);
+ /*
+ * note: bch_bkey_try_merge_inline() may modify either argument
+ */
+
/* prev is in the tree, if we merge we're done */
if (prev &&
bch_bkey_try_merge_inline(b, iter, prev,
@@ -909,22 +914,10 @@ struct bkey_packed *bch_bset_insert(struct btree_keys *b,
return NULL;
if (where != bset_bkey_last(i) &&
- bkey_bytes(&insert->k) <= sizeof(tmp)) {
- bkey_copy(&tmp.k, insert);
- insert = &tmp.k;
-
- /*
- * bch_bkey_try_merge() modifies the left argument, but we can't
- * modify insert since the caller needs to be able to journal
- * the key that was actually inserted (and it can't just pass us
- * a copy of insert, since ->insert_fixup() might trim insert if
- * this is a replace operation)
- */
- if (bch_bkey_try_merge_inline(b, iter,
- bkey_to_packed(insert),
- where, false))
- return NULL;
- }
+ bch_bkey_try_merge_inline(b, iter,
+ bkey_to_packed(insert),
+ where, false))
+ return NULL;
/*
* Can we overwrite the current key, instead of doing a memmove()?
diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c
index d49ddc24d475..0136601841e8 100644
--- a/drivers/md/bcache/btree_update.c
+++ b/drivers/md/bcache/btree_update.c
@@ -694,8 +694,6 @@ void bch_btree_insert_and_journal(struct btree_iter *iter,
BUG_ON(b->level);
- bch_btree_bset_insert(iter, b, node_iter, insert);
-
if (!btree_node_dirty(b)) {
set_btree_node_dirty(b);
@@ -722,6 +720,8 @@ void bch_btree_insert_and_journal(struct btree_iter *iter,
insert, b->level);
btree_bset_last(b)->journal_seq = cpu_to_le64(c->journal.seq);
}
+
+ bch_btree_bset_insert(iter, b, node_iter, insert);
}
/**