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