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 btree=%s l=%u\n", b, bch2_btree_id_str(b->c.btree_id), b->c.level); 476 477 printbuf_indent_add(out, 2); 478 479 bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(&b->key)); 480 prt_newline(out); 481 482 prt_printf(out, "flags:\t"); 483 prt_bitflags(out, bch2_btree_node_flags, b->flags); 484 prt_newline(out); 485 486 prt_printf(out, "pcpu read locks:\t%u\n", b->c.lock.readers != NULL); 487 prt_printf(out, "written:\t%u\n", b->written); 488 prt_printf(out, "writes blocked:\t%u\n", !list_empty_careful(&b->write_blocked)); 489 prt_printf(out, "will make reachable:\t%lx\n", b->will_make_reachable); 490 491 prt_printf(out, "journal pin %px:\t%llu\n", 492 &b->writes[0].journal, b->writes[0].journal.seq); 493 prt_printf(out, "journal pin %px:\t%llu\n", 494 &b->writes[1].journal, b->writes[1].journal.seq); 495 496 printbuf_indent_sub(out, 2); 497 } 498 499 static ssize_t bch2_cached_btree_nodes_read(struct file *file, char __user *buf, 500 size_t size, loff_t *ppos) 501 { 502 struct dump_iter *i = file->private_data; 503 struct bch_fs *c = i->c; 504 bool done = false; 505 ssize_t ret = 0; 506 507 i->ubuf = buf; 508 i->size = size; 509 i->ret = 0; 510 511 do { 512 struct bucket_table *tbl; 513 struct rhash_head *pos; 514 struct btree *b; 515 516 ret = flush_buf(i); 517 if (ret) 518 return ret; 519 520 rcu_read_lock(); 521 i->buf.atomic++; 522 tbl = rht_dereference_rcu(c->btree_cache.table.tbl, 523 &c->btree_cache.table); 524 if (i->iter < tbl->size) { 525 rht_for_each_entry_rcu(b, pos, tbl, i->iter, hash) 526 bch2_cached_btree_node_to_text(&i->buf, c, b); 527 i->iter++; 528 } else { 529 done = true; 530 } 531 --i->buf.atomic; 532 rcu_read_unlock(); 533 } while (!done); 534 535 if (i->buf.allocation_failure) 536 ret = -ENOMEM; 537 538 if (!ret) 539 ret = flush_buf(i); 540 541 return ret ?: i->ret; 542 } 543 544 static const struct file_operations cached_btree_nodes_ops = { 545 .owner = THIS_MODULE, 546 .open = bch2_dump_open, 547 .release = bch2_dump_release, 548 .read = bch2_cached_btree_nodes_read, 549 }; 550 551 typedef int (*list_cmp_fn)(const struct list_head *l, const struct list_head *r); 552 553 static void list_sort(struct list_head *head, list_cmp_fn cmp) 554 { 555 struct list_head *pos; 556 557 list_for_each(pos, head) 558 while (!list_is_last(pos, head) && 559 cmp(pos, pos->next) > 0) { 560 struct list_head *pos2, *next = pos->next; 561 562 list_del(next); 563 list_for_each(pos2, head) 564 if (cmp(next, pos2) < 0) 565 goto pos_found; 566 BUG(); 567 pos_found: 568 list_add_tail(next, pos2); 569 } 570 } 571 572 static int list_ptr_order_cmp(const struct list_head *l, const struct list_head *r) 573 { 574 return cmp_int(l, r); 575 } 576 577 static ssize_t bch2_btree_transactions_read(struct file *file, char __user *buf, 578 size_t size, loff_t *ppos) 579 { 580 struct dump_iter *i = file->private_data; 581 struct bch_fs *c = i->c; 582 struct btree_trans *trans; 583 ssize_t ret = 0; 584 585 i->ubuf = buf; 586 i->size = size; 587 i->ret = 0; 588 restart: 589 seqmutex_lock(&c->btree_trans_lock); 590 list_sort(&c->btree_trans_list, list_ptr_order_cmp); 591 592 list_for_each_entry(trans, &c->btree_trans_list, list) { 593 if ((ulong) trans <= i->iter) 594 continue; 595 596 i->iter = (ulong) trans; 597 598 if (!closure_get_not_zero(&trans->ref)) 599 continue; 600 601 u32 seq = seqmutex_unlock(&c->btree_trans_lock); 602 603 bch2_btree_trans_to_text(&i->buf, trans); 604 605 prt_printf(&i->buf, "backtrace:\n"); 606 printbuf_indent_add(&i->buf, 2); 607 bch2_prt_task_backtrace(&i->buf, trans->locking_wait.task, 0, GFP_KERNEL); 608 printbuf_indent_sub(&i->buf, 2); 609 prt_newline(&i->buf); 610 611 closure_put(&trans->ref); 612 613 ret = flush_buf(i); 614 if (ret) 615 goto unlocked; 616 617 if (!seqmutex_relock(&c->btree_trans_lock, seq)) 618 goto restart; 619 } 620 seqmutex_unlock(&c->btree_trans_lock); 621 unlocked: 622 if (i->buf.allocation_failure) 623 ret = -ENOMEM; 624 625 if (!ret) 626 ret = flush_buf(i); 627 628 return ret ?: i->ret; 629 } 630 631 static const struct file_operations btree_transactions_ops = { 632 .owner = THIS_MODULE, 633 .open = bch2_dump_open, 634 .release = bch2_dump_release, 635 .read = bch2_btree_transactions_read, 636 }; 637 638 static ssize_t bch2_journal_pins_read(struct file *file, char __user *buf, 639 size_t size, loff_t *ppos) 640 { 641 struct dump_iter *i = file->private_data; 642 struct bch_fs *c = i->c; 643 bool done = false; 644 int err; 645 646 i->ubuf = buf; 647 i->size = size; 648 i->ret = 0; 649 650 while (1) { 651 err = flush_buf(i); 652 if (err) 653 return err; 654 655 if (!i->size) 656 break; 657 658 if (done) 659 break; 660 661 done = bch2_journal_seq_pins_to_text(&i->buf, &c->journal, &i->iter); 662 i->iter++; 663 } 664 665 if (i->buf.allocation_failure) 666 return -ENOMEM; 667 668 return i->ret; 669 } 670 671 static const struct file_operations journal_pins_ops = { 672 .owner = THIS_MODULE, 673 .open = bch2_dump_open, 674 .release = bch2_dump_release, 675 .read = bch2_journal_pins_read, 676 }; 677 678 static ssize_t bch2_btree_updates_read(struct file *file, char __user *buf, 679 size_t size, loff_t *ppos) 680 { 681 struct dump_iter *i = file->private_data; 682 struct bch_fs *c = i->c; 683 int err; 684 685 i->ubuf = buf; 686 i->size = size; 687 i->ret = 0; 688 689 if (!i->iter) { 690 bch2_btree_updates_to_text(&i->buf, c); 691 i->iter++; 692 } 693 694 err = flush_buf(i); 695 if (err) 696 return err; 697 698 if (i->buf.allocation_failure) 699 return -ENOMEM; 700 701 return i->ret; 702 } 703 704 static const struct file_operations btree_updates_ops = { 705 .owner = THIS_MODULE, 706 .open = bch2_dump_open, 707 .release = bch2_dump_release, 708 .read = bch2_btree_updates_read, 709 }; 710 711 static int btree_transaction_stats_open(struct inode *inode, struct file *file) 712 { 713 struct bch_fs *c = inode->i_private; 714 struct dump_iter *i; 715 716 i = kzalloc(sizeof(struct dump_iter), GFP_KERNEL); 717 if (!i) 718 return -ENOMEM; 719 720 i->iter = 1; 721 i->c = c; 722 i->buf = PRINTBUF; 723 file->private_data = i; 724 725 return 0; 726 } 727 728 static int btree_transaction_stats_release(struct inode *inode, struct file *file) 729 { 730 struct dump_iter *i = file->private_data; 731 732 printbuf_exit(&i->buf); 733 kfree(i); 734 735 return 0; 736 } 737 738 static ssize_t btree_transaction_stats_read(struct file *file, char __user *buf, 739 size_t size, loff_t *ppos) 740 { 741 struct dump_iter *i = file->private_data; 742 struct bch_fs *c = i->c; 743 int err; 744 745 i->ubuf = buf; 746 i->size = size; 747 i->ret = 0; 748 749 while (1) { 750 struct btree_transaction_stats *s = &c->btree_transaction_stats[i->iter]; 751 752 err = flush_buf(i); 753 if (err) 754 return err; 755 756 if (!i->size) 757 break; 758 759 if (i->iter == ARRAY_SIZE(bch2_btree_transaction_fns) || 760 !bch2_btree_transaction_fns[i->iter]) 761 break; 762 763 prt_printf(&i->buf, "%s:\n", bch2_btree_transaction_fns[i->iter]); 764 printbuf_indent_add(&i->buf, 2); 765 766 mutex_lock(&s->lock); 767 768 prt_printf(&i->buf, "Max mem used: %u\n", s->max_mem); 769 prt_printf(&i->buf, "Transaction duration:\n"); 770 771 printbuf_indent_add(&i->buf, 2); 772 bch2_time_stats_to_text(&i->buf, &s->duration); 773 printbuf_indent_sub(&i->buf, 2); 774 775 if (IS_ENABLED(CONFIG_BCACHEFS_LOCK_TIME_STATS)) { 776 prt_printf(&i->buf, "Lock hold times:\n"); 777 778 printbuf_indent_add(&i->buf, 2); 779 bch2_time_stats_to_text(&i->buf, &s->lock_hold_times); 780 printbuf_indent_sub(&i->buf, 2); 781 } 782 783 if (s->max_paths_text) { 784 prt_printf(&i->buf, "Maximum allocated btree paths (%u):\n", s->nr_max_paths); 785 786 printbuf_indent_add(&i->buf, 2); 787 prt_str_indented(&i->buf, s->max_paths_text); 788 printbuf_indent_sub(&i->buf, 2); 789 } 790 791 mutex_unlock(&s->lock); 792 793 printbuf_indent_sub(&i->buf, 2); 794 prt_newline(&i->buf); 795 i->iter++; 796 } 797 798 if (i->buf.allocation_failure) 799 return -ENOMEM; 800 801 return i->ret; 802 } 803 804 static const struct file_operations btree_transaction_stats_op = { 805 .owner = THIS_MODULE, 806 .open = btree_transaction_stats_open, 807 .release = btree_transaction_stats_release, 808 .read = btree_transaction_stats_read, 809 }; 810 811 /* walk btree transactions until we find a deadlock and print it */ 812 static void btree_deadlock_to_text(struct printbuf *out, struct bch_fs *c) 813 { 814 struct btree_trans *trans; 815 ulong iter = 0; 816 restart: 817 seqmutex_lock(&c->btree_trans_lock); 818 list_sort(&c->btree_trans_list, list_ptr_order_cmp); 819 820 list_for_each_entry(trans, &c->btree_trans_list, list) { 821 if ((ulong) trans <= iter) 822 continue; 823 824 iter = (ulong) trans; 825 826 if (!closure_get_not_zero(&trans->ref)) 827 continue; 828 829 u32 seq = seqmutex_unlock(&c->btree_trans_lock); 830 831 bool found = bch2_check_for_deadlock(trans, out) != 0; 832 833 closure_put(&trans->ref); 834 835 if (found) 836 return; 837 838 if (!seqmutex_relock(&c->btree_trans_lock, seq)) 839 goto restart; 840 } 841 seqmutex_unlock(&c->btree_trans_lock); 842 } 843 844 static ssize_t bch2_btree_deadlock_read(struct file *file, char __user *buf, 845 size_t size, loff_t *ppos) 846 { 847 struct dump_iter *i = file->private_data; 848 struct bch_fs *c = i->c; 849 ssize_t ret = 0; 850 851 i->ubuf = buf; 852 i->size = size; 853 i->ret = 0; 854 855 if (!i->iter) { 856 btree_deadlock_to_text(&i->buf, c); 857 i->iter++; 858 } 859 860 if (i->buf.allocation_failure) 861 ret = -ENOMEM; 862 863 if (!ret) 864 ret = flush_buf(i); 865 866 return ret ?: i->ret; 867 } 868 869 static const struct file_operations btree_deadlock_ops = { 870 .owner = THIS_MODULE, 871 .open = bch2_dump_open, 872 .release = bch2_dump_release, 873 .read = bch2_btree_deadlock_read, 874 }; 875 876 void bch2_fs_debug_exit(struct bch_fs *c) 877 { 878 if (!IS_ERR_OR_NULL(c->fs_debug_dir)) 879 debugfs_remove_recursive(c->fs_debug_dir); 880 } 881 882 static void bch2_fs_debug_btree_init(struct bch_fs *c, struct btree_debug *bd) 883 { 884 struct dentry *d; 885 886 d = debugfs_create_dir(bch2_btree_id_str(bd->id), c->btree_debug_dir); 887 888 debugfs_create_file("keys", 0400, d, bd, &btree_debug_ops); 889 890 debugfs_create_file("formats", 0400, d, bd, &btree_format_debug_ops); 891 892 debugfs_create_file("bfloat-failed", 0400, d, bd, 893 &bfloat_failed_debug_ops); 894 } 895 896 void bch2_fs_debug_init(struct bch_fs *c) 897 { 898 struct btree_debug *bd; 899 char name[100]; 900 901 if (IS_ERR_OR_NULL(bch_debug)) 902 return; 903 904 snprintf(name, sizeof(name), "%pU", c->sb.user_uuid.b); 905 c->fs_debug_dir = debugfs_create_dir(name, bch_debug); 906 if (IS_ERR_OR_NULL(c->fs_debug_dir)) 907 return; 908 909 debugfs_create_file("cached_btree_nodes", 0400, c->fs_debug_dir, 910 c->btree_debug, &cached_btree_nodes_ops); 911 912 debugfs_create_file("btree_transactions", 0400, c->fs_debug_dir, 913 c->btree_debug, &btree_transactions_ops); 914 915 debugfs_create_file("journal_pins", 0400, c->fs_debug_dir, 916 c->btree_debug, &journal_pins_ops); 917 918 debugfs_create_file("btree_updates", 0400, c->fs_debug_dir, 919 c->btree_debug, &btree_updates_ops); 920 921 debugfs_create_file("btree_transaction_stats", 0400, c->fs_debug_dir, 922 c, &btree_transaction_stats_op); 923 924 debugfs_create_file("btree_deadlock", 0400, c->fs_debug_dir, 925 c->btree_debug, &btree_deadlock_ops); 926 927 c->btree_debug_dir = debugfs_create_dir("btrees", c->fs_debug_dir); 928 if (IS_ERR_OR_NULL(c->btree_debug_dir)) 929 return; 930 931 for (bd = c->btree_debug; 932 bd < c->btree_debug + ARRAY_SIZE(c->btree_debug); 933 bd++) { 934 bd->id = bd - c->btree_debug; 935 bch2_fs_debug_btree_init(c, bd); 936 } 937 } 938 939 #endif 940 941 void bch2_debug_exit(void) 942 { 943 if (!IS_ERR_OR_NULL(bch_debug)) 944 debugfs_remove_recursive(bch_debug); 945 } 946 947 int __init bch2_debug_init(void) 948 { 949 bch_debug = debugfs_create_dir("bcachefs", NULL); 950 return 0; 951 } 952