summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-02-12 23:15:53 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-06-20 22:52:26 -0400
commit16d9bb0d05fa8bd47d0445e4039d3994895b5535 (patch)
treefbf21741dd8d9ccaba6fcaed512cb5ef10ebb4a4
parent5145797398be4ac878c25a20134f64edaf8f2180 (diff)
bcachefs: New backtrace utility code
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/btree_locking.c2
-rw-r--r--fs/bcachefs/debug.c2
-rw-r--r--fs/bcachefs/util.c44
-rw-r--r--fs/bcachefs/util.h8
4 files changed, 44 insertions, 12 deletions
diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c
index d09e42381fb3..a411f5c5e3b2 100644
--- a/fs/bcachefs/btree_locking.c
+++ b/fs/bcachefs/btree_locking.c
@@ -191,7 +191,7 @@ static noinline int break_cycle(struct lock_graph *g, struct printbuf *cycle)
prt_printf(&buf, "backtrace:");
prt_newline(&buf);
printbuf_indent_add(&buf, 2);
- bch2_prt_backtrace(&buf, trans->locking_wait.task);
+ bch2_prt_task_backtrace(&buf, trans->locking_wait.task);
printbuf_indent_sub(&buf, 2);
prt_newline(&buf);
}
diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c
index fcefd55a5322..8f43581f3972 100644
--- a/fs/bcachefs/debug.c
+++ b/fs/bcachefs/debug.c
@@ -527,7 +527,7 @@ static ssize_t bch2_btree_transactions_read(struct file *file, char __user *buf,
prt_printf(&i->buf, "backtrace:");
prt_newline(&i->buf);
printbuf_indent_add(&i->buf, 2);
- bch2_prt_backtrace(&i->buf, trans->locking_wait.task);
+ bch2_prt_task_backtrace(&i->buf, trans->locking_wait.task);
printbuf_indent_sub(&i->buf, 2);
prt_newline(&i->buf);
diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c
index 38b3f24fe476..bf8029f8c170 100644
--- a/fs/bcachefs/util.c
+++ b/fs/bcachefs/util.c
@@ -266,22 +266,48 @@ void bch2_print_string_as_lines(const char *prefix, const char *lines)
console_unlock();
}
-int bch2_prt_backtrace(struct printbuf *out, struct task_struct *task)
+int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *task)
{
- unsigned long entries[32];
- unsigned i, nr_entries;
+ unsigned nr_entries = 0;
+ int ret = 0;
+
+ stack->nr = 0;
+ ret = darray_make_room(stack, 32);
+ if (ret)
+ return ret;
if (!down_read_trylock(&task->signal->exec_update_lock))
- return 0;
+ return -1;
+
+ do {
+ nr_entries = stack_trace_save_tsk(task, stack->data, stack->size, 0);
+ } while (nr_entries == stack->size &&
+ !(ret = darray_make_room(stack, stack->size * 2)));
+
+ stack->nr = nr_entries;
+ up_read(&task->signal->exec_update_lock);
- nr_entries = stack_trace_save_tsk(task, entries, ARRAY_SIZE(entries), 0);
- for (i = 0; i < nr_entries; i++) {
- prt_printf(out, "[<0>] %pB", (void *)entries[i]);
+ return ret;
+}
+
+void bch2_prt_backtrace(struct printbuf *out, bch_stacktrace *stack)
+{
+ unsigned long *i;
+
+ darray_for_each(*stack, i) {
+ prt_printf(out, "[<0>] %pB", (void *) *i);
prt_newline(out);
}
+}
- up_read(&task->signal->exec_update_lock);
- return 0;
+int bch2_prt_task_backtrace(struct printbuf *out, struct task_struct *task)
+{
+ bch_stacktrace stack = { 0 };
+ int ret = bch2_save_backtrace(&stack, task);
+
+ bch2_prt_backtrace(out, &stack);
+ darray_exit(&stack);
+ return ret;
}
/* time stats: */
diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h
index faecf8b5c03b..a41544f5a397 100644
--- a/fs/bcachefs/util.h
+++ b/fs/bcachefs/util.h
@@ -19,6 +19,8 @@
#include <linux/workqueue.h>
#include <linux/mean_and_variance.h>
+#include "darray.h"
+
struct closure;
#ifdef CONFIG_BCACHEFS_DEBUG
@@ -360,7 +362,11 @@ u64 bch2_read_flag_list(char *, const char * const[]);
void bch2_prt_u64_binary(struct printbuf *, u64, unsigned);
void bch2_print_string_as_lines(const char *prefix, const char *lines);
-int bch2_prt_backtrace(struct printbuf *, struct task_struct *);
+
+typedef DARRAY(unsigned long) bch_stacktrace;
+int bch2_save_backtrace(bch_stacktrace *stack, struct task_struct *);
+void bch2_prt_backtrace(struct printbuf *, bch_stacktrace *);
+int bch2_prt_task_backtrace(struct printbuf *, struct task_struct *);
#define NR_QUANTILES 15
#define QUANTILE_IDX(i) inorder_to_eytzinger0(i, NR_QUANTILES)