])
])
+#
+# LN_FUNC_DUMP_TRACE
+#
+# 2.6.27 exports dump_trace() so we can dump_stack() on any task
+#
+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])
+],[
+])
+])
+
# 2.6.27 have second argument to sock_map_fd
AC_DEFUN([LN_SOCK_MAP_FD_2ARG],
[AC_MSG_CHECKING([sock_map_fd have second argument])
LN_SEM_COUNT
# 2.6.27
LN_SOCK_MAP_FD_2ARG
+LN_FUNC_DUMP_TRACE
])
#
#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;
+}
+
+void printk_address(unsigned long address, int reliable)
+{
+ printk(" [<%016lx>] %s%pS\n", address, reliable ? "": "? ", (void *) address);
+}
+
+static void print_trace_address(void *data, unsigned long addr, int reliable)
+{
+ touch_nmi_watchdog();
+ printk_address(addr, reliable);
+}
+
+static 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__)
tsk = current;
CWARN("showing stack for process %d\n", tsk->pid);
show_task(tsk);
+#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, 0, &print_trace_ops, "");
+ printk("\n");
#else
if ((tsk == NULL) || (tsk == current))
dump_stack();
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 %d was not found in the task list; "
- "watchdog callback may be incomplete\n", (int)lcw->lcw_pid);
- } else if (tsk != lcw->lcw_task) {
- CWARN("The current process %d did not set the watchdog; "
- "watchdog callback may be incomplete\n", (int)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)