Whamcloud - gitweb
use special macro for print time_t, cleanup in includes.
[fs/lustre-release.git] / lnet / libcfs / debug.c
index 862918a..4b275e6 100644 (file)
@@ -26,6 +26,7 @@
 
 # define DEBUG_SUBSYSTEM S_LNET
 
+#include <stdarg.h>
 #include <libcfs/kp30.h>
 #include <libcfs/libcfs.h>
 #include "tracefile.h"
@@ -34,18 +35,46 @@ static char debug_file_name[1024];
 
 #ifdef __KERNEL__
 unsigned int libcfs_subsystem_debug = ~0;
+CFS_MODULE_PARM(libcfs_subsystem_debug, "i", int, 0644,
+                "Lustre kernel debug subsystem mask");
 EXPORT_SYMBOL(libcfs_subsystem_debug);
 
 unsigned int libcfs_debug = (D_EMERG | D_ERROR | D_WARNING | D_CONSOLE |
                              D_NETERROR | D_HA | D_CONFIG | D_IOCTL);
+CFS_MODULE_PARM(libcfs_debug, "i", int, 0644,
+                "Lustre kernel debug mask");
 EXPORT_SYMBOL(libcfs_debug);
 
-unsigned int libcfs_printk;
+int libcfs_debug_mb = -1;
+CFS_MODULE_PARM(libcfs_debug_mb, "i", int, 0644,
+                "Total debug buffer size.");
+EXPORT_SYMBOL(libcfs_debug_mb);
+
+unsigned int libcfs_printk = D_CANTMASK;
+CFS_MODULE_PARM(libcfs_printk, "i", uint, 0644,
+                "Lustre kernel debug console mask");
 EXPORT_SYMBOL(libcfs_printk);
 
 unsigned int libcfs_console_ratelimit = 1;
+CFS_MODULE_PARM(libcfs_console_ratelimit, "i", uint, 0644,
+                "Lustre kernel debug console ratelimit (0 to disable)");
 EXPORT_SYMBOL(libcfs_console_ratelimit);
 
+cfs_duration_t libcfs_console_max_delay;
+CFS_MODULE_PARM(libcfs_console_max_delay, "l", ulong, 0644,
+                "Lustre kernel debug console max delay (jiffies)");
+EXPORT_SYMBOL(libcfs_console_max_delay);
+
+cfs_duration_t libcfs_console_min_delay;
+CFS_MODULE_PARM(libcfs_console_min_delay, "l", ulong, 0644,
+                "Lustre kernel debug console min delay (jiffies)");
+EXPORT_SYMBOL(libcfs_console_min_delay);
+
+unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
+CFS_MODULE_PARM(libcfs_console_backoff, "i", uint, 0644,
+                "Lustre kernel debug console backoff factor");
+EXPORT_SYMBOL(libcfs_console_backoff);
+
 unsigned int libcfs_debug_binary = 1;
 EXPORT_SYMBOL(libcfs_debug_binary);
 
@@ -59,6 +88,8 @@ unsigned int libcfs_catastrophe;
 EXPORT_SYMBOL(libcfs_catastrophe);
 
 unsigned int libcfs_panic_on_lbug = 0;
+CFS_MODULE_PARM(libcfs_panic_on_lbug, "i", uint, 0644,
+                "Lustre kernel panic on LBUG");
 EXPORT_SYMBOL(libcfs_panic_on_lbug);
 
 atomic_t libcfs_kmemory = ATOMIC_INIT(0);
@@ -71,6 +102,9 @@ char debug_file_path[1024] = "/r/tmp/lustre-log";
 #else
 char debug_file_path[1024] = "/tmp/lustre-log";
 #endif
+CFS_MODULE_PARM(debug_file_path, "s", charp, 0644,
+                "Path for dumping debug logs, "
+                "set 'NONE' to prevent log dumping");
 
 int libcfs_panic_in_progress;
 
@@ -228,7 +262,7 @@ libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys)
                                         str[len] = ' ';
                                 len++;
                         }
-                
+
                         while (*token != 0) {
                                 if (len < size)
                                         str[len] = *token;
@@ -264,7 +298,7 @@ libcfs_debug_token2mask(int *mask, const char *str, int len, int is_subsys)
                 token = fn(bit);
                 if (token == NULL)              /* unused? */
                         continue;
-                
+
                 /* strcasecmp */
                 for (j = 0; ; j++) {
                         if (j == len) {         /* end of token */
@@ -274,13 +308,13 @@ libcfs_debug_token2mask(int *mask, const char *str, int len, int is_subsys)
                                 }
                                 break;
                         }
-                        
+
                         if (token[j] == 0)
                                 break;
-                                
+
                         if (str[j] == token[j])
                                 continue;
-                        
+
                         if (str[j] < 'A' || 'Z' < str[j])
                                 break;
 
@@ -288,7 +322,7 @@ libcfs_debug_token2mask(int *mask, const char *str, int len, int is_subsys)
                                 break;
                 }
         }
-        
+
         return -EINVAL;                         /* no match */
 }
 
@@ -296,17 +330,31 @@ int
 libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
 {
         int         m = 0;
-        int         matched = 0;
         char        op = 0;
+        int         matched;
         int         n;
         int         t;
 
+        /* Allow a number for backwards compatibility */
+
+        for (n = strlen(str); n > 0; n--)
+                if (!isspace(str[n-1]))
+                        break;
+        matched = n;
+
+        if ((t = sscanf(str, "%i%n", &m, &matched)) >= 1 &&
+            matched == n) {
+                *mask = m;
+                return 0;
+        }
+
         /* <str> must be a list of debug tokens or numbers separated by
          * whitespace and optionally an operator ('+' or '-').  If an operator
          * appears first in <str>, '*mask' is used as the starting point
          * (relative), otherwise 0 is used (absolute).  An operator applies to
          * all following tokens up to the next operator. */
-        
+
+        matched = 0;
         while (*str != 0) {
                 while (isspace(*str)) /* skip whitespace */
                         str++;
@@ -334,13 +382,13 @@ libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
                 /* match token */
                 if (libcfs_debug_token2mask(&t, str, n, is_subsys) != 0)
                         return -EINVAL;
-                
+
                 matched = 1;
                 if (op == '-')
                         m &= ~t;
                 else
                         m |= t;
-                
+
                 str += n;
         }
 
@@ -357,11 +405,14 @@ void libcfs_debug_dumplog_internal(void *arg)
 
         CFS_PUSH_JOURNAL;
 
-        snprintf(debug_file_name, sizeof(debug_file_path) - 1, "%s.%ld.%ld",
-                 debug_file_path, cfs_time_current_sec(), (long)arg);
-        printk(KERN_ALERT "LustreError: dumping log to %s\n", debug_file_name);
-        tracefile_dump_all_pages(debug_file_name);
-
+        if (strncmp(debug_file_path, "NONE", 4) != 0) {
+                snprintf(debug_file_name, sizeof(debug_file_path) - 1,
+                         "%s.%ld.%ld", debug_file_path, cfs_time_current_sec(),
+                         (long)arg);
+                printk(KERN_ALERT "LustreError: dumping log to %s\n",
+                       debug_file_name);
+                tracefile_dump_all_pages(debug_file_name);
+        }
         CFS_POP_JOURNAL;
 }
 
@@ -402,10 +453,21 @@ void libcfs_debug_dumplog(void)
 
 int libcfs_debug_init(unsigned long bufsize)
 {
-        int    rc;
+        int    rc = 0;
+        int    max = libcfs_debug_mb;
 
         cfs_waitq_init(&debug_ctlwq);
-        rc = tracefile_init();
+        libcfs_console_max_delay = CDEBUG_DEFAULT_MAX_DELAY;
+        libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY;
+        /* If libcfs_debug_mb is set to an invalid value or uninitialized
+         * then just make the total buffers smp_num_cpus * TCD_MAX_PAGES */
+        if (max > trace_max_debug_mb() || max < num_possible_cpus()) {
+                max = TCD_MAX_PAGES;
+        } else {
+                max = (max / num_possible_cpus());
+                max = (max << (20 - CFS_PAGE_SHIFT));
+        }
+        rc = tracefile_init(max);
 
         if (rc == 0)
                 libcfs_register_panic_notifier();
@@ -456,10 +518,6 @@ EXPORT_SYMBOL(libcfs_debug_set_level);
 
 #include <libcfs/libcfs.h>
 
-#ifdef HAVE_SYS_USER_H
-# include <sys/user.h>
-#endif
-
 #ifdef HAVE_CATAMOUNT_DATA_H
 #include <catamount/data.h>
 #include <catamount/lputs.h>
@@ -468,13 +526,16 @@ static char source_nid[16];
 /* 0 indicates no messages to console, 1 is errors, > 1 is all debug messages */
 static int toconsole = 1;
 unsigned int libcfs_console_ratelimit = 1;
+cfs_duration_t libcfs_console_max_delay;
+cfs_duration_t libcfs_console_min_delay;
+unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
 #else /* !HAVE_CATAMOUNT_DATA_H */
 #ifdef HAVE_NETDB_H
 #include <sys/utsname.h>
-#endif /* HAVE_CATAMOUNT_DATA_H */
+#endif /* HAVE_NETDB_H */
 struct utsname *tmp_utsname;
 static char source_nid[sizeof(tmp_utsname->nodename)];
-#endif /* __KERNEL__ */
+#endif /* HAVE_CATAMOUNT_DATA_H */
 
 static int source_pid;
 int smp_processor_id = 1;
@@ -509,6 +570,12 @@ int libcfs_debug_init(unsigned long bufsize)
 #ifdef HAVE_CATAMOUNT_DATA_H
         char *debug_console = NULL;
         char *debug_ratelimit = NULL;
+        char *debug_max_delay = NULL;
+        char *debug_min_delay = NULL;
+        char *debug_backoff = NULL;
+
+        libcfs_console_max_delay = CDEBUG_DEFAULT_MAX_DELAY;
+        libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY;
 
         snprintf(source_nid, sizeof(source_nid) - 1, "%u", _my_pnid);
         source_pid = _my_pid;
@@ -521,7 +588,47 @@ int libcfs_debug_init(unsigned long bufsize)
         debug_ratelimit = getenv("LIBLUSTRE_DEBUG_CONSOLE_RATELIMIT");
         if (debug_ratelimit != NULL) {
                 libcfs_console_ratelimit = strtoul(debug_ratelimit, NULL, 0);
-                CDEBUG(D_INFO, "set liblustre console ratelimit to %u\n", libcfs_console_ratelimit);
+                CDEBUG(D_INFO, "set liblustre console ratelimit to %u\n",
+                                libcfs_console_ratelimit);
+        }
+        debug_max_delay = getenv("LIBLUSTRE_DEBUG_CONSOLE_MAX_DELAY");
+        if (debug_max_delay != NULL)
+                libcfs_console_max_delay =
+                            cfs_time_seconds(strtoul(debug_max_delay, NULL, 0));
+        debug_min_delay = getenv("LIBLUSTRE_DEBUG_CONSOLE_MIN_DELAY");
+        if (debug_min_delay != NULL)
+                libcfs_console_min_delay =
+                            cfs_time_seconds(strtoul(debug_min_delay, NULL, 0));
+        if (debug_min_delay || debug_max_delay) {
+                if (!libcfs_console_max_delay || !libcfs_console_min_delay ||
+                    libcfs_console_max_delay < libcfs_console_min_delay) {
+                        libcfs_console_max_delay = CDEBUG_DEFAULT_MAX_DELAY;
+                        libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY;
+                        CDEBUG(D_INFO, "LIBLUSTRE_DEBUG_CONSOLE_MAX_DELAY "
+                                       "should be greater than "
+                                       "LIBLUSTRE_DEBUG_CONSOLE_MIN_DELAY "
+                                       "and both parameters should be non-null"
+                                       ": restore default values\n");
+                } else {
+                        CDEBUG(D_INFO, "set liblustre console max delay to %lus"
+                                       " and min delay to %lus\n",
+                               (cfs_duration_t)
+                                     cfs_duration_sec(libcfs_console_max_delay),
+                               (cfs_duration_t)
+                                    cfs_duration_sec(libcfs_console_min_delay));
+                }
+        }
+        debug_backoff = getenv("LIBLUSTRE_DEBUG_CONSOLE_BACKOFF");
+        if (debug_backoff != NULL) {
+                libcfs_console_backoff = strtoul(debug_backoff, NULL, 0);
+                if (libcfs_console_backoff <= 0) {
+                        libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
+                        CDEBUG(D_INFO, "LIBLUSTRE_DEBUG_CONSOLE_BACKOFF <= 0: "
+                                       "restore default value\n");
+                } else {
+                        CDEBUG(D_INFO, "set liblustre console backoff to %u\n",
+                               libcfs_console_backoff);
+                }
         }
 #else
         struct utsname myname;
@@ -550,7 +657,7 @@ int libcfs_debug_init(unsigned long bufsize)
 
         if (debug_file_name[0] == '\0' && debug_file_path[0] != '\0')
                 snprintf(debug_file_name, sizeof(debug_file_name) - 1,
-                         "%s-%s-%lu.log", debug_file_path, source_nid, time(0));
+                         "%s-%s-"CFS_TIME_T".log", debug_file_path, source_nid, time(0));
 
         if (strcmp(debug_file_name, "stdout") == 0 ||
             strcmp(debug_file_name, "-") == 0) {
@@ -618,8 +725,9 @@ libcfs_debug_vmsg2(cfs_debug_limit_state_t *cdls,
         int            nob;
         int            remain;
         va_list        ap;
-        char           buf[PAGE_SIZE]; /* size 4096 used for compatimble with linux,
-                                        * where message can`t be exceed PAGE_SIZE */
+        char           buf[CFS_PAGE_SIZE]; /* size 4096 used for compatimble
+                                            * with linux, where message can`t
+                                            * be exceed PAGE_SIZE */
         int            console = 0;
         char *prefix = "Lustre";
 
@@ -627,10 +735,8 @@ libcfs_debug_vmsg2(cfs_debug_limit_state_t *cdls,
         /* toconsole == 0 - all messages to debug_file_fd
          * toconsole == 1 - warnings to console, all to debug_file_fd
          * toconsole >  1 - all debug to console */
-        if ( ((mask & D_CANTMASK) &&
-             (toconsole == 1)) || (toconsole > 1)) {
+        if (((mask & libcfs_printk) && toconsole == 1) || toconsole > 1)
                 console = 1;
-        }
 #endif
 
         if ((!console) && (!debug_file_fd)) {
@@ -659,10 +765,6 @@ libcfs_debug_vmsg2(cfs_debug_limit_state_t *cdls,
         if (console) {
                 /* check rate limit for console */
                 if (cdls != NULL) {
-                        cfs_time_t t = cdls->cdls_next +
-                                       cfs_time_seconds(CDEBUG_MAX_LIMIT + 10);
-                        cfs_duration_t  dmax = cfs_time_seconds(CDEBUG_MAX_LIMIT);
-
                         if (libcfs_console_ratelimit &&
                                 cdls->cdls_next != 0 &&     /* not first time ever */
                                 !cfs_time_after(cfs_time_current(), cdls->cdls_next)) {
@@ -672,16 +774,22 @@ libcfs_debug_vmsg2(cfs_debug_limit_state_t *cdls,
                                 goto out_file;
                         }
 
-                        if (cfs_time_after(cfs_time_current(), t)) {
+                        if (cfs_time_after(cfs_time_current(), cdls->cdls_next +
+                                           libcfs_console_max_delay +
+                                           cfs_time_seconds(10))) {
                                 /* last timeout was a long time ago */
-                                cdls->cdls_delay /= 8;
+                                cdls->cdls_delay /= libcfs_console_backoff * 4;
                         } else {
-                                cdls->cdls_delay *= 2;
-
-                                if (cdls->cdls_delay < CFS_TICK)
-                                        cdls->cdls_delay = CFS_TICK;
-                                else if (cdls->cdls_delay > dmax)
-                                        cdls->cdls_delay = dmax;
+                                cdls->cdls_delay *= libcfs_console_backoff;
+
+                                if (cdls->cdls_delay <
+                                                libcfs_console_min_delay)
+                                        cdls->cdls_delay =
+                                                libcfs_console_min_delay;
+                                else if (cdls->cdls_delay >
+                                                libcfs_console_max_delay)
+                                        cdls->cdls_delay =
+                                                libcfs_console_max_delay;
                         }
 
                         /* ensure cdls_next is never zero after it's been seen */
@@ -712,7 +820,7 @@ out_file:
 
         gettimeofday(&tv, NULL);
 
-        fprintf(debug_file_fd, "%lu.%06lu:%u:%s:(%s:%d:%s()): %s",
+        fprintf(debug_file_fd, CFS_TIME_T".%06lu:%u:%s:(%s:%d:%s()): %s",
                 tv.tv_sec, tv.tv_usec, source_pid, source_nid,
                 file, line, fn, buf);