aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-12-18 02:47:33 -0500
committerKent Overstreet <kmo@daterainc.com>2014-01-08 16:05:13 -0500
commitdc9d98d621bdce0552997200ce855659875a5c9f (patch)
treed0339299ab01f50dd225446734a7d34164df2817 /drivers/md
parentc052dd9a26f60bcf70c0c3fcc08e07abb60295cd (diff)
bcache: Convert debug code to btree_keys
More work to disentangle various code from struct btree Signed-off-by: Kent Overstreet <kmo@daterainc.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/bcache/bset.c117
-rw-r--r--drivers/md/bcache/bset.h56
-rw-r--r--drivers/md/bcache/btree.c8
-rw-r--r--drivers/md/bcache/debug.c179
-rw-r--r--drivers/md/bcache/debug.h23
-rw-r--r--drivers/md/bcache/extents.c93
-rw-r--r--drivers/md/bcache/extents.h1
-rw-r--r--drivers/md/bcache/super.c2
-rw-r--r--drivers/md/bcache/util.h2
9 files changed, 264 insertions, 217 deletions
diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c
index 097bd8d2acba..448cff8cc052 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -7,11 +7,121 @@
7 7
8#include "bcache.h" 8#include "bcache.h"
9#include "btree.h" 9#include "btree.h"
10#include "debug.h"
11 10
11#include <linux/console.h>
12#include <linux/random.h> 12#include <linux/random.h>
13#include <linux/prefetch.h> 13#include <linux/prefetch.h>
14 14
15#ifdef CONFIG_BCACHE_DEBUG
16
17void bch_dump_bset(struct btree_keys *b, struct bset *i, unsigned set)
18{
19 struct bkey *k, *next;
20
21 for (k = i->start; k < bset_bkey_last(i); k = next) {
22 next = bkey_next(k);
23
24 printk(KERN_ERR "block %u key %zi/%u: ", set,
25 (uint64_t *) k - i->d, i->keys);
26
27 if (b->ops->key_dump)
28 b->ops->key_dump(b, k);
29 else
30 printk("%llu:%llu\n", KEY_INODE(k), KEY_OFFSET(k));
31
32 if (next < bset_bkey_last(i) &&
33 bkey_cmp(k, b->ops->is_extents ?
34 &START_KEY(next) : next) > 0)
35 printk(KERN_ERR "Key skipped backwards\n");
36 }
37}
38
39void bch_dump_bucket(struct btree_keys *b)
40{
41 unsigned i;
42
43 console_lock();
44 for (i = 0; i <= b->nsets; i++)
45 bch_dump_bset(b, b->set[i].data,
46 bset_sector_offset(b, b->set[i].data));
47 console_unlock();
48}
49
50int __bch_count_data(struct btree_keys *b)
51{
52 unsigned ret = 0;
53 struct btree_iter iter;
54 struct bkey *k;
55
56 if (b->ops->is_extents)
57 for_each_key(b, k, &iter)
58 ret += KEY_SIZE(k);
59 return ret;
60}
61
62void __bch_check_keys(struct btree_keys *b, const char *fmt, ...)
63{
64 va_list args;
65 struct bkey *k, *p = NULL;
66 struct btree_iter iter;
67 const char *err;
68
69 for_each_key(b, k, &iter) {
70 if (b->ops->is_extents) {
71 err = "Keys out of order";
72 if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0)
73 goto bug;
74
75 if (bch_ptr_invalid(b, k))
76 continue;
77
78 err = "Overlapping keys";
79 if (p && bkey_cmp(p, &START_KEY(k)) > 0)
80 goto bug;
81 } else {
82 if (bch_ptr_bad(b, k))
83 continue;
84
85 err = "Duplicate keys";
86 if (p && !bkey_cmp(p, k))
87 goto bug;
88 }
89 p = k;
90 }
91#if 0
92 err = "Key larger than btree node key";
93 if (p && bkey_cmp(p, &b->key) > 0)
94 goto bug;
95#endif
96 return;
97bug:
98 bch_dump_bucket(b);
99
100 va_start(args, fmt);
101 vprintk(fmt, args);
102 va_end(args);
103
104 panic("bch_check_keys error: %s:\n", err);
105}
106
107static void bch_btree_iter_next_check(struct btree_iter *iter)
108{
109 struct bkey *k = iter->data->k, *next = bkey_next(k);
110
111 if (next < iter->data->end &&
112 bkey_cmp(k, iter->b->ops->is_extents ?
113 &START_KEY(next) : next) > 0) {
114 bch_dump_bucket(iter->b);
115 panic("Key skipped backwards\n");
116 }
117}
118
119#else
120
121static inline void bch_btree_iter_next_check(struct btree_iter *iter) {}
122
123#endif
124
15/* Keylists */ 125/* Keylists */
16 126
17int __bch_keylist_realloc(struct keylist *l, unsigned u64s) 127int __bch_keylist_realloc(struct keylist *l, unsigned u64s)
@@ -1045,7 +1155,7 @@ void bch_btree_sort_partial(struct btree *b, unsigned start,
1045{ 1155{
1046 size_t order = b->keys.page_order, keys = 0; 1156 size_t order = b->keys.page_order, keys = 0;
1047 struct btree_iter iter; 1157 struct btree_iter iter;
1048 int oldsize = bch_count_data(b); 1158 int oldsize = bch_count_data(&b->keys);
1049 1159
1050 __bch_btree_iter_init(&b->keys, &iter, NULL, &b->keys.set[start]); 1160 __bch_btree_iter_init(&b->keys, &iter, NULL, &b->keys.set[start]);
1051 1161
@@ -1063,7 +1173,8 @@ void bch_btree_sort_partial(struct btree *b, unsigned start,
1063 1173
1064 __btree_sort(&b->keys, &iter, start, order, false, state); 1174 __btree_sort(&b->keys, &iter, start, order, false, state);
1065 1175
1066 EBUG_ON(b->written && oldsize >= 0 && bch_count_data(b) != oldsize); 1176 EBUG_ON(b->written && oldsize >= 0 &&
1177 bch_count_data(&b->keys) != oldsize);
1067} 1178}
1068EXPORT_SYMBOL(bch_btree_sort_partial); 1179EXPORT_SYMBOL(bch_btree_sort_partial);
1069 1180
diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h
index 563130c28142..e01e69e00654 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -193,6 +193,8 @@ struct btree_keys_ops {
193 bool (*key_bad)(struct btree_keys *, const struct bkey *); 193 bool (*key_bad)(struct btree_keys *, const struct bkey *);
194 bool (*key_merge)(struct btree_keys *, 194 bool (*key_merge)(struct btree_keys *,
195 struct bkey *, struct bkey *); 195 struct bkey *, struct bkey *);
196 void (*key_to_text)(char *, size_t, const struct bkey *);
197 void (*key_dump)(struct btree_keys *, const struct bkey *);
196 198
197 /* 199 /*
198 * Only used for deciding whether to use START_KEY(k) or just the key 200 * Only used for deciding whether to use START_KEY(k) or just the key
@@ -243,15 +245,6 @@ static inline unsigned bset_sector_offset(struct btree_keys *b, struct bset *i)
243 return bset_byte_offset(b, i) >> 9; 245 return bset_byte_offset(b, i) >> 9;
244} 246}
245 247
246static inline bool btree_keys_expensive_checks(struct btree_keys *b)
247{
248#ifdef CONFIG_BCACHE_DEBUG
249 return *b->expensive_debug_checks;
250#else
251 return false;
252#endif
253}
254
255#define __set_bytes(i, k) (sizeof(*(i)) + (k) * sizeof(uint64_t)) 248#define __set_bytes(i, k) (sizeof(*(i)) + (k) * sizeof(uint64_t))
256#define set_bytes(i) __set_bytes(i, i->keys) 249#define set_bytes(i) __set_bytes(i, i->keys)
257 250
@@ -446,6 +439,12 @@ static inline bool bch_ptr_bad(struct btree_keys *b, const struct bkey *k)
446 return b->ops->key_bad(b, k); 439 return b->ops->key_bad(b, k);
447} 440}
448 441
442static inline void bch_bkey_to_text(struct btree_keys *b, char *buf,
443 size_t size, const struct bkey *k)
444{
445 return b->ops->key_to_text(buf, size, k);
446}
447
449/* Keylists */ 448/* Keylists */
450 449
451struct keylist { 450struct keylist {
@@ -509,7 +508,42 @@ struct bkey *bch_keylist_pop(struct keylist *);
509void bch_keylist_pop_front(struct keylist *); 508void bch_keylist_pop_front(struct keylist *);
510int __bch_keylist_realloc(struct keylist *, unsigned); 509int __bch_keylist_realloc(struct keylist *, unsigned);
511 510
512struct cache_set; 511/* Debug stuff */
513const char *bch_ptr_status(struct cache_set *, const struct bkey *); 512
513#ifdef CONFIG_BCACHE_DEBUG
514
515int __bch_count_data(struct btree_keys *);
516void __bch_check_keys(struct btree_keys *, const char *, ...);
517void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
518void bch_dump_bucket(struct btree_keys *);
519
520#else
521
522static inline int __bch_count_data(struct btree_keys *b) { return -1; }
523static inline void __bch_check_keys(struct btree_keys *b, const char *fmt, ...) {}
524static inline void bch_dump_bucket(struct btree_keys *b) {}
525void bch_dump_bset(struct btree_keys *, struct bset *, unsigned);
526
527#endif
528
529static inline bool btree_keys_expensive_checks(struct btree_keys *b)
530{
531#ifdef CONFIG_BCACHE_DEBUG
532 return *b->expensive_debug_checks;
533#else
534 return false;
535#endif
536}
537
538static inline int bch_count_data(struct btree_keys *b)
539{
540 return btree_keys_expensive_checks(b) ? __bch_count_data(b) : -1;
541}
542
543#define bch_check_keys(b, ...) \
544do { \
545 if (btree_keys_expensive_checks(b)) \
546 __bch_check_keys(b, __VA_ARGS__); \
547} while (0)
514 548
515#endif 549#endif
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 9424c8a15e37..2128ee1e6916 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -460,7 +460,7 @@ void bch_btree_node_write(struct btree *b, struct closure *parent)
460 BUG_ON(b->written >= btree_blocks(b)); 460 BUG_ON(b->written >= btree_blocks(b));
461 BUG_ON(b->written && !i->keys); 461 BUG_ON(b->written && !i->keys);
462 BUG_ON(btree_bset_first(b)->seq != i->seq); 462 BUG_ON(btree_bset_first(b)->seq != i->seq);
463 bch_check_keys(b, "writing"); 463 bch_check_keys(&b->keys, "writing");
464 464
465 cancel_delayed_work(&b->work); 465 cancel_delayed_work(&b->work);
466 466
@@ -2007,7 +2007,7 @@ static bool btree_insert_key(struct btree *b, struct btree_op *op,
2007insert: bch_bset_insert(&b->keys, m, k); 2007insert: bch_bset_insert(&b->keys, m, k);
2008copy: bkey_copy(m, k); 2008copy: bkey_copy(m, k);
2009merged: 2009merged:
2010 bch_check_keys(b, "%u for %s", status, 2010 bch_check_keys(&b->keys, "%u for %s", status,
2011 replace_key ? "replace" : "insert"); 2011 replace_key ? "replace" : "insert");
2012 2012
2013 if (b->level && !KEY_OFFSET(k)) 2013 if (b->level && !KEY_OFFSET(k))
@@ -2036,7 +2036,7 @@ static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
2036 struct bkey *replace_key) 2036 struct bkey *replace_key)
2037{ 2037{
2038 bool ret = false; 2038 bool ret = false;
2039 int oldsize = bch_count_data(b); 2039 int oldsize = bch_count_data(&b->keys);
2040 2040
2041 while (!bch_keylist_empty(insert_keys)) { 2041 while (!bch_keylist_empty(insert_keys)) {
2042 struct bkey *k = insert_keys->keys; 2042 struct bkey *k = insert_keys->keys;
@@ -2066,7 +2066,7 @@ static bool bch_btree_insert_keys(struct btree *b, struct btree_op *op,
2066 2066
2067 BUG_ON(!bch_keylist_empty(insert_keys) && b->level); 2067 BUG_ON(!bch_keylist_empty(insert_keys) && b->level);
2068 2068
2069 BUG_ON(bch_count_data(b) < oldsize); 2069 BUG_ON(bch_count_data(&b->keys) < oldsize);
2070 return ret; 2070 return ret;
2071} 2071}
2072 2072
diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c
index 3de27e2a4e07..8b1f1d5c1819 100644
--- a/drivers/md/bcache/debug.c
+++ b/drivers/md/bcache/debug.c
@@ -8,6 +8,7 @@
8#include "bcache.h" 8#include "bcache.h"
9#include "btree.h" 9#include "btree.h"
10#include "debug.h" 10#include "debug.h"
11#include "extents.h"
11 12
12#include <linux/console.h> 13#include <linux/console.h>
13#include <linux/debugfs.h> 14#include <linux/debugfs.h>
@@ -17,108 +18,8 @@
17 18
18static struct dentry *debug; 19static struct dentry *debug;
19 20
20const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
21{
22 unsigned i;
23
24 for (i = 0; i < KEY_PTRS(k); i++)
25 if (ptr_available(c, k, i)) {
26 struct cache *ca = PTR_CACHE(c, k, i);
27 size_t bucket = PTR_BUCKET_NR(c, k, i);
28 size_t r = bucket_remainder(c, PTR_OFFSET(k, i));
29
30 if (KEY_SIZE(k) + r > c->sb.bucket_size)
31 return "bad, length too big";
32 if (bucket < ca->sb.first_bucket)
33 return "bad, short offset";
34 if (bucket >= ca->sb.nbuckets)
35 return "bad, offset past end of device";
36 if (ptr_stale(c, k, i))
37 return "stale";
38 }
39
40 if (!bkey_cmp(k, &ZERO_KEY))
41 return "bad, null key";
42 if (!KEY_PTRS(k))
43 return "bad, no pointers";
44 if (!KEY_SIZE(k))
45 return "zeroed key";
46 return "";
47}
48
49int bch_bkey_to_text(char *buf, size_t size, const struct bkey *k)
50{
51 unsigned i = 0;
52 char *out = buf, *end = buf + size;
53
54#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
55
56 p("%llu:%llu len %llu -> [", KEY_INODE(k), KEY_START(k), KEY_SIZE(k));
57
58 for (i = 0; i < KEY_PTRS(k); i++) {
59 if (i)
60 p(", ");
61
62 if (PTR_DEV(k, i) == PTR_CHECK_DEV)
63 p("check dev");
64 else
65 p("%llu:%llu gen %llu", PTR_DEV(k, i),
66 PTR_OFFSET(k, i), PTR_GEN(k, i));
67 }
68
69 p("]");
70
71 if (KEY_DIRTY(k))
72 p(" dirty");
73 if (KEY_CSUM(k))
74 p(" cs%llu %llx", KEY_CSUM(k), k->ptr[1]);
75#undef p
76 return out - buf;
77}
78
79#ifdef CONFIG_BCACHE_DEBUG 21#ifdef CONFIG_BCACHE_DEBUG
80 22
81static void dump_bset(struct btree *b, struct bset *i, unsigned set)
82{
83 struct bkey *k, *next;
84 unsigned j;
85 char buf[80];
86
87 for (k = i->start; k < bset_bkey_last(i); k = next) {
88 next = bkey_next(k);
89
90 bch_bkey_to_text(buf, sizeof(buf), k);
91 printk(KERN_ERR "b %u k %zi/%u: %s", set,
92 (uint64_t *) k - i->d, i->keys, buf);
93
94 for (j = 0; j < KEY_PTRS(k); j++) {
95 size_t n = PTR_BUCKET_NR(b->c, k, j);
96 printk(" bucket %zu", n);
97
98 if (n >= b->c->sb.first_bucket && n < b->c->sb.nbuckets)
99 printk(" prio %i",
100 PTR_BUCKET(b->c, k, j)->prio);
101 }
102
103 printk(" %s\n", bch_ptr_status(b->c, k));
104
105 if (next < bset_bkey_last(i) &&
106 bkey_cmp(k, !b->level ? &START_KEY(next) : next) > 0)
107 printk(KERN_ERR "Key skipped backwards\n");
108 }
109}
110
111static void bch_dump_bucket(struct btree *b)
112{
113 unsigned i;
114
115 console_lock();
116 for (i = 0; i <= b->keys.nsets; i++)
117 dump_bset(b, b->keys.set[i].data,
118 bset_block_offset(b, b->keys.set[i].data));
119 console_unlock();
120}
121
122#define for_each_written_bset(b, start, i) \ 23#define for_each_written_bset(b, start, i) \
123 for (i = (start); \ 24 for (i = (start); \
124 (void *) i < (void *) (start) + (KEY_SIZE(&b->key) << 9) &&\ 25 (void *) i < (void *) (start) + (KEY_SIZE(&b->key) << 9) &&\
@@ -171,17 +72,17 @@ void bch_btree_verify(struct btree *b)
171 console_lock(); 72 console_lock();
172 73
173 printk(KERN_ERR "*** in memory:\n"); 74 printk(KERN_ERR "*** in memory:\n");
174 dump_bset(b, inmemory, 0); 75 bch_dump_bset(&b->keys, inmemory, 0);
175 76
176 printk(KERN_ERR "*** read back in:\n"); 77 printk(KERN_ERR "*** read back in:\n");
177 dump_bset(v, sorted, 0); 78 bch_dump_bset(&v->keys, sorted, 0);
178 79
179 for_each_written_bset(b, ondisk, i) { 80 for_each_written_bset(b, ondisk, i) {
180 unsigned block = ((void *) i - (void *) ondisk) / 81 unsigned block = ((void *) i - (void *) ondisk) /
181 block_bytes(b->c); 82 block_bytes(b->c);
182 83
183 printk(KERN_ERR "*** on disk block %u:\n", block); 84 printk(KERN_ERR "*** on disk block %u:\n", block);
184 dump_bset(b, i, block); 85 bch_dump_bset(&b->keys, i, block);
185 } 86 }
186 87
187 printk(KERN_ERR "*** block %zu not written\n", 88 printk(KERN_ERR "*** block %zu not written\n",
@@ -239,76 +140,6 @@ out_put:
239 bio_put(check); 140 bio_put(check);
240} 141}
241 142
242int __bch_count_data(struct btree *b)
243{
244 unsigned ret = 0;
245 struct btree_iter iter;
246 struct bkey *k;
247
248 if (!b->level)
249 for_each_key(&b->keys, k, &iter)
250 ret += KEY_SIZE(k);
251 return ret;
252}
253
254void __bch_check_keys(struct btree *b, const char *fmt, ...)
255{
256 va_list args;
257 struct bkey *k, *p = NULL;
258 struct btree_iter iter;
259 const char *err;
260
261 for_each_key(&b->keys, k, &iter) {
262 if (!b->level) {
263 err = "Keys out of order";
264 if (p && bkey_cmp(&START_KEY(p), &START_KEY(k)) > 0)
265 goto bug;
266
267 if (bch_ptr_invalid(&b->keys, k))
268 continue;
269
270 err = "Overlapping keys";
271 if (p && bkey_cmp(p, &START_KEY(k)) > 0)
272 goto bug;
273 } else {
274 if (bch_ptr_bad(&b->keys, k))
275 continue;
276
277 err = "Duplicate keys";
278 if (p && !bkey_cmp(p, k))
279 goto bug;
280 }
281 p = k;
282 }
283
284 err = "Key larger than btree node key";
285 if (p && bkey_cmp(p, &b->key) > 0)
286 goto bug;
287
288 return;
289bug:
290 bch_dump_bucket(b);
291
292 va_start(args, fmt);
293 vprintk(fmt, args);
294 va_end(args);
295
296 panic("bcache error: %s:\n", err);
297}
298
299void bch_btree_iter_next_check(struct btree_iter *iter)
300{
301#if 0
302 struct bkey *k = iter->data->k, *next = bkey_next(k);
303
304 if (next < iter->data->end &&
305 bkey_cmp(k, iter->b->level ? next : &START_KEY(next)) > 0) {
306 bch_dump_bucket(iter->b);
307 panic("Key skipped backwards\n");
308 }
309#endif
310}
311
312#endif 143#endif
313 144
314#ifdef CONFIG_DEBUG_FS 145#ifdef CONFIG_DEBUG_FS
@@ -355,7 +186,7 @@ static ssize_t bch_dump_read(struct file *file, char __user *buf,
355 if (!w) 186 if (!w)
356 break; 187 break;
357 188
358 bch_bkey_to_text(kbuf, sizeof(kbuf), &w->key); 189 bch_extent_to_text(kbuf, sizeof(kbuf), &w->key);
359 i->bytes = snprintf(i->buf, PAGE_SIZE, "%s\n", kbuf); 190 i->bytes = snprintf(i->buf, PAGE_SIZE, "%s\n", kbuf);
360 bch_keybuf_del(&i->keys, w); 191 bch_keybuf_del(&i->keys, w);
361 } 192 }
diff --git a/drivers/md/bcache/debug.h b/drivers/md/bcache/debug.h
index 08e116e74d36..1f63c195d247 100644
--- a/drivers/md/bcache/debug.h
+++ b/drivers/md/bcache/debug.h
@@ -1,19 +1,15 @@
1#ifndef _BCACHE_DEBUG_H 1#ifndef _BCACHE_DEBUG_H
2#define _BCACHE_DEBUG_H 2#define _BCACHE_DEBUG_H
3 3
4/* Btree/bkey debug printing */ 4struct bio;
5 5struct cached_dev;
6int bch_bkey_to_text(char *buf, size_t size, const struct bkey *k); 6struct cache_set;
7 7
8#ifdef CONFIG_BCACHE_DEBUG 8#ifdef CONFIG_BCACHE_DEBUG
9 9
10void bch_btree_verify(struct btree *); 10void bch_btree_verify(struct btree *);
11void bch_data_verify(struct cached_dev *, struct bio *); 11void bch_data_verify(struct cached_dev *, struct bio *);
12int __bch_count_data(struct btree *);
13void __bch_check_keys(struct btree *, const char *, ...);
14void bch_btree_iter_next_check(struct btree_iter *);
15 12
16#define EBUG_ON(cond) BUG_ON(cond)
17#define expensive_debug_checks(c) ((c)->expensive_debug_checks) 13#define expensive_debug_checks(c) ((c)->expensive_debug_checks)
18#define key_merging_disabled(c) ((c)->key_merging_disabled) 14#define key_merging_disabled(c) ((c)->key_merging_disabled)
19#define bypass_torture_test(d) ((d)->bypass_torture_test) 15#define bypass_torture_test(d) ((d)->bypass_torture_test)
@@ -22,26 +18,13 @@ void bch_btree_iter_next_check(struct btree_iter *);
22 18
23static inline void bch_btree_verify(struct btree *b) {} 19static inline void bch_btree_verify(struct btree *b) {}
24static inline void bch_data_verify(struct cached_dev *dc, struct bio *bio) {} 20static inline void bch_data_verify(struct cached_dev *dc, struct bio *bio) {}
25static inline int __bch_count_data(struct btree *b) { return -1; }
26static inline void __bch_check_keys(struct btree *b, const char *fmt, ...) {}
27static inline void bch_btree_iter_next_check(struct btree_iter *iter) {}
28 21
29#define EBUG_ON(cond) do { if (cond); } while (0)
30#define expensive_debug_checks(c) 0 22#define expensive_debug_checks(c) 0
31#define key_merging_disabled(c) 0 23#define key_merging_disabled(c) 0
32#define bypass_torture_test(d) 0 24#define bypass_torture_test(d) 0
33 25
34#endif 26#endif
35 27
36#define bch_count_data(b) \
37 (expensive_debug_checks((b)->c) ? __bch_count_data(b) : -1)
38
39#define bch_check_keys(b, ...) \
40do { \
41 if (expensive_debug_checks((b)->c)) \
42 __bch_check_keys(b, __VA_ARGS__); \
43} while (0)
44
45#ifdef CONFIG_DEBUG_FS 28#ifdef CONFIG_DEBUG_FS
46void bch_debug_init_cache_set(struct cache_set *); 29void bch_debug_init_cache_set(struct cache_set *);
47#else 30#else
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c
index ba3021128e7a..bc1c3eed07e7 100644
--- a/drivers/md/bcache/extents.c
+++ b/drivers/md/bcache/extents.c
@@ -62,6 +62,87 @@ static bool __ptr_invalid(struct cache_set *c, const struct bkey *k)
62 return false; 62 return false;
63} 63}
64 64
65/* Common among btree and extent ptrs */
66
67static const char *bch_ptr_status(struct cache_set *c, const struct bkey *k)
68{
69 unsigned i;
70
71 for (i = 0; i < KEY_PTRS(k); i++)
72 if (ptr_available(c, k, i)) {
73 struct cache *ca = PTR_CACHE(c, k, i);
74 size_t bucket = PTR_BUCKET_NR(c, k, i);
75 size_t r = bucket_remainder(c, PTR_OFFSET(k, i));
76
77 if (KEY_SIZE(k) + r > c->sb.bucket_size)
78 return "bad, length too big";
79 if (bucket < ca->sb.first_bucket)
80 return "bad, short offset";
81 if (bucket >= ca->sb.nbuckets)
82 return "bad, offset past end of device";
83 if (ptr_stale(c, k, i))
84 return "stale";
85 }
86
87 if (!bkey_cmp(k, &ZERO_KEY))
88 return "bad, null key";
89 if (!KEY_PTRS(k))
90 return "bad, no pointers";
91 if (!KEY_SIZE(k))
92 return "zeroed key";
93 return "";
94}
95
96void bch_extent_to_text(char *buf, size_t size, const struct bkey *k)
97{
98 unsigned i = 0;
99 char *out = buf, *end = buf + size;
100
101#define p(...) (out += scnprintf(out, end - out, __VA_ARGS__))
102
103 p("%llu:%llu len %llu -> [", KEY_INODE(k), KEY_START(k), KEY_SIZE(k));
104
105 for (i = 0; i < KEY_PTRS(k); i++) {
106 if (i)
107 p(", ");
108
109 if (PTR_DEV(k, i) == PTR_CHECK_DEV)
110 p("check dev");
111 else
112 p("%llu:%llu gen %llu", PTR_DEV(k, i),
113 PTR_OFFSET(k, i), PTR_GEN(k, i));
114 }
115
116 p("]");
117
118 if (KEY_DIRTY(k))
119 p(" dirty");
120 if (KEY_CSUM(k))
121 p(" cs%llu %llx", KEY_CSUM(k), k->ptr[1]);
122#undef p
123}
124
125static void bch_bkey_dump(struct btree_keys *keys, const struct bkey *k)
126{
127 struct btree *b = container_of(keys, struct btree, keys);
128 unsigned j;
129 char buf[80];
130
131 bch_extent_to_text(buf, sizeof(buf), k);
132 printk(" %s", buf);
133
134 for (j = 0; j < KEY_PTRS(k); j++) {
135 size_t n = PTR_BUCKET_NR(b->c, k, j);
136 printk(" bucket %zu", n);
137
138 if (n >= b->c->sb.first_bucket && n < b->c->sb.nbuckets)
139 printk(" prio %i",
140 PTR_BUCKET(b->c, k, j)->prio);
141 }
142
143 printk(" %s\n", bch_ptr_status(b->c, k));
144}
145
65/* Btree ptrs */ 146/* Btree ptrs */
66 147
67bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k) 148bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k)
@@ -76,7 +157,7 @@ bool __bch_btree_ptr_invalid(struct cache_set *c, const struct bkey *k)
76 157
77 return false; 158 return false;
78bad: 159bad:
79 bch_bkey_to_text(buf, sizeof(buf), k); 160 bch_extent_to_text(buf, sizeof(buf), k);
80 cache_bug(c, "spotted btree ptr %s: %s", buf, bch_ptr_status(c, k)); 161 cache_bug(c, "spotted btree ptr %s: %s", buf, bch_ptr_status(c, k));
81 return true; 162 return true;
82} 163}
@@ -111,7 +192,7 @@ static bool btree_ptr_bad_expensive(struct btree *b, const struct bkey *k)
111 return false; 192 return false;
112err: 193err:
113 mutex_unlock(&b->c->bucket_lock); 194 mutex_unlock(&b->c->bucket_lock);
114 bch_bkey_to_text(buf, sizeof(buf), k); 195 bch_extent_to_text(buf, sizeof(buf), k);
115 btree_bug(b, 196 btree_bug(b,
116"inconsistent btree pointer %s: bucket %li pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i", 197"inconsistent btree pointer %s: bucket %li pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
117 buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin), 198 buf, PTR_BUCKET_NR(b->c, k, i), atomic_read(&g->pin),
@@ -145,6 +226,8 @@ const struct btree_keys_ops bch_btree_keys_ops = {
145 .sort_cmp = bch_key_sort_cmp, 226 .sort_cmp = bch_key_sort_cmp,
146 .key_invalid = bch_btree_ptr_invalid, 227 .key_invalid = bch_btree_ptr_invalid,
147 .key_bad = bch_btree_ptr_bad, 228 .key_bad = bch_btree_ptr_bad,
229 .key_to_text = bch_extent_to_text,
230 .key_dump = bch_bkey_dump,
148}; 231};
149 232
150/* Extents */ 233/* Extents */
@@ -227,7 +310,7 @@ static bool bch_extent_invalid(struct btree_keys *bk, const struct bkey *k)
227 310
228 return false; 311 return false;
229bad: 312bad:
230 bch_bkey_to_text(buf, sizeof(buf), k); 313 bch_extent_to_text(buf, sizeof(buf), k);
231 cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k)); 314 cache_bug(b->c, "spotted extent %s: %s", buf, bch_ptr_status(b->c, k));
232 return true; 315 return true;
233} 316}
@@ -254,7 +337,7 @@ static bool bch_extent_bad_expensive(struct btree *b, const struct bkey *k,
254 return false; 337 return false;
255err: 338err:
256 mutex_unlock(&b->c->bucket_lock); 339 mutex_unlock(&b->c->bucket_lock);
257 bch_bkey_to_text(buf, sizeof(buf), k); 340 bch_extent_to_text(buf, sizeof(buf), k);
258 btree_bug(b, 341 btree_bug(b,
259"inconsistent extent pointer %s:\nbucket %zu pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i", 342"inconsistent extent pointer %s:\nbucket %zu pin %i prio %i gen %i last_gc %i mark %llu gc_gen %i",
260 buf, PTR_BUCKET_NR(b->c, k, ptr), atomic_read(&g->pin), 343 buf, PTR_BUCKET_NR(b->c, k, ptr), atomic_read(&g->pin),
@@ -355,5 +438,7 @@ const struct btree_keys_ops bch_extent_keys_ops = {
355 .key_invalid = bch_extent_invalid, 438 .key_invalid = bch_extent_invalid,
356 .key_bad = bch_extent_bad, 439 .key_bad = bch_extent_bad,
357 .key_merge = bch_extent_merge, 440 .key_merge = bch_extent_merge,
441 .key_to_text = bch_extent_to_text,
442 .key_dump = bch_bkey_dump,
358 .is_extents = true, 443 .is_extents = true,
359}; 444};
diff --git a/drivers/md/bcache/extents.h b/drivers/md/bcache/extents.h
index e0c0b685d2f7..e4e23409782d 100644
--- a/drivers/md/bcache/extents.h
+++ b/drivers/md/bcache/extents.h
@@ -7,6 +7,7 @@ extern const struct btree_keys_ops bch_extent_keys_ops;
7struct bkey; 7struct bkey;
8struct cache_set; 8struct cache_set;
9 9
10void bch_extent_to_text(char *, size_t, const struct bkey *);
10bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *); 11bool __bch_btree_ptr_invalid(struct cache_set *, const struct bkey *);
11 12
12#endif /* _BCACHE_EXTENTS_H */ 13#endif /* _BCACHE_EXTENTS_H */
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 6d6a7a15043e..24a3a1546caa 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -384,7 +384,7 @@ static void uuid_io(struct cache_set *c, unsigned long rw,
384 break; 384 break;
385 } 385 }
386 386
387 bch_bkey_to_text(buf, sizeof(buf), k); 387 bch_extent_to_text(buf, sizeof(buf), k);
388 pr_debug("%s UUIDs at %s", rw & REQ_WRITE ? "wrote" : "read", buf); 388 pr_debug("%s UUIDs at %s", rw & REQ_WRITE ? "wrote" : "read", buf);
389 389
390 for (u = c->uuids; u < c->uuids + c->nr_uuids; u++) 390 for (u = c->uuids; u < c->uuids + c->nr_uuids; u++)
diff --git a/drivers/md/bcache/util.h b/drivers/md/bcache/util.h
index 3ebaef5f645b..ac7d0d1f70d7 100644
--- a/drivers/md/bcache/util.h
+++ b/drivers/md/bcache/util.h
@@ -18,11 +18,13 @@ struct closure;
18 18
19#ifdef CONFIG_BCACHE_DEBUG 19#ifdef CONFIG_BCACHE_DEBUG
20 20
21#define EBUG_ON(cond) BUG_ON(cond)
21#define atomic_dec_bug(v) BUG_ON(atomic_dec_return(v) < 0) 22#define atomic_dec_bug(v) BUG_ON(atomic_dec_return(v) < 0)
22#define atomic_inc_bug(v, i) BUG_ON(atomic_inc_return(v) <= i) 23#define atomic_inc_bug(v, i) BUG_ON(atomic_inc_return(v) <= i)
23 24
24#else /* DEBUG */ 25#else /* DEBUG */
25 26
27#define EBUG_ON(cond) do { if (cond); } while (0)
26#define atomic_dec_bug(v) atomic_dec(v) 28#define atomic_dec_bug(v) atomic_dec(v)
27#define atomic_inc_bug(v, i) atomic_inc(v) 29#define atomic_inc_bug(v, i) atomic_inc(v)
28 30