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