Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Slava Pestov and committed by
Kent Overstreet
2452cc89 c9a78332

+25 -20
+21 -16
drivers/md/bcache/btree.c
··· 117 117 ({ \ 118 118 int _r, l = (b)->level - 1; \ 119 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 122 if (!IS_ERR(_child)) { \ 122 - _child->parent = (b); \ 123 123 _r = bch_btree_ ## fn(_child, op, ##__VA_ARGS__); \ 124 124 rw_unlock(_w, _child); \ 125 125 } else \ ··· 142 142 rw_lock(_w, _b, _b->level); \ 143 143 if (_b == (c)->root && \ 144 144 _w == insert_lock(op, _b)) { \ 145 - _b->parent = NULL; \ 146 145 _r = bch_btree_ ## fn(_b, op, ##__VA_ARGS__); \ 147 146 } \ 148 147 rw_unlock(_w, _b); \ ··· 966 967 * level and op->lock. 967 968 */ 968 969 struct btree *bch_btree_node_get(struct cache_set *c, struct btree_op *op, 969 - struct bkey *k, int level, bool write) 970 + struct bkey *k, int level, bool write, 971 + struct btree *parent) 970 972 { 971 973 int i = 0; 972 974 struct btree *b; ··· 1002 1002 BUG_ON(b->level != level); 1003 1003 } 1004 1004 1005 + b->parent = parent; 1005 1006 b->accessed = 1; 1006 1007 1007 1008 for (; i <= b->keys.nsets && b->keys.set[i].size; i++) { ··· 1023 1022 return b; 1024 1023 } 1025 1024 1026 - static void btree_node_prefetch(struct cache_set *c, struct bkey *k, int level) 1025 + static void btree_node_prefetch(struct btree *parent, struct bkey *k) 1027 1026 { 1028 1027 struct btree *b; 1029 1028 1030 - mutex_lock(&c->bucket_lock); 1031 - b = mca_alloc(c, NULL, k, level); 1032 - mutex_unlock(&c->bucket_lock); 1029 + mutex_lock(&parent->c->bucket_lock); 1030 + b = mca_alloc(parent->c, NULL, k, parent->level - 1); 1031 + mutex_unlock(&parent->c->bucket_lock); 1033 1032 1034 1033 if (!IS_ERR_OR_NULL(b)) { 1034 + b->parent = parent; 1035 1035 bch_btree_node_read(b); 1036 1036 rw_unlock(true, b); 1037 1037 } ··· 1063 1061 } 1064 1062 1065 1063 struct btree *__bch_btree_node_alloc(struct cache_set *c, struct btree_op *op, 1066 - int level, bool wait) 1064 + int level, bool wait, 1065 + struct btree *parent) 1067 1066 { 1068 1067 BKEY_PADDED(key) k; 1069 1068 struct btree *b = ERR_PTR(-EAGAIN); ··· 1088 1085 } 1089 1086 1090 1087 b->accessed = 1; 1088 + b->parent = parent; 1091 1089 bch_bset_init_next(&b->keys, b->keys.set->data, bset_magic(&b->c->sb)); 1092 1090 1093 1091 mutex_unlock(&c->bucket_lock); ··· 1105 1101 } 1106 1102 1107 1103 static struct btree *bch_btree_node_alloc(struct cache_set *c, 1108 - struct btree_op *op, int level) 1104 + struct btree_op *op, int level, 1105 + struct btree *parent) 1109 1106 { 1110 - return __bch_btree_node_alloc(c, op, level, op != NULL); 1107 + return __bch_btree_node_alloc(c, op, level, op != NULL, parent); 1111 1108 } 1112 1109 1113 1110 static struct btree *btree_node_alloc_replacement(struct btree *b, 1114 1111 struct btree_op *op) 1115 1112 { 1116 - struct btree *n = bch_btree_node_alloc(b->c, op, b->level); 1113 + struct btree *n = bch_btree_node_alloc(b->c, op, b->level, b->parent); 1117 1114 if (!IS_ERR_OR_NULL(n)) { 1118 1115 mutex_lock(&n->write_lock); 1119 1116 bch_btree_sort_into(&b->keys, &n->keys, &b->c->sort); ··· 1528 1523 k = bch_btree_iter_next_filter(&iter, &b->keys, bch_ptr_bad); 1529 1524 if (k) { 1530 1525 r->b = bch_btree_node_get(b->c, op, k, b->level - 1, 1531 - true); 1526 + true, b); 1532 1527 if (IS_ERR(r->b)) { 1533 1528 ret = PTR_ERR(r->b); 1534 1529 break; ··· 1823 1818 k = bch_btree_iter_next_filter(&iter, &b->keys, 1824 1819 bch_ptr_bad); 1825 1820 if (k) 1826 - btree_node_prefetch(b->c, k, b->level - 1); 1821 + btree_node_prefetch(b, k); 1827 1822 1828 1823 if (p) 1829 1824 ret = btree(check_recurse, p, b, op); ··· 1988 1983 1989 1984 trace_bcache_btree_node_split(b, btree_bset_first(n1)->keys); 1990 1985 1991 - n2 = bch_btree_node_alloc(b->c, op, b->level); 1986 + n2 = bch_btree_node_alloc(b->c, op, b->level, b->parent); 1992 1987 if (IS_ERR(n2)) 1993 1988 goto err_free1; 1994 1989 1995 1990 if (!b->parent) { 1996 - n3 = bch_btree_node_alloc(b->c, op, b->level + 1); 1991 + n3 = bch_btree_node_alloc(b->c, op, b->level + 1, NULL); 1997 1992 if (IS_ERR(n3)) 1998 1993 goto err_free2; 1999 1994 }
+2 -2
drivers/md/bcache/btree.h
··· 243 243 244 244 void bch_btree_set_root(struct btree *); 245 245 struct btree *__bch_btree_node_alloc(struct cache_set *, struct btree_op *, 246 - int, bool); 246 + int, bool, struct btree *); 247 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 250 int bch_btree_insert_check_key(struct btree *, struct btree_op *, 251 251 struct bkey *);
+2 -2
drivers/md/bcache/super.c
··· 1601 1601 goto err; 1602 1602 1603 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 1605 if (IS_ERR_OR_NULL(c->root)) 1606 1606 goto err; 1607 1607 ··· 1676 1676 goto err; 1677 1677 1678 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 1680 if (IS_ERR_OR_NULL(c->root)) 1681 1681 goto err; 1682 1682