linux/drivers/staging/lustre/lnet/libcfs/debug.c
<<
>>
Prefs
   1/*
   2 * GPL HEADER START
   3 *
   4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 only,
   8 * as published by the Free Software Foundation.
   9 *
  10 * This program is distributed in the hope that it will be useful, but
  11 * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 * General Public License version 2 for more details (a copy is included
  14 * in the LICENSE file that accompanied this code).
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * version 2 along with this program; If not, see
  18 * http://www.gnu.org/licenses/gpl-2.0.html
  19 *
  20 * GPL HEADER END
  21 */
  22/*
  23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  24 * Use is subject to license terms.
  25 *
  26 * Copyright (c) 2011, 2012, Intel Corporation.
  27 */
  28/*
  29 * This file is part of Lustre, http://www.lustre.org/
  30 * Lustre is a trademark of Sun Microsystems, Inc.
  31 *
  32 * libcfs/libcfs/debug.c
  33 *
  34 * Author: Phil Schwan <phil@clusterfs.com>
  35 *
  36 */
  37
  38# define DEBUG_SUBSYSTEM S_LNET
  39
  40#include <linux/libcfs/libcfs.h>
  41#include "tracefile.h"
  42
  43static char debug_file_name[1024];
  44
  45unsigned int libcfs_subsystem_debug = ~0;
  46EXPORT_SYMBOL(libcfs_subsystem_debug);
  47module_param(libcfs_subsystem_debug, int, 0644);
  48MODULE_PARM_DESC(libcfs_subsystem_debug, "Lustre kernel debug subsystem mask");
  49
  50unsigned int libcfs_debug = (D_CANTMASK |
  51                             D_NETERROR | D_HA | D_CONFIG | D_IOCTL);
  52EXPORT_SYMBOL(libcfs_debug);
  53module_param(libcfs_debug, int, 0644);
  54MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask");
  55
  56static int libcfs_param_debug_mb_set(const char *val,
  57                                     const struct kernel_param *kp)
  58{
  59        int rc;
  60        unsigned int num;
  61
  62        rc = kstrtouint(val, 0, &num);
  63        if (rc < 0)
  64                return rc;
  65
  66        if (!*((unsigned int *)kp->arg)) {
  67                *((unsigned int *)kp->arg) = num;
  68                return 0;
  69        }
  70
  71        rc = cfs_trace_set_debug_mb(num);
  72
  73        if (!rc)
  74                *((unsigned int *)kp->arg) = cfs_trace_get_debug_mb();
  75
  76        return rc;
  77}
  78
  79/* While debug_mb setting look like unsigned int, in fact
  80 * it needs quite a bunch of extra processing, so we define special
  81 * debugmb parameter type with corresponding methods to handle this case
  82 */
  83static const struct kernel_param_ops param_ops_debugmb = {
  84        .set = libcfs_param_debug_mb_set,
  85        .get = param_get_uint,
  86};
  87
  88#define param_check_debugmb(name, p) \
  89                __param_check(name, p, unsigned int)
  90
  91static unsigned int libcfs_debug_mb;
  92module_param(libcfs_debug_mb, debugmb, 0644);
  93MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size.");
  94
  95unsigned int libcfs_printk = D_CANTMASK;
  96module_param(libcfs_printk, uint, 0644);
  97MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask");
  98
  99unsigned int libcfs_console_ratelimit = 1;
 100module_param(libcfs_console_ratelimit, uint, 0644);
 101MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)");
 102
 103static int param_set_delay_minmax(const char *val,
 104                                  const struct kernel_param *kp,
 105                                  long min, long max)
 106{
 107        long d;
 108        int sec;
 109        int rc;
 110
 111        rc = kstrtoint(val, 0, &sec);
 112        if (rc)
 113                return -EINVAL;
 114
 115        d = cfs_time_seconds(sec) / 100;
 116        if (d < min || d > max)
 117                return -EINVAL;
 118
 119        *((unsigned int *)kp->arg) = d;
 120
 121        return 0;
 122}
 123
 124static int param_get_delay(char *buffer, const struct kernel_param *kp)
 125{
 126        unsigned int d = *(unsigned int *)kp->arg;
 127
 128        return sprintf(buffer, "%u", (unsigned int)cfs_duration_sec(d * 100));
 129}
 130
 131unsigned int libcfs_console_max_delay;
 132unsigned int libcfs_console_min_delay;
 133
 134static int param_set_console_max_delay(const char *val,
 135                                       const struct kernel_param *kp)
 136{
 137        return param_set_delay_minmax(val, kp,
 138                                      libcfs_console_min_delay, INT_MAX);
 139}
 140
 141static const struct kernel_param_ops param_ops_console_max_delay = {
 142        .set = param_set_console_max_delay,
 143        .get = param_get_delay,
 144};
 145
 146#define param_check_console_max_delay(name, p) \
 147                __param_check(name, p, unsigned int)
 148
 149module_param(libcfs_console_max_delay, console_max_delay, 0644);
 150MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)");
 151
 152static int param_set_console_min_delay(const char *val,
 153                                       const struct kernel_param *kp)
 154{
 155        return param_set_delay_minmax(val, kp,
 156                                      1, libcfs_console_max_delay);
 157}
 158
 159static const struct kernel_param_ops param_ops_console_min_delay = {
 160        .set = param_set_console_min_delay,
 161        .get = param_get_delay,
 162};
 163
 164#define param_check_console_min_delay(name, p) \
 165                __param_check(name, p, unsigned int)
 166
 167module_param(libcfs_console_min_delay, console_min_delay, 0644);
 168MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)");
 169
 170static int param_set_uint_minmax(const char *val,
 171                                 const struct kernel_param *kp,
 172                                 unsigned int min, unsigned int max)
 173{
 174        unsigned int num;
 175        int ret;
 176
 177        if (!val)
 178                return -EINVAL;
 179        ret = kstrtouint(val, 0, &num);
 180        if (ret < 0 || num < min || num > max)
 181                return -EINVAL;
 182        *((unsigned int *)kp->arg) = num;
 183        return 0;
 184}
 185
 186static int param_set_uintpos(const char *val, const struct kernel_param *kp)
 187{
 188        return param_set_uint_minmax(val, kp, 1, -1);
 189}
 190
 191static const struct kernel_param_ops param_ops_uintpos = {
 192        .set = param_set_uintpos,
 193        .get = param_get_uint,
 194};
 195
 196#define param_check_uintpos(name, p) \
 197                __param_check(name, p, unsigned int)
 198
 199unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
 200module_param(libcfs_console_backoff, uintpos, 0644);
 201MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor");
 202
 203unsigned int libcfs_debug_binary = 1;
 204
 205unsigned int libcfs_stack = 3 * THREAD_SIZE / 4;
 206EXPORT_SYMBOL(libcfs_stack);
 207
 208unsigned int libcfs_catastrophe;
 209EXPORT_SYMBOL(libcfs_catastrophe);
 210
 211unsigned int libcfs_panic_on_lbug = 1;
 212module_param(libcfs_panic_on_lbug, uint, 0644);
 213MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG");
 214
 215static wait_queue_head_t debug_ctlwq;
 216
 217char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT;
 218
 219/* We need to pass a pointer here, but elsewhere this must be a const */
 220static char *libcfs_debug_file_path;
 221module_param(libcfs_debug_file_path, charp, 0644);
 222MODULE_PARM_DESC(libcfs_debug_file_path,
 223                 "Path for dumping debug logs, set 'NONE' to prevent log dumping");
 224
 225int libcfs_panic_in_progress;
 226
 227/* libcfs_debug_token2mask() expects the returned string in lower-case */
 228static const char *
 229libcfs_debug_subsys2str(int subsys)
 230{
 231        static const char * const libcfs_debug_subsystems[] =
 232                LIBCFS_DEBUG_SUBSYS_NAMES;
 233
 234        if (subsys >= ARRAY_SIZE(libcfs_debug_subsystems))
 235                return NULL;
 236
 237        return libcfs_debug_subsystems[subsys];
 238}
 239
 240/* libcfs_debug_token2mask() expects the returned string in lower-case */
 241static const char *
 242libcfs_debug_dbg2str(int debug)
 243{
 244        static const char * const libcfs_debug_masks[] =
 245                LIBCFS_DEBUG_MASKS_NAMES;
 246
 247        if (debug >= ARRAY_SIZE(libcfs_debug_masks))
 248                return NULL;
 249
 250        return libcfs_debug_masks[debug];
 251}
 252
 253int
 254libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys)
 255{
 256        const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str :
 257                                                 libcfs_debug_dbg2str;
 258        int len = 0;
 259        const char *token;
 260        int i;
 261
 262        if (!mask) {                    /* "0" */
 263                if (size > 0)
 264                        str[0] = '0';
 265                len = 1;
 266        } else {                                /* space-separated tokens */
 267                for (i = 0; i < 32; i++) {
 268                        if (!(mask & (1 << i)))
 269                                continue;
 270
 271                        token = fn(i);
 272                        if (!token)           /* unused bit */
 273                                continue;
 274
 275                        if (len > 0) {            /* separator? */
 276                                if (len < size)
 277                                        str[len] = ' ';
 278                                len++;
 279                        }
 280
 281                        while (*token) {
 282                                if (len < size)
 283                                        str[len] = *token;
 284                                token++;
 285                                len++;
 286                        }
 287                }
 288        }
 289
 290        /* terminate 'str' */
 291        if (len < size)
 292                str[len] = 0;
 293        else
 294                str[size - 1] = 0;
 295
 296        return len;
 297}
 298
 299int
 300libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
 301{
 302        const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str :
 303                                                 libcfs_debug_dbg2str;
 304        int m = 0;
 305        int matched;
 306        int n;
 307        int t;
 308
 309        /* Allow a number for backwards compatibility */
 310
 311        for (n = strlen(str); n > 0; n--)
 312                if (!isspace(str[n - 1]))
 313                        break;
 314        matched = n;
 315        t = sscanf(str, "%i%n", &m, &matched);
 316        if (t >= 1 && matched == n) {
 317                /* don't print warning for lctl set_param debug=0 or -1 */
 318                if (m && m != -1)
 319                        CWARN("You are trying to use a numerical value for the mask - this will be deprecated in a future release.\n");
 320                *mask = m;
 321                return 0;
 322        }
 323
 324        return cfs_str2mask(str, fn, mask, is_subsys ? 0 : D_CANTMASK,
 325                            0xffffffff);
 326}
 327
 328/**
 329 * Dump Lustre log to ::debug_file_path by calling tracefile_dump_all_pages()
 330 */
 331void libcfs_debug_dumplog_internal(void *arg)
 332{
 333        static time64_t last_dump_time;
 334        time64_t current_time;
 335        void *journal_info;
 336
 337        journal_info = current->journal_info;
 338        current->journal_info = NULL;
 339        current_time = ktime_get_real_seconds();
 340
 341        if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) &&
 342            current_time > last_dump_time) {
 343                last_dump_time = current_time;
 344                snprintf(debug_file_name, sizeof(debug_file_name) - 1,
 345                         "%s.%lld.%ld", libcfs_debug_file_path_arr,
 346                         (s64)current_time, (long)arg);
 347                pr_alert("LustreError: dumping log to %s\n", debug_file_name);
 348                cfs_tracefile_dump_all_pages(debug_file_name);
 349                libcfs_run_debug_log_upcall(debug_file_name);
 350        }
 351
 352        current->journal_info = journal_info;
 353}
 354
 355static int libcfs_debug_dumplog_thread(void *arg)
 356{
 357        libcfs_debug_dumplog_internal(arg);
 358        wake_up(&debug_ctlwq);
 359        return 0;
 360}
 361
 362void libcfs_debug_dumplog(void)
 363{
 364        wait_queue_entry_t wait;
 365        struct task_struct *dumper;
 366
 367        /* we're being careful to ensure that the kernel thread is
 368         * able to set our state to running as it exits before we
 369         * get to schedule()
 370         */
 371        init_waitqueue_entry(&wait, current);
 372        add_wait_queue(&debug_ctlwq, &wait);
 373
 374        dumper = kthread_run(libcfs_debug_dumplog_thread,
 375                             (void *)(long)current_pid(),
 376                             "libcfs_debug_dumper");
 377        set_current_state(TASK_INTERRUPTIBLE);
 378        if (IS_ERR(dumper))
 379                pr_err("LustreError: cannot start log dump thread: %ld\n",
 380                       PTR_ERR(dumper));
 381        else
 382                schedule();
 383
 384        /* be sure to teardown if cfs_create_thread() failed */
 385        remove_wait_queue(&debug_ctlwq, &wait);
 386        set_current_state(TASK_RUNNING);
 387}
 388EXPORT_SYMBOL(libcfs_debug_dumplog);
 389
 390int libcfs_debug_init(unsigned long bufsize)
 391{
 392        unsigned int max = libcfs_debug_mb;
 393        int rc = 0;
 394
 395        init_waitqueue_head(&debug_ctlwq);
 396
 397        if (libcfs_console_max_delay <= 0 || /* not set by user or */
 398            libcfs_console_min_delay <= 0 || /* set to invalid values */
 399            libcfs_console_min_delay >= libcfs_console_max_delay) {
 400                libcfs_console_max_delay = CDEBUG_DEFAULT_MAX_DELAY;
 401                libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY;
 402        }
 403
 404        if (libcfs_debug_file_path) {
 405                strlcpy(libcfs_debug_file_path_arr,
 406                        libcfs_debug_file_path,
 407                        sizeof(libcfs_debug_file_path_arr));
 408        }
 409
 410        /* If libcfs_debug_mb is set to an invalid value or uninitialized
 411         * then just make the total buffers smp_num_cpus * TCD_MAX_PAGES
 412         */
 413        if (max > cfs_trace_max_debug_mb() || max < num_possible_cpus()) {
 414                max = TCD_MAX_PAGES;
 415        } else {
 416                max = max / num_possible_cpus();
 417                max <<= (20 - PAGE_SHIFT);
 418        }
 419
 420        rc = cfs_tracefile_init(max);
 421        if (!rc) {
 422                libcfs_register_panic_notifier();
 423                libcfs_debug_mb = cfs_trace_get_debug_mb();
 424        }
 425
 426        return rc;
 427}
 428
 429int libcfs_debug_cleanup(void)
 430{
 431        libcfs_unregister_panic_notifier();
 432        cfs_tracefile_exit();
 433        return 0;
 434}
 435
 436int libcfs_debug_clear_buffer(void)
 437{
 438        cfs_trace_flush_pages();
 439        return 0;
 440}
 441
 442/* Debug markers, although printed by S_LNET should not be be marked as such. */
 443#undef DEBUG_SUBSYSTEM
 444#define DEBUG_SUBSYSTEM S_UNDEFINED
 445int libcfs_debug_mark_buffer(const char *text)
 446{
 447        CDEBUG(D_TRACE,
 448               "***************************************************\n");
 449        LCONSOLE(D_WARNING, "DEBUG MARKER: %s\n", text);
 450        CDEBUG(D_TRACE,
 451               "***************************************************\n");
 452
 453        return 0;
 454}
 455
 456#undef DEBUG_SUBSYSTEM
 457#define DEBUG_SUBSYSTEM S_LNET
 458