4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
18 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
20 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21 * CA 95054 USA or visit www.sun.com if you need additional information or
27 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28 * Use is subject to license terms.
31 * This file is part of Lustre, http://www.lustre.org/
32 * Lustre is a trademark of Sun Microsystems, Inc.
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/systm.h>
39 #include <sys/sysctl.h>
41 #include <sys/unistd.h>
42 #include <mach/mach_types.h>
44 #define DEBUG_SUBSYSTEM S_LNET
46 #include <libcfs/libcfs.h>
48 #define LIBCFS_SYSCTL "libcfs"
49 #define LIBCFS_SYSCTL_SPRITE "sprite"
50 #define LIBCFS_SYSCTL_MAGIC 0xbabeface
52 static struct libcfs_sysctl_sprite {
54 struct sysctl_oid_list *ss_link;
55 } libcfs_sysctl_sprite = { 0, NULL };
57 static struct ctl_table_header *libcfs_table_header = NULL;
58 extern unsigned int libcfs_debug;
59 extern unsigned int libcfs_subsystem_debug;
60 extern unsigned int libcfs_printk;
61 extern unsigned int libcfs_console_ratelimit;
62 extern unsigned int libcfs_catastrophe;
63 extern atomic_t libcfs_kmemory;
65 static int sysctl_debug_kernel SYSCTL_HANDLER_ARGS
68 const int maxstr = 1024;
72 if (req->newptr == USER_ADDR_NULL) {
78 error = trace_allocate_string_buffer(&str, maxstr + 1);
82 error = SYSCTL_IN(req, str, maxstr);
84 /* NB str guaranteed terminted */
86 error = tracefile_dump_all_pages(str);
88 trace_free_string_buffer(str, maxstr + 1);
92 static int sysctl_daemon_file SYSCTL_HANDLER_ARGS
98 if (req->newptr == USER_ADDR_NULL) {
100 tracefile_read_lock();
102 /* include terminating '\0' */
103 error = SYSCTL_OUT(req, tracefile, strlen(tracefile) + 1);
105 tracefile_read_unlock();
110 error = trace_allocate_string_buffer(&str, TRACEFILE_NAME_SIZE);
114 error = SYSCTL_IN(req, str, TRACEFILE_NAME_SIZE - 1);
116 /* NB str guaranteed terminted */
118 error = trace_daemon_command(str);
120 trace_free_string_buffer(str, TRACEFILE_NAME_SIZE);
125 static int sysctl_debug_mb SYSCTL_HANDLER_ARGS
131 if (req->newptr == USER_ADDR_NULL) {
133 mb = trace_get_debug_mb();
134 error = SYSCTL_OUT(req, &mb, sizeof(mb));
137 error = SYSCTL_IN(req, &mb, sizeof(mb));
139 error = trace_set_debug_mb(mb);
145 static int proc_fail_loc SYSCTL_HANDLER_ARGS
148 long old_fail_loc = cfs_fail_loc;
150 error = sysctl_handle_long(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
151 if (!error && req->newptr != USER_ADDR_NULL) {
152 if (old_fail_loc != cfs_fail_loc)
153 wake_up(&cfs_race_waitq);
154 } else if (req->newptr != USER_ADDR_NULL) {
155 /* Something was wrong with the write request */
156 printf ("sysctl fail loc fault: %d.\n", error);
159 error = SYSCTL_OUT(req, &cfs_fail_loc, sizeof cfs_fail_loc);
165 * sysctl table for lnet
168 SYSCTL_NODE (, OID_AUTO, lnet, CTLFLAG_RW,
169 0, "lnet sysctl top");
171 SYSCTL_INT(_lnet, OID_AUTO, debug,
172 CTLTYPE_INT | CTLFLAG_RW , &libcfs_debug,
174 SYSCTL_INT(_lnet, OID_AUTO, subsystem_debug,
175 CTLTYPE_INT | CTLFLAG_RW, &libcfs_subsystem_debug,
176 0, "subsystem debug");
177 SYSCTL_INT(_lnet, OID_AUTO, printk,
178 CTLTYPE_INT | CTLFLAG_RW, &libcfs_printk,
180 SYSCTL_INT(_lnet, OID_AUTO, console_ratelimit,
181 CTLTYPE_INT | CTLFLAG_RW, &libcfs_console_ratelimit,
182 0, "console_ratelimit");
183 SYSCTL_STRING(_lnet, OID_AUTO, debug_path,
184 CTLTYPE_STRING | CTLFLAG_RW, debug_file_path,
186 SYSCTL_INT(_lnet, OID_AUTO, memused,
187 CTLTYPE_INT | CTLFLAG_RW, (int *)&libcfs_kmemory.counter,
189 SYSCTL_INT(_lnet, OID_AUTO, catastrophe,
190 CTLTYPE_INT | CTLFLAG_RW, (int *)&libcfs_catastrophe,
194 SYSCTL_PROC(_lnet, OID_AUTO, debug_kernel,
195 CTLTYPE_STRING | CTLFLAG_W, 0,
196 0, &sysctl_debug_kernel, "A", "debug_kernel");
197 SYSCTL_PROC(_lnet, OID_AUTO, daemon_file,
198 CTLTYPE_STRING | CTLFLAG_RW, 0,
199 0, &sysctl_daemon_file, "A", "daemon_file");
200 SYSCTL_PROC(_lnet, OID_AUTO, debug_mb,
201 CTLTYPE_INT | CTLFLAG_RW, 0,
202 0, &sysctl_debug_mb, "L", "debug_mb");
203 SYSCTL_PROC(_lnet, OID_AUTO, fail_loc,
204 CTLTYPE_INT | CTLFLAG_RW , &cfs_fail_loc,
205 0, &proc_fail_loc, "I", "cfs_fail_loc");
207 static struct ctl_table top_table[] = {
210 &sysctl__lnet_subsystem_debug,
211 &sysctl__lnet_printk,
212 &sysctl__lnet_console_ratelimit,
213 &sysctl__lnet_debug_path,
214 &sysctl__lnet_memused,
215 &sysctl__lnet_catastrophe,
216 &sysctl__lnet_debug_kernel,
217 &sysctl__lnet_daemon_file,
218 &sysctl__lnet_debug_mb,
219 &sysctl__lnet_cfs_fail_loc
224 * Register sysctl table
226 struct ctl_table_header *
227 register_sysctl_table(struct ctl_table *table, int arg)
229 struct ctl_table item;
232 while ((item = table[i++]) != NULL)
233 sysctl_register_oid(item);
238 * Unregister sysctl table
240 void unregister_sysctl_table(struct ctl_table_header *table)
243 struct ctl_table item;
245 while ((item = table[i++]) != NULL)
246 sysctl_unregister_oid(item);
251 * Allocate a sysctl oid.
253 static struct sysctl_oid *
254 cfs_alloc_sysctl(struct sysctl_oid_list *parent, int nbr, int access,
255 const char *name, void *arg1, int arg2, const char *fmt,
256 int (*handler) SYSCTL_HANDLER_ARGS)
258 struct sysctl_oid *oid;
262 if (strlen(name) + 1 > CTL_MAXNAME) {
263 printf("libcfs: sysctl name: %s is too long.\n", name);
266 oid = (struct sysctl_oid*)_MALLOC(sizeof(struct sysctl_oid),
267 M_TEMP, M_WAITOK | M_ZERO);
271 sname = (char *)_MALLOC(sizeof(CTL_MAXNAME),
272 M_TEMP, M_WAITOK | M_ZERO);
277 sfmt = (char *)_MALLOC(4, M_TEMP, M_WAITOK | M_ZERO);
283 oid->oid_parent = &sysctl__children;
285 oid->oid_parent = parent;
286 oid->oid_number = nbr;
287 oid->oid_kind = access;
288 oid->oid_name = sname;
289 oid->oid_handler = handler;
292 if ((access & CTLTYPE) == CTLTYPE_NODE){
293 /* It's a sysctl node */
294 struct sysctl_oid_list *link;
296 link = (struct sysctl_oid_list *)_MALLOC(sizeof(struct sysctl_oid_list),
297 M_TEMP, M_WAITOK | M_ZERO);
300 oid->oid_arg1 = link;
303 oid->oid_arg1 = arg1;
304 oid->oid_arg2 = arg2;
312 _FREE(sname, M_TEMP);
318 void cfs_free_sysctl(struct sysctl_oid *oid)
320 if (oid->oid_name != NULL)
321 _FREE((void *)oid->oid_name, M_TEMP);
322 if (oid->oid_fmt != NULL)
323 _FREE((void *)oid->oid_fmt, M_TEMP);
324 if ((oid->oid_kind & CTLTYPE_NODE != 0) && oid->oid_arg1)
325 /* XXX Liang: need to assert the list is empty */
326 _FREE(oid->oid_arg1, M_TEMP);
330 #define CFS_SYSCTL_ISVALID ((libcfs_sysctl_sprite.ss_magic == LIBCFS_SYSCTL_MAGIC) && \
331 (libcfs_sysctl_sprite.ss_link != NULL))
334 cfs_sysctl_isvalid(void)
336 return CFS_SYSCTL_ISVALID;
340 cfs_alloc_sysctl_node(struct sysctl_oid_list *parent, int nbr, int access,
341 const char *name, int (*handler) SYSCTL_HANDLER_ARGS)
343 if (parent == NULL && CFS_SYSCTL_ISVALID)
344 parent = libcfs_sysctl_sprite.ss_link;
345 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_NODE | access, name,
346 NULL, 0, "N", handler);
350 cfs_alloc_sysctl_int(struct sysctl_oid_list *parent, int nbr, int access,
351 const char *name, int *ptr, int val)
353 if (parent == NULL && CFS_SYSCTL_ISVALID)
354 parent = libcfs_sysctl_sprite.ss_link;
355 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_INT | access, name,
356 ptr, val, "I", sysctl_handle_int);
360 cfs_alloc_sysctl_long(struct sysctl_oid_list *parent, int nbr, int access,
361 const char *name, int *ptr, int val)
363 if (parent == NULL && CFS_SYSCTL_ISVALID)
364 parent = libcfs_sysctl_sprite.ss_link;
365 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_INT | access, name,
366 ptr, val, "L", sysctl_handle_long);
370 cfs_alloc_sysctl_string(struct sysctl_oid_list *parent, int nbr, int access,
371 const char *name, char *ptr, int len)
373 if (parent == NULL && CFS_SYSCTL_ISVALID)
374 parent = libcfs_sysctl_sprite.ss_link;
375 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_STRING | access, name,
376 ptr, len, "A", sysctl_handle_string);
380 cfs_alloc_sysctl_struct(struct sysctl_oid_list *parent, int nbr, int access,
381 const char *name, void *ptr, int size)
383 if (parent == NULL && CFS_SYSCTL_ISVALID)
384 parent = libcfs_sysctl_sprite.ss_link;
385 return cfs_alloc_sysctl(parent, nbr, CTLTYPE_OPAQUE | access, name,
386 ptr, size, "S", sysctl_handle_opaque);
390 cfs_proc_dir_entry_t *
391 cfs_create_proc_entry(char *name, int mod, cfs_proc_dir_entry_t *parent)
393 cfs_proc_dir_entry_t *entry;
394 MALLOC(entry, cfs_proc_dir_entry_t *, sizeof(cfs_proc_dir_entry_t), M_TEMP, M_WAITOK|M_ZERO);
400 cfs_free_proc_entry(cfs_proc_dir_entry_t *de){
406 cfs_remove_proc_entry(char *name, cfs_proc_dir_entry_t *entry)
408 cfs_free_proc_entry(entry);
416 if (!libcfs_table_header)
417 libcfs_table_header = register_sysctl_table(top_table);
426 if (libcfs_table_header != NULL)
427 unregister_sysctl_table(libcfs_table_header);
428 libcfs_table_header = NULL;
434 cfs_sysctl_init(void)
436 struct sysctl_oid *oid_root;
437 struct sysctl_oid *oid_sprite;
438 struct libcfs_sysctl_sprite *sprite;
442 len = sizeof(struct libcfs_sysctl_sprite);
443 rc = sysctlbyname("libcfs.sprite",
444 (void *)&libcfs_sysctl_sprite, &len, NULL, 0);
447 * XXX Liang: assert (rc == 0 || rc == ENOENT)
449 * libcfs.sprite has been registered by previous
452 if (libcfs_sysctl_sprite.ss_magic != LIBCFS_SYSCTL_MAGIC) {
453 printf("libcfs: magic number of libcfs.sprite "
454 "is not right (%lx, %lx)\n",
455 libcfs_sysctl_sprite.ss_magic,
456 LIBCFS_SYSCTL_MAGIC);
459 assert(libcfs_sysctl_sprite.ss_link != NULL);
460 printf("libcfs: registered libcfs.sprite found.\n");
463 oid_root = cfs_alloc_sysctl_node(NULL, OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN,
465 if (oid_root == NULL)
467 sysctl_register_oid(oid_root);
469 sprite = (struct libcfs_sysctl_sprite *)_MALLOC(sizeof(struct libcfs_sysctl_sprite),
470 M_TEMP, M_WAITOK | M_ZERO);
471 if (sprite == NULL) {
472 sysctl_unregister_oid(oid_root);
473 cfs_free_sysctl(oid_root);
476 sprite->ss_magic = LIBCFS_SYSCTL_MAGIC;
477 sprite->ss_link = (struct sysctl_oid_list *)oid_root->oid_arg1;
478 oid_sprite = cfs_alloc_sysctl_struct((struct sysctl_oid_list *)oid_root->oid_arg1,
479 OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN,
480 LIBCFS_SYSCTL_SPRITE, sprite,
481 sizeof(struct libcfs_sysctl_sprite));
482 if (oid_sprite == NULL) {
483 cfs_free_sysctl(oid_sprite);
484 sysctl_unregister_oid(oid_root);
485 cfs_free_sysctl(oid_root);
488 sysctl_register_oid(oid_sprite);
490 libcfs_sysctl_sprite.ss_magic = sprite->ss_magic;
491 libcfs_sysctl_sprite.ss_link = sprite->ss_link;
497 cfs_sysctl_fini(void)
499 libcfs_sysctl_sprite.ss_magic = 0;
500 libcfs_sysctl_sprite.ss_link = NULL;