]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bcachefs: Make btree_deadlock_to_text() clearer
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 23 Jun 2024 00:59:09 +0000 (20:59 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 23 Jun 2024 04:57:21 +0000 (00:57 -0400)
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: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/debug.c

index 8ec2d44e4956edede156923b4e0aaebdbcf3ffc3..ecfdb21ebade9fa9b33726e516341595791ebfb4 100644 (file)
@@ -802,48 +802,54 @@ static const struct file_operations btree_transaction_stats_op = {
        .read           = btree_transaction_stats_read,
 };
 
-static ssize_t bch2_btree_deadlock_read(struct file *file, char __user *buf,
-                                           size_t size, loff_t *ppos)
+/* walk btree transactions until we find a deadlock and print it */
+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;
-       ssize_t ret = 0;
-
-       i->ubuf = buf;
-       i->size = size;
-       i->ret  = 0;
-
-       if (i->iter)
-               goto out;
+       pid_t iter = 0;
 restart:
        seqmutex_lock(&c->btree_trans_lock);
        list_for_each_entry(trans, &c->btree_trans_list, list) {
                struct task_struct *task = READ_ONCE(trans->locking_wait.task);
 
-               if (!task || task->pid <= i->iter)
+               if (!task || task->pid <= iter)
                        continue;
 
+               iter = task->pid;
+
                closure_get(&trans->ref);
-               u32 seq = seqmutex_unlock(&c->btree_trans_lock);
 
-               ret = flush_buf(i);
-               if (ret) {
-                       closure_put(&trans->ref);
-                       goto out;
-               }
+               u32 seq = seqmutex_unlock(&c->btree_trans_lock);
 
-               bch2_check_for_deadlock(trans, &i->buf);
-
-               i->iter = task->pid;
+               bool found = bch2_check_for_deadlock(trans, out) != 0;
 
                closure_put(&trans->ref);
 
+               if (found)
+                       return;
+
                if (!seqmutex_relock(&c->btree_trans_lock, seq))
                        goto restart;
        }
        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)
                ret = -ENOMEM;