diff options
author | Slava Pestov <sp@daterainc.com> | 2014-07-12 03:22:53 -0400 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2014-08-04 18:23:04 -0400 |
commit | 2452cc89063a2a6890368f185c4b6d7d8802179e (patch) | |
tree | 842af976b4c614cb1cf6b27c60bb7bbaac1f8cb1 /drivers/md | |
parent | c9a78332b42cbdcdd386a95192a716b67d1711a4 (diff) |
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
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/bcache/btree.c | 37 | ||||
-rw-r--r-- | drivers/md/bcache/btree.h | 4 | ||||
-rw-r--r-- | drivers/md/bcache/super.c | 4 |
3 files changed, 25 insertions, 20 deletions
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 776583f7247d..00cde40db572 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c | |||
@@ -117,9 +117,9 @@ | |||
117 | ({ \ | 117 | ({ \ |
118 | int _r, l = (b)->level - 1; \ | 118 | int _r, l = (b)->level - 1; \ |
119 | bool _w = l <= (op)->lock; \ | 119 | bool _w = l <= (op)->lock; \ |
120 | struct btree *_child = bch_btree_node_get((b)->c, op, key, l, _w);\ | 120 | struct btree *_child = bch_btree_node_get((b)->c, op, key, l, \ |
121 | _w, b); \ | ||
121 | if (!IS_ERR(_child)) { \ | 122 | if (!IS_ERR(_child)) { \ |
122 | _child->parent = (b); \ | ||
123 | _r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \ | 123 | _r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \ |
124 | rw_unlock(_w, _child); \ | 124 | rw_unlock(_w, _child); \ |
125 | } else \ | 125 | } else \ |
@@ -142,7 +142,6 @@ | |||
142 | rw_lock(_w, _b, _b->level); \ | 142 | rw_lock(_w, _b, _b->level); \ |
143 | if (_b == (c)->root && \ | 143 | if (_b == (c)->root && \ |
144 | _w == insert_lock(op, _b)) { \ | 144 | _w == insert_lock(op, _b)) { \ |
145 | _b->parent = NULL; \ | ||
146 | _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \ | 145 | _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \ |
147 | } \ | 146 | } \ |
148 | rw_unlock(_w, _b); \ | 147 | rw_unlock(_w, _b); \ |
@@ -967,7 +966,8 @@ err: | |||
967 | * level and op->lock. | 966 | * level and op->lock. |
968 | */ | 967 | */ |
969 | struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, | 968 | struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, |
970 | struct bkey *k, int level, bool write) | 969 | struct bkey *k, int level, bool write, |
970 | struct btree *parent) | ||
971 | { | 971 | { |
972 | int i = 0; | 972 | int i = 0; |
973 | struct btree *b; | 973 | struct btree *b; |
@@ -1002,6 +1002,7 @@ retry: | |||
1002 | BUG_ON(b->level != level); | 1002 | BUG_ON(b->level != level); |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | b->parent = parent; | ||
1005 | b->accessed = 1; | 1006 | b->accessed = 1; |
1006 | 1007 | ||
1007 | for (; i <= b->keys.nsets && b->keys.set[i].size; i++) { | 1008 | for (; i <= b->keys.nsets && b->keys.set[i].size; i++) { |
@@ -1022,15 +1023,16 @@ retry: | |||
1022 | return b; | 1023 | return b; |
1023 | } | 1024 | } |
1024 | 1025 | ||
1025 | static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level) | 1026 | static void btree_node_prefetch(struct btree *parent, struct bkey *k) |
1026 | { | 1027 | { |
1027 | struct btree *b; | 1028 | struct btree *b; |
1028 | 1029 | ||
1029 | mutex_lock(&c->bucket_lock); | 1030 | mutex_lock(&parent->c->bucket_lock); |
1030 | b = mca_alloc(c, NULL, k, level); | 1031 | b = mca_alloc(parent->c, NULL, k, parent->level - 1); |
1031 | mutex_unlock(&c->bucket_lock); | 1032 | mutex_unlock(&parent->c->bucket_lock); |
1032 | 1033 | ||
1033 | if (!IS_ERR_OR_NULL(b)) { | 1034 | if (!IS_ERR_OR_NULL(b)) { |
1035 | b->parent = parent; | ||
1034 | bch_btree_node_read(b); | 1036 | bch_btree_node_read(b); |
1035 | rw_unlock(true, b); | 1037 | rw_unlock(true, b); |
1036 | } | 1038 | } |
@@ -1061,7 +1063,8 @@ static void btree_node_free(struct btree *b) | |||
1061 | } | 1063 | } |
1062 | 1064 | ||
1063 | struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, | 1065 | struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, |
1064 | int level, bool wait) | 1066 | int level, bool wait, |
1067 | struct btree *parent) | ||
1065 | { | 1068 | { |
1066 | BKEY_PADDED(key) k; | 1069 | BKEY_PADDED(key) k; |
1067 | struct btree *b = ERR_PTR(-EAGAIN); | 1070 | struct btree *b = ERR_PTR(-EAGAIN); |
@@ -1085,6 +1088,7 @@ retry: | |||
1085 | } | 1088 | } |
1086 | 1089 | ||
1087 | b->accessed = 1; | 1090 | b->accessed = 1; |
1091 | b->parent = parent; | ||
1088 | bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb)); | 1092 | bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb)); |
1089 | 1093 | ||
1090 | mutex_unlock(&c->bucket_lock); | 1094 | mutex_unlock(&c->bucket_lock); |
@@ -1101,15 +1105,16 @@ err: | |||
1101 | } | 1105 | } |
1102 | 1106 | ||
1103 | static struct btree *bch_btree_node_alloc(struct cache_set *c, | 1107 | static struct btree *bch_btree_node_alloc(struct cache_set *c, |
1104 | struct btree_op *op, int level) | 1108 | struct btree_op *op, int level, |
1109 | struct btree *parent) | ||
1105 | { | 1110 | { |
1106 | return __bch_btree_node_alloc(c, op, level, op != NULL); | 1111 | return __bch_btree_node_alloc(c, op, level, op != NULL, parent); |
1107 | } | 1112 | } |
1108 | 1113 | ||
1109 | static struct btree *btree_node_alloc_replacement(struct btree *b, | 1114 | static struct btree *btree_node_alloc_replacement(struct btree *b, |
1110 | struct btree_op *op) | 1115 | struct btree_op *op) |
1111 | { | 1116 | { |
1112 | struct btree *n = bch_btree_node_alloc(b->c, op, b->level); | 1117 | struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent); |
1113 | if (!IS_ERR_OR_NULL(n)) { | 1118 | if (!IS_ERR_OR_NULL(n)) { |
1114 | mutex_lock(&n->write_lock); | 1119 | mutex_lock(&n->write_lock); |
1115 | bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort); | 1120 | 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 | k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad); | 1528 | k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad); |
1524 | if (k) { | 1529 | if (k) { |
1525 | r->b = bch_btree_node_get(b->c, op, k, b->level - 1, | 1530 | r->b = bch_btree_node_get(b->c, op, k, b->level - 1, |
1526 | true); | 1531 | true, b); |
1527 | if (IS_ERR(r->b)) { | 1532 | if (IS_ERR(r->b)) { |
1528 | ret = PTR_ERR(r->b); | 1533 | ret = PTR_ERR(r->b); |
1529 | break; | 1534 | break; |
@@ -1818,7 +1823,7 @@ static int bch_btree_check_recurse(struct btree *b, struct btree_op *op) | |||
1818 | k = bch_btree_iter_next_filter(&iter, &b->keys, | 1823 | k = bch_btree_iter_next_filter(&iter, &b->keys, |
1819 | bch_ptr_bad); | 1824 | bch_ptr_bad); |
1820 | if (k) | 1825 | if (k) |
1821 | btree_node_prefetch(b->c, k, b->level - 1); | 1826 | btree_node_prefetch(b, k); |
1822 | 1827 | ||
1823 | if (p) | 1828 | if (p) |
1824 | ret = btree(check_recurse, p, b, op); | 1829 | ret = btree(check_recurse, p, b, op); |
@@ -1983,12 +1988,12 @@ static int btree_split(struct btree *b, struct btree_op *op, | |||
1983 | 1988 | ||
1984 | trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys); | 1989 | trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys); |
1985 | 1990 | ||
1986 | n2 = bch_btree_node_alloc(b->c, op, b->level); | 1991 | n2 = bch_btree_node_alloc(b->c, op, b->level, b->parent); |
1987 | if (IS_ERR(n2)) | 1992 | if (IS_ERR(n2)) |
1988 | goto err_free1; | 1993 | goto err_free1; |
1989 | 1994 | ||
1990 | if (!b->parent) { | 1995 | if (!b->parent) { |
1991 | n3 = bch_btree_node_alloc(b->c, op, b->level + 1); | 1996 | n3 = bch_btree_node_alloc(b->c, op, b->level + 1, NULL); |
1992 | if (IS_ERR(n3)) | 1997 | if (IS_ERR(n3)) |
1993 | goto err_free2; | 1998 | goto err_free2; |
1994 | } | 1999 | } |
diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h index 00441821f5ad..5c391fa01bed 100644 --- a/drivers/md/bcache/btree.h +++ b/drivers/md/bcache/btree.h | |||
@@ -243,9 +243,9 @@ void bch_btree_node_write(struct btree *, struct closure *); | |||
243 | 243 | ||
244 | void bch_btree_set_root(struct btree *); | 244 | void bch_btree_set_root(struct btree *); |
245 | struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *, | 245 | struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *, |
246 | int, bool); | 246 | int, bool, struct btree *); |
247 | struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *, | 247 | struct btree *bch_btree_node_get(struct cache_set *, struct btree_op *, |
248 | struct bkey *, int, bool); | 248 | struct bkey *, int, bool, struct btree *); |
249 | 249 | ||
250 | int bch_btree_insert_check_key(struct btree *, struct btree_op *, | 250 | int bch_btree_insert_check_key(struct btree *, struct btree_op *, |
251 | struct bkey *); | 251 | struct bkey *); |
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 12ad381bdbab..b6114d672413 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c | |||
@@ -1601,7 +1601,7 @@ static void run_cache_set(struct cache_set *c) | |||
1601 | goto err; | 1601 | goto err; |
1602 | 1602 | ||
1603 | err = "error reading btree root"; | 1603 | err = "error reading btree root"; |
1604 | c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true); | 1604 | c->root = bch_btree_node_get(c, NULL, k, j->btree_level, true, NULL); |
1605 | if (IS_ERR_OR_NULL(c->root)) | 1605 | if (IS_ERR_OR_NULL(c->root)) |
1606 | goto err; | 1606 | goto err; |
1607 | 1607 | ||
@@ -1676,7 +1676,7 @@ static void run_cache_set(struct cache_set *c) | |||
1676 | goto err; | 1676 | goto err; |
1677 | 1677 | ||
1678 | err = "cannot allocate new btree root"; | 1678 | err = "cannot allocate new btree root"; |
1679 | c->root = __bch_btree_node_alloc(c, NULL, 0, true); | 1679 | c->root = __bch_btree_node_alloc(c, NULL, 0, true, NULL); |
1680 | if (IS_ERR_OR_NULL(c->root)) | 1680 | if (IS_ERR_OR_NULL(c->root)) |
1681 | goto err; | 1681 | goto err; |
1682 | 1682 | ||