Commit 2452cc89 authored by Slava Pestov's avatar Slava Pestov Committed by Kent Overstreet

bcache: try to set b->parent properly

bcache_flash_dev.ktest would reliably crash with 8k and 16k bucket size
before; now it passes.

Change-Id: Ib542232235e39298c3a7548fe52b645cabb823d1
parent c9a78332
...@@ -117,9 +117,9 @@ ...@@ -117,9 +117,9 @@
({ \ ({ \
int _r, l = (b)->level - 1; \ int _r, l = (b)->level - 1; \
bool _w = l <= (op)->lock; \ bool _w = l <= (op)->lock; \
struct btree *_child = bch_btree_node_get((b)->c, op, key, l, _w);\ struct btree *_child = bch_btree_node_get((b)->c, op, key, l, \
_w, b); \
if (!IS_ERR(_child)) { \ if (!IS_ERR(_child)) { \
_child->parent = (b); \
_r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \ _r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \
rw_unlock(_w, _child); \ rw_unlock(_w, _child); \
} else \ } else \
...@@ -142,7 +142,6 @@ ...@@ -142,7 +142,6 @@
rw_lock(_w, _b, _b->level); \ rw_lock(_w, _b, _b->level); \
if (_b == (c)->root && \ if (_b == (c)->root && \
_w == insert_lock(op, _b)) { \ _w == insert_lock(op, _b)) { \
_b->parent = NULL; \
_r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \ _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \
} \ } \
rw_unlock(_w, _b); \ rw_unlock(_w, _b); \
...@@ -967,7 +966,8 @@ static struct btree *mca_alloc(struct cache_set *c, struct btree_op *op, ...@@ -967,7 +966,8 @@ static struct btree *mca_alloc(struct cache_set *c, struct btree_op *op,
* level and op->lock. * level and op->lock.
*/ */
struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
struct bkey *k, int level, bool write) struct bkey *k, int level, bool write,
struct btree *parent)
{ {
int i = 0; int i = 0;
struct btree *b; struct btree *b;
...@@ -1002,6 +1002,7 @@ struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, ...@@ -1002,6 +1002,7 @@ struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
BUG_ON(b->level != level); BUG_ON(b->level != level);
} }
b->parent = parent;
b->accessed = 1; b->accessed = 1;
for (; i <= b->keys.nsets && b->keys.set[i].size; i++) { for (; i <= b->keys.nsets && b->keys.set[i].size; i++) {
...@@ -1022,15 +1023,16 @@ struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, ...@@ -1022,15 +1023,16 @@ struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op,
return b; return b;
} }
static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level) static void btree_node_prefetch(struct btree *parent, struct bkey *k)
{ {
struct btree *b; struct btree *b;
mutex_lock(&c->bucket_lock); mutex_lock(&parent->c->bucket_lock);
b = mca_alloc(c, NULL, k, level); b = mca_alloc(parent->c, NULL, k, parent->level - 1);
mutex_unlock(&c->bucket_lock); mutex_unlock(&parent->c->bucket_lock);
if (!IS_ERR_OR_NULL(b)) { if (!IS_ERR_OR_NULL(b)) {
b->parent = parent;
bch_btree_node_read(b); bch_btree_node_read(b);
rw_unlock(true, b); rw_unlock(true, b);
} }
...@@ -1061,7 +1063,8 @@ static void btree_node_free(struct btree *b) ...@@ -1061,7 +1063,8 @@ static void btree_node_free(struct btree *b)
} }
struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
int level, bool wait) int level, bool wait,
struct btree *parent)
{ {
BKEY_PADDED(key) k; BKEY_PADDED(key) k;
struct btree *b = ERR_PTR(-EAGAIN); struct btree *b = ERR_PTR(-EAGAIN);
...@@ -1085,6 +1088,7 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, ...@@ -1085,6 +1088,7 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
} }
b->accessed = 1; b->accessed = 1;
b->parent = parent;
bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb)); bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb));
mutex_unlock(&c->bucket_lock); mutex_unlock(&c->bucket_lock);
...@@ -1101,15 +1105,16 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, ...@@ -1101,15 +1105,16 @@ struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op,
} }
static struct btree *bch_btree_node_alloc(struct cache_set *c, static struct btree *bch_btree_node_alloc(struct cache_set *c,
struct btree_op *op, int level) struct btree_op *op, int level,
struct btree *parent)
{ {
return __bch_btree_node_alloc(c, op, level, op != NULL); return __bch_btree_node_alloc(c, op, level, op != NULL, parent);
} }
static struct btree *btree_node_alloc_replacement(struct btree *b, static struct btree *btree_node_alloc_replacement(struct btree *b,
struct btree_op *op) struct btree_op *op)
{ {
struct btree *n = bch_btree_node_alloc(b->c, op, b->level); struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent);
if (!IS_ERR_OR_NULL(n)) { if (!IS_ERR_OR_NULL(n)) {
mutex_lock(&n->write_lock); mutex_lock(&n->write_lock);
bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort); bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort);
...@@ -1523,7 +1528,7 @@ static int btree_gc_recurse(struct btree *b, struct btree_op *op, ...@@ -1523,7 +1528,7 @@ static int btree_gc_recurse(struct btree *b, struct btree_op *op,
k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad); k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad);
if (k) { if (k) {
r->b = bch_btree_node_get(b->c, op, k, b->level - 1, r->b = bch_btree_node_get(b->c, op, k, b->level - 1,
true); true, b);
if (IS_ERR(r->b)) { if (IS_ERR(r->b)) {
ret = PTR_ERR(r->b); ret = PTR_ERR(r->b);
break; break;
...@@ -1818,7 +1823,7 @@ static int bch_btree_check_recurse(struct btree *b, struct btree_op *op) ...@@ -1818,7 +1823,7 @@ static int bch_btree_check_recurse(struct btree *b, struct btree_op *op)
k = bch_btree_iter_next_filter(&iter, &b->keys, k = bch_btree_iter_next_filter(&iter, &b->keys,
bch_ptr_bad); bch_ptr_bad);
if (k) if (k)
btree_node_prefetch(b->c, k, b->level - 1); btree_node_prefetch(b, k);
if (p) if (p)
ret = btree(check_recurse, p, b, op); ret = btree(check_recurse, p, b, op);
...@@ -1983,12 +1988,12 @@ static int btree_split(struct btree *b, struct btree_op *op, ...@@ -1983,12 +1988,12 @@ static int btree_split(struct btree *b, struct btree_op *op,
trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys); trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys);
n2 = bch_btree_node_alloc(b->c, op, b->level); n2 = bch_btree_node_alloc(b->c, op, b->level, b->parent);
if (IS_ERR(n2)) if (IS_ERR(n2))
goto err_free1; goto err_free1;
if (!b->parent) { if (!b->parent) {
n3 = bch_btree_node_alloc(b->c, op, b->level + 1); n3 = bch_btree_node_alloc(b->c, op, b->level + 1, NULL);
if (IS_ERR(n3)) if (IS_ERR(n3))
goto err_free2; goto err_free2;
} }
......
...@@ -243,9 +243,9 @@ void bch_btree_node_write(struct btree *, struct closure *); ...@@ -243,9 +243,9 @@ void bch_btree_node_write(struct btree *, struct closure *);
void bch_btree_set_root(struct btree *); void bch_btree_set_root(struct btree *);
struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *, struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *,
int, bool); int, bool, struct btree *);
struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *, struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *,
struct bkey *, int, bool); struct bkey *, int, bool, struct btree *);
int bch_btree_insert_check_key(struct btree *, struct btree_op *, int bch_btree_insert_check_key(struct btree *, struct btree_op *,
struct bkey *); struct bkey *);
......
...@@ -1601,7 +1601,7 @@ static void run_cache_set(struct cache_set *c) ...@@ -1601,7 +1601,7 @@ static void run_cache_set(struct cache_set *c)
goto err; goto err;
err = "error reading btree root"; err = "error reading btree root";
c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true); c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true, NULL);
if (IS_ERR_OR_NULL(c->root)) if (IS_ERR_OR_NULL(c->root))
goto err; goto err;
...@@ -1676,7 +1676,7 @@ static void run_cache_set(struct cache_set *c) ...@@ -1676,7 +1676,7 @@ static void run_cache_set(struct cache_set *c)
goto err; goto err;
err = "cannot allocate new btree root"; err = "cannot allocate new btree root";
c->root = __bch_btree_node_alloc(c, NULL, 0, true); c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL);
if (IS_ERR_OR_NULL(c->root)) if (IS_ERR_OR_NULL(c->root))
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment