1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
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>
9 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
26 # define EXPORT_SYMTAB
29 #include <linux/config.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
33 #include <linux/string.h>
34 #include <linux/stat.h>
35 #include <linux/errno.h>
36 #include <linux/smp_lock.h>
37 #include <linux/unistd.h>
39 #include <linux/uio.h>
41 #include <asm/system.h>
42 #include <asm/uaccess.h>
45 #include <linux/file.h>
46 #include <linux/stat.h>
47 #include <linux/list.h>
48 #include <asm/uaccess.h>
49 #include <asm/segment.h>
51 #include <linux/proc_fs.h>
52 #include <linux/sysctl.h>
54 # define DEBUG_SUBSYSTEM S_PORTALS
56 #include <linux/kp30.h>
57 #include <asm/div64.h>
58 #include "tracefile.h"
60 static struct ctl_table_header *portals_table_header = NULL;
61 extern char debug_file_path[1024];
62 extern char portals_upcall[1024];
64 #define PSDEV_PORTALS (0x100)
66 PSDEV_DEBUG = 1, /* control debugging */
67 PSDEV_SUBSYSTEM_DEBUG, /* control debugging */
68 PSDEV_PRINTK, /* force all errors to console */
69 PSDEV_CONSOLE, /* allow _any_ messages to console */
70 PSDEV_DEBUG_PATH, /* crashdump log location */
71 PSDEV_DEBUG_DUMP_PATH, /* crashdump tracelog location */
72 PSDEV_PORTALS_UPCALL, /* User mode upcall script */
73 PSDEV_PORTALS_MEMUSED, /* bytes currently PORTAL_ALLOCated */
76 static struct ctl_table portals_table[] = {
77 {PSDEV_DEBUG, "debug", &portal_debug, sizeof(int), 0644, NULL,
79 {PSDEV_SUBSYSTEM_DEBUG, "subsystem_debug", &portal_subsystem_debug,
80 sizeof(int), 0644, NULL, &proc_dointvec},
81 {PSDEV_PRINTK, "printk", &portal_printk, sizeof(int), 0644, NULL,
83 {PSDEV_DEBUG_PATH, "debug_path", debug_file_path,
84 sizeof(debug_file_path), 0644, NULL, &proc_dostring, &sysctl_string},
85 {PSDEV_PORTALS_UPCALL, "upcall", portals_upcall,
86 sizeof(portals_upcall), 0644, NULL, &proc_dostring,
88 {PSDEV_PORTALS_MEMUSED, "memused", (int *)&portal_kmemory.counter,
89 sizeof(int), 0644, NULL, &proc_dointvec},
93 static struct ctl_table top_table[2] = {
94 {PSDEV_PORTALS, "portals", NULL, 0, 0555, portals_table},
99 #ifdef PORTALS_PROFILING
101 * profiling stuff. we do this statically for now 'cause its simple,
102 * but we could do some tricks with elf sections to have this array
103 * automatically built.
105 #define def_prof(FOO) [PROF__##FOO] = {#FOO, 0, }
107 struct prof_ent prof_ents[] = {
108 def_prof(our_recvmsg),
109 def_prof(our_sendmsg),
110 def_prof(socknal_recv),
112 def_prof(conn_list_walk),
114 def_prof(lib_finalize),
115 def_prof(pingcli_time),
116 def_prof(gmnal_send),
117 def_prof(gmnal_recv),
120 EXPORT_SYMBOL(prof_ents);
123 * this function is as crazy as the proc filling api
126 * buffer: page allocated for us to scribble in. the
127 * data returned to the user will be taken from here.
128 * *start: address of the pointer that will tell the
129 * caller where in buffer the data the user wants is.
130 * ppos: offset in the entire /proc file that the user
132 * wanted: the amount of data the user wants.
134 * while going, 'curpos' is the offset in the entire
135 * file where we currently are. We only actually
136 * start filling buffer when we get to a place in
137 * the file that the user cares about.
139 * we take care to only sprintf when the user cares because
140 * we're holding a lock while we do this.
142 * we're smart and know that we generate fixed size lines.
143 * we only start writing to the buffer when the user cares.
144 * This is unpredictable because we don't snapshot the
145 * list between calls that are filling in a file from
146 * the list. The list could change mid read and the
147 * output will look very weird indeed. oh well.
150 static int prof_read_proc(char *buffer, char **start, off_t ppos, int wanted,
151 int *eof, void *data)
155 char *header = "Interval Cycles_per (Starts Finishes Total)\n";
156 int header_len = strlen(header);
157 char *format = "%-15s %.12Ld (%.12d %.12d %.12Ld)";
158 int line_len = (15 + 1 + 12 + 2 + 12 + 1 + 12 + 1 + 12 + 1);
162 if (ppos < header_len) {
163 int diff = MIN(header_len, wanted);
164 memcpy(buffer, header + ppos, diff);
174 for ( i = 0; i < MAX_PROFS ; i++) {
176 struct prof_ent *pe = &prof_ents[i];
177 long long cycles_per;
179 * find the part of the array that the buffer wants
181 if (ppos >= (curpos + line_len)) {
185 /* the clever caller split a line */
187 *start = buffer + (ppos - curpos);
190 if (pe->finishes == 0)
194 cycles_per = pe->total_cycles;
195 do_div (cycles_per, pe->finishes);
198 copied = sprintf(buffer + len, format, pe->str, cycles_per,
199 pe->starts, pe->finishes, pe->total_cycles);
203 /* pad to line len, -1 for \n */
204 if ((copied < line_len-1)) {
205 int diff = (line_len-1) - copied;
206 memset(buffer + len, ' ', diff);
213 /* bail if we have enough */
214 if (((buffer + len) - *start) >= wanted)
225 return MIN(((buffer + len) - *start), wanted);
229 * all kids love /proc :/
231 static unsigned char basedir[]="net/portals";
232 #endif /* PORTALS_PROFILING */
234 int insert_proc(void)
236 struct proc_dir_entry *ent;
237 #if PORTALS_PROFILING
238 unsigned char dir[128];
240 if (ARRAY_SIZE(prof_ents) != MAX_PROFS) {
241 CERROR("profiling enum and array are out of sync.\n");
246 * This is pretty lame. assuming that failure just
247 * means that they already existed.
249 strcat(dir, basedir);
250 create_proc_entry(dir, S_IFDIR, 0);
252 strcat(dir, "/cycles");
253 ent = create_proc_entry(dir, 0, 0);
255 CERROR("couldn't register %s?\n", dir);
260 ent->read_proc = prof_read_proc;
261 #endif /* PORTALS_PROFILING */
264 if (!portals_table_header)
265 portals_table_header = register_sysctl_table(top_table, 0);
268 ent = create_proc_entry("sys/portals/dump_kernel", 0, NULL);
270 CERROR("couldn't register dump_kernel\n");
273 ent->write_proc = trace_dk;
275 ent = create_proc_entry("sys/portals/daemon_file", 0, NULL);
277 CERROR("couldn't register daemon_file\n");
280 ent->write_proc = trace_write_daemon_file;
281 ent->read_proc = trace_read_daemon_file;
283 ent = create_proc_entry("sys/portals/debug_mb", 0, NULL);
285 CERROR("couldn't register debug_mb\n");
288 ent->write_proc = trace_write_debug_mb;
289 ent->read_proc = trace_read_debug_mb;
294 void remove_proc(void)
296 #if PORTALS_PROFILING
297 unsigned char dir[128];
301 strcat(dir, basedir);
305 strcat(dir, "/cycles");
306 remove_proc_entry(dir, 0);
309 remove_proc_entry(dir, 0);
310 #endif /* PORTALS_PROFILING */
312 remove_proc_entry("sys/portals/dump_kernel", NULL);
313 remove_proc_entry("sys/portals/daemon_file", NULL);
314 remove_proc_entry("sys/portals/debug_mb", NULL);
317 if (portals_table_header)
318 unregister_sysctl_table(portals_table_header);
319 portals_table_header = NULL;