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