Whamcloud - gitweb
Branch b1_6
[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 struct ctl_table_header *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 };
78
79 int LL_PROC_PROTO(proc_dobitmasks);
80
81 static struct ctl_table lnet_table[] = {
82         {
83                 .ctl_name = PSDEV_DEBUG,
84                 .procname = "debug",
85                 .data     = &libcfs_debug,
86                 .maxlen   = sizeof(int),
87                 .mode     = 0644,
88                 .proc_handler = &proc_dobitmasks
89         },
90         {
91                 .ctl_name = PSDEV_SUBSYSTEM_DEBUG,
92                 .procname = "subsystem_debug",
93                 .data     = &libcfs_subsystem_debug,
94                 .maxlen   = sizeof(int),
95                 .mode     = 0644,
96                 .proc_handler = &proc_dobitmasks
97         },
98         {
99                 .ctl_name = PSDEV_PRINTK,
100                 .procname = "printk",
101                 .data     = &libcfs_printk,
102                 .maxlen   = sizeof(int),
103                 .mode     = 0644,
104                 .proc_handler = &proc_dobitmasks
105         },
106         {
107                 .ctl_name = PSDEV_CONSOLE_RATELIMIT,
108                 .procname = "console_ratelimit",
109                 .data     = &libcfs_console_ratelimit,
110                 .maxlen   = sizeof(int),
111                 .mode     = 0644,
112                 .proc_handler = &proc_dointvec
113         },
114
115         {
116                 .ctl_name = PSDEV_DEBUG_PATH,
117                 .procname = "debug_path",
118                 .data     = debug_file_path,
119                 .maxlen   = sizeof(debug_file_path),
120                 .mode     = 0644,
121                 .proc_handler = &proc_dostring,
122                 .strategy =  &sysctl_string
123         },
124
125         {
126                 .ctl_name = PSDEV_LNET_UPCALL,
127                 .procname = "upcall",
128                 .data     = lnet_upcall,
129                 .maxlen   = sizeof(lnet_upcall),
130                 .mode     = 0644,
131                 .proc_handler = &proc_dostring,
132                 .strategy =  &sysctl_string
133         },
134         {
135                 .ctl_name = PSDEV_LNET_MEMUSED,
136                 .procname = "memused",
137                 .data     = (int *)&libcfs_kmemory.counter,
138                 .maxlen   = sizeof(int),
139                 .mode     = 0444,
140                 .proc_handler = &proc_dointvec
141         },
142         {
143                 .ctl_name = PSDEV_LNET_CATASTROPHE,
144                 .procname = "catastrophe",
145                 .data     = &libcfs_catastrophe,
146                 .maxlen   = sizeof(int),
147                 .mode     = 0444,
148                 .proc_handler = &proc_dointvec
149         },
150         {
151                 .ctl_name = PSDEV_LNET_PANIC_ON_LBUG,
152                 .procname = "panic_on_lbug",
153                 .data     = &libcfs_panic_on_lbug,
154                 .maxlen   = sizeof(int),
155                 .mode     = 0444,
156                 .proc_handler = &proc_dointvec
157         },
158         {0}
159 };
160
161 static struct ctl_table top_table[2] = {
162         {
163                 .ctl_name = PSDEV_LNET,
164                 .procname = "lnet",
165                 .data     = NULL,
166                 .maxlen   = 0,
167                 .mode     = 0555,
168                 .child    = lnet_table
169         },
170         {0}
171 };
172
173 int LL_PROC_PROTO(proc_dobitmasks)
174 {
175         const int     tmpstrlen = 512;
176         char         *str;
177         int           rc = 0;
178         /* the proc filling api stumps me always, coax proc_dointvec
179          * and proc_dostring into doing the drudgery by cheating
180          * with a dummy ctl_table
181          */
182         struct ctl_table dummy = *table;
183         unsigned int *mask = (unsigned int *)table->data;
184         int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
185
186         str = kmalloc(tmpstrlen, GFP_USER);
187         if (str == NULL)
188                 return -ENOMEM;
189
190         if (write) {
191                 size_t oldlen = *lenp;
192 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
193                 loff_t oldpos = *ppos;
194 #endif
195
196                 dummy.proc_handler = &proc_dointvec;
197
198                 /* old proc interface allows user to specify just an int
199                  * value; be compatible and don't break userland.
200                  */
201                 rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
202
203                 if (rc != -EINVAL)
204                         goto out;
205
206                 /* using new interface */
207                 dummy.data = str;
208                 dummy.maxlen = tmpstrlen;
209                 dummy.proc_handler = &proc_dostring;
210
211                 /* proc_dointvec might have changed these */
212                 *lenp = oldlen;
213 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
214                 *ppos = oldpos;
215 #endif
216
217                 rc = ll_proc_dostring(&dummy, write, filp, buffer, lenp, ppos);
218
219                 if (rc != 0)
220                         goto out;
221
222                 rc = libcfs_debug_str2mask(mask, dummy.data, is_subsys);
223         } else {
224                 dummy.data = str;
225                 dummy.maxlen = tmpstrlen;
226                 dummy.proc_handler = &proc_dostring;
227
228                 libcfs_debug_mask2str(dummy.data, dummy.maxlen,*mask,is_subsys);
229
230                 rc = ll_proc_dostring(&dummy, write, filp, buffer, lenp, ppos);
231         }
232
233 out:
234         kfree(str);
235         return rc;
236 }
237
238 int insert_proc(void)
239 {
240         struct proc_dir_entry *ent;
241
242 #ifdef CONFIG_SYSCTL
243         if (!lnet_table_header)
244                 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
245 #endif
246
247         ent = create_proc_entry("sys/lnet/dump_kernel", 0, NULL);
248         if (ent == NULL) {
249                 CERROR("couldn't register dump_kernel\n");
250                 return -1;
251         }
252         ent->write_proc = trace_dk;
253
254         ent = create_proc_entry("sys/lnet/daemon_file", 0, NULL);
255         if (ent == NULL) {
256                 CERROR("couldn't register daemon_file\n");
257                 return -1;
258         }
259         ent->write_proc = trace_write_daemon_file;
260         ent->read_proc = trace_read_daemon_file;
261
262         ent = create_proc_entry("sys/lnet/debug_mb", 0, NULL);
263         if (ent == NULL) {
264                 CERROR("couldn't register debug_mb\n");
265                 return -1;
266         }
267         ent->write_proc = trace_write_debug_mb;
268         ent->read_proc = trace_read_debug_mb;
269
270         return 0;
271 }
272
273 void remove_proc(void)
274 {
275         remove_proc_entry("sys/lnet/dump_kernel", NULL);
276         remove_proc_entry("sys/lnet/daemon_file", NULL);
277         remove_proc_entry("sys/lnet/debug_mb", NULL);
278
279 #ifdef CONFIG_SYSCTL
280         if (lnet_table_header)
281                 cfs_unregister_sysctl_table(lnet_table_header);
282         lnet_table_header = NULL;
283 #endif
284 }