Whamcloud - gitweb
dca51e057406753fcba388887499bb04b195358b
[fs/lustre-release.git] / libcfs / libcfs / darwin / darwin-proc.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
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.
11  *
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).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see
20  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
21  *
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
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
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>
42 #include <sys/proc.h>
43 #include <sys/unistd.h>
44 #include <mach/mach_types.h>
45
46 #define DEBUG_SUBSYSTEM S_LNET
47
48 #include <libcfs/libcfs.h>
49
50 #define LIBCFS_SYSCTL           "libcfs"
51 #define LIBCFS_SYSCTL_SPRITE    "sprite"
52 #define LIBCFS_SYSCTL_MAGIC     0xbabeface
53
54 static struct libcfs_sysctl_sprite {
55         int                     ss_magic;
56         struct sysctl_oid_list  *ss_link;
57 } libcfs_sysctl_sprite = { 0, NULL };
58
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;
66
67 static int sysctl_debug_kernel SYSCTL_HANDLER_ARGS
68 {
69 #error "Check me"
70         const int  maxstr = 1024;
71         char      *str;
72         int        error;
73
74         if (req->newptr == USER_ADDR_NULL) {
75                 /* read request */
76                 return -EINVAL;
77         }
78
79         /* write request */
80         error = trace_allocate_string_buffer(&str, maxstr + 1);
81         if (error != 0)
82                 return error;
83
84         error = SYSCTL_IN(req, str, maxstr);
85
86         /* NB str guaranteed terminted */
87         if (error == 0)
88                 error = tracefile_dump_all_pages(str);
89
90         trace_free_string_buffer(str, maxstr + 1);
91         return error;
92 }
93
94 static int sysctl_daemon_file SYSCTL_HANDLER_ARGS
95 {
96 #error "Check me"
97         int   error;
98         char *str;
99
100         if (req->newptr == USER_ADDR_NULL) {
101                 /* a read */
102                 tracefile_read_lock();
103
104                 /* include terminating '\0' */
105                 error = SYSCTL_OUT(req, tracefile, strlen(tracefile) + 1);
106
107                 tracefile_read_unlock();
108                 return error;
109         }
110         
111         /* write request */
112         error = trace_allocate_string_buffer(&str, TRACEFILE_NAME_SIZE);
113         if (error != 0)
114                 return error;
115
116         error = SYSCTL_IN(req, str, TRACEFILE_NAME_SIZE - 1);
117
118         /* NB str guaranteed terminted */
119         if (error == 0)
120                 error = trace_daemon_command(str);
121
122         trace_free_string_buffer(str, TRACEFILE_NAME_SIZE);
123         return error;
124 }
125
126
127 static int sysctl_debug_mb SYSCTL_HANDLER_ARGS
128 {
129 #error "Check me"
130         long mb;
131         int  error;
132         
133         if (req->newptr == USER_ADDR_NULL) {
134                 /* read */
135                 mb = trace_get_debug_mb();
136                 error = SYSCTL_OUT(req, &mb, sizeof(mb));
137         } else {
138                 /* write */
139                 error = SYSCTL_IN(req, &mb, sizeof(mb));
140                 if (error == 0)
141                         error = trace_set_debug_mb(mb);
142         }
143         
144         return error;
145 }
146
147 static int proc_fail_loc SYSCTL_HANDLER_ARGS
148 {
149         int error = 0;
150         long old_fail_loc = cfs_fail_loc;
151
152         error = sysctl_handle_long(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
153         if (!error && req->newptr != USER_ADDR_NULL) {
154                 if (old_fail_loc != cfs_fail_loc)
155                         cfs_waitq_signal(&cfs_race_waitq);
156         } else  if (req->newptr != USER_ADDR_NULL) {
157                 /* Something was wrong with the write request */
158                 printf ("sysctl fail loc fault: %d.\n", error);
159         } else {
160                 /* Read request */
161                 error = SYSCTL_OUT(req, &cfs_fail_loc, sizeof cfs_fail_loc);
162         }
163         return error;
164 }
165
166 /*
167  * sysctl table for lnet
168  */
169
170 SYSCTL_NODE (,                  OID_AUTO,       lnet,   CTLFLAG_RW,
171              0,                 "lnet sysctl top");
172
173 SYSCTL_INT(_lnet,                       OID_AUTO,       debug,
174              CTLTYPE_INT | CTLFLAG_RW ,                 &libcfs_debug,
175              0,         "debug");
176 SYSCTL_INT(_lnet,                       OID_AUTO,       subsystem_debug,
177              CTLTYPE_INT | CTLFLAG_RW,                  &libcfs_subsystem_debug,
178              0,         "subsystem debug");
179 SYSCTL_INT(_lnet,                       OID_AUTO,       printk,
180              CTLTYPE_INT | CTLFLAG_RW,                  &libcfs_printk,
181              0,         "printk");
182 SYSCTL_INT(_lnet,                       OID_AUTO,       console_ratelimit,
183              CTLTYPE_INT | CTLFLAG_RW,                  &libcfs_console_ratelimit,
184              0,         "console_ratelimit");
185 SYSCTL_STRING(_lnet,                    OID_AUTO,       debug_path,
186              CTLTYPE_STRING | CTLFLAG_RW,               debug_file_path,
187              1024,      "debug path");
188 SYSCTL_INT(_lnet,                       OID_AUTO,       memused,
189              CTLTYPE_INT | CTLFLAG_RW,                  (int *)&libcfs_kmemory.counter,
190              0,         "memused");
191 SYSCTL_INT(_lnet,                       OID_AUTO,       catastrophe,
192              CTLTYPE_INT | CTLFLAG_RW,                  (int *)&libcfs_catastrophe,
193              0,         "catastrophe");
194
195 #error "check me"
196 SYSCTL_PROC(_lnet,                      OID_AUTO,       debug_kernel,
197              CTLTYPE_STRING | CTLFLAG_W,                0,
198              0,         &sysctl_debug_kernel,           "A",    "debug_kernel");
199 SYSCTL_PROC(_lnet,                      OID_AUTO,       daemon_file,
200              CTLTYPE_STRING | CTLFLAG_RW,               0,
201              0,         &sysctl_daemon_file,            "A",    "daemon_file");
202 SYSCTL_PROC(_lnet,                      OID_AUTO,       debug_mb,
203              CTLTYPE_INT | CTLFLAG_RW,                  0,
204              0,         &sysctl_debug_mb,               "L",    "debug_mb");
205 SYSCTL_PROC(_lnet,                      OID_AUTO,       fail_loc, 
206              CTLTYPE_INT | CTLFLAG_RW ,                 &cfs_fail_loc,
207              0,         &proc_fail_loc,                 "I",    "cfs_fail_loc");
208
209 static cfs_sysctl_table_t       top_table[] = {
210         &sysctl__lnet,
211         &sysctl__lnet_debug,
212         &sysctl__lnet_subsystem_debug,
213         &sysctl__lnet_printk,
214         &sysctl__lnet_console_ratelimit,
215         &sysctl__lnet_debug_path,
216         &sysctl__lnet_memused,
217         &sysctl__lnet_catastrophe,
218         &sysctl__lnet_debug_kernel,
219         &sysctl__lnet_daemon_file,
220         &sysctl__lnet_debug_mb,
221         &sysctl__lnet_cfs_fail_loc
222         NULL
223 };
224
225 /*
226  * Register sysctl table
227  */
228 cfs_sysctl_table_header_t *
229 cfs_register_sysctl_table (cfs_sysctl_table_t *table, int arg)
230 {
231         cfs_sysctl_table_t      item;
232         int i = 0;
233
234         while ((item = table[i++]) != NULL) 
235                 sysctl_register_oid(item);
236         return table;
237 }
238
239 /*
240  * Unregister sysctl table
241  */
242 void
243 cfs_unregister_sysctl_table (cfs_sysctl_table_header_t *table) {
244         int i = 0;
245         cfs_sysctl_table_t      item;
246
247         while ((item = table[i++]) != NULL) 
248                 sysctl_unregister_oid(item);
249         return;
250 }
251
252 /*
253  * Allocate a sysctl oid. 
254  */
255 static struct sysctl_oid *
256 cfs_alloc_sysctl(struct sysctl_oid_list *parent, int nbr, int access,
257                  const char *name, void *arg1, int arg2, const char *fmt,
258                  int (*handler) SYSCTL_HANDLER_ARGS)
259 {
260         struct sysctl_oid *oid;
261         char    *sname = NULL;
262         char    *sfmt = NULL;
263
264         if (strlen(name) + 1 > CTL_MAXNAME) {
265                 printf("libcfs: sysctl name: %s is too long.\n", name);
266                 return NULL;
267         }
268         oid = (struct sysctl_oid*)_MALLOC(sizeof(struct sysctl_oid), 
269                                           M_TEMP, M_WAITOK | M_ZERO);
270         if (oid == NULL) 
271                 return NULL;
272
273         sname = (char *)_MALLOC(sizeof(CTL_MAXNAME), 
274                                 M_TEMP, M_WAITOK | M_ZERO);
275         if (sname == NULL) 
276                 goto error;
277         strcpy(sname, name);
278
279         sfmt = (char *)_MALLOC(4, M_TEMP, M_WAITOK | M_ZERO);
280         if (sfmt == NULL) 
281                 goto error;
282         strcpy(sfmt, fmt);
283
284         if (parent == NULL)
285                 oid->oid_parent = &sysctl__children;
286         else
287                 oid->oid_parent = parent;
288         oid->oid_number = nbr;
289         oid->oid_kind = access;
290         oid->oid_name = sname;
291         oid->oid_handler = handler;
292         oid->oid_fmt = sfmt;
293
294         if ((access & CTLTYPE) == CTLTYPE_NODE){
295                 /* It's a sysctl node */
296                 struct sysctl_oid_list *link;
297
298                 link = (struct sysctl_oid_list *)_MALLOC(sizeof(struct sysctl_oid_list), 
299                                                          M_TEMP, M_WAITOK | M_ZERO);
300                 if (link == NULL)
301                         goto error;
302                 oid->oid_arg1 = link;
303                 oid->oid_arg2 = 0;
304         } else {
305                 oid->oid_arg1 = arg1;
306                 oid->oid_arg2 = arg2;
307         }
308
309         return oid;
310 error:
311         if (sfmt != NULL)
312                 _FREE(sfmt, M_TEMP);
313         if (sname != NULL)
314                 _FREE(sname, M_TEMP);
315         if (oid != NULL)
316                 _FREE(oid, M_TEMP);
317         return NULL;
318 }
319
320 void cfs_free_sysctl(struct sysctl_oid *oid)
321 {
322         if (oid->oid_name != NULL)
323                 _FREE((void *)oid->oid_name, M_TEMP);
324         if (oid->oid_fmt != NULL)
325                 _FREE((void *)oid->oid_fmt, M_TEMP);
326         if ((oid->oid_kind & CTLTYPE_NODE != 0) && oid->oid_arg1)
327                 /* XXX Liang: need to assert the list is empty */
328                 _FREE(oid->oid_arg1, M_TEMP);
329         _FREE(oid, M_TEMP);
330 }
331
332 #define CFS_SYSCTL_ISVALID ((libcfs_sysctl_sprite.ss_magic == LIBCFS_SYSCTL_MAGIC) && \
333                             (libcfs_sysctl_sprite.ss_link != NULL))       
334
335 int
336 cfs_sysctl_isvalid(void)
337 {
338         return CFS_SYSCTL_ISVALID;
339 }
340
341 struct sysctl_oid *
342 cfs_alloc_sysctl_node(struct sysctl_oid_list *parent, int nbr, int access,
343                       const char *name, int (*handler) SYSCTL_HANDLER_ARGS)
344 {
345         if (parent == NULL && CFS_SYSCTL_ISVALID)
346                 parent = libcfs_sysctl_sprite.ss_link;
347         return cfs_alloc_sysctl(parent, nbr, CTLTYPE_NODE | access, name,
348                                 NULL, 0, "N", handler);
349 }
350
351 struct sysctl_oid *
352 cfs_alloc_sysctl_int(struct sysctl_oid_list *parent, int nbr, int access,
353                      const char *name, int *ptr, int val)
354 {
355         if (parent == NULL && CFS_SYSCTL_ISVALID)
356                 parent = libcfs_sysctl_sprite.ss_link;
357         return cfs_alloc_sysctl(parent, nbr, CTLTYPE_INT | access, name, 
358                                 ptr, val, "I", sysctl_handle_int);
359 }
360
361 struct sysctl_oid *
362 cfs_alloc_sysctl_long(struct sysctl_oid_list *parent, int nbr, int access,
363                       const char *name, int *ptr, int val)
364 {
365         if (parent == NULL && CFS_SYSCTL_ISVALID)
366                 parent = libcfs_sysctl_sprite.ss_link;
367         return cfs_alloc_sysctl(parent, nbr, CTLTYPE_INT | access, name, 
368                                 ptr, val, "L", sysctl_handle_long);
369 }
370
371 struct sysctl_oid *
372 cfs_alloc_sysctl_string(struct sysctl_oid_list *parent, int nbr, int access,
373                         const char *name, char *ptr, int len)
374 {
375         if (parent == NULL && CFS_SYSCTL_ISVALID)
376                 parent = libcfs_sysctl_sprite.ss_link;
377         return cfs_alloc_sysctl(parent, nbr, CTLTYPE_STRING | access, name, 
378                                 ptr, len, "A", sysctl_handle_string);
379 }
380
381 struct sysctl_oid *
382 cfs_alloc_sysctl_struct(struct sysctl_oid_list *parent, int nbr, int access,
383                         const char *name, void *ptr, int size)
384 {
385         if (parent == NULL && CFS_SYSCTL_ISVALID)
386                 parent = libcfs_sysctl_sprite.ss_link;
387         return cfs_alloc_sysctl(parent, nbr, CTLTYPE_OPAQUE | access, name,
388                                 ptr, size, "S", sysctl_handle_opaque);
389 }
390
391 /* no proc in osx */
392 cfs_proc_dir_entry_t *
393 cfs_create_proc_entry(char *name, int mod, cfs_proc_dir_entry_t *parent)
394 {
395         cfs_proc_dir_entry_t *entry;
396         MALLOC(entry, cfs_proc_dir_entry_t *, sizeof(cfs_proc_dir_entry_t), M_TEMP, M_WAITOK|M_ZERO);
397
398         return  entry;
399 }
400
401 void
402 cfs_free_proc_entry(cfs_proc_dir_entry_t *de){
403         FREE(de, M_TEMP);
404         return;
405 };
406
407 void
408 cfs_remove_proc_entry(char *name, cfs_proc_dir_entry_t *entry)
409 {
410         cfs_free_proc_entry(entry);
411         return;
412 }
413
414 int
415 insert_proc(void)
416 {
417 #if 1
418         if (!libcfs_table_header) 
419                 libcfs_table_header = cfs_register_sysctl_table(top_table, 0);
420 #endif
421         return 0;
422 }
423
424 void
425 remove_proc(void)
426 {
427 #if 1
428         if (libcfs_table_header != NULL) 
429                 cfs_unregister_sysctl_table(libcfs_table_header); 
430         libcfs_table_header = NULL;
431 #endif
432         return;
433 }
434
435 int
436 cfs_sysctl_init(void)
437 {
438         struct sysctl_oid               *oid_root;
439         struct sysctl_oid               *oid_sprite;
440         struct libcfs_sysctl_sprite     *sprite;
441         size_t  len; 
442         int     rc;
443
444         len = sizeof(struct libcfs_sysctl_sprite);
445         rc = sysctlbyname("libcfs.sprite", 
446                           (void *)&libcfs_sysctl_sprite, &len, NULL, 0);
447         if (rc == 0) {
448                 /* 
449                  * XXX Liang: assert (rc == 0 || rc == ENOENT)
450                  *
451                  * libcfs.sprite has been registered by previous 
452                  * loading of libcfs 
453                  */
454                 if (libcfs_sysctl_sprite.ss_magic != LIBCFS_SYSCTL_MAGIC) {
455                         printf("libcfs: magic number of libcfs.sprite "
456                                "is not right (%lx, %lx)\n", 
457                                libcfs_sysctl_sprite.ss_magic,
458                                LIBCFS_SYSCTL_MAGIC);
459                         return -1;
460                 }
461                 assert(libcfs_sysctl_sprite.ss_link != NULL);
462                 printf("libcfs: registered libcfs.sprite found.\n");
463                 return 0;
464         }
465         oid_root = cfs_alloc_sysctl_node(NULL, OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN,
466                                          LIBCFS_SYSCTL, 0);
467         if (oid_root == NULL)
468                 return -1;
469         sysctl_register_oid(oid_root);
470
471         sprite = (struct libcfs_sysctl_sprite *)_MALLOC(sizeof(struct libcfs_sysctl_sprite), 
472                                                         M_TEMP, M_WAITOK | M_ZERO);
473         if (sprite == NULL) {
474                 sysctl_unregister_oid(oid_root);
475                 cfs_free_sysctl(oid_root);
476                 return -1;
477         }
478         sprite->ss_magic = LIBCFS_SYSCTL_MAGIC;
479         sprite->ss_link = (struct sysctl_oid_list *)oid_root->oid_arg1;
480         oid_sprite = cfs_alloc_sysctl_struct((struct sysctl_oid_list *)oid_root->oid_arg1, 
481                                              OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN, 
482                                              LIBCFS_SYSCTL_SPRITE, sprite, 
483                                              sizeof(struct libcfs_sysctl_sprite));
484         if (oid_sprite == NULL) {
485                 cfs_free_sysctl(oid_sprite);
486                 sysctl_unregister_oid(oid_root);
487                 cfs_free_sysctl(oid_root);
488                 return -1;
489         }
490         sysctl_register_oid(oid_sprite);
491
492         libcfs_sysctl_sprite.ss_magic = sprite->ss_magic;
493         libcfs_sysctl_sprite.ss_link = sprite->ss_link;
494
495         return 0;
496 }
497
498 void
499 cfs_sysctl_fini(void)
500 {
501         libcfs_sysctl_sprite.ss_magic = 0;
502         libcfs_sysctl_sprite.ss_link = NULL;
503 }