1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Assorted bcachefs debug code 4 * 5 * Copyright 2010, 2011 Kent Overstreet <kent.overstreet@gmail.com> 6 * Copyright 2012 Google, Inc. 7 */ 8 9 #include "bcachefs.h" 10 #include "bkey_methods.h" 11 #include "btree_cache.h" 12 #include "btree_io.h" 13 #include "btree_iter.h" 14 #include "btree_locking.h" 15 #include "btree_update.h" 16 #include "btree_update_interior.h" 17 #include "buckets.h" 18 #include "debug.h" 19 #include "error.h" 20 #include "extents.h" 21 #include "fsck.h" 22 #include "inode.h" 23 #include "super.h" 24 25 #include <linux/console.h> 26 #include <linux/debugfs.h> 27 #include <linux/module.h> 28 #include <linux/random.h> 29 #include <linux/seq_file.h> 30 31 static struct dentry *bch_debug; 32 33 static bool bch2_btree_verify_replica(struct bch_fs *c, struct btree *b, 34 struct extent_ptr_decoded pick) 35 { 36 struct btree *v = c->verify_data; 37 struct btree_node *n_ondisk = c->verify_ondisk; 38 struct btree_node *n_sorted = c->verify_data->data; 39 struct bset *sorted, *inmemory = &b->data->keys; 40 struct bio *bio; 41 bool failed = false, saw_error = false; 42 43 struct bch_dev *ca = bch2_dev_get_ioref(c, pick.ptr.dev, READ); 44 if (!ca) 45 return false; 46 47 bio = bio_alloc_bioset(ca->disk_sb.bdev, 48 buf_pages(n_sorted, btree_buf_bytes(b)), 49 REQ_OP_READ|REQ_META, 50 GFP_NOFS, 51 &c->btree_bio); 52 bio->bi_iter.bi_sector = pick.ptr.offset; 53 bch2_bio_map(bio, n_sorted, btree_buf_bytes(b)); 54 55 submit_bio_wait(bio); 56 57 bio_put(bio); 58 percpu_ref_put(&ca->io_ref); 59 60 memcpy(n_ondisk, n_sorted, btree_buf_bytes(b)); 61 62 v->written = 0; 63 if (bch2_btree_node_read_done(c, ca, v, false, &saw_error) || saw_error) 64 return false; 65 66 n_sorted = c->verify_data->data; 67 sorted = &n_sorted->keys; 68 69 if (inmemory->u64s != sorted->u64s || 70 memcmp(inmemory->start, 71 sorted->start, 72 vstruct_end(inmemory) - (void *) inmemory->start)) { 73 unsigned offset = 0, sectors; 74 struct bset *i; 75 unsigned j; 76 77 console_lock(); 78 79 printk(KERN_ERR "*** in memory:\n"); 80 bch2_dump_bset(c, b, inmemory, 0); 81 82 printk(KERN_ERR "*** read back in:\n"); 83 bch2_dump_bset(c, v, sorted, 0); 84 85 while (offset < v->written) { 86 if (!offset) { 87 i = &n_ondisk->keys; 88 sectors = vstruct_blocks(n_ondisk, c->block_bits) << 89 c->block_bits; 90 } else { 91 struct btree_node_entry *bne = 92 (void *) n_ondisk + (offset << 9); 93 i = &bne->keys; 94 95 sectors = vstruct_blocks(bne, c->block_bits) << 96 c->block_bits; 97 } 98 99 printk(KERN_ERR "*** on disk block %u:\n", offset); 100 bch2_dump_bset(c, b, i, offset); 101 102 offset += sectors; 103 } 104 105 for (j = 0; j < le16_to_cpu(inmemory->u64s); j++) 106 if (inmemory->_data[j] != sorted->_data[j]) 107 break; 108 109 console_unlock(); 110 bch_err(c, "verify failed at key %u", j); 111 112 failed = true; 113 } 114 115 if (v->written != b->written) { 116 bch_err(c, "written wrong: expected %u, got %u", 117 b->written, v->written); 118 failed = true; 119 } 120 121 return failed; 122 } 123 124 void __bch2_btree_verify(struct bch_fs *c, struct btree *b) 125 { 126 struct bkey_ptrs_c ptrs; 127 struct extent_ptr_decoded p; 128 const union bch_extent_entry *entry; 129 struct btree *v; 130 struct bset *inmemory = &b->data->keys; 131 struct bkey_packed *k; 132 bool failed = false; 133 134 if (c->opts.nochanges) 135 return; 136 137 bch2_btree_node_io_lock(b); 138 mutex_lock(&c->verify_lock); 139 140 if (!c->verify_ondisk) { 141 c->verify_ondisk = kvmalloc(btree_buf_bytes(b), GFP_KERNEL); 142 if (!c->verify_ondisk) 143 goto out; 144 } 145 146 if (!c->verify_data) { 147 c->verify_data = __bch2_btree_node_mem_alloc(c); 148 if (!c->verify_data) 149 goto out; 150 151 list_del_init(&c->verify_data->list); 152 } 153 154 BUG_ON(b->nsets != 1); 155 156 for (k = inmemory->start; k != vstruct_last(inmemory); k = bkey_p_next(k)) 157 if (k->type == KEY_TYPE_btree_ptr_v2) 158 ((struct bch_btree_ptr_v2 *) bkeyp_val(&b->format, k))->mem_ptr = 0; 159 160 v = c->verify_data; 161 bkey_copy(&v->key, &b->key); 162 v->c.level = b->c.level; 163 v->c.btree_id = b->c.btree_id; 164 bch2_btree_keys_init(v); 165 166 ptrs = bch2_bkey_ptrs_c(bkey_i_to_s_c(&b->key)); 167 bkey_for_each_ptr_decode(&b->key.k, ptrs, p, entry) 168 failed |= bch2_btree_verify_replica(c, b, p); 169 170 if (failed) { 171 struct printbuf buf = PRINTBUF; 172 173 bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(&b->key)); 174 bch2_fs_fatal_error(c, ": btree node verify failed for: %s\n", buf.buf); 175 printbuf_exit(&buf); 176 } 177 out: 178 mutex_unlock(&c->verify_lock); 179 bch2_btree_node_io_unlock(b); 180 } 181 182 void bch2_btree_node_ondisk_to_text(struct printbuf *out, struct bch_fs *c, 183 const struct btree *b) 184 { 185 struct btree_node *n_ondisk = NULL; 186 struct extent_ptr_decoded pick; 187 struct bch_dev *ca; 188 struct bio *bio = NULL; 189 unsigned offset = 0; 190 int ret; 191 192 if (bch2_bkey_pick_read_device(c, bkey_i_to_s_c(&b->key), NULL, &pick) <= 0) { 193 prt_printf(out, "error getting device to read from: invalid device\n"); 194 return; 195 } 196 197 ca = bch2_dev_get_ioref(c, pick.ptr.dev, READ); 198 if (!ca) { 199 prt_printf(out, "error getting device to read from: not online\n"); 200 return; 201 } 202 203 n_ondisk = kvmalloc(btree_buf_bytes(b), GFP_KERNEL); 204 if (!n_ondisk) { 205 prt_printf(out, "memory allocation failure\n"); 206 goto out; 207 } 208 209 bio = bio_alloc_bioset(ca->disk_sb.bdev, 210 buf_pages(n_ondisk, btree_buf_bytes(b)), 211 REQ_OP_READ|REQ_META, 212 GFP_NOFS, 213 &c->btree_bio); 214 bio->bi_iter.bi_sector = pick.ptr.offset; 215 bch2_bio_map(bio, n_ondisk, btree_buf_bytes(b)); 216 217 ret = submit_bio_wait(bio); 218 if (ret) { 219 prt_printf(out, "IO error reading btree node: %s\n", bch2_err_str(ret)); 220 goto out; 221 } 222 223 while (offset < btree_sectors(c)) { 224 struct bset *i; 225 struct nonce nonce; 226 struct bch_csum csum; 227 struct bkey_packed *k; 228 unsigned sectors; 229 230 if (!offset) { 231 i = &n_ondisk->keys; 232 233 if (!bch2_checksum_type_valid(c, BSET_CSUM_TYPE(i))) { 234 prt_printf(out, "unknown checksum type at offset %u: %llu\n", 235 offset, BSET_CSUM_TYPE(i)); 236 goto out; 237 } 238 239 nonce = btree_nonce(i, offset << 9); 240 csum = csum_vstruct(c, BSET_CSUM_TYPE(i), nonce, n_ondisk); 241 242 if (bch2_crc_cmp(csum, n_ondisk->csum)) { 243 prt_printf(out, "invalid checksum\n"); 244 goto out; 245 } 246 247 bset_encrypt(c, i, offset << 9); 248 249 sectors = vstruct_sectors(n_ondisk, c->block_bits); 250 } else { 251 struct btree_node_entry *bne = (void *) n_ondisk + (offset << 9); 252 253 i = &bne->keys; 254 255 if (i->seq != n_ondisk->keys.seq) 256 break; 257 258 if (!bch2_checksum_type_valid(c, BSET_CSUM_TYPE(i))) { 259 prt_printf(out, "unknown checksum type at offset %u: %llu\n", 260 offset, BSET_CSUM_TYPE(i)); 261 goto out; 262 } 263 264 nonce = btree_nonce(i, offset << 9); 265 csum = csum_vstruct(c, BSET_CSUM_TYPE(i), nonce, bne); 266 267 if (bch2_crc_cmp(csum, bne->csum)) { 268 prt_printf(out, "invalid checksum"); 269 goto out; 270 } 271 272 bset_encrypt(c, i, offset << 9); 273 274 sectors = vstruct_sectors(bne, c->block_bits); 275 } 276 277 prt_printf(out, " offset %u version %u, journal seq %llu\n", 278 offset, 279 le16_to_cpu(i->version), 280 le64_to_cpu(i->journal_seq)); 281 offset += sectors; 282 283 printbuf_indent_add(out, 4); 284 285 for (k = i->start; k != vstruct_last(i); k = bkey_p_next(k)) { 286 struct bkey u; 287 288 bch2_bkey_val_to_text(out, c, bkey_disassemble(b, k, &u)); 289 prt_newline(out); 290 } 291 292 printbuf_indent_sub(out, 4); 293 } 294 out: 295 if (bio) 296 bio_put(bio); 297 kvfree(n_ondisk); 298 percpu_ref_put(&ca->io_ref); 299 } 300 301 #ifdef CONFIG_DEBUG_FS 302 303 /* XXX: bch_fs refcounting */ 304 305 struct dump_iter { 306 struct bch_fs *c; 307 enum btree_id id; 308 struct bpos from; 309 struct bpos prev_node; 310 u64 iter; 311 312 struct printbuf buf; 313 314 char __user *ubuf; /* destination user buffer */ 315 size_t size; /* size of requested read */ 316 ssize_t ret; /* bytes read so far */ 317 }; 318 319 static ssize_t flush_buf(struct dump_iter *i) 320 { 321 if (i->buf.pos) { 322 size_t bytes = min_t(size_t, i->buf.pos, i->size); 323 int copied = bytes - copy_to_user(i->ubuf, i->buf.buf, bytes); 324 325 i->ret += copied; 326 i->ubuf += copied; 327 i->size -= copied; 328 i->buf.pos -= copied; 329 memmove(i->buf.buf, i->buf.buf + copied, i->buf.pos); 330 331 if (copied != bytes) 332 return -EFAULT; 333 } 334 335 return i->size ? 0 : i->ret; 336 } 337 338 static int bch2_dump_open(struct inode *inode, struct file *file) 339 { 340 struct btree_debug *bd = inode->i_private; 341 struct dump_iter *i; 342 343 i = kzalloc(sizeof(struct dump_iter), GFP_KERNEL); 344 if (!i) 345 return -ENOMEM; 346 347 file->private_data = i; 348 i->from = POS_MIN; 349 i->iter = 0; 350 i->c = container_of(bd, struct bch_fs, btree_debug[bd->id]); 351 i->id = bd->id; 352 i->buf = PRINTBUF; 353 354 return 0; 355 } 356 357 static int bch2_dump_release(struct inode *inode, struct file *file) 358 { 359 struct dump_iter *i = file->private_data; 360 361 printbuf_exit(&i->buf); 362 kfree(i); 363 return 0; 364 } 365 366 static ssize_t bch2_read_btree(struct file *file, char __user *buf, 367 size_t size, loff_t *ppos) 368 { 369 struct dump_iter *i = file->private_data; 370 371 i->ubuf = buf; 372 i->size = size; 373 i->ret = 0; 374 375 return flush_buf(i) ?: 376 bch2_trans_run(i->c, 377 for_each_btree_key(trans, iter, i->id, i->from, 378 BTREE_ITER_prefetch| 379 BTREE_ITER_all_snapshots, k, ({ 380 bch2_bkey_val_to_text(&i->buf, i->c, k); 381 prt_newline(&i->buf); 382 bch2_trans_unlock(trans); 383 i->from = bpos_successor(iter.pos); 384 flush_buf(i); 385 }))) ?: 386 i->ret; 387 } 388 389 static const struct file_operations btree_debug_ops = { 390 .owner = THIS_MODULE, 391 .open = bch2_dump_open, 392 .release = bch2_dump_release, 393 .read = bch2_read_btree, 394 }; 395 396 static ssize_t bch2_read_btree_formats(struct file *file, char __user *buf, 397 size_t size, loff_t *ppos) 398 { 399 struct dump_iter *i = file->private_data; 400 401 i->ubuf = buf; 402 i->size = size; 403 i->ret = 0; 404 405 ssize_t ret = flush_buf(i); 406 if (ret) 407 return ret; 408 409 if (bpos_eq(SPOS_MAX, i->from)) 410 return i->ret; 411 412 return bch2_trans_run(i->c, 413 for_each_btree_node(trans, iter, i->id, i->from, 0, b, ({ 414 bch2_btree_node_to_text(&i->buf, i->c, b); 415 i->from = !bpos_eq(SPOS_MAX, b->key.k.p) 416 ? bpos_successor(b->key.k.p) 417 : b->key.k.p; 418 419 drop_locks_do(trans, flush_buf(i)); 420 }))) ?: i->ret; 421 } 422 423 static const struct file_operations btree_format_debug_ops = { 424 .owner = THIS_MODULE, 425 .open = bch2_dump_open, 426 .release = bch2_dump_release, 427 .read = bch2_read_btree_formats, 428 }; 429 430 static ssize_t bch2_read_bfloat_failed(struct file *file, char __user *buf, 431 size_t size, loff_t *ppos) 432 { 433 struct dump_iter *i = file->private_data; 434 435 i->ubuf = buf; 436 i->size = size; 437 i->ret = 0; 438 439 return flush_buf(i) ?: 440 bch2_trans_run(i->c, 441 for_each_btree_key(trans, iter, i->id, i->from, 442 BTREE_ITER_prefetch| 443 BTREE_ITER_all_snapshots, k, ({ 444 struct btree_path_level *l = 445 &btree_iter_path(trans, &iter)->l[0]; 446 struct bkey_packed *_k = 447 bch2_btree_node_iter_peek(&l->iter, l->b); 448 449 if (bpos_gt(l->b->key.k.p, i->prev_node)) { 450 bch2_btree_node_to_text(&i->buf, i->c, l->b); 451 i->prev_node = l->b->key.k.p; 452 } 453 454 bch2_bfloat_to_text(&i->buf, l->b, _k); 455 bch2_trans_unlock(trans); 456 i->from = bpos_successor(iter.pos); 457 flush_buf(i); 458 }))) ?: 459 i->ret; 460 } 461 462 static const struct file_operations bfloat_failed_debug_ops = { 463 .owner = THIS_MODULE, 464 .open = bch2_dump_open, 465 .release = bch2_dump_release, 466 .read = bch2_read_bfloat_failed, 467 }; 468 469 static void bch2_cached_btree_node_to_text(struct printbuf *out, struct bch_fs *c, 470 struct btree *b) 471 { 472 if (!out->nr_tabstops) 473 printbuf_tabstop_push(out, 32); 474 475 prt_printf(out, "%px ", b); 476 bch2_btree_id_level_to_text(out, b->c.btree_id, b->c.level); 477 prt_printf(out, "\n"); 478 479 printbuf_indent_add(out, 2); 480 481 bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(&b->key)); 482 prt_newline(out); 483 484 prt_printf(out, "flags:\t"); 485 prt_bitflags(out, bch2_btree_node_flags, b->flags); 486 prt_newline(out); 487 488 prt_printf(out, "pcpu read locks:\t%u\n", b->c.lock.readers != NULL); 489 prt_printf(out, "written:\t%u\n", b->written); 490 prt_printf(out, "writes blocked:\t%u\n", !list_empty_careful(&b->write_blocked)); 491 prt_printf(out, "will make reachable:\t%lx\n", b->will_make_reachable); 492 493 prt_printf(out, "journal pin %px:\t%llu\n", 494 &b->writes[0].journal, b->writes[0].journal.seq); 495 prt_printf(out, "journal pin %px:\t%llu\n", 496 &b->writes[1].journal, b->writes[1].journal.seq); 497 498 printbuf_indent_sub(out, 2); 499 } 500 501 static ssize_t bch2_cached_btree_nodes_read(struct file *file, char __user *buf, 502 size_t size, loff_t *ppos) 503 { 504 struct dump_iter *i = file->private_data; 505 struct bch_fs *c = i->c; 506 bool done = false; 507 ssize_t ret = 0; 508 509 i->ubuf = buf; 510 i->size = size; 511 i->ret = 0; 512 513 do { 514 struct bucket_table *tbl; 515 struct rhash_head *pos; 516 struct btree *b; 517 518 ret = flush_buf(i); 519 if (ret) 520 return ret; 521 522 rcu_read_lock(); 523 i->buf.atomic++; 524 tbl = rht_dereference_rcu(c->btree_cache.table.tbl, 525 &c->btree_cache.table); 526 if (i->iter < tbl->size) { 527 rht_for_each_entry_rcu(b, pos, tbl, i->iter, hash) 528 bch2_cached_btree_node_to_text(&i->buf, c, b); 529 i->iter++; 530 } else { 531 done = true; 532 } 533 --i->buf.atomic; 534 rcu_read_unlock(); 535 } while (!done); 536 537 if (i->buf.allocation_failure) 538 ret = -ENOMEM; 539 540 if (!ret) 541 ret = flush_buf(i); 542 543 return ret ?: i->ret; 544 } 545 546 static const struct file_operations cached_btree_nodes_ops = { 547 .owner = THIS_MODULE, 548 .open = bch2_dump_open, 549 .release = bch2_dump_release, 550 .read = bch2_cached_btree_nodes_read, 551 }; 552 553 typedef int (*list_cmp_fn)(const struct list_head *l, const struct list_head *r); 554 555 static void list_sort(struct list_head *head, list_cmp_fn cmp) 556 { 557 struct list_head *pos; 558 559 list_for_each(pos, head) 560 while (!list_is_last(pos, head) && 561 cmp(pos, pos->next) > 0) { 562 struct list_head *pos2, *next = pos->next; 563 564 list_del(next); 565 list_for_each(pos2, head) 566 if (cmp(next, pos2) < 0) 567 goto pos_found; 568 BUG(); 569 pos_found: 570 list_add_tail(next, pos2); 571 } 572 } 573 574 static int list_ptr_order_cmp(const struct list_head *l, const struct list_head *r) 575 { 576 return cmp_int(l, r); 577 } 578 579 static ssize_t bch2_btree_transactions_read(struct file *file, char __user *buf, 580 size_t size, loff_t *ppos) 581 { 582 struct dump_iter *i = file->private_data; 583 struct bch_fs *c = i->c; 584 struct btree_trans *trans; 585 ssize_t ret = 0; 586 587 i->ubuf = buf; 588 i->size = size; 589 i->ret = 0; 590 restart: 591 seqmutex_lock(&c->btree_trans_lock); 592 list_sort(&c->btree_trans_list, list_ptr_order_cmp); 593 594 list_for_each_entry(trans, &c->btree_trans_list, list) { 595 if ((ulong) trans <= i->iter) 596 continue; 597 598 i->iter = (ulong) trans; 599 600 if (!closure_get_not_zero(&trans->ref)) 601 continue; 602 603 u32 seq = seqmutex_unlock(&c->btree_trans_lock); 604 605 bch2_btree_trans_to_text(&i->buf, trans); 606 607 prt_printf(&i->buf, "backtrace:\n"); 608 printbuf_indent_add(&i->buf, 2); 609 bch2_prt_task_backtrace(&i->buf, trans->locking_wait.task, 0, GFP_KERNEL); 610 printbuf_indent_sub(&i->buf, 2); 611 prt_newline(&i->buf); 612 613 closure_put(&trans->ref); 614 615 ret = flush_buf(i); 616 if (ret) 617 goto unlocked; 618 619 if (!seqmutex_relock(&c->btree_trans_lock, seq)) 620 goto restart; 621 } 622 seqmutex_unlock(&c->btree_trans_lock); 623 unlocked: 624 if (i->buf.allocation_failure) 625 ret = -ENOMEM; 626 627 if (!ret) 628 ret = flush_buf(i); 629 630 return ret ?: i->ret; 631 } 632 633 static const struct file_operations btree_transactions_ops = { 634 .owner = THIS_MODULE, 635 .open = bch2_dump_open, 636 .release = bch2_dump_release, 637 .read = bch2_btree_transactions_read, 638 }; 639 640 static ssize_t bch2_journal_pins_read(struct file *file, char __user *buf, 641 size_t size, loff_t *ppos) 642 { 643 struct dump_iter *i = file->private_data; 644 struct bch_fs *c = i->c; 645 bool done = false; 646 int err; 647 648 i->ubuf = buf; 649 i->size = size; 650 i->ret = 0; 651 652 while (1) { 653 err = flush_buf(i); 654 if (err) 655 return err; 656 657 if (!i->size) 658 break; 659 660 if (done) 661 break; 662 663 done = bch2_journal_seq_pins_to_text(&i->buf, &c->journal, &i->iter); 664 i->iter++; 665 } 666 667 if (i->buf.allocation_failure) 668 return -ENOMEM; 669 670 return i->ret; 671 } 672 673 static const struct file_operations journal_pins_ops = { 674 .owner = THIS_MODULE, 675 .open = bch2_dump_open, 676 .release = bch2_dump_release, 677 .read = bch2_journal_pins_read, 678 }; 679 680 static ssize_t bch2_btree_updates_read(struct file *file, char __user *buf, 681 size_t size, loff_t *ppos) 682 { 683 struct dump_iter *i = file->private_data; 684 struct bch_fs *c = i->c; 685 int err; 686 687 i->ubuf = buf; 688 i->size = size; 689 i->ret = 0; 690 691 if (!i->iter) { 692 bch2_btree_updates_to_text(&i->buf, c); 693 i->iter++; 694 } 695 696 err = flush_buf(i); 697 if (err) 698 return err; 699 700 if (i->buf.allocation_failure) 701 return -ENOMEM; 702 703 return i->ret; 704 } 705 706 static const struct file_operations btree_updates_ops = { 707 .owner = THIS_MODULE, 708 .open = bch2_dump_open, 709 .release = bch2_dump_release, 710 .read = bch2_btree_updates_read, 711 }; 712 713 static int btree_transaction_stats_open(struct inode *inode, struct file *file) 714 { 715 struct bch_fs *c = inode->i_private; 716 struct dump_iter *i; 717 718 i = kzalloc(sizeof(struct dump_iter), GFP_KERNEL); 719 if (!i) 720 return -ENOMEM; 721 722 i->iter = 1; 723 i->c = c; 724 i->buf = PRINTBUF; 725 file->private_data = i; 726 727 return 0; 728 } 729 730 static int btree_transaction_stats_release(struct inode *inode, struct file *file) 731 { 732 struct dump_iter *i = file->private_data; 733 734 printbuf_exit(&i->buf); 735 kfree(i); 736 737 return 0; 738 } 739 740 static ssize_t btree_transaction_stats_read(struct file *file, char __user *buf, 741 size_t size, loff_t *ppos) 742 { 743 struct dump_iter *i = file->private_data; 744 struct bch_fs *c = i->c; 745 int err; 746 747 i->ubuf = buf; 748 i->size = size; 749 i->ret = 0; 750 751 while (1) { 752 struct btree_transaction_stats *s = &c->btree_transaction_stats[i->iter]; 753 754 err = flush_buf(i); 755 if (err) 756 return err; 757 758 if (!i->size) 759 break; 760 761 if (i->iter == ARRAY_SIZE(bch2_btree_transaction_fns) || 762 !bch2_btree_transaction_fns[i->iter]) 763 break; 764 765 prt_printf(&i->buf, "%s:\n", bch2_btree_transaction_fns[i->iter]); 766 printbuf_indent_add(&i->buf, 2); 767 768 mutex_lock(&s->lock); 769 770 prt_printf(&i->buf, "Max mem used: %u\n", s->max_mem); 771 prt_printf(&i->buf, "Transaction duration:\n"); 772 773 printbuf_indent_add(&i->buf, 2); 774 bch2_time_stats_to_text(&i->buf, &s->duration); 775 printbuf_indent_sub(&i->buf, 2); 776 777 if (IS_ENABLED(CONFIG_BCACHEFS_LOCK_TIME_STATS)) { 778 prt_printf(&i->buf, "Lock hold times:\n"); 779 780 printbuf_indent_add(&i->buf, 2); 781 bch2_time_stats_to_text(&i->buf, &s->lock_hold_times); 782 printbuf_indent_sub(&i->buf, 2); 783 } 784 785 if (s->max_paths_text) { 786 prt_printf(&i->buf, "Maximum allocated btree paths (%u):\n", s->nr_max_paths); 787 788 printbuf_indent_add(&i->buf, 2); 789 prt_str_indented(&i->buf, s->max_paths_text); 790 printbuf_indent_sub(&i->buf, 2); 791 } 792 793 mutex_unlock(&s->lock); 794 795 printbuf_indent_sub(&i->buf, 2); 796 prt_newline(&i->buf); 797 i->iter++; 798 } 799 800 if (i->buf.allocation_failure) 801 return -ENOMEM; 802 803 return i->ret; 804 } 805 806 static const struct file_operations btree_transaction_stats_op = { 807 .owner = THIS_MODULE, 808 .open = btree_transaction_stats_open, 809 .release = btree_transaction_stats_release, 810 .read = btree_transaction_stats_read, 811 }; 812 813 /* walk btree transactions until we find a deadlock and print it */ 814 static void btree_deadlock_to_text(struct printbuf *out, struct bch_fs *c) 815 { 816 struct btree_trans *trans; 817 ulong iter = 0; 818 restart: 819 seqmutex_lock(&c->btree_trans_lock); 820 list_sort(&c->btree_trans_list, list_ptr_order_cmp); 821 822 list_for_each_entry(trans, &c->btree_trans_list, list) { 823 if ((ulong) trans <= iter) 824 continue; 825 826 iter = (ulong) trans; 827 828 if (!closure_get_not_zero(&trans->ref)) 829 continue; 830 831 u32 seq = seqmutex_unlock(&c->btree_trans_lock); 832 833 bool found = bch2_check_for_deadlock(trans, out) != 0; 834 835 closure_put(&trans->ref); 836 837 if (found) 838 return; 839 840 if (!seqmutex_relock(&c->btree_trans_lock, seq)) 841 goto restart; 842 } 843 seqmutex_unlock(&c->btree_trans_lock); 844 } 845 846 static ssize_t bch2_btree_deadlock_read(struct file *file, char __user *buf, 847 size_t size, loff_t *ppos) 848 { 849 struct dump_iter *i = file->private_data; 850 struct bch_fs *c = i->c; 851 ssize_t ret = 0; 852 853 i->ubuf = buf; 854 i->size = size; 855 i->ret = 0; 856 857 if (!i->iter) { 858 btree_deadlock_to_text(&i->buf, c); 859 i->iter++; 860 } 861 862 if (i->buf.allocation_failure) 863 ret = -ENOMEM; 864 865 if (!ret) 866 ret = flush_buf(i); 867 868 return ret ?: i->ret; 869 } 870 871 static const struct file_operations btree_deadlock_ops = { 872 .owner = THIS_MODULE, 873 .open = bch2_dump_open, 874 .release = bch2_dump_release, 875 .read = bch2_btree_deadlock_read, 876 }; 877 878 void bch2_fs_debug_exit(struct bch_fs *c) 879 { 880 if (!IS_ERR_OR_NULL(c->fs_debug_dir)) 881 debugfs_remove_recursive(c->fs_debug_dir); 882 } 883 884 static void bch2_fs_debug_btree_init(struct bch_fs *c, struct btree_debug *bd) 885 { 886 struct dentry *d; 887 888 d = debugfs_create_dir(bch2_btree_id_str(bd->id), c->btree_debug_dir); 889 890 debugfs_create_file("keys", 0400, d, bd, &btree_debug_ops); 891 892 debugfs_create_file("formats", 0400, d, bd, &btree_format_debug_ops); 893 894 debugfs_create_file("bfloat-failed", 0400, d, bd, 895 &bfloat_failed_debug_ops); 896 } 897 898 void bch2_fs_debug_init(struct bch_fs *c) 899 { 900 struct btree_debug *bd; 901 char name[100]; 902 903 if (IS_ERR_OR_NULL(bch_debug)) 904 return; 905 906 snprintf(name, sizeof(name), "%pU", c->sb.user_uuid.b); 907 c->fs_debug_dir = debugfs_create_dir(name, bch_debug); 908 if (IS_ERR_OR_NULL(c->fs_debug_dir)) 909 return; 910 911 debugfs_create_file("cached_btree_nodes", 0400, c->fs_debug_dir, 912 c->btree_debug, &cached_btree_nodes_ops); 913 914 debugfs_create_file("btree_transactions", 0400, c->fs_debug_dir, 915 c->btree_debug, &btree_transactions_ops); 916 917 debugfs_create_file("journal_pins", 0400, c->fs_debug_dir, 918 c->btree_debug, &journal_pins_ops); 919 920 debugfs_create_file("btree_updates", 0400, c->fs_debug_dir, 921 c->btree_debug, &btree_updates_ops); 922 923 debugfs_create_file("btree_transaction_stats", 0400, c->fs_debug_dir, 924 c, &btree_transaction_stats_op); 925 926 debugfs_create_file("btree_deadlock", 0400, c->fs_debug_dir, 927 c->btree_debug, &btree_deadlock_ops); 928 929 c->btree_debug_dir = debugfs_create_dir("btrees", c->fs_debug_dir); 930 if (IS_ERR_OR_NULL(c->btree_debug_dir)) 931 return; 932 933 for (bd = c->btree_debug; 934 bd < c->btree_debug + ARRAY_SIZE(c->btree_debug); 935 bd++) { 936 bd->id = bd - c->btree_debug; 937 bch2_fs_debug_btree_init(c, bd); 938 } 939 } 940 941 #endif 942 943 void bch2_debug_exit(void) 944 { 945 if (!IS_ERR_OR_NULL(bch_debug)) 946 debugfs_remove_recursive(bch_debug); 947 } 948 949 int __init bch2_debug_init(void) 950 { 951 bch_debug = debugfs_create_dir("bcachefs", NULL); 952 return 0; 953 } 954