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