Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lnet / libcfs / linux / linux-proc.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc.
5  *   Author: Zach Brown <zab@zabbo.net>
6  *   Author: Peter J. Braam <braam@clusterfs.com>
7  *   Author: Phil Schwan <phil@clusterfs.com>
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
11  *   Lustre is free software; you can redistribute it and/or
12  *   modify it under the terms of version 2 of the GNU General Public
13  *   License as published by the Free Software Foundation.
14  *
15  *   Lustre is distributed in the hope that it will be useful,
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *   GNU General Public License for more details.
19  *
20  *   You should have received a copy of the GNU General Public License
21  *   along with Lustre; if not, write to the Free Software
22  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #ifndef EXPORT_SYMTAB
26 # define EXPORT_SYMTAB
27 #endif
28
29 #ifndef AUTOCONF_INCLUDED
30 #include <linux/config.h>
31 #endif
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/mm.h>
35 #include <linux/string.h>
36 #include <linux/stat.h>
37 #include <linux/errno.h>
38 #include <linux/smp_lock.h>
39 #include <linux/unistd.h>
40 #include <net/sock.h>
41 #include <linux/uio.h>
42
43 #include <asm/system.h>
44 #include <asm/uaccess.h>
45
46 #include <linux/fs.h>
47 #include <linux/file.h>
48 #include <linux/stat.h>
49 #include <linux/list.h>
50 #include <asm/uaccess.h>
51 #include <asm/segment.h>
52
53 #include <linux/proc_fs.h>
54 #include <linux/sysctl.h>
55
56 # define DEBUG_SUBSYSTEM S_LNET
57
58 #include <libcfs/kp30.h>
59 #include <asm/div64.h>
60 #include "tracefile.h"
61
62 static cfs_sysctl_table_header_t *lnet_table_header = NULL;
63 extern char lnet_upcall[1024];
64
65 #define PSDEV_LNET  (0x100)
66 enum {
67         PSDEV_DEBUG = 1,          /* control debugging */
68         PSDEV_SUBSYSTEM_DEBUG,    /* control debugging */
69         PSDEV_PRINTK,             /* force all messages to console */
70         PSDEV_CONSOLE_RATELIMIT,  /* ratelimit console messages */
71         PSDEV_DEBUG_PATH,         /* crashdump log location */
72         PSDEV_DEBUG_DUMP_PATH,    /* crashdump tracelog location */
73         PSDEV_LNET_UPCALL,        /* User mode upcall script  */
74         PSDEV_LNET_MEMUSED,       /* bytes currently PORTAL_ALLOCated */
75         PSDEV_LNET_CATASTROPHE,   /* if we have LBUGged or panic'd */
76         PSDEV_LNET_PANIC_ON_LBUG, /* flag to panic on LBUG */
77         PSDEV_LNET_DUMP_KERNEL,   /* snapshot kernel debug buffer to file */
78         PSDEV_LNET_DAEMON_FILE,   /* spool kernel debug buffer to file */
79         PSDEV_LNET_DEBUG_MB,      /* size of debug buffer */
80 };
81
82 static int 
83 proc_call_handler(void *data, int write, 
84                   loff_t *ppos, void *buffer, size_t *lenp, 
85                   int (*handler)(void *data, int write,
86                                  loff_t pos, void *buffer, int len))
87 {
88         int rc = handler(data, write, *ppos, buffer, *lenp);
89
90         if (rc < 0)
91                 return rc;
92
93         if (write) {
94                 *ppos += *lenp;
95         } else {
96                 *lenp = rc;
97                 *ppos += rc;
98         }
99         return 0;
100 }
101
102 #define DECLARE_PROC_HANDLER(name)                      \
103 static int                                              \
104 LL_PROC_PROTO(name)                                     \
105 {                                                       \
106         DECLARE_LL_PROC_PPOS;                           \
107                                                         \
108         return proc_call_handler(table->data, write,    \
109                                  ppos, buffer, lenp,    \
110                                  __##name);             \
111 }
112
113 static int __proc_dobitmasks(void *data, int write, 
114                              loff_t pos, void *buffer, int nob)
115 {
116         const int     tmpstrlen = 512;
117         char         *tmpstr;
118         int           rc;
119         unsigned int *mask = data;
120         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
121
122         rc = trace_allocate_string_buffer(&tmpstr, tmpstrlen);
123         if (rc < 0)
124                 return rc;
125         
126         if (!write) {
127                 libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
128                 rc = strlen(tmpstr);
129
130                 if (pos >= rc) {
131                         rc = 0;
132                 } else {
133                         rc = trace_copyout_string(buffer, nob,
134                                                   tmpstr + pos, "\n");
135                 }
136         } else {
137                 rc = trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
138                 if (rc < 0)
139                         return rc;
140                 
141                 rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
142         }
143
144         trace_free_string_buffer(tmpstr, tmpstrlen);
145         return rc;
146 }
147
148 DECLARE_PROC_HANDLER(proc_dobitmasks)
149
150 static int __proc_dump_kernel(void *data, int write,
151                               loff_t pos, void *buffer, int nob)
152 {
153         if (!write)
154                 return 0;
155         
156         return trace_dump_debug_buffer_usrstr(buffer, nob);
157 }
158
159 DECLARE_PROC_HANDLER(proc_dump_kernel)
160
161 static int __proc_daemon_file(void *data, int write,
162                               loff_t pos, void *buffer, int nob)
163 {
164         if (!write) {
165                 int len = strlen(tracefile);
166                 
167                 if (pos >= len)
168                         return 0;
169                 
170                 return trace_copyout_string(buffer, nob, 
171                                             tracefile + pos, "\n");
172         }
173         
174         return trace_daemon_command_usrstr(buffer, nob);
175 }
176
177 DECLARE_PROC_HANDLER(proc_daemon_file)
178
179 static int __proc_debug_mb(void *data, int write,
180                            loff_t pos, void *buffer, int nob)
181 {
182         if (!write) {
183                 char tmpstr[32];
184                 int  len = snprintf(tmpstr, sizeof(tmpstr), "%d",
185                                     trace_get_debug_mb());
186
187                 if (pos >= len)
188                         return 0;
189                 
190                 return trace_copyout_string(buffer, nob, tmpstr + pos, "\n");
191         }
192         
193         return trace_set_debug_mb_usrstr(buffer, nob);
194 }
195
196 DECLARE_PROC_HANDLER(proc_debug_mb)
197
198 static cfs_sysctl_table_t lnet_table[] = {
199         /*
200          * NB No .strategy entries have been provided since sysctl(8) prefers
201          * to go via /proc for portability.
202          */
203         {
204                 .ctl_name = PSDEV_DEBUG,
205                 .procname = "debug",
206                 .data     = &libcfs_debug,
207                 .maxlen   = sizeof(int),
208                 .mode     = 0644,
209                 .proc_handler = &proc_dobitmasks
210         },
211         {
212                 .ctl_name = PSDEV_SUBSYSTEM_DEBUG,
213                 .procname = "subsystem_debug",
214                 .data     = &libcfs_subsystem_debug,
215                 .maxlen   = sizeof(int),
216                 .mode     = 0644,
217                 .proc_handler = &proc_dobitmasks
218         },
219         {
220                 .ctl_name = PSDEV_PRINTK,
221                 .procname = "printk",
222                 .data     = &libcfs_printk,
223                 .maxlen   = sizeof(int),
224                 .mode     = 0644,
225                 .proc_handler = &proc_dobitmasks
226         },
227         {
228                 .ctl_name = PSDEV_CONSOLE_RATELIMIT,
229                 .procname = "console_ratelimit",
230                 .data     = &libcfs_console_ratelimit,
231                 .maxlen   = sizeof(int),
232                 .mode     = 0644,
233                 .proc_handler = &proc_dointvec
234         },
235
236         {
237                 .ctl_name = PSDEV_DEBUG_PATH,
238                 .procname = "debug_path",
239                 .data     = debug_file_path,
240                 .maxlen   = sizeof(debug_file_path),
241                 .mode     = 0644,
242                 .proc_handler = &proc_dostring,
243         },
244
245         {
246                 .ctl_name = PSDEV_LNET_UPCALL,
247                 .procname = "upcall",
248                 .data     = lnet_upcall,
249                 .maxlen   = sizeof(lnet_upcall),
250                 .mode     = 0644,
251                 .proc_handler = &proc_dostring,
252         },
253         {
254                 .ctl_name = PSDEV_LNET_MEMUSED,
255                 .procname = "memused",
256                 .data     = (int *)&libcfs_kmemory.counter,
257                 .maxlen   = sizeof(int),
258                 .mode     = 0444,
259                 .proc_handler = &proc_dointvec
260         },
261         {
262                 .ctl_name = PSDEV_LNET_CATASTROPHE,
263                 .procname = "catastrophe",
264                 .data     = &libcfs_catastrophe,
265                 .maxlen   = sizeof(int),
266                 .mode     = 0444,
267                 .proc_handler = &proc_dointvec
268         },
269         {
270                 .ctl_name = PSDEV_LNET_PANIC_ON_LBUG,
271                 .procname = "panic_on_lbug",
272                 .data     = &libcfs_panic_on_lbug,
273                 .maxlen   = sizeof(int),
274                 .mode     = 0644,
275                 .proc_handler = &proc_dointvec
276         },
277         {
278                 .ctl_name = PSDEV_LNET_DUMP_KERNEL,
279                 .procname = "dump_kernel",
280                 .mode     = 0200,
281                 .proc_handler = &proc_dump_kernel,
282         },
283         {
284                 .ctl_name = PSDEV_LNET_DAEMON_FILE,
285                 .procname = "daemon_file",
286                 .mode     = 0644,
287                 .proc_handler = &proc_daemon_file,
288         },
289         {
290                 .ctl_name = PSDEV_LNET_DEBUG_MB,
291                 .procname = "debug_mb",
292                 .mode     = 0644,
293                 .proc_handler = &proc_debug_mb,
294         },
295         {0}
296 };
297
298 static cfs_sysctl_table_t top_table[2] = {
299         {
300                 .ctl_name = PSDEV_LNET,
301                 .procname = "lnet",
302                 .data     = NULL,
303                 .maxlen   = 0,
304                 .mode     = 0555,
305                 .child    = lnet_table
306         },
307         {0}
308 };
309
310 int insert_proc(void)
311 {
312 #ifdef CONFIG_SYSCTL
313         if (lnet_table_header == NULL)
314                 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
315 #endif
316         return 0;
317 }
318
319 void remove_proc(void)
320 {
321 #ifdef CONFIG_SYSCTL
322         if (lnet_table_header != NULL)
323                 cfs_unregister_sysctl_table(lnet_table_header);
324
325         lnet_table_header = NULL;
326 #endif
327 }