diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2022-08-22 23:12:11 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:41 -0400 |
commit | 96d994b37cfcf468bf1d71527ae95ad93a311e38 (patch) | |
tree | d87dc4766e6ccf5a7d32b995a9749d2ee8583eec /fs/bcachefs/debug.c | |
parent | 33bd5d068603f9e81e0b73dbe50e9b88b2e56d0d (diff) |
bcachefs: Print deadlock cycle in debugfs
In the event that we're not finished debugging the cycle detector, this
adds a new file to debugfs that shows what the cycle detector finds, if
anything. By comparing this with btree_transactions, which shows held
locks for every btree_transaction, we'll be able to determine if it's
the cycle detector that's buggy or something else.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/debug.c')
-rw-r--r-- | fs/bcachefs/debug.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 6944dfef5bcb..41b2772afef9 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c @@ -11,6 +11,7 @@ #include "btree_cache.h" #include "btree_io.h" #include "btree_iter.h" +#include "btree_locking.h" #include "btree_update.h" #include "buckets.h" #include "debug.h" @@ -708,6 +709,45 @@ static const struct file_operations lock_held_stats_op = { .read = lock_held_stats_read, }; +static ssize_t bch2_btree_deadlock_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct dump_iter *i = file->private_data; + struct bch_fs *c = i->c; + struct btree_trans *trans; + ssize_t ret = 0; + + i->ubuf = buf; + i->size = size; + i->ret = 0; + + if (i->iter) + goto out; + + mutex_lock(&c->btree_trans_lock); + list_for_each_entry(trans, &c->btree_trans_list, list) + if (bch2_check_for_deadlock(trans, &i->buf)) { + i->iter = 1; + break; + } + mutex_unlock(&c->btree_trans_lock); +out: + if (i->buf.allocation_failure) + ret = -ENOMEM; + + if (!ret) + ret = flush_buf(i); + + return ret ?: i->ret; +} + +static const struct file_operations btree_deadlock_ops = { + .owner = THIS_MODULE, + .open = bch2_dump_open, + .release = bch2_dump_release, + .read = bch2_btree_deadlock_read, +}; + void bch2_fs_debug_exit(struct bch_fs *c) { if (!IS_ERR_OR_NULL(c->fs_debug_dir)) @@ -741,6 +781,9 @@ void bch2_fs_debug_init(struct bch_fs *c) debugfs_create_file("btree_transaction_stats", 0400, c->fs_debug_dir, c, &lock_held_stats_op); + debugfs_create_file("btree_deadlock", 0400, c->fs_debug_dir, + c->btree_debug, &btree_deadlock_ops); + c->btree_debug_dir = debugfs_create_dir("btrees", c->fs_debug_dir); if (IS_ERR_OR_NULL(c->btree_debug_dir)) return; |