summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-11-17 07:34:59 -0900
committerKent Overstreet <kent.overstreet@gmail.com>2017-01-18 21:40:56 -0900
commit765c0735740c681e0bc44c103d6c9797bebc1135 (patch)
treeab127853cd639f627a11ab99acf21003bda9b932
parent486b6304937fb3f51fe3a36c5d1b3ae117bd0edd (diff)
bcache: ensure iterators for interior nodes never point to whiteouts
-rw-r--r--drivers/md/bcache/bset.c13
-rw-r--r--drivers/md/bcache/btree_iter.c69
-rw-r--r--drivers/md/bcache/btree_update.c10
3 files changed, 67 insertions, 25 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 83d3347c2159..c4bf087235c6 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -206,8 +206,17 @@ void bch_verify_key_order(struct btree_keys *b,
struct bkey uk, uw = bkey_unpack_key(f, where);
k = bkey_prev_all(t, where);
- BUG_ON(k &&
- keys_out_of_order(f, k, where, b->ops->is_extents));
+ if (k &&
+ keys_out_of_order(f, k, where, b->ops->is_extents)) {
+ char buf1[100], buf2[100];
+
+ bch_dump_bucket(b);
+ uk = bkey_unpack_key(f, k);
+ bch_bkey_to_text(buf1, sizeof(buf1), &uk);
+ bch_bkey_to_text(buf2, sizeof(buf2), &uw);
+ panic("out of order with prev:\n%s\n%s\n",
+ buf1, buf2);
+ }
k = bkey_next(where);
BUG_ON(k != bset_bkey_last(t->data) &&
diff --git a/drivers/md/bcache/btree_iter.c b/drivers/md/bcache/btree_iter.c
index 0a9c2487fa7a..a0d7a204b03c 100644
--- a/drivers/md/bcache/btree_iter.c
+++ b/drivers/md/bcache/btree_iter.c
@@ -303,12 +303,26 @@ static void __bch_btree_iter_verify(struct btree_iter *iter,
k = b->level
? bch_btree_node_iter_prev(&tmp, &b->keys)
: bch_btree_node_iter_prev_all(&tmp, &b->keys);
- BUG_ON(k && btree_iter_pos_cmp_packed(f, iter->pos, k,
- iter->is_extents));
+ if (k && btree_iter_pos_cmp_packed(f, iter->pos, k,
+ iter->is_extents)) {
+ char buf[100];
+ struct bkey uk = bkey_unpack_key(&b->keys.format, k);
+
+ bch_bkey_to_text(buf, sizeof(buf), &uk);
+ panic("prev key should be before after pos:\n%s\n%llu:%llu\n",
+ buf, iter->pos.inode, iter->pos.offset);
+ }
k = bch_btree_node_iter_peek_all(node_iter, &b->keys);
- BUG_ON(k && !btree_iter_pos_cmp_packed(f, iter->pos, k,
- iter->is_extents));
+ if (k && !btree_iter_pos_cmp_packed(f, iter->pos, k,
+ iter->is_extents)) {
+ char buf[100];
+ struct bkey uk = bkey_unpack_key(&b->keys.format, k);
+
+ bch_bkey_to_text(buf, sizeof(buf), &uk);
+ panic("next key should be before iter pos:\n%llu:%llu\n%s\n",
+ iter->pos.inode, iter->pos.offset, buf);
+ }
}
void bch_btree_iter_verify(struct btree_iter *iter, struct btree *b)
@@ -451,7 +465,10 @@ void bch_btree_node_iter_fix(struct btree_iter *iter,
__bch_btree_node_iter_fix(linked, b,
&linked->node_iters[b->level], t,
where, clobber_u64s, new_u64s);
- bch_btree_iter_verify(iter, b);
+
+ /* interior node iterators are... special... */
+ if (!b->level)
+ bch_btree_iter_verify(iter, b);
}
/* peek_all() doesn't skip deleted keys */
@@ -522,14 +539,33 @@ static void btree_iter_verify_new_node(struct btree_iter *iter, struct btree *b)
k = bch_btree_node_iter_peek_all(&iter->node_iters[b->level + 1],
&iter->nodes[b->level + 1]->keys);
- BUG_ON(!k ||
- bkey_cmp_left_packed(&iter->nodes[b->level + 1]->keys.format,
- k, b->key.k.p));
+ if (!k ||
+ bkey_deleted(k) ||
+ bkey_cmp_left_packed(&iter->nodes[b->level + 1]->keys.format,
+ k, b->key.k.p)) {
+ char buf[100];
+ struct bkey uk = bkey_unpack_key(&b->keys.format, k);
+
+ bch_bkey_to_text(buf, sizeof(buf), &uk);
+ panic("parent iter doesn't point to new node:\n%s\n%llu:%llu\n",
+ buf, b->key.k.p.inode, b->key.k.p.offset);
+ }
if (!parent_locked)
btree_node_unlock(iter, b->level + 1);
}
+static inline void __btree_iter_init(struct btree_iter *iter,
+ struct btree *b)
+{
+ bch_btree_node_iter_init(&iter->node_iters[b->level], &b->keys,
+ iter->pos, iter->is_extents);
+
+ /* Skip to first non whiteout: */
+ if (b->level)
+ bch_btree_node_iter_peek(&iter->node_iters[b->level], &b->keys);
+}
+
static inline void btree_iter_node_set(struct btree_iter *iter,
struct btree *b)
{
@@ -539,8 +575,7 @@ static inline void btree_iter_node_set(struct btree_iter *iter,
iter->lock_seq[b->level] = b->lock.state.seq;
iter->nodes[b->level] = b;
- bch_btree_node_iter_init(&iter->node_iters[b->level], &b->keys,
- iter->pos, iter->is_extents);
+ __btree_iter_init(iter, b);
}
static bool btree_iter_pos_in_node(struct btree_iter *iter, struct btree *b)
@@ -628,13 +663,8 @@ void bch_btree_iter_reinit_node(struct btree_iter *iter, struct btree *b)
struct btree_iter *linked;
for_each_linked_btree_node(iter, b, linked)
- bch_btree_node_iter_init(&linked->node_iters[b->level],
- &linked->nodes[b->level]->keys,
- linked->pos, linked->is_extents);
-
- bch_btree_node_iter_init(&iter->node_iters[b->level],
- &iter->nodes[b->level]->keys,
- iter->pos, iter->is_extents);
+ __btree_iter_init(linked, b);
+ __btree_iter_init(iter, b);
}
static inline int btree_iter_lock_root(struct btree_iter *iter,
@@ -987,10 +1017,7 @@ void bch_btree_iter_rewind(struct btree_iter *iter, struct bpos pos)
BUG_ON(bkey_cmp(pos, iter->nodes[iter->level]->data->min_key) < 0);
iter->pos = pos;
-
- bch_btree_node_iter_init(&iter->node_iters[iter->level],
- &iter->nodes[iter->level]->keys,
- pos, iter->is_extents);
+ __btree_iter_init(iter, iter->nodes[iter->level]);
}
struct bkey_s_c bch_btree_iter_peek(struct btree_iter *iter)
diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c
index b621f411147d..8a6ea6e180c6 100644
--- a/drivers/md/bcache/btree_update.c
+++ b/drivers/md/bcache/btree_update.c
@@ -678,8 +678,6 @@ overwrite:
if (k->u64s != clobber_u64s || bkey_deleted(&insert->k))
bch_btree_node_iter_fix(iter, b, node_iter, t, k,
clobber_u64s, k->u64s);
- else
- bch_btree_iter_verify(iter, b);
}
static void btree_node_flush(struct journal *j, struct journal_entry_pin *pin)
@@ -1095,6 +1093,7 @@ bch_btree_insert_keys_interior(struct btree *b,
struct btree_interior_update *as,
struct btree_reserve *res)
{
+ struct btree_iter *linked;
struct btree_node_iter node_iter;
const struct bkey_format *f = &b->keys.format;
struct bkey_i *insert = bch_keylist_front(insert_keys);
@@ -1135,6 +1134,13 @@ bch_btree_insert_keys_interior(struct btree *b,
btree_interior_update_updated_btree(iter->c, as, b);
+ for_each_linked_btree_node(iter, b, linked)
+ bch_btree_node_iter_peek(&linked->node_iters[b->level],
+ &b->keys);
+ bch_btree_node_iter_peek(&iter->node_iters[b->level], &b->keys);
+
+ bch_btree_iter_verify(iter, b);
+
if (bch_maybe_compact_deleted_keys(&b->keys))
bch_btree_iter_reinit_node(iter, b);