X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=libcfs%2Flibcfs%2Flinux%2Flinux-debug.c;h=46fbc2911821ba8aa92ed28b18b4cdc878f0f406;hb=4f6be250fdfa6530886597d13d3d1377c90e20a7;hp=b8a49820eff7fe3845a5398c5ffa2a885bbcd067;hpb=6a2efe954715cef16683e3215094f855e654533b;p=fs%2Flustre-release.git diff --git a/libcfs/libcfs/linux/linux-debug.c b/libcfs/libcfs/linux/linux-debug.c index b8a4982..46fbc29 100644 --- a/libcfs/libcfs/linux/linux-debug.c +++ b/libcfs/libcfs/linux/linux-debug.c @@ -1,6 +1,4 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * GPL HEADER START * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -17,17 +15,15 @@ * * You should have received a copy of the GNU General Public License * version 2 along with this program; If not, see - * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf - * - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, - * CA 95054 USA or visit www.sun.com if you need additional information or - * have any questions. + * http://www.gnu.org/licenses/gpl-2.0.html * * GPL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. + * + * Copyright (c) 2012, 2017, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -38,46 +34,26 @@ * Author: Phil Schwan */ -#ifndef EXPORT_SYMTAB -# define EXPORT_SYMTAB -#endif - -#ifndef AUTOCONF_INCLUDED -#include -#endif -#include +#include +#include +#include #include +#include #include -#include -#include -#include -#include -#include +#ifdef HAVE_KERNEL_LOCKED #include +#endif +#include #include -#include -#include -#include -#include - -#include -#include -#include -#include -#include +#include +#include # define DEBUG_SUBSYSTEM S_LNET #include -#include #include "tracefile.h" -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) -#include -#endif - -char lnet_upcall[1024] = "/usr/lib/lustre/lnet_upcall"; char lnet_debug_log_upcall[1024] = "/usr/lib/lustre/lnet_debug_log_upcall"; /** @@ -102,7 +78,7 @@ void libcfs_run_debug_log_upcall(char *file) argv[2] = NULL; - rc = USERMODEHELPER(argv[0], argv, envp); + rc = call_usermodehelper(argv[0], argv, envp, 1); if (rc < 0 && rc != -ENOENT) { CERROR("Error %d invoking LNET debug log upcall %s %s; " "check /proc/sys/lnet/debug_log_upcall\n", @@ -115,124 +91,148 @@ void libcfs_run_debug_log_upcall(char *file) EXIT; } -void libcfs_run_upcall(char **argv) +/* coverity[+kill] */ +void lbug_with_loc(struct libcfs_debug_msg_data *msgdata) { - int rc; - int argc; - char *envp[] = { - "HOME=/", - "PATH=/sbin:/bin:/usr/sbin:/usr/bin", - NULL}; - ENTRY; + libcfs_catastrophe = 1; + libcfs_debug_msg(msgdata, "LBUG\n"); + + if (in_interrupt()) { + panic("LBUG in interrupt.\n"); + /* not reached */ + } + + libcfs_debug_dumpstack(NULL); + if (libcfs_panic_on_lbug) + panic("LBUG"); + else + libcfs_debug_dumplog(); + set_current_state(TASK_UNINTERRUPTIBLE); + while (1) + schedule(); +} +EXPORT_SYMBOL(lbug_with_loc); - argv[0] = lnet_upcall; - argc = 1; - while (argv[argc] != NULL) - argc++; +#ifdef CONFIG_STACKTRACE - LASSERT(argc >= 2); +#define MAX_ST_ENTRIES 100 +static DEFINE_SPINLOCK(st_lock); - rc = USERMODEHELPER(argv[0], argv, envp); - if (rc < 0 && rc != -ENOENT) { - CERROR("Error %d invoking LNET upcall %s %s%s%s%s%s%s%s%s; " - "check /proc/sys/lnet/upcall\n", - rc, argv[0], argv[1], - argc < 3 ? "" : ",", argc < 3 ? "" : argv[2], - argc < 4 ? "" : ",", argc < 4 ? "" : argv[3], - argc < 5 ? "" : ",", argc < 5 ? "" : argv[4], - argc < 6 ? "" : ",..."); - } else { - CDEBUG(D_HA, "Invoked LNET upcall %s %s%s%s%s%s%s%s%s\n", - argv[0], argv[1], - argc < 3 ? "" : ",", argc < 3 ? "" : argv[2], - argc < 4 ? "" : ",", argc < 4 ? "" : argv[3], - argc < 5 ? "" : ",", argc < 5 ? "" : argv[4], - argc < 6 ? "" : ",..."); - } +static void libcfs_call_trace(struct task_struct *tsk) +{ + struct stack_trace trace; + static unsigned long entries[MAX_ST_ENTRIES]; + + trace.nr_entries = 0; + trace.max_entries = MAX_ST_ENTRIES; + trace.entries = entries; + trace.skip = 0; + + spin_lock(&st_lock); + pr_info("Pid: %d, comm: %.20s %s %s\n", tsk->pid, tsk->comm, + init_utsname()->release, init_utsname()->version); + pr_info("Call Trace:\n"); + save_stack_trace_tsk(tsk, &trace); + print_stack_trace(&trace, 0); + spin_unlock(&st_lock); } -void libcfs_run_lbug_upcall(const char *file, const char *fn, const int line) -{ - char *argv[6]; - char buf[32]; +#else /* !CONFIG_STACKTRACE */ - ENTRY; - snprintf (buf, sizeof buf, "%d", line); +#ifdef CONFIG_X86 +#include +#include - argv[1] = "LBUG"; - argv[2] = (char *)file; - argv[3] = (char *)fn; - argv[4] = buf; - argv[5] = NULL; +#ifdef HAVE_STACKTRACE_OPS +#ifdef HAVE_STACKTRACE_WARNING +static void +print_trace_warning_symbol(void *data, char *msg, unsigned long symbol) +{ + printk("%s", (char *)data); + print_symbol(msg, symbol); + printk("\n"); +} - libcfs_run_upcall (argv); +static void print_trace_warning(void *data, char *msg) +{ + printk("%s%s\n", (char *)data, msg); } +#endif -#ifdef __arch_um__ -void lbug_with_loc(const char *file, const char *func, const int line) +static int print_trace_stack(void *data, char *name) { - libcfs_catastrophe = 1; - libcfs_debug_msg(NULL, 0, D_EMERG, file, func, line, - "LBUG - trying to dump log to %s\n", debug_file_path); - libcfs_debug_dumplog(); - libcfs_run_lbug_upcall(file, func, line); - asm("int $3"); - panic("LBUG"); + printk(" <%s> ", name); + return 0; } + +#ifdef STACKTRACE_OPS_ADDRESS_RETURN_INT +static int #else -/* coverity[+kill] */ -void lbug_with_loc(const char *file, const char *func, const int line) +static void +#endif +print_trace_address(void *data, unsigned long addr, int reliable) { - libcfs_catastrophe = 1; - libcfs_debug_msg(NULL, 0, D_EMERG, file, func, line, "LBUG\n"); + char fmt[32]; - if (in_interrupt()) { - panic("LBUG in interrupt.\n"); - /* not reached */ - } + touch_nmi_watchdog(); + sprintf(fmt, " [<%016lx>] %s%%s\n", addr, reliable ? "": "? "); + __print_symbol(fmt, addr); +#ifdef STACKTRACE_OPS_ADDRESS_RETURN_INT + return 0; +#endif +} - libcfs_debug_dumpstack(NULL); - if (!libcfs_panic_on_lbug) - libcfs_debug_dumplog(); - libcfs_run_lbug_upcall(file, func, line); - if (libcfs_panic_on_lbug) - panic("LBUG"); - set_task_state(current, TASK_UNINTERRUPTIBLE); - while (1) - schedule(); +static const struct stacktrace_ops print_trace_ops = { +#ifdef HAVE_STACKTRACE_WARNING + .warning = print_trace_warning, + .warning_symbol = print_trace_warning_symbol, +#endif + .stack = print_trace_stack, + .address = print_trace_address, +#ifdef STACKTRACE_OPS_HAVE_WALK_STACK + .walk_stack = print_context_stack, +#endif +}; +#endif /* HAVE_STACKTRACE_OPS */ + +static void libcfs_call_trace(struct task_struct *tsk) +{ +#ifdef HAVE_STACKTRACE_OPS + printk("Pid: %d, comm: %.20s\n", tsk->pid, tsk->comm); + printk("\nCall Trace:\n"); + dump_trace(tsk, NULL, NULL, +#ifdef HAVE_DUMP_TRACE_ADDRESS + 0, +#endif /* HAVE_DUMP_TRACE_ADDRESS */ + &print_trace_ops, NULL); + printk("\n"); +#else /* !HAVE_STACKTRACE_OPS */ + if (tsk == current) + dump_stack(); + else + CWARN("can't show stack: kernel doesn't export show_task\n"); +#endif /* HAVE_STACKTRACE_OPS */ } -#endif /* __arch_um__ */ -#ifdef __KERNEL__ +#else /* !CONFIG_X86 */ -void libcfs_debug_dumpstack(struct task_struct *tsk) +static void libcfs_call_trace(struct task_struct *tsk) { -#if defined(__arch_um__) - if (tsk != NULL) - CWARN("stack dump for pid %d (%d) requested; wake up gdb.\n", - tsk->pid, UML_PID(tsk)); - //asm("int $3"); -#elif defined(HAVE_SHOW_TASK) - /* this is exported by lustre kernel version 42 */ - extern void show_task(struct task_struct *); - - if (tsk == NULL) - tsk = current; - CWARN("showing stack for process %d\n", tsk->pid); - show_task(tsk); -#else - if ((tsk == NULL) || (tsk == current)) - dump_stack(); - else - CWARN("can't show stack: kernel doesn't export show_task\n"); -#endif + if (tsk == current) + dump_stack(); + else + CWARN("can't show stack: kernel doesn't export show_task\n"); } -cfs_task_t *libcfs_current(void) +#endif /* CONFIG_X86 */ + +#endif /* CONFIG_STACKTRACE */ + +void libcfs_debug_dumpstack(struct task_struct *tsk) { - CWARN("current task struct is %p\n", current); - return current; + libcfs_call_trace(tsk ?: current); } +EXPORT_SYMBOL(libcfs_debug_dumpstack); static int panic_notifier(struct notifier_block *self, unsigned long unused1, void *unused2) @@ -248,46 +248,30 @@ static int panic_notifier(struct notifier_block *self, unsigned long unused1, * console on the rare cases it is ever triggered. */ if (in_interrupt()) { - trace_debug_print(); + cfs_trace_debug_print(); } else { - while (current->lock_depth >= 0) - unlock_kernel(); - - libcfs_debug_dumplog_internal((void *)(long)cfs_curproc_pid()); +#ifdef HAVE_KERNEL_LOCKED + while (kernel_locked()) + unlock_kernel(); +#endif + libcfs_debug_dumplog_internal((void *)(long)current_pid()); } #endif return 0; } static struct notifier_block libcfs_panic_notifier = { - notifier_call : panic_notifier, - next : NULL, - priority : 10000 + .notifier_call = panic_notifier, + .next = NULL, + .priority = 10000 }; void libcfs_register_panic_notifier(void) { -#ifdef HAVE_ATOMIC_PANIC_NOTIFIER atomic_notifier_chain_register(&panic_notifier_list, &libcfs_panic_notifier); -#else - notifier_chain_register(&panic_notifier_list, &libcfs_panic_notifier); -#endif } void libcfs_unregister_panic_notifier(void) { -#ifdef HAVE_ATOMIC_PANIC_NOTIFIER atomic_notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier); -#else - notifier_chain_unregister(&panic_notifier_list, &libcfs_panic_notifier); -#endif } - -EXPORT_SYMBOL(libcfs_debug_dumpstack); -EXPORT_SYMBOL(libcfs_current); - -#endif /* __KERNEL__ */ - -EXPORT_SYMBOL(libcfs_run_upcall); -EXPORT_SYMBOL(libcfs_run_lbug_upcall); -EXPORT_SYMBOL(lbug_with_loc);