summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2016-04-09 07:24:06 -0800
committerKent Overstreet <kent.overstreet@gmail.com>2016-10-07 12:36:08 -0800
commit64e2031d6916042baf920e01e5c9b4e212d6c4a2 (patch)
tree4077c365019b46f132d5eede096829c9400162c5
parent9fb193f1c8fed094a7f8b0480b6f9d06074aba4d (diff)
bcache: verify btree node lock ordering
-rw-r--r--drivers/md/bcache/btree_iter.c20
-rw-r--r--drivers/md/bcache/btree_iter.h8
-rw-r--r--drivers/md/bcache/btree_update.c4
3 files changed, 22 insertions, 10 deletions
diff --git a/drivers/md/bcache/btree_iter.c b/drivers/md/bcache/btree_iter.c
index 8b2636541959..d7a28673f68f 100644
--- a/drivers/md/bcache/btree_iter.c
+++ b/drivers/md/bcache/btree_iter.c
@@ -155,8 +155,8 @@ bool btree_node_relock(struct btree_iter *iter, unsigned level)
/* Btree iterator: */
-static bool btree_iter_cmp(struct btree_iter *iter,
- struct bpos pos, struct bpos k)
+static bool btree_iter_pos_cmp(struct btree_iter *iter,
+ struct bpos pos, struct bpos k)
{
return iter->is_extents
? bkey_cmp(pos, k) < 0
@@ -176,7 +176,7 @@ void bch_btree_node_iter_fix(struct btree_iter *iter,
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,
+ bool iter_pos_before_new = btree_iter_pos_cmp(iter, iter->pos,
bkey_unpack_key(f, where).p);
BUG_ON(node_iter->used > MAX_BSETS);
@@ -264,7 +264,7 @@ static bool btree_iter_pos_in_node(struct btree_iter *iter,
{
return iter->btree_id == b->btree_id &&
bkey_cmp(iter->pos, b->data->min_key) >= 0 &&
- btree_iter_cmp(iter, iter->pos, b->key.k.p);
+ btree_iter_pos_cmp(iter, iter->pos, b->key.k.p);
}
/*
@@ -410,7 +410,6 @@ static void btree_iter_verify_locking(struct btree_iter *iter)
* retaking fails then return -EINTR... but, let's keep things simple
* for now:
*/
-
for_each_linked_btree_iter(iter, linked)
for (level = 0; level < BTREE_MAX_DEPTH; level++)
BUG_ON(btree_node_read_locked(linked, level));
@@ -423,6 +422,12 @@ static void btree_iter_verify_locking(struct btree_iter *iter)
for_each_linked_btree_iter(iter, linked)
for (level = 0; level < iter->level; level++)
BUG_ON(btree_node_intent_locked(linked, level));
+
+ /* And, lock ordering: */
+ for_each_linked_btree_iter(iter, linked)
+ BUG_ON(btree_node_intent_locked(linked, 0) &&
+ btree_iter_cmp(iter, linked) < 0);
+
#endif
}
@@ -451,7 +456,8 @@ retry:
while (iter->nodes[iter->level] &&
!(is_btree_node(iter, iter->level) &&
btree_node_relock(iter, iter->level) &&
- btree_iter_cmp(iter, pos, iter->nodes[iter->level]->key.k.p)))
+ btree_iter_pos_cmp(iter, pos,
+ iter->nodes[iter->level]->key.k.p)))
btree_iter_up(iter);
/*
@@ -462,7 +468,7 @@ retry:
struct bkey_s_c k;
while ((k = __btree_iter_peek_all(iter)).k &&
- !btree_iter_cmp(iter, pos, k.k->p))
+ !btree_iter_pos_cmp(iter, pos, k.k->p))
__btree_iter_next_all(iter);
}
diff --git a/drivers/md/bcache/btree_iter.h b/drivers/md/bcache/btree_iter.h
index 1d0186af5000..55fe9236ea7c 100644
--- a/drivers/md/bcache/btree_iter.h
+++ b/drivers/md/bcache/btree_iter.h
@@ -168,6 +168,14 @@ static inline struct bpos btree_type_successor(enum btree_id id,
return pos;
}
+static inline int btree_iter_cmp(const struct btree_iter *l,
+ const struct btree_iter *r)
+{
+ if (l->btree_id != r->btree_id)
+ return l->btree_id < r->btree_id ? -1 : 1;
+ return bkey_cmp(l->pos, r->pos);
+}
+
#define for_each_btree_node(_iter, _c, _btree_id, _start, _b) \
for (bch_btree_iter_init((_iter), (_c), (_btree_id), _start), \
(_iter)->is_extents = false, \
diff --git a/drivers/md/bcache/btree_update.c b/drivers/md/bcache/btree_update.c
index c480c9647ef9..001066763dcf 100644
--- a/drivers/md/bcache/btree_update.c
+++ b/drivers/md/bcache/btree_update.c
@@ -1532,9 +1532,7 @@ static int btree_trans_iter_cmp(const void *_l, const void *_r)
const struct btree_insert_trans *l = _l;
const struct btree_insert_trans *r = _r;
- if (l->iter->btree_id != r->iter->btree_id)
- return l->iter->btree_id < r->iter->btree_id ? -1 : 1;
- return bkey_cmp(l->iter->pos, r->iter->pos);
+ return btree_iter_cmp(l->iter, r->iter);
}
/* Normal update interface: */