Commit 18e92841 authored by Kent Overstreet's avatar Kent Overstreet

bcachefs: Make btree_deadlock_to_text() clearer

btree_deadlock_to_text() searches the list of btree transactions to find
a deadlock - when it finds one it's done; it's not like other *_read()
functions that's printing each object.

Factor out btree_deadlock_to_text() to make this clearer.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent f44cc269
...@@ -802,48 +802,54 @@ static const struct file_operations btree_transaction_stats_op = { ...@@ -802,48 +802,54 @@ static const struct file_operations btree_transaction_stats_op = {
.read = btree_transaction_stats_read, .read = btree_transaction_stats_read,
}; };
static ssize_t bch2_btree_deadlock_read(struct file *file, char __user *buf, /* walk btree transactions until we find a deadlock and print it */
size_t size, loff_t *ppos) static void btree_deadlock_to_text(struct printbuf *out, struct bch_fs *c)
{ {
struct dump_iter *i = file->private_data;
struct bch_fs *c = i->c;
struct btree_trans *trans; struct btree_trans *trans;
ssize_t ret = 0; pid_t iter = 0;
i->ubuf = buf;
i->size = size;
i->ret = 0;
if (i->iter)
goto out;
restart: restart:
seqmutex_lock(&c->btree_trans_lock); seqmutex_lock(&c->btree_trans_lock);
list_for_each_entry(trans, &c->btree_trans_list, list) { list_for_each_entry(trans, &c->btree_trans_list, list) {
struct task_struct *task = READ_ONCE(trans->locking_wait.task); struct task_struct *task = READ_ONCE(trans->locking_wait.task);
if (!task || task->pid <= i->iter) if (!task || task->pid <= iter)
continue; continue;
closure_get(&trans->ref); iter = task->pid;
u32 seq = seqmutex_unlock(&c->btree_trans_lock);
ret = flush_buf(i); closure_get(&trans->ref);
if (ret) {
closure_put(&trans->ref);
goto out;
}
bch2_check_for_deadlock(trans, &i->buf); u32 seq = seqmutex_unlock(&c->btree_trans_lock);
i->iter = task->pid; bool found = bch2_check_for_deadlock(trans, out) != 0;
closure_put(&trans->ref); closure_put(&trans->ref);
if (found)
return;
if (!seqmutex_relock(&c->btree_trans_lock, seq)) if (!seqmutex_relock(&c->btree_trans_lock, seq))
goto restart; goto restart;
} }
seqmutex_unlock(&c->btree_trans_lock); seqmutex_unlock(&c->btree_trans_lock);
out: }
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;
ssize_t ret = 0;
i->ubuf = buf;
i->size = size;
i->ret = 0;
if (!i->iter) {
btree_deadlock_to_text(&i->buf, c);
i->iter++;
}
if (i->buf.allocation_failure) if (i->buf.allocation_failure)
ret = -ENOMEM; ret = -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment