1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2cafe5635SKent Overstreet /* 3cafe5635SKent Overstreet * Assorted bcache debug code 4cafe5635SKent Overstreet * 5cafe5635SKent Overstreet * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com> 6cafe5635SKent Overstreet * Copyright 2012 Google, Inc. 7cafe5635SKent Overstreet */ 8cafe5635SKent Overstreet 9cafe5635SKent Overstreet #include "bcache.h" 10cafe5635SKent Overstreet #include "btree.h" 11cafe5635SKent Overstreet #include "debug.h" 12dc9d98d6SKent Overstreet #include "extents.h" 13cafe5635SKent Overstreet 14cafe5635SKent Overstreet #include <linux/console.h> 15cafe5635SKent Overstreet #include <linux/debugfs.h> 16cafe5635SKent Overstreet #include <linux/module.h> 17cafe5635SKent Overstreet #include <linux/random.h> 18cafe5635SKent Overstreet #include <linux/seq_file.h> 19cafe5635SKent Overstreet 20df2b9431SChengguang Xu struct dentry *bcache_debug; 21cafe5635SKent Overstreet 22280481d0SKent Overstreet #ifdef CONFIG_BCACHE_DEBUG 23cafe5635SKent Overstreet 2478b77bf8SKent Overstreet #define for_each_written_bset(b, start, i) \ 2578b77bf8SKent Overstreet for (i = (start); \ 2678b77bf8SKent Overstreet (void *) i < (void *) (start) + (KEY_SIZE(&b->key) << 9) &&\ 2778b77bf8SKent Overstreet i->seq == (start)->seq; \ 28ee811287SKent Overstreet i = (void *) i + set_blocks(i, block_bytes(b->c)) * \ 29ee811287SKent Overstreet block_bytes(b->c)) 3078b77bf8SKent Overstreet 3178b77bf8SKent Overstreet void bch_btree_verify(struct btree *b) 32cafe5635SKent Overstreet { 33cafe5635SKent Overstreet struct btree *v = b->c->verify_data; 3478b77bf8SKent Overstreet struct bset *ondisk, *sorted, *inmemory; 3578b77bf8SKent Overstreet struct bio *bio; 36cafe5635SKent Overstreet 3778b77bf8SKent Overstreet if (!b->c->verify || !b->c->verify_ondisk) 38cafe5635SKent Overstreet return; 39cafe5635SKent Overstreet 40cb7a583eSKent Overstreet down(&b->io_mutex); 41cafe5635SKent Overstreet mutex_lock(&b->c->verify_lock); 42cafe5635SKent Overstreet 4378b77bf8SKent Overstreet ondisk = b->c->verify_ondisk; 44a85e968eSKent Overstreet sorted = b->c->verify_data->keys.set->data; 45a85e968eSKent Overstreet inmemory = b->keys.set->data; 4678b77bf8SKent Overstreet 47cafe5635SKent Overstreet bkey_copy(&v->key, &b->key); 48cafe5635SKent Overstreet v->written = 0; 49cafe5635SKent Overstreet v->level = b->level; 50a85e968eSKent Overstreet v->keys.ops = b->keys.ops; 51cafe5635SKent Overstreet 5278b77bf8SKent Overstreet bio = bch_bbio_alloc(b->c); 5374d46992SChristoph Hellwig bio_set_dev(bio, PTR_CACHE(b->c, &b->key, 0)->bdev); 5478b77bf8SKent Overstreet bio->bi_iter.bi_sector = PTR_OFFSET(&b->key, 0); 5578b77bf8SKent Overstreet bio->bi_iter.bi_size = KEY_SIZE(&v->key) << 9; 5670fd7614SChristoph Hellwig bio->bi_opf = REQ_OP_READ | REQ_META; 5778b77bf8SKent Overstreet bch_bio_map(bio, sorted); 58cafe5635SKent Overstreet 594e49ea4aSMike Christie submit_bio_wait(bio); 6078b77bf8SKent Overstreet bch_bbio_free(bio, b->c); 6178b77bf8SKent Overstreet 6278b77bf8SKent Overstreet memcpy(ondisk, sorted, KEY_SIZE(&v->key) << 9); 6378b77bf8SKent Overstreet 6478b77bf8SKent Overstreet bch_btree_node_read_done(v); 65a85e968eSKent Overstreet sorted = v->keys.set->data; 6678b77bf8SKent Overstreet 6778b77bf8SKent Overstreet if (inmemory->keys != sorted->keys || 6878b77bf8SKent Overstreet memcmp(inmemory->start, 6978b77bf8SKent Overstreet sorted->start, 70b0d30981SColy Li (void *) bset_bkey_last(inmemory) - 71b0d30981SColy Li (void *) inmemory->start)) { 7278b77bf8SKent Overstreet struct bset *i; 736f10f7d1SColy Li unsigned int j; 74cafe5635SKent Overstreet 75cafe5635SKent Overstreet console_lock(); 76cafe5635SKent Overstreet 776ae63e35SColy Li pr_err("*** in memory:\n"); 78dc9d98d6SKent Overstreet bch_dump_bset(&b->keys, inmemory, 0); 79cafe5635SKent Overstreet 806ae63e35SColy Li pr_err("*** read back in:\n"); 81dc9d98d6SKent Overstreet bch_dump_bset(&v->keys, sorted, 0); 82cafe5635SKent Overstreet 8378b77bf8SKent Overstreet for_each_written_bset(b, ondisk, i) { 846f10f7d1SColy Li unsigned int block = ((void *) i - (void *) ondisk) / 8578b77bf8SKent Overstreet block_bytes(b->c); 86cafe5635SKent Overstreet 876ae63e35SColy Li pr_err("*** on disk block %u:\n", block); 88dc9d98d6SKent Overstreet bch_dump_bset(&b->keys, i, block); 8978b77bf8SKent Overstreet } 9078b77bf8SKent Overstreet 916ae63e35SColy Li pr_err("*** block %zu not written\n", 9278b77bf8SKent Overstreet ((void *) i - (void *) ondisk) / block_bytes(b->c)); 9378b77bf8SKent Overstreet 9478b77bf8SKent Overstreet for (j = 0; j < inmemory->keys; j++) 9578b77bf8SKent Overstreet if (inmemory->d[j] != sorted->d[j]) 96cafe5635SKent Overstreet break; 97cafe5635SKent Overstreet 986ae63e35SColy Li pr_err("b->written %u\n", b->written); 9978b77bf8SKent Overstreet 100cafe5635SKent Overstreet console_unlock(); 101cafe5635SKent Overstreet panic("verify failed at %u\n", j); 102cafe5635SKent Overstreet } 103cafe5635SKent Overstreet 104cafe5635SKent Overstreet mutex_unlock(&b->c->verify_lock); 105cb7a583eSKent Overstreet up(&b->io_mutex); 106cafe5635SKent Overstreet } 107cafe5635SKent Overstreet 108220bb38cSKent Overstreet void bch_data_verify(struct cached_dev *dc, struct bio *bio) 109cafe5635SKent Overstreet { 110cafe5635SKent Overstreet struct bio *check; 1114113b88aSMing Lei struct bio_vec bv, cbv; 1124113b88aSMing Lei struct bvec_iter iter, citer = { 0 }; 113cafe5635SKent Overstreet 114c8b27accSChristoph Hellwig check = bio_kmalloc(GFP_NOIO, bio_segments(bio)); 115cafe5635SKent Overstreet if (!check) 116cafe5635SKent Overstreet return; 117c8b27accSChristoph Hellwig check->bi_disk = bio->bi_disk; 11870fd7614SChristoph Hellwig check->bi_opf = REQ_OP_READ; 119c8b27accSChristoph Hellwig check->bi_iter.bi_sector = bio->bi_iter.bi_sector; 120c8b27accSChristoph Hellwig check->bi_iter.bi_size = bio->bi_iter.bi_size; 121cafe5635SKent Overstreet 122c8b27accSChristoph Hellwig bch_bio_map(check, NULL); 12325d8be77SMing Lei if (bch_bio_alloc_pages(check, GFP_NOIO)) 124cafe5635SKent Overstreet goto out_put; 125cafe5635SKent Overstreet 1264e49ea4aSMike Christie submit_bio_wait(check); 127cafe5635SKent Overstreet 1284113b88aSMing Lei citer.bi_size = UINT_MAX; 1297988613bSKent Overstreet bio_for_each_segment(bv, bio, iter) { 1307988613bSKent Overstreet void *p1 = kmap_atomic(bv.bv_page); 1314113b88aSMing Lei void *p2; 1324113b88aSMing Lei 1334113b88aSMing Lei cbv = bio_iter_iovec(check, citer); 1344113b88aSMing Lei p2 = page_address(cbv.bv_page); 135cafe5635SKent Overstreet 1367988613bSKent Overstreet cache_set_err_on(memcmp(p1 + bv.bv_offset, 1377988613bSKent Overstreet p2 + bv.bv_offset, 1387988613bSKent Overstreet bv.bv_len), 1395ceaaad7SKent Overstreet dc->disk.c, 1405ceaaad7SKent Overstreet "verify failed at dev %s sector %llu", 1416e916a7eSColy Li dc->backing_dev_name, 1424f024f37SKent Overstreet (uint64_t) bio->bi_iter.bi_sector); 1435ceaaad7SKent Overstreet 144220bb38cSKent Overstreet kunmap_atomic(p1); 1454113b88aSMing Lei bio_advance_iter(check, &citer, bv.bv_len); 146cafe5635SKent Overstreet } 147cafe5635SKent Overstreet 148491221f8SGuoqing Jiang bio_free_pages(check); 149cafe5635SKent Overstreet out_put: 150cafe5635SKent Overstreet bio_put(check); 151cafe5635SKent Overstreet } 152cafe5635SKent Overstreet 153cafe5635SKent Overstreet #endif 154cafe5635SKent Overstreet 155cafe5635SKent Overstreet #ifdef CONFIG_DEBUG_FS 156cafe5635SKent Overstreet 157cafe5635SKent Overstreet /* XXX: cache set refcounting */ 158cafe5635SKent Overstreet 159cafe5635SKent Overstreet struct dump_iterator { 160cafe5635SKent Overstreet char buf[PAGE_SIZE]; 161cafe5635SKent Overstreet size_t bytes; 162cafe5635SKent Overstreet struct cache_set *c; 163cafe5635SKent Overstreet struct keybuf keys; 164cafe5635SKent Overstreet }; 165cafe5635SKent Overstreet 166cafe5635SKent Overstreet static bool dump_pred(struct keybuf *buf, struct bkey *k) 167cafe5635SKent Overstreet { 168cafe5635SKent Overstreet return true; 169cafe5635SKent Overstreet } 170cafe5635SKent Overstreet 171cafe5635SKent Overstreet static ssize_t bch_dump_read(struct file *file, char __user *buf, 172cafe5635SKent Overstreet size_t size, loff_t *ppos) 173cafe5635SKent Overstreet { 174cafe5635SKent Overstreet struct dump_iterator *i = file->private_data; 175cafe5635SKent Overstreet ssize_t ret = 0; 17685b1492eSKent Overstreet char kbuf[80]; 177cafe5635SKent Overstreet 178cafe5635SKent Overstreet while (size) { 179cafe5635SKent Overstreet struct keybuf_key *w; 1806f10f7d1SColy Li unsigned int bytes = min(i->bytes, size); 181cafe5635SKent Overstreet int err = copy_to_user(buf, i->buf, bytes); 1821fae7cf0SColy Li 183cafe5635SKent Overstreet if (err) 184cafe5635SKent Overstreet return err; 185cafe5635SKent Overstreet 186cafe5635SKent Overstreet ret += bytes; 187cafe5635SKent Overstreet buf += bytes; 188cafe5635SKent Overstreet size -= bytes; 189cafe5635SKent Overstreet i->bytes -= bytes; 190cafe5635SKent Overstreet memmove(i->buf, i->buf + bytes, i->bytes); 191cafe5635SKent Overstreet 192cafe5635SKent Overstreet if (i->bytes) 193cafe5635SKent Overstreet break; 194cafe5635SKent Overstreet 19572c27061SKent Overstreet w = bch_keybuf_next_rescan(i->c, &i->keys, &MAX_KEY, dump_pred); 196cafe5635SKent Overstreet if (!w) 197cafe5635SKent Overstreet break; 198cafe5635SKent Overstreet 199dc9d98d6SKent Overstreet bch_extent_to_text(kbuf, sizeof(kbuf), &w->key); 20085b1492eSKent Overstreet i->bytes = snprintf(i->buf, PAGE_SIZE, "%s\n", kbuf); 201cafe5635SKent Overstreet bch_keybuf_del(&i->keys, w); 202cafe5635SKent Overstreet } 203cafe5635SKent Overstreet 204cafe5635SKent Overstreet return ret; 205cafe5635SKent Overstreet } 206cafe5635SKent Overstreet 207cafe5635SKent Overstreet static int bch_dump_open(struct inode *inode, struct file *file) 208cafe5635SKent Overstreet { 209cafe5635SKent Overstreet struct cache_set *c = inode->i_private; 210cafe5635SKent Overstreet struct dump_iterator *i; 211cafe5635SKent Overstreet 212cafe5635SKent Overstreet i = kzalloc(sizeof(struct dump_iterator), GFP_KERNEL); 213cafe5635SKent Overstreet if (!i) 214cafe5635SKent Overstreet return -ENOMEM; 215cafe5635SKent Overstreet 216cafe5635SKent Overstreet file->private_data = i; 217cafe5635SKent Overstreet i->c = c; 21872c27061SKent Overstreet bch_keybuf_init(&i->keys); 219cafe5635SKent Overstreet i->keys.last_scanned = KEY(0, 0, 0); 220cafe5635SKent Overstreet 221cafe5635SKent Overstreet return 0; 222cafe5635SKent Overstreet } 223cafe5635SKent Overstreet 224cafe5635SKent Overstreet static int bch_dump_release(struct inode *inode, struct file *file) 225cafe5635SKent Overstreet { 226cafe5635SKent Overstreet kfree(file->private_data); 227cafe5635SKent Overstreet return 0; 228cafe5635SKent Overstreet } 229cafe5635SKent Overstreet 230cafe5635SKent Overstreet static const struct file_operations cache_set_debug_ops = { 231cafe5635SKent Overstreet .owner = THIS_MODULE, 232cafe5635SKent Overstreet .open = bch_dump_open, 233cafe5635SKent Overstreet .read = bch_dump_read, 234cafe5635SKent Overstreet .release = bch_dump_release 235cafe5635SKent Overstreet }; 236cafe5635SKent Overstreet 237cafe5635SKent Overstreet void bch_debug_init_cache_set(struct cache_set *c) 238cafe5635SKent Overstreet { 239df2b9431SChengguang Xu if (!IS_ERR_OR_NULL(bcache_debug)) { 240cafe5635SKent Overstreet char name[50]; 241cafe5635SKent Overstreet 2421fae7cf0SColy Li snprintf(name, 50, "bcache-%pU", c->sb.set_uuid); 243df2b9431SChengguang Xu c->debug = debugfs_create_file(name, 0400, bcache_debug, c, 244cafe5635SKent Overstreet &cache_set_debug_ops); 245cafe5635SKent Overstreet } 246cafe5635SKent Overstreet } 247cafe5635SKent Overstreet 248cafe5635SKent Overstreet #endif 249cafe5635SKent Overstreet 250cafe5635SKent Overstreet void bch_debug_exit(void) 251cafe5635SKent Overstreet { 252df2b9431SChengguang Xu if (!IS_ERR_OR_NULL(bcache_debug)) 253df2b9431SChengguang Xu debugfs_remove_recursive(bcache_debug); 254cafe5635SKent Overstreet } 255cafe5635SKent Overstreet 256*91bafdf0SDongbo Cao void __init bch_debug_init(void) 257cafe5635SKent Overstreet { 25878ac2107SColy Li /* 25978ac2107SColy Li * it is unnecessary to check return value of 26078ac2107SColy Li * debugfs_create_file(), we should not care 26178ac2107SColy Li * about this. 26278ac2107SColy Li */ 2631c1a2ee1SColy Li bcache_debug = debugfs_create_dir("bcache", NULL); 264cafe5635SKent Overstreet } 265