#ifdef __KERNEL__
+#ifdef HAVE_DUMP_TRACE
+#include <linux/nmi.h>
+#include <asm/stacktrace.h>
+
+static void
+print_trace_warning_symbol(void *data, char *msg, unsigned long symbol)
+{
+ printk(data);
+ print_symbol(msg, symbol);
+ printk("\n");
+}
+
+static void print_trace_warning(void *data, char *msg)
+{
+ printk("%s%s\n", (char *)data, msg);
+}
+
+static int print_trace_stack(void *data, char *name)
+{
+ printk(" <%s> ", name);
+ return 0;
+}
+
+#ifdef HAVE_TRACE_ADDRESS_RELIABLE
+# define RELIABLE reliable
+# define DUMP_TRACE_CONST const
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+#else
+/* before 2.6.24 there was no reliable arg */
+# define RELIABLE 1
+# define DUMP_TRACE_CONST
+static void print_trace_address(void *data, unsigned long addr)
+#endif
+{
+ char fmt[32];
+ touch_nmi_watchdog();
+ sprintf(fmt, " [<%016lx>] %s%%s\n", addr, RELIABLE ? "": "? ");
+ __print_symbol(fmt, addr);
+}
+
+static DUMP_TRACE_CONST struct stacktrace_ops print_trace_ops = {
+ .warning = print_trace_warning,
+ .warning_symbol = print_trace_warning_symbol,
+ .stack = print_trace_stack,
+ .address = print_trace_address,
+};
+#endif
+
void libcfs_debug_dumpstack(struct task_struct *tsk)
{
#if defined(__arch_um__)
CWARN("stack dump for pid %d (%d) requested; wake up gdb.\n",
tsk->pid, UML_PID(tsk));
//asm("int $3");
+#elif defined(HAVE_DUMP_TRACE)
+ /* dump_stack() */
+ /* show_trace() */
+ printk("Pid: %d, comm: %.20s\n", current->pid, current->comm);
+ /* show_trace_log_lvl() */
+ printk("\nCall Trace:\n");
+ dump_trace(tsk, NULL, NULL,
+#ifdef HAVE_TRACE_ADDRESS_RELIABLE
+ 0,
+#endif /* HAVE_TRACE_ADDRESS_RELIABLE */
+ &print_trace_ops, NULL);
+ printk("\n");
#elif defined(HAVE_SHOW_TASK)
/* this is exported by lustre kernel version 42 */
extern void show_task(struct task_struct *);
static void
lcw_dump(struct lc_watchdog *lcw)
{
- cfs_task_t *tsk;
+ ENTRY;
#if defined(HAVE_TASKLIST_LOCK)
read_lock(&tasklist_lock);
#elif defined(HAVE_TASK_RCU)
rcu_read_lock();
#else
CERROR("unable to dump stack because of missing export\n");
- return;
+ RETURN_EXIT;
#endif
- ENTRY;
-
- tsk = find_task_by_pid(lcw->lcw_pid);
-
- if (tsk == NULL) {
+ if (lcw->lcw_task == NULL) {
CWARN("Process " LPPID " was not found in the task list; "
- "watchdog callback may be incomplete\n", lcw->lcw_pid);
- } else if (tsk != lcw->lcw_task) {
- CWARN("The current process " LPPID " did not set the watchdog; "
- "watchdog callback may be incomplete\n", lcw->lcw_pid);
+ "watchdog callback may be incomplete\n",
+ (int)lcw->lcw_pid);
} else {
- libcfs_debug_dumpstack(tsk);
+ libcfs_debug_dumpstack(lcw->lcw_task);
}
#if defined(HAVE_TASKLIST_LOCK)
])
+#
+# LN_FUNC_DUMP_TRACE
+#
+# 2.6.23 exports dump_trace() so we can dump_stack() on any task
+# 2.6.24 has stacktrace_ops.address with "reliable" parameter
+#
+AC_DEFUN([LN_FUNC_DUMP_TRACE],
+[LB_CHECK_SYMBOL_EXPORT([dump_trace],
+[kernel/ksyms.c arch/${LINUX_ARCH%_64}/kernel/traps_64.c],[
+ AC_DEFINE(HAVE_DUMP_TRACE, 1, [dump_trace is exported])
+ AC_MSG_CHECKING([whether print_trace_address has reliable argument])
+ tmp_flags="$EXTRA_KCFLAGS"
+ EXTRA_KCFLAGS="-Werror"
+ LB_LINUX_TRY_COMPILE([
+ struct task_struct;
+ struct pt_regs;
+ void print_addr(void *data, unsigned long addr, int reliable);
+ #include <asm/stacktrace.h>
+ ],[
+ struct stacktrace_ops ops;
+
+ ops.address = print_addr;
+ ],[
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_TRACE_ADDRESS_RELIABLE, 1,
+ [print_trace_address has reliable argument])
+ ],[
+ AC_MSG_RESULT(no)
+ ],[
+ ])
+EXTRA_KCFLAGS="$tmp_flags"
+])
+])
#
# LN_PROG_LINUX
LN_CONFIG_RALND
LN_CONFIG_PTLLND
LN_CONFIG_MX
+LN_FUNC_DUMP_TRACE
])
#