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