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