1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see [sun.com URL with a
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
37 #include <sys/param.h>
38 #include <sys/kernel.h>
39 #include <sys/malloc.h>
40 #include <sys/systm.h>
41 #include <sys/sysctl.h>
43 #include <sys/unistd.h>
44 #include <mach/mach_types.h>
46 #define DEBUG_SUBSYSTEM S_LNET
48 #include <libcfs/libcfs.h>
50 #define LIBCFS_SYSCTL "libcfs"
51 #define LIBCFS_SYSCTL_SPRITE "sprite"
52 #define LIBCFS_SYSCTL_MAGIC 0xbabeface
54 static struct libcfs_sysctl_sprite {
56 struct sysctl_oid_list *ss_link;
57 } libcfs_sysctl_sprite = { 0, NULL };
59 static cfs_sysctl_table_header_t *libcfs_table_header = NULL;
60 extern unsigned int libcfs_debug;
61 extern unsigned int libcfs_subsystem_debug;
62 extern unsigned int libcfs_printk;
63 extern unsigned int libcfs_console_ratelimit;
64 extern unsigned int libcfs_catastrophe;
65 extern atomic_t libcfs_kmemory;
67 static int sysctl_debug_kernel SYSCTL_HANDLER_ARGS
70 const int maxstr = 1024;
74 if (req->newptr == USER_ADDR_NULL) {
80 error = trace_allocate_string_buffer(&str, maxstr + 1);
84 error = SYSCTL_IN(req, str, maxstr);
86 /* NB str guaranteed terminted */
88 error = tracefile_dump_all_pages(str);
90 trace_free_string_buffer(str, maxstr + 1);
94 static int sysctl_daemon_file SYSCTL_HANDLER_ARGS
100 if (req->newptr == USER_ADDR_NULL) {
102 tracefile_read_lock();
104 /* include terminating '\0' */
105 error = SYSCTL_OUT(req, tracefile, strlen(tracefile) + 1);
107 tracefile_read_unlock();
112 error = trace_allocate_string_buffer(&str, TRACEFILE_NAME_SIZE);
116 error = SYSCTL_IN(req, str, TRACEFILE_NAME_SIZE - 1);
118 /* NB str guaranteed terminted */
120 error = trace_daemon_command(str);
122 trace_free_string_buffer(str, TRACEFILE_NAME_SIZE);
127 static int sysctl_debug_mb SYSCTL_HANDLER_ARGS
133 if (req->newptr == USER_ADDR_NULL) {
135 mb = trace_get_debug_mb();
136 error = SYSCTL_OUT(req, &mb, sizeof(mb));
139 error = SYSCTL_IN(req, &mb, sizeof(mb));
141 error = trace_set_debug_mb(mb);
148 * sysctl table for lnet
151 SYSCTL_NODE (, OID_AUTO, lnet, CTLFLAG_RW,
152 0, "lnet sysctl top");
154 SYSCTL_INT(_lnet, OID_AUTO, debug,
155 CTLTYPE_INT | CTLFLAG_RW , &libcfs_debug,
157 SYSCTL_INT(_lnet, OID_AUTO, subsystem_debug,
158 CTLTYPE_INT | CTLFLAG_RW, &libcfs_subsystem_debug,
159 0, "subsystem debug");
160 SYSCTL_INT(_lnet, OID_AUTO, printk,
161 CTLTYPE_INT | CTLFLAG_RW, &libcfs_printk,
163 SYSCTL_INT(_lnet, OID_AUTO, console_ratelimit,
164 CTLTYPE_INT | CTLFLAG_RW, &libcfs_console_ratelimit,
165 0, "console_ratelimit");
166 SYSCTL_STRING(_lnet, OID_AUTO, debug_path,
167 CTLTYPE_STRING | CTLFLAG_RW, debug_file_path,
169 SYSCTL_INT(_lnet, OID_AUTO, memused,
170 CTLTYPE_INT | CTLFLAG_RW, (int *)&libcfs_kmemory.counter,
172 SYSCTL_INT(_lnet, OID_AUTO, catastrophe,
173 CTLTYPE_INT | CTLFLAG_RW, (int *)&libcfs_catastrophe,
177 SYSCTL_PROC(_lnet, OID_AUTO, debug_kernel,
178 CTLTYPE_STRING | CTLFLAG_W, 0,
179 0, &sysctl_debug_kernel, "A", "debug_kernel");
180 SYSCTL_PROC(_lnet, OID_AUTO, daemon_file,
181 CTLTYPE_STRING | CTLFLAG_RW, 0,
182 0, &sysctl_daemon_file, "A", "daemon_file");
183 SYSCTL_PROC(_lnet, OID_AUTO, debug_mb,
184 CTLTYPE_INT | CTLFLAG_RW, 0,
185 0, &sysctl_debug_mb, "L", "debug_mb");
188 static cfs_sysctl_table_t top_table[] = {
191 &sysctl__lnet_subsystem_debug,
192 &sysctl__lnet_printk,
193 &sysctl__lnet_console_ratelimit,
194 &sysctl__lnet_debug_path,
195 &sysctl__lnet_memused,
196 &sysctl__lnet_catastrophe,
197 &sysctl__lnet_debug_kernel,
198 &sysctl__lnet_daemon_file,
199 &sysctl__lnet_debug_mb,
204 * Register sysctl table
206 cfs_sysctl_table_header_t *
207 cfs_register_sysctl_table (cfs_sysctl_table_t *table, int arg)
209 cfs_sysctl_table_t item;
212 while ((item = table[i++]) != NULL)
213 sysctl_register_oid(item);
218 * Unregister sysctl table
221 cfs_unregister_sysctl_table (cfs_sysctl_table_header_t *table) {
223 cfs_sysctl_table_t item;
225 while ((item = table[i++]) != NULL)
226 sysctl_unregister_oid(item);
231 * Allocate a sysctl oid.
233 static struct sysctl_oid *
234 cfs_alloc_sysctl(struct sysctl_oid_list *parent, int nbr, int access,
235 const char *name, void *arg1, int arg2, const char *fmt,
236 int (*handler) SYSCTL_HANDLER_ARGS)
238 struct sysctl_oid *oid;
242 if (strlen(name) + 1 > CTL_MAXNAME) {
243 printf("libcfs: sysctl name: %s is too long.\n", name);
246 oid = (struct sysctl_oid*)_MALLOC(sizeof(struct sysctl_oid),
247 M_TEMP, M_WAITOK | M_ZERO);
251 sname = (char *)_MALLOC(sizeof(CTL_MAXNAME),
252 M_TEMP, M_WAITOK | M_ZERO);
257 sfmt = (char *)_MALLOC(4, M_TEMP, M_WAITOK | M_ZERO);
263 oid->oid_parent = &sysctl__children;
265 oid->oid_parent = parent;
266 oid->oid_number = nbr;
267 oid->oid_kind = access;
268 oid->oid_name = sname;
269 oid->oid_handler = handler;
272 if ((access & CTLTYPE) == CTLTYPE_NODE){
273 /* It's a sysctl node */
274 struct sysctl_oid_list *link;
276 link = (struct sysctl_oid_list *)_MALLOC(sizeof(struct sysctl_oid_list),
277 M_TEMP, M_WAITOK | M_ZERO);
280 oid->oid_arg1 = link;
283 oid->oid_arg1 = arg1;
284 oid->oid_arg2 = arg2;
292 _FREE(sname, M_TEMP);
298 void cfs_free_sysctl(struct sysctl_oid *oid)
300 if (oid->oid_name != NULL)
301 _FREE((void *)oid->oid_name, M_TEMP);
302 if (oid->oid_fmt != NULL)
303 _FREE((void *)oid->oid_fmt, M_TEMP);
304 if ((oid->oid_kind & CTLTYPE_NODE != 0) && oid->oid_arg1)
305 /* XXX Liang: need to assert the list is empty */
306 _FREE(oid->oid_arg1, M_TEMP);
310 #define CFS_SYSCTL_ISVALID ((libcfs_sysctl_sprite.ss_magic == LIBCFS_SYSCTL_MAGIC) && \
311 (libcfs_sysctl_sprite.ss_link != NULL))
314 cfs_sysctl_isvalid(void)
316 return CFS_SYSCTL_ISVALID;
320 cfs_alloc_sysctl_node(struct sysctl_oid_list *parent, int nbr, int access,
321 const char *name, int (*handler) SYSCTL_HANDLER_ARGS)
323 if (parent == NULL && CFS_SYSCTL_ISVALID)
324 parent = libcfs_sysctl_sprite.ss_link;
325 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_NODE | access, name,
326 NULL, 0, "N", handler);
330 cfs_alloc_sysctl_int(struct sysctl_oid_list *parent, int nbr, int access,
331 const char *name, int *ptr, int val)
333 if (parent == NULL && CFS_SYSCTL_ISVALID)
334 parent = libcfs_sysctl_sprite.ss_link;
335 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_INT | access, name,
336 ptr, val, "I", sysctl_handle_int);
340 cfs_alloc_sysctl_long(struct sysctl_oid_list *parent, int nbr, int access,
341 const char *name, int *ptr, int val)
343 if (parent == NULL && CFS_SYSCTL_ISVALID)
344 parent = libcfs_sysctl_sprite.ss_link;
345 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_INT | access, name,
346 ptr, val, "L", sysctl_handle_long);
350 cfs_alloc_sysctl_string(struct sysctl_oid_list *parent, int nbr, int access,
351 const char *name, char *ptr, int len)
353 if (parent == NULL && CFS_SYSCTL_ISVALID)
354 parent = libcfs_sysctl_sprite.ss_link;
355 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_STRING | access, name,
356 ptr, len, "A", sysctl_handle_string);
360 cfs_alloc_sysctl_struct(struct sysctl_oid_list *parent, int nbr, int access,
361 const char *name, void *ptr, int size)
363 if (parent == NULL && CFS_SYSCTL_ISVALID)
364 parent = libcfs_sysctl_sprite.ss_link;
365 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_OPAQUE | access, name,
366 ptr, size, "S", sysctl_handle_opaque);
370 cfs_proc_dir_entry_t *
371 cfs_create_proc_entry(char *name, int mod, cfs_proc_dir_entry_t *parent)
373 cfs_proc_dir_entry_t *entry;
374 MALLOC(entry, cfs_proc_dir_entry_t *, sizeof(cfs_proc_dir_entry_t), M_TEMP, M_WAITOK|M_ZERO);
380 cfs_free_proc_entry(cfs_proc_dir_entry_t *de){
386 cfs_remove_proc_entry(char *name, cfs_proc_dir_entry_t *entry)
388 cfs_free_proc_entry(entry);
396 if (!libcfs_table_header)
397 libcfs_table_header = cfs_register_sysctl_table(top_table, 0);
406 if (libcfs_table_header != NULL)
407 cfs_unregister_sysctl_table(libcfs_table_header);
408 libcfs_table_header = NULL;
414 cfs_sysctl_init(void)
416 struct sysctl_oid *oid_root;
417 struct sysctl_oid *oid_sprite;
418 struct libcfs_sysctl_sprite *sprite;
422 len = sizeof(struct libcfs_sysctl_sprite);
423 rc = sysctlbyname("libcfs.sprite",
424 (void *)&libcfs_sysctl_sprite, &len, NULL, 0);
427 * XXX Liang: assert (rc == 0 || rc == ENOENT)
429 * libcfs.sprite has been registered by previous
432 if (libcfs_sysctl_sprite.ss_magic != LIBCFS_SYSCTL_MAGIC) {
433 printf("libcfs: magic number of libcfs.sprite "
434 "is not right (%lx, %lx)\n",
435 libcfs_sysctl_sprite.ss_magic,
436 LIBCFS_SYSCTL_MAGIC);
439 assert(libcfs_sysctl_sprite.ss_link != NULL);
440 printf("libcfs: registered libcfs.sprite found.\n");
443 oid_root = cfs_alloc_sysctl_node(NULL, OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN,
445 if (oid_root == NULL)
447 sysctl_register_oid(oid_root);
449 sprite = (struct libcfs_sysctl_sprite *)_MALLOC(sizeof(struct libcfs_sysctl_sprite),
450 M_TEMP, M_WAITOK | M_ZERO);
451 if (sprite == NULL) {
452 sysctl_unregister_oid(oid_root);
453 cfs_free_sysctl(oid_root);
456 sprite->ss_magic = LIBCFS_SYSCTL_MAGIC;
457 sprite->ss_link = (struct sysctl_oid_list *)oid_root->oid_arg1;
458 oid_sprite = cfs_alloc_sysctl_struct((struct sysctl_oid_list *)oid_root->oid_arg1,
459 OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN,
460 LIBCFS_SYSCTL_SPRITE, sprite,
461 sizeof(struct libcfs_sysctl_sprite));
462 if (oid_sprite == NULL) {
463 cfs_free_sysctl(oid_sprite);
464 sysctl_unregister_oid(oid_root);
465 cfs_free_sysctl(oid_root);
468 sysctl_register_oid(oid_sprite);
470 libcfs_sysctl_sprite.ss_magic = sprite->ss_magic;
471 libcfs_sysctl_sprite.ss_link = sprite->ss_link;
477 cfs_sysctl_fini(void)
479 libcfs_sysctl_sprite.ss_magic = 0;
480 libcfs_sysctl_sprite.ss_link = NULL;