Whamcloud - gitweb
LU-1346 libcfs: cleanup libcfs primitive (linux-prim.h)
[fs/lustre-release.git] / libcfs / libcfs / darwin / darwin-proc.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
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.
9  *
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).
15  *
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
19  *
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
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
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>
40 #include <sys/proc.h>
41 #include <sys/unistd.h>
42 #include <mach/mach_types.h>
43
44 #define DEBUG_SUBSYSTEM S_LNET
45
46 #include <libcfs/libcfs.h>
47
48 #define LIBCFS_SYSCTL           "libcfs"
49 #define LIBCFS_SYSCTL_SPRITE    "sprite"
50 #define LIBCFS_SYSCTL_MAGIC     0xbabeface
51
52 static struct libcfs_sysctl_sprite {
53         int                     ss_magic;
54         struct sysctl_oid_list  *ss_link;
55 } libcfs_sysctl_sprite = { 0, NULL };
56
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;
64
65 static int sysctl_debug_kernel SYSCTL_HANDLER_ARGS
66 {
67 #error "Check me"
68         const int  maxstr = 1024;
69         char      *str;
70         int        error;
71
72         if (req->newptr == USER_ADDR_NULL) {
73                 /* read request */
74                 return -EINVAL;
75         }
76
77         /* write request */
78         error = trace_allocate_string_buffer(&str, maxstr + 1);
79         if (error != 0)
80                 return error;
81
82         error = SYSCTL_IN(req, str, maxstr);
83
84         /* NB str guaranteed terminted */
85         if (error == 0)
86                 error = tracefile_dump_all_pages(str);
87
88         trace_free_string_buffer(str, maxstr + 1);
89         return error;
90 }
91
92 static int sysctl_daemon_file SYSCTL_HANDLER_ARGS
93 {
94 #error "Check me"
95         int   error;
96         char *str;
97
98         if (req->newptr == USER_ADDR_NULL) {
99                 /* a read */
100                 tracefile_read_lock();
101
102                 /* include terminating '\0' */
103                 error = SYSCTL_OUT(req, tracefile, strlen(tracefile) + 1);
104
105                 tracefile_read_unlock();
106                 return error;
107         }
108         
109         /* write request */
110         error = trace_allocate_string_buffer(&str, TRACEFILE_NAME_SIZE);
111         if (error != 0)
112                 return error;
113
114         error = SYSCTL_IN(req, str, TRACEFILE_NAME_SIZE - 1);
115
116         /* NB str guaranteed terminted */
117         if (error == 0)
118                 error = trace_daemon_command(str);
119
120         trace_free_string_buffer(str, TRACEFILE_NAME_SIZE);
121         return error;
122 }
123
124
125 static int sysctl_debug_mb SYSCTL_HANDLER_ARGS
126 {
127 #error "Check me"
128         long mb;
129         int  error;
130         
131         if (req->newptr == USER_ADDR_NULL) {
132                 /* read */
133                 mb = trace_get_debug_mb();
134                 error = SYSCTL_OUT(req, &mb, sizeof(mb));
135         } else {
136                 /* write */
137                 error = SYSCTL_IN(req, &mb, sizeof(mb));
138                 if (error == 0)
139                         error = trace_set_debug_mb(mb);
140         }
141         
142         return error;
143 }
144
145 static int proc_fail_loc SYSCTL_HANDLER_ARGS
146 {
147         int error = 0;
148         long old_fail_loc = cfs_fail_loc;
149
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                         cfs_waitq_signal(&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);
157         } else {
158                 /* Read request */
159                 error = SYSCTL_OUT(req, &cfs_fail_loc, sizeof cfs_fail_loc);
160         }
161         return error;
162 }
163
164 /*
165  * sysctl table for lnet
166  */
167
168 SYSCTL_NODE (,                  OID_AUTO,       lnet,   CTLFLAG_RW,
169              0,                 "lnet sysctl top");
170
171 SYSCTL_INT(_lnet,                       OID_AUTO,       debug,
172              CTLTYPE_INT | CTLFLAG_RW ,                 &libcfs_debug,
173              0,         "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,
179              0,         "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,
185              1024,      "debug path");
186 SYSCTL_INT(_lnet,                       OID_AUTO,       memused,
187              CTLTYPE_INT | CTLFLAG_RW,                  (int *)&libcfs_kmemory.counter,
188              0,         "memused");
189 SYSCTL_INT(_lnet,                       OID_AUTO,       catastrophe,
190              CTLTYPE_INT | CTLFLAG_RW,                  (int *)&libcfs_catastrophe,
191              0,         "catastrophe");
192
193 #error "check me"
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");
206
207 static struct ctl_table top_table[] = {
208         &sysctl__lnet,
209         &sysctl__lnet_debug,
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
220         NULL
221 };
222
223 /*
224  * Register sysctl table
225  */
226 struct ctl_table_header *
227 register_sysctl_table(struct ctl_table *table, int arg)
228 {
229         struct ctl_table      item;
230         int i = 0;
231
232         while ((item = table[i++]) != NULL)
233                 sysctl_register_oid(item);
234         return table;
235 }
236
237 /*
238  * Unregister sysctl table
239  */
240 void unregister_sysctl_table(struct ctl_table_header *table)
241 {
242         int i = 0;
243         struct ctl_table      item;
244
245         while ((item = table[i++]) != NULL)
246                 sysctl_unregister_oid(item);
247         return;
248 }
249
250 /*
251  * Allocate a sysctl oid. 
252  */
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)
257 {
258         struct sysctl_oid *oid;
259         char    *sname = NULL;
260         char    *sfmt = NULL;
261
262         if (strlen(name) + 1 > CTL_MAXNAME) {
263                 printf("libcfs: sysctl name: %s is too long.\n", name);
264                 return NULL;
265         }
266         oid = (struct sysctl_oid*)_MALLOC(sizeof(struct sysctl_oid), 
267                                           M_TEMP, M_WAITOK | M_ZERO);
268         if (oid == NULL) 
269                 return NULL;
270
271         sname = (char *)_MALLOC(sizeof(CTL_MAXNAME), 
272                                 M_TEMP, M_WAITOK | M_ZERO);
273         if (sname == NULL) 
274                 goto error;
275         strcpy(sname, name);
276
277         sfmt = (char *)_MALLOC(4, M_TEMP, M_WAITOK | M_ZERO);
278         if (sfmt == NULL) 
279                 goto error;
280         strcpy(sfmt, fmt);
281
282         if (parent == NULL)
283                 oid->oid_parent = &sysctl__children;
284         else
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;
290         oid->oid_fmt = sfmt;
291
292         if ((access & CTLTYPE) == CTLTYPE_NODE){
293                 /* It's a sysctl node */
294                 struct sysctl_oid_list *link;
295
296                 link = (struct sysctl_oid_list *)_MALLOC(sizeof(struct sysctl_oid_list), 
297                                                          M_TEMP, M_WAITOK | M_ZERO);
298                 if (link == NULL)
299                         goto error;
300                 oid->oid_arg1 = link;
301                 oid->oid_arg2 = 0;
302         } else {
303                 oid->oid_arg1 = arg1;
304                 oid->oid_arg2 = arg2;
305         }
306
307         return oid;
308 error:
309         if (sfmt != NULL)
310                 _FREE(sfmt, M_TEMP);
311         if (sname != NULL)
312                 _FREE(sname, M_TEMP);
313         if (oid != NULL)
314                 _FREE(oid, M_TEMP);
315         return NULL;
316 }
317
318 void cfs_free_sysctl(struct sysctl_oid *oid)
319 {
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);
327         _FREE(oid, M_TEMP);
328 }
329
330 #define CFS_SYSCTL_ISVALID ((libcfs_sysctl_sprite.ss_magic == LIBCFS_SYSCTL_MAGIC) && \
331                             (libcfs_sysctl_sprite.ss_link != NULL))       
332
333 int
334 cfs_sysctl_isvalid(void)
335 {
336         return CFS_SYSCTL_ISVALID;
337 }
338
339 struct sysctl_oid *
340 cfs_alloc_sysctl_node(struct sysctl_oid_list *parent, int nbr, int access,
341                       const char *name, int (*handler) SYSCTL_HANDLER_ARGS)
342 {
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);
347 }
348
349 struct sysctl_oid *
350 cfs_alloc_sysctl_int(struct sysctl_oid_list *parent, int nbr, int access,
351                      const char *name, int *ptr, int val)
352 {
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);
357 }
358
359 struct sysctl_oid *
360 cfs_alloc_sysctl_long(struct sysctl_oid_list *parent, int nbr, int access,
361                       const char *name, int *ptr, int val)
362 {
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);
367 }
368
369 struct sysctl_oid *
370 cfs_alloc_sysctl_string(struct sysctl_oid_list *parent, int nbr, int access,
371                         const char *name, char *ptr, int len)
372 {
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);
377 }
378
379 struct sysctl_oid *
380 cfs_alloc_sysctl_struct(struct sysctl_oid_list *parent, int nbr, int access,
381                         const char *name, void *ptr, int size)
382 {
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);
387 }
388
389 /* no proc in osx */
390 cfs_proc_dir_entry_t *
391 cfs_create_proc_entry(char *name, int mod, cfs_proc_dir_entry_t *parent)
392 {
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);
395
396         return  entry;
397 }
398
399 void
400 cfs_free_proc_entry(cfs_proc_dir_entry_t *de){
401         FREE(de, M_TEMP);
402         return;
403 };
404
405 void
406 cfs_remove_proc_entry(char *name, cfs_proc_dir_entry_t *entry)
407 {
408         cfs_free_proc_entry(entry);
409         return;
410 }
411
412 int
413 insert_proc(void)
414 {
415 #if 1
416         if (!libcfs_table_header)
417                 libcfs_table_header = register_sysctl_table(top_table);
418 #endif
419         return 0;
420 }
421
422 void
423 remove_proc(void)
424 {
425 #if 1
426         if (libcfs_table_header != NULL)
427                 unregister_sysctl_table(libcfs_table_header);
428         libcfs_table_header = NULL;
429 #endif
430         return;
431 }
432
433 int
434 cfs_sysctl_init(void)
435 {
436         struct sysctl_oid               *oid_root;
437         struct sysctl_oid               *oid_sprite;
438         struct libcfs_sysctl_sprite     *sprite;
439         size_t  len; 
440         int     rc;
441
442         len = sizeof(struct libcfs_sysctl_sprite);
443         rc = sysctlbyname("libcfs.sprite", 
444                           (void *)&libcfs_sysctl_sprite, &len, NULL, 0);
445         if (rc == 0) {
446                 /* 
447                  * XXX Liang: assert (rc == 0 || rc == ENOENT)
448                  *
449                  * libcfs.sprite has been registered by previous 
450                  * loading of libcfs 
451                  */
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);
457                         return -1;
458                 }
459                 assert(libcfs_sysctl_sprite.ss_link != NULL);
460                 printf("libcfs: registered libcfs.sprite found.\n");
461                 return 0;
462         }
463         oid_root = cfs_alloc_sysctl_node(NULL, OID_AUTO, CTLFLAG_RD | CTLFLAG_KERN,
464                                          LIBCFS_SYSCTL, 0);
465         if (oid_root == NULL)
466                 return -1;
467         sysctl_register_oid(oid_root);
468
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);
474                 return -1;
475         }
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);
486                 return -1;
487         }
488         sysctl_register_oid(oid_sprite);
489
490         libcfs_sysctl_sprite.ss_magic = sprite->ss_magic;
491         libcfs_sysctl_sprite.ss_link = sprite->ss_link;
492
493         return 0;
494 }
495
496 void
497 cfs_sysctl_fini(void)
498 {
499         libcfs_sysctl_sprite.ss_magic = 0;
500         libcfs_sysctl_sprite.ss_link = NULL;
501 }