Whamcloud - gitweb
417a4948bdf1102c2c62d460a25c4ef62b317b3c
[fs/lustre-release.git] / libcfs / libcfs / debug.c
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 <libcfs/libcfs.h>
45 #include "tracefile.h"
46
47 static char debug_file_name[1024];
48
49 unsigned int libcfs_subsystem_debug = ~0;
50 CFS_MODULE_PARM(libcfs_subsystem_debug, "i", int, 0644,
51                 "Lustre kernel debug subsystem mask");
52 EXPORT_SYMBOL(libcfs_subsystem_debug);
53
54 unsigned int libcfs_debug = (D_CANTMASK |
55                              D_NETERROR | D_HA | D_CONFIG | D_IOCTL | D_LFSCK);
56 CFS_MODULE_PARM(libcfs_debug, "i", int, 0644,
57                 "Lustre kernel debug mask");
58 EXPORT_SYMBOL(libcfs_debug);
59
60 unsigned int libcfs_debug_mb = 0;
61 CFS_MODULE_PARM(libcfs_debug_mb, "i", uint, 0644,
62                 "Total debug buffer size.");
63 EXPORT_SYMBOL(libcfs_debug_mb);
64
65 unsigned int libcfs_printk = D_CANTMASK;
66 CFS_MODULE_PARM(libcfs_printk, "i", uint, 0644,
67                 "Lustre kernel debug console mask");
68 EXPORT_SYMBOL(libcfs_printk);
69
70 unsigned int libcfs_console_ratelimit = 1;
71 CFS_MODULE_PARM(libcfs_console_ratelimit, "i", uint, 0644,
72                 "Lustre kernel debug console ratelimit (0 to disable)");
73 EXPORT_SYMBOL(libcfs_console_ratelimit);
74
75 unsigned int libcfs_console_max_delay;
76 CFS_MODULE_PARM(libcfs_console_max_delay, "l", uint, 0644,
77                 "Lustre kernel debug console max delay (jiffies)");
78 EXPORT_SYMBOL(libcfs_console_max_delay);
79
80 unsigned int libcfs_console_min_delay;
81 CFS_MODULE_PARM(libcfs_console_min_delay, "l", uint, 0644,
82                 "Lustre kernel debug console min delay (jiffies)");
83 EXPORT_SYMBOL(libcfs_console_min_delay);
84
85 unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
86 CFS_MODULE_PARM(libcfs_console_backoff, "i", uint, 0644,
87                 "Lustre kernel debug console backoff factor");
88 EXPORT_SYMBOL(libcfs_console_backoff);
89
90 unsigned int libcfs_debug_binary = 1;
91 EXPORT_SYMBOL(libcfs_debug_binary);
92
93 unsigned int libcfs_stack = 3 * THREAD_SIZE / 4;
94 EXPORT_SYMBOL(libcfs_stack);
95
96 unsigned int portal_enter_debugger;
97 EXPORT_SYMBOL(portal_enter_debugger);
98
99 unsigned int libcfs_catastrophe;
100 EXPORT_SYMBOL(libcfs_catastrophe);
101
102 unsigned int libcfs_watchdog_ratelimit = 300;
103 EXPORT_SYMBOL(libcfs_watchdog_ratelimit);
104
105 unsigned int libcfs_panic_on_lbug = 1;
106 CFS_MODULE_PARM(libcfs_panic_on_lbug, "i", uint, 0644,
107                 "Lustre kernel panic on LBUG");
108 EXPORT_SYMBOL(libcfs_panic_on_lbug);
109
110 atomic_t libcfs_kmemory = ATOMIC_INIT(0);
111 EXPORT_SYMBOL(libcfs_kmemory);
112
113 static wait_queue_head_t debug_ctlwq;
114
115 char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT;
116
117 /* We need to pass a pointer here, but elsewhere this must be a const */
118 char *libcfs_debug_file_path;
119 CFS_MODULE_PARM(libcfs_debug_file_path, "s", charp, 0644,
120                 "Path for dumping debug logs, "
121                 "set 'NONE' to prevent log dumping");
122
123 int libcfs_panic_in_progress;
124
125 /* libcfs_debug_token2mask() expects the returned
126  * string in lower-case */
127 const char *libcfs_debug_subsys2str(int subsys)
128 {
129         static const char *libcfs_debug_subsystems[] = LIBCFS_DEBUG_SUBSYS_NAMES;
130
131         if (subsys >= ARRAY_SIZE(libcfs_debug_subsystems))
132                 return NULL;
133
134         return libcfs_debug_subsystems[subsys];
135 }
136
137 /* libcfs_debug_token2mask() expects the returned
138  * string in lower-case */
139 const char *libcfs_debug_dbg2str(int debug)
140 {
141         static const char *libcfs_debug_masks[] = LIBCFS_DEBUG_MASKS_NAMES;
142
143         if (debug >= ARRAY_SIZE(libcfs_debug_masks))
144                 return NULL;
145
146         return libcfs_debug_masks[debug];
147 }
148
149 int
150 libcfs_debug_mask2str(char *str, int size, int mask, int is_subsys)
151 {
152         const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str :
153                                                  libcfs_debug_dbg2str;
154         int           len = 0;
155         const char   *token;
156         int           i;
157
158         if (mask == 0) {                        /* "0" */
159                 if (size > 0)
160                         str[0] = '0';
161                 len = 1;
162         } else {                                /* space-separated tokens */
163                 for (i = 0; i < 32; i++) {
164                         if ((mask & (1 << i)) == 0)
165                                 continue;
166
167                         token = fn(i);
168                         if (token == NULL)              /* unused bit */
169                                 continue;
170
171                         if (len > 0) {                  /* separator? */
172                                 if (len < size)
173                                         str[len] = ' ';
174                                 len++;
175                         }
176
177                         while (*token != 0) {
178                                 if (len < size)
179                                         str[len] = *token;
180                                 token++;
181                                 len++;
182                         }
183                 }
184         }
185
186         /* terminate 'str' */
187         if (len < size)
188                 str[len] = 0;
189         else
190                 str[size - 1] = 0;
191
192         return len;
193 }
194
195 int
196 libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
197 {
198         const char *(*fn)(int bit) = is_subsys ? libcfs_debug_subsys2str :
199                                                  libcfs_debug_dbg2str;
200         int         m = 0;
201         int         matched;
202         int         n;
203         int         t;
204
205         /* Allow a number for backwards compatibility */
206
207         for (n = strlen(str); n > 0; n--)
208                 if (!isspace(str[n-1]))
209                         break;
210         matched = n;
211
212         if ((t = sscanf(str, "%i%n", &m, &matched)) >= 1 &&
213             matched == n) {
214                 /* don't print warning for lctl set_param debug=0 or -1 */
215                 if (m != 0 && m != -1)
216                         CWARN("You are trying to use a numerical value for the "
217                               "mask - this will be deprecated in a future "
218                               "release.\n");
219                 *mask = m;
220                 return 0;
221         }
222
223         return cfs_str2mask(str, fn, mask, is_subsys ? 0 : D_CANTMASK,
224                             0xffffffff);
225 }
226
227 /**
228  * Dump Lustre log to ::debug_file_path by calling tracefile_dump_all_pages()
229  */
230 void libcfs_debug_dumplog_internal(void *arg)
231 {
232         static time_t last_dump_time;
233         time_t current_time;
234         DECL_JOURNAL_DATA;
235
236         PUSH_JOURNAL;
237
238         current_time = cfs_time_current_sec();
239
240         if (strncmp(libcfs_debug_file_path_arr, "NONE", 4) != 0 &&
241             current_time > last_dump_time) {
242                 last_dump_time = current_time;
243                 snprintf(debug_file_name, sizeof(debug_file_name) - 1,
244                          "%s.%ld." LPLD, libcfs_debug_file_path_arr,
245                          current_time, (long_ptr_t)arg);
246                 printk(KERN_ALERT "LustreError: dumping log to %s\n",
247                        debug_file_name);
248                 cfs_tracefile_dump_all_pages(debug_file_name);
249                 libcfs_run_debug_log_upcall(debug_file_name);
250         }
251         POP_JOURNAL;
252 }
253
254 int libcfs_debug_dumplog_thread(void *arg)
255 {
256         libcfs_debug_dumplog_internal(arg);
257         wake_up(&debug_ctlwq);
258         return 0;
259 }
260
261 void libcfs_debug_dumplog(void)
262 {
263         wait_queue_t wait;
264         struct task_struct    *dumper;
265         ENTRY;
266
267         /* we're being careful to ensure that the kernel thread is
268          * able to set our state to running as it exits before we
269          * get to schedule() */
270         init_waitqueue_entry_current(&wait);
271         set_current_state(TASK_INTERRUPTIBLE);
272         add_wait_queue(&debug_ctlwq, &wait);
273
274         dumper = kthread_run(libcfs_debug_dumplog_thread,
275                              (void *)(long)current_pid(),
276                              "libcfs_debug_dumper");
277         if (IS_ERR(dumper))
278                 printk(KERN_ERR "LustreError: cannot start log dump thread:"
279                        " %ld\n", PTR_ERR(dumper));
280         else
281                 waitq_wait(&wait, TASK_INTERRUPTIBLE);
282
283         /* be sure to teardown if cfs_create_thread() failed */
284         remove_wait_queue(&debug_ctlwq, &wait);
285         set_current_state(TASK_RUNNING);
286 }
287 EXPORT_SYMBOL(libcfs_debug_dumplog);
288
289 int libcfs_debug_init(unsigned long bufsize)
290 {
291         int    rc = 0;
292         unsigned int max = libcfs_debug_mb;
293
294         init_waitqueue_head(&debug_ctlwq);
295
296         if (libcfs_console_max_delay <= 0 || /* not set by user or */
297             libcfs_console_min_delay <= 0 || /* set to invalid values */
298             libcfs_console_min_delay >= libcfs_console_max_delay) {
299                 libcfs_console_max_delay = CDEBUG_DEFAULT_MAX_DELAY;
300                 libcfs_console_min_delay = CDEBUG_DEFAULT_MIN_DELAY;
301         }
302
303         if (libcfs_debug_file_path != NULL) {
304                 strlcpy(libcfs_debug_file_path_arr,
305                         libcfs_debug_file_path,
306                         sizeof(libcfs_debug_file_path_arr));
307         }
308
309         /* If libcfs_debug_mb is set to an invalid value or uninitialized
310          * then just make the total buffers smp_num_cpus * TCD_MAX_PAGES */
311         if (max > cfs_trace_max_debug_mb() || max < num_possible_cpus()) {
312                 max = TCD_MAX_PAGES;
313         } else {
314                 max = (max / num_possible_cpus());
315                 max = (max << (20 - PAGE_CACHE_SHIFT));
316         }
317         rc = cfs_tracefile_init(max);
318
319         if (rc == 0)
320                 libcfs_register_panic_notifier();
321
322         return rc;
323 }
324
325 int libcfs_debug_cleanup(void)
326 {
327         libcfs_unregister_panic_notifier();
328         cfs_tracefile_exit();
329         return 0;
330 }
331
332 int libcfs_debug_clear_buffer(void)
333 {
334         cfs_trace_flush_pages();
335         return 0;
336 }
337
338 /* Debug markers, although printed by S_LNET
339  * should not be be marked as such. */
340 #undef DEBUG_SUBSYSTEM
341 #define DEBUG_SUBSYSTEM S_UNDEFINED
342 int libcfs_debug_mark_buffer(const char *text)
343 {
344         CDEBUG(D_TRACE,"***************************************************\n");
345         LCONSOLE(D_WARNING, "DEBUG MARKER: %s\n", text);
346         CDEBUG(D_TRACE,"***************************************************\n");
347
348         return 0;
349 }
350 #undef DEBUG_SUBSYSTEM
351 #define DEBUG_SUBSYSTEM S_LNET
352
353 void libcfs_debug_set_level(unsigned int debug_level)
354 {
355         printk(KERN_WARNING "Lustre: Setting portals debug level to %08x\n",
356                debug_level);
357         libcfs_debug = debug_level;
358 }
359
360 EXPORT_SYMBOL(libcfs_debug_set_level);
361
362 long libcfs_log_return(struct libcfs_debug_msg_data *msgdata, long rc)
363 {
364         libcfs_debug_msg(msgdata, "Process leaving (rc=%lu : %ld : %lx)\n",
365                          rc, rc, rc);
366         return rc;
367 }
368 EXPORT_SYMBOL(libcfs_log_return);
369
370 void libcfs_log_goto(struct libcfs_debug_msg_data *msgdata, const char *label,
371                      long_ptr_t rc)
372 {
373         libcfs_debug_msg(msgdata, "Process leaving via %s (rc=" LPLU " : " LPLD
374                          " : " LPLX ")\n", label, (ulong_ptr_t)rc, rc, rc);
375 }
376 EXPORT_SYMBOL(libcfs_log_goto);