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.sun.com/software/products/lustre/docs/GPLv2.pdf
  19 *
  20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  21 * CA 95054 USA or visit www.sun.com if you need additional information or
  22 * have any questions.
  23 *
  24 * GPL HEADER END
  25 */
  26/*
  27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  28 * Use is subject to license terms.
  29 *
  30 * Copyright (c) 2011, 2012, Intel Corporation.
  31 */
  32/*
  33 * This file is part of Lustre, http://www.lustre.org/
  34 * Lustre is a trademark of Sun Microsystems, Inc.
  35 *
  36 * libcfs/libcfs/debug.c
  37 *
  38 * Author: Phil Schwan <phil@clusterfs.com>
  39 *
  40 */
  41
  42# define DEBUG_SUBSYSTEM S_LNET
  43
  44#include "../../include/linux/libcfs/libcfs.h"
  45#include "tracefile.h"
  46
  47static char debug_file_name[1024];
  48
  49unsigned int libcfs_subsystem_debug = ~0;
  50EXPORT_SYMBOL(libcfs_subsystem_debug);
  51module_param(libcfs_subsystem_debug, int, 0644);
  52MODULE_PARM_DESC(libcfs_subsystem_debug, "Lustre kernel debug subsystem mask");
  53
  54unsigned int libcfs_debug = (D_CANTMASK |
  55                             D_NETERROR | D_HA | D_CONFIG | D_IOCTL);
  56EXPORT_SYMBOL(libcfs_debug);
  57module_param(libcfs_debug, int, 0644);
  58MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask");
  59
  60static int libcfs_param_debug_mb_set(const char *val,
  61                                     const struct kernel_param *kp)
  62{
  63        int rc;
  64        unsigned num;
  65
  66        rc = kstrtouint(val, 0, &num);
  67        if (rc < 0)
  68                return rc;
  69
  70        if (!*((unsigned int *)kp->arg)) {
  71                *((unsigned int *)kp->arg) = num;
  72                return 0;
  73        }
  74
  75        rc = cfs_trace_set_debug_mb(num);
  76
  77        if (!rc)
  78                *((unsigned int *)kp->arg) = cfs_trace_get_debug_mb();
  79
  80        return rc;
  81}
  82
  83/* While debug_mb setting look like unsigned int, in fact
  84 * it needs quite a bunch of extra processing, so we define special
  85 * debugmb parameter type with corresponding methods to handle this case
  86 */
  87static struct kernel_param_ops param_ops_debugmb = {
  88        .set = libcfs_param_debug_mb_set,
  89        .get = param_get_uint,
  90};
  91
  92#define param_check_debugmb(name, p) \
  93                __param_check(name, p, unsigned int)
  94
  95static unsigned int libcfs_debug_mb;
  96module_param(libcfs_debug_mb, debugmb, 0644);
  97MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size.");
  98
  99unsigned int libcfs_printk = D_CANTMASK;
 100module_param(libcfs_printk, uint, 0644);
 101MODULE_PARM_DESC(libcfs_printk, "Lustre kernel debug console mask");
 102
 103unsigned int libcfs_console_ratelimit = 1;
 104module_param(libcfs_console_ratelimit, uint, 0644);
 105MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)");
 106
 107static int param_set_delay_minmax(const char *val,
 108                                  const struct kernel_param *kp,
 109                                  long min, long max)
 110{
 111        long d;
 112        int sec;
 113        int rc;
 114
 115        rc = kstrtoint(val, 0, &sec);
 116        if (rc)
 117                return -EINVAL;
 118
 119        d = cfs_time_seconds(sec) / 100;
 120        if (d < min || d > max)
 121                return -EINVAL;
 122
 123        *((unsigned int *)kp->arg) = d;
 124
 125        return 0;
 126}
 127
 128static int param_get_delay(char *buffer, const struct kernel_param *kp)
 129{
 130        unsigned int d = *(unsigned int *)kp->arg;
 131
 132        return sprintf(buffer, "%u", (unsigned int)cfs_duration_sec(d * 100));
 133}
 134
 135unsigned int libcfs_console_max_delay;
 136unsigned int libcfs_console_min_delay;
 137
 138static int param_set_console_max_delay(const char *val,
 139                                       const struct kernel_param *kp)
 140{
 141        return param_set_delay_minmax(val, kp,
 142                                      libcfs_console_min_delay, INT_MAX);
 143}
 144
 145static struct kernel_param_ops param_ops_console_max_delay = {
 146        .set = param_set_console_max_delay,
 147        .get = param_get_delay,
 148};
 149
 150#define param_check_console_max_delay(name, p) \
 151                __param_check(name, p, unsigned int)
 152
 153module_param(libcfs_console_max_delay, console_max_delay, 0644);
 154MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)");
 155
 156static int param_set_console_min_delay(const char *val,
 157                                       const struct kernel_param *kp)
 158{
 159        return param_set_delay_minmax(val, kp,
 160                                      1, libcfs_console_max_delay);
 161}
 162
 163static struct kernel_param_ops param_ops_console_min_delay = {
 164        .set = param_set_console_min_delay,
 165        .get = param_get_delay,
 166};
 167
 168#define param_check_console_min_delay(name, p) \
 169                __param_check(name, p, unsigned int)
 170
 171module_param(libcfs_console_min_delay, console_min_delay, 0644);
 172MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)");
 173
 174static int param_set_uint_minmax(const char *val,
 175                                 const struct kernel_param *kp,
 176                                 unsigned int min, unsigned int max)
 177{
 178        unsigned int num;
 179        int ret;
 180
 181        if (!val)
 182                return -EINVAL;
 183        ret = kstrtouint(val, 0, &num);
 184        if (ret < 0 || num < min || num > max)
 185                return -EINVAL;
 186        *((unsigned int *)kp->arg) = num;
 187        return 0;
 188}
 189
 190static int param_set_uintpos(const char *val, const struct kernel_param *kp)
 191{
 192        return param_set_uint_minmax(val, kp, 1, -1);
 193}
 194
 195static struct kernel_param_ops param_ops_uintpos = {
 196        .set = param_set_uintpos,
 197        .get = param_get_uint,
 198};
 199
 200#define param_check_uintpos(name, p) \
 201                __param_check(name, p, unsigned int)
 202
 203unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
 204module_param(libcfs_console_backoff, uintpos, 0644);
 205MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor");
 206
 207unsigned int libcfs_debug_binary = 1;
 208
 209unsigned int libcfs_stack = 3 * THREAD_SIZE / 4;
 210EXPORT_SYMBOL(libcfs_stack);
 211
 212unsigned int libcfs_catastrophe;
 213EXPORT_SYMBOL(libcfs_catastrophe);
 214
 215unsigned int libcfs_panic_on_lbug = 1;
 216module_param(libcfs_panic_on_lbug, uint, 0644);
 217MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG");
 218
 219static wait_queue_head_t debug_ctlwq;
 220
 221char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT;
 222
 223/* We need to pass a pointer here, but elsewhere this must be a const */
 224static char *libcfs_debug_file_path;
 225module_param(libcfs_debug_file_path, charp, 0644);
 226MODULE_PARM_DESC(libcfs_debug_file_path,
 227                 "Path for dumping debug logs, set 'NONE' to prevent log dumping");
 228
 229int libcfs_panic_in_progress;
 230
 231/* libcfs_debug_token2mask() expects the returned string in lower-case */
 232static const char *
 233libcfs_debug_subsys2str(int subsys)
 234{
 235        switch (1 << subsys) {
 236        default:
 237                return NULL;
 238        case S_UNDEFINED:
 239                return "undefined";
 240        case S_MDC:
 241                return "mdc";
 242        case S_MDS:
 243                return "mds";
 244        case S_OSC:
 245                return "osc";
 246        case S_OST:
 247                return "ost";
 248        case S_CLASS:
 249                return "class";
 250        case S_LOG:
 251                return "log";
 252        case S_LLITE:
 253                return "llite";
 254        case S_RPC:
 255                return "rpc";
 256        case S_LNET:
 257                return "lnet";
 258        case S_LND:
 259                return "lnd";
 260        case S_PINGER:
 261                return "pinger";
 262        case S_FILTER:
 263                return "filter";
 264        case S_ECHO:
 265                return "echo";
 266        case S_LDLM:
 267                return "ldlm";
 268        case S_LOV:
 269                return "lov";
 270        case S_LQUOTA:
 271                return "lquota";
 272        case S_OSD:
 273                return "osd";
 274        case S_LFSCK:
 275                return "lfsck";
 276        case S_LMV:
 277                return "lmv";
 278        case S_SEC:
 279                return "sec";
 280        case S_GSS:
 281                return "gss";
 282        case S_MGC:
 283                return "mgc";
 284        case S_MGS:
 285                return "mgs";
 286        case S_FID:
 287                return "fid";
 288        case S_FLD:
 289                return "fld";
 290        }
 291}
 292
 293/* libcfs_debug_token2mask() expects the returned string in lower-case */
 294static const char *
 295libcfs_debug_dbg2str(int debug)
 296{
 297        switch (1 << debug) {
 298        default:
 299                return NULL;
 300        case D_TRACE:
 301                return "trace";
 302        case D_INODE:
 303                return "inode";
 304        case D_SUPER:
 305                return "super";
 306        case D_EXT2:
 307                return "ext2";
 308        case D_MALLOC:
 309                return "malloc";
 310        case D_CACHE:
 311                return "cache";
 312        case D_INFO:
 313                return "info";
 314        case D_IOCTL:
 315                return "ioctl";
 316        case D_NETERROR:
 317                return "neterror";
 318        case D_NET:
 319                return "net";
 320        case D_WARNING:
 321                return "warning";
 322        case D_BUFFS:
 323                return "buffs";
 324        case D_OTHER:
 325                return "other";
 326        case D_DENTRY:
 327                return "dentry";
 328        case D_NETTRACE:
 329                return "nettrace";
 330        case D_PAGE:
 331                return "page";
 332        case D_DLMTRACE:
 333                return "dlmtrace";
 334        case D_ERROR:
 335                return "error";
 336        case D_EMERG:
 337                return "emerg";
 338        case D_HA:
 339                return "ha";
 340        case D_RPCTRACE:
 341                return "rpctrace";
 342        case D_VFSTRACE:
 343                return "vfstrace";
 344        case D_READA:
 345                return "reada";
 346        case D_MMAP:
 347                return "mmap";
 348        case D_CONFIG:
 349                return "config";
 350        case D_CONSOLE:
 351                return "console";
 352        case D_QUOTA:
 353                return "quota";
 354        case D_SEC:
 355                return "sec";
 356        case D_LFSCK:
 357                return "lfsck";
 358        }
 359}
 360
 361int
 362libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys)
 363{
 364        const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str :
 365                                                 libcfs_debug_dbg2str;
 366        int        len = 0;
 367        const char   *token;
 368        int        i;
 369
 370        if (mask == 0) {                        /* "0" */
 371                if (size > 0)
 372                        str[0] = '0';
 373                len = 1;
 374        } else {                                /* space-separated tokens */
 375                for (i = 0; i < 32; i++) {
 376                        if ((mask & (1 << i)) == 0)
 377                                continue;
 378
 379                        token = fn(i);
 380                        if (!token)           /* unused bit */
 381                                continue;
 382
 383                        if (len > 0) {            /* separator? */
 384                                if (len < size)
 385                                        str[len] = ' ';
 386                                len++;
 387                        }
 388
 389                        while (*token != 0) {
 390                                if (len < size)
 391                                        str[len] = *token;
 392                                token++;
 393                                len++;
 394                        }
 395                }
 396        }
 397
 398        /* terminate 'str' */
 399        if (len < size)
 400                str[len] = 0;
 401        else
 402                str[size - 1] = 0;
 403
 404        return len;
 405}
 406
 407int
 408libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
 409{
 410        const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str :
 411                                                 libcfs_debug_dbg2str;
 412        int      m = 0;
 413        int      matched;
 414        int      n;
 415        int      t;
 416
 417        /* Allow a number for backwards compatibility */
 418
 419        for (n = strlen(str); n > 0; n--)
 420                if (!isspace(str[n - 1]))
 421                        break;
 422        matched = n;
 423        t = sscanf(str, "%i%n", &m, &matched);
 424        if (t >= 1 && matched == n) {
 425                /* don't print warning for lctl set_param debug=0 or -1 */
 426                if (m != 0 && m != -1)
 427                        CWARN("You are trying to use a numerical value for the mask - this will be deprecated in a future release.\n");
 428                *mask = m;
 429                return 0;
 430        }
 431
 432        return cfs_str2mask(str, fn, mask, is_subsys ? 0 : D_CANTMASK,
 433                            0xffffffff);
 434}
 435
 436/**
 437 * Dump Lustre log to ::debug_file_path by calling tracefile_dump_all_pages()
 438 */
 439void libcfs_debug_dumplog_internal(void *arg)
 440{
 441        void *journal_info;
 442
 443        journal_info = current->journal_info;
 444        current->journal_info = NULL;
 445
 446        if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) != 0) {
 447                snprintf(debug_file_name, sizeof(debug_file_name) - 1,
 448                         "%s.%lld.%ld", libcfs_debug_file_path_arr,
 449                         (s64)ktime_get_real_seconds(), (long_ptr_t)arg);
 450                pr_alert("LustreError: dumping log to %s\n", debug_file_name);
 451                cfs_tracefile_dump_all_pages(debug_file_name);
 452                libcfs_run_debug_log_upcall(debug_file_name);
 453        }
 454
 455        current->journal_info = journal_info;
 456}
 457
 458static int libcfs_debug_dumplog_thread(void *arg)
 459{
 460        libcfs_debug_dumplog_internal(arg);
 461        wake_up(&debug_ctlwq);
 462        return 0;
 463}
 464
 465void libcfs_debug_dumplog(void)
 466{
 467        wait_queue_t wait;
 468        struct task_struct *dumper;
 469
 470        /* we're being careful to ensure that the kernel thread is
 471         * able to set our state to running as it exits before we
 472         * get to schedule()
 473         */
 474        init_waitqueue_entry(&wait, current);
 475        set_current_state(TASK_INTERRUPTIBLE);
 476        add_wait_queue(&debug_ctlwq, &wait);
 477
 478        dumper = kthread_run(libcfs_debug_dumplog_thread,
 479                             (void *)(long)current_pid(),
 480                             "libcfs_debug_dumper");
 481        if (IS_ERR(dumper))
 482                pr_err("LustreError: cannot start log dump thread: %ld\n",
 483                       PTR_ERR(dumper));
 484        else
 485                schedule();
 486
 487        /* be sure to teardown if cfs_create_thread() failed */
 488        remove_wait_queue(&debug_ctlwq, &wait);
 489        set_current_state(TASK_RUNNING);
 490}
 491EXPORT_SYMBOL(libcfs_debug_dumplog);
 492
 493int libcfs_debug_init(unsigned long bufsize)
 494{
 495        int    rc = 0;
 496        unsigned int max = libcfs_debug_mb;
 497
 498        init_waitqueue_head(&debug_ctlwq);
 499
 500        if (libcfs_console_max_delay <= 0 || /* not set by user or */
 501            libcfs_console_min_delay <= 0 || /* set to invalid values */
 502            libcfs_console_min_delay >= libcfs_console_max_delay) {
 503                libcfs_console_max_delay = CDEBUG_DEFAULT_MAX_DELAY;
 504                libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY;
 505        }
 506
 507        if (libcfs_debug_file_path) {
 508                strlcpy(libcfs_debug_file_path_arr,
 509                        libcfs_debug_file_path,
 510                        sizeof(libcfs_debug_file_path_arr));
 511        }
 512
 513        /* If libcfs_debug_mb is set to an invalid value or uninitialized
 514         * then just make the total buffers smp_num_cpus * TCD_MAX_PAGES
 515         */
 516        if (max > cfs_trace_max_debug_mb() || max < num_possible_cpus()) {
 517                max = TCD_MAX_PAGES;
 518        } else {
 519                max = max / num_possible_cpus();
 520                max <<= (20 - PAGE_SHIFT);
 521        }
 522        rc = cfs_tracefile_init(max);
 523
 524        if (rc == 0) {
 525                libcfs_register_panic_notifier();
 526                libcfs_debug_mb = cfs_trace_get_debug_mb();
 527        }
 528
 529        return rc;
 530}
 531
 532int libcfs_debug_cleanup(void)
 533{
 534        libcfs_unregister_panic_notifier();
 535        cfs_tracefile_exit();
 536        return 0;
 537}
 538
 539int libcfs_debug_clear_buffer(void)
 540{
 541        cfs_trace_flush_pages();
 542        return 0;
 543}
 544
 545/* Debug markers, although printed by S_LNET should not be be marked as such. */
 546#undef DEBUG_SUBSYSTEM
 547#define DEBUG_SUBSYSTEM S_UNDEFINED
 548int libcfs_debug_mark_buffer(const char *text)
 549{
 550        CDEBUG(D_TRACE,
 551               "***************************************************\n");
 552        LCONSOLE(D_WARNING, "DEBUG MARKER: %s\n", text);
 553        CDEBUG(D_TRACE,
 554               "***************************************************\n");
 555
 556        return 0;
 557}
 558
 559#undef DEBUG_SUBSYSTEM
 560#define DEBUG_SUBSYSTEM S_LNET
 561