|
|
| version 1.14, 2003/11/23 22:15:22 | version 1.15, 2004/03/29 14:06:31 |
|---|---|
| Line 49 | Line 49 |
| #include <sys/malloc.h> | #include <sys/malloc.h> |
| #include <sys/proc.h> | #include <sys/proc.h> |
| #include <sys/sysproto.h> | #include <sys/sysproto.h> |
| #include <sys/lock.h> | |
| #include <vm/vm.h> | #include <vm/vm.h> |
| #include <vm/vm_extern.h> | #include <vm/vm_extern.h> |
| static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); | static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); |
| static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids"); | static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids"); |
| /* | static struct lock sysctl_lkp; |
| * Locking and stats | static struct lock sysctl_ctx_lkp; |
| */ | |
| static struct sysctl_lock { | |
| int sl_lock; | |
| int sl_want; | |
| int sl_locked; | |
| } memlock; | |
| static int sysctl_root(SYSCTL_HANDLER_ARGS); | static void sysctl_lock(int type); |
| static void sysctl_unlock(void); | |
| static void sysctl_ctx_lock(int type); | |
| static void sysctl_ctx_unlock(void); | |
| static int sysctl_root(SYSCTL_HANDLER_ARGS); | |
| static void sysctl_register_oid_int(struct sysctl_oid *oipd); | |
| static void sysctl_unregister_oid_int(struct sysctl_oid *oipd); | |
| static struct sysctl_ctx_entry* sysctl_ctx_entry_find_int | |
| (struct sysctl_ctx_list *, struct sysctl_oid *oidp); | |
| struct sysctl_oid_list sysctl__children; /* root list */ | struct sysctl_oid_list sysctl__children; /* root list */ |
| static struct sysctl_oid * | static struct sysctl_oid * |
| sysctl_find_oidname(const char *name, struct sysctl_oid_list *list) | sysctl_find_oidname(const char *name, struct sysctl_oid_list *list, int lock) |
| { | { |
| struct sysctl_oid *oidp; | struct sysctl_oid *oidp; |
| SLIST_FOREACH(oidp, list, oid_link) { | SLIST_FOREACH(oidp, list, oid_link) { |
| if (strcmp(oidp->oid_name, name) == 0) { | if (strcmp(oidp->oid_name, name) == 0) { |
| return (oidp); | break; |
| } | } |
| } | } |
| return (NULL); | return (oidp); |
| } | } |
| /* | /* |
| Line 87 sysctl_find_oidname(const char *name, st | Line 91 sysctl_find_oidname(const char *name, st |
| * Order by number in each list. | * Order by number in each list. |
| */ | */ |
| void sysctl_register_oid(struct sysctl_oid *oidp) | void |
| sysctl_register_oid(struct sysctl_oid *oidp) | |
| { | |
| sysctl_lock(LK_EXCLUSIVE); | |
| sysctl_register_oid_int(oidp); | |
| sysctl_unlock(); | |
| } | |
| static void | |
| sysctl_register_oid_int(struct sysctl_oid *oidp) | |
| { | { |
| struct sysctl_oid_list *parent = oidp->oid_parent; | struct sysctl_oid_list *parent = oidp->oid_parent; |
| struct sysctl_oid *p; | struct sysctl_oid *p; |
| Line 97 void sysctl_register_oid(struct sysctl_o | Line 110 void sysctl_register_oid(struct sysctl_o |
| * First check if another oid with the same name already | * First check if another oid with the same name already |
| * exists in the parent's list. | * exists in the parent's list. |
| */ | */ |
| p = sysctl_find_oidname(oidp->oid_name, parent); | p = sysctl_find_oidname(oidp->oid_name, parent, 0); |
| if (p != NULL) { | if (p != NULL) { |
| if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) { | if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) |
| p->oid_refcnt++; | p->oid_refcnt++; |
| return; | else |
| } else { | |
| printf("can't re-use a leaf (%s)!\n", p->oid_name); | printf("can't re-use a leaf (%s)!\n", p->oid_name); |
| return; | return; |
| } | |
| } | } |
| /* | /* |
| * If this oid has a number OID_AUTO, give it a number which | * If this oid has a number OID_AUTO, give it a number which |
| * is greater than any current oid. Make sure it is at least | * is greater than any current oid. Make sure it is at least |
| Line 140 void sysctl_register_oid(struct sysctl_o | Line 152 void sysctl_register_oid(struct sysctl_o |
| SLIST_INSERT_HEAD(parent, oidp, oid_link); | SLIST_INSERT_HEAD(parent, oidp, oid_link); |
| } | } |
| void sysctl_unregister_oid(struct sysctl_oid *oidp) | void |
| sysctl_unregister_oid(struct sysctl_oid *oidp) | |
| { | |
| sysctl_lock(LK_EXCLUSIVE); | |
| sysctl_unregister_oid_int(oidp); | |
| sysctl_unlock(); | |
| } | |
| static void | |
| sysctl_unregister_oid_int(struct sysctl_oid *oidp) | |
| { | { |
| struct sysctl_oid *p; | struct sysctl_oid *p; |
| int error; | |
| error = ENOENT; | if (oidp->oid_number == OID_AUTO) |
| if (oidp->oid_number == OID_AUTO) { | panic("Trying to unregister OID_AUTO entry: %p\n", oidp); |
| error = EINVAL; | |
| } else { | SLIST_FOREACH(p, oidp->oid_parent, oid_link) { |
| SLIST_FOREACH(p, oidp->oid_parent, oid_link) { | if (p != oidp) |
| if (p == oidp) { | continue; |
| SLIST_REMOVE(oidp->oid_parent, oidp, | SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link); |
| sysctl_oid, oid_link); | return; |
| error = 0; | |
| break; | |
| } | |
| } | |
| } | } |
| /* | /* |
| Line 164 void sysctl_unregister_oid(struct sysctl | Line 180 void sysctl_unregister_oid(struct sysctl |
| * being unloaded afterwards. It should not be a panic() | * being unloaded afterwards. It should not be a panic() |
| * for normal use. | * for normal use. |
| */ | */ |
| if (error) | printf("%s: failed to unregister sysctl\n", __func__); |
| printf("%s: failed to unregister sysctl\n", __func__); | |
| } | } |
| /* Initialize a new context to keep track of dynamically added sysctls. */ | /* Initialize a new context to keep track of dynamically added sysctls. */ |
| int | int |
| sysctl_ctx_init(struct sysctl_ctx_list *c) | sysctl_ctx_init(struct sysctl_ctx_list *c) |
| { | { |
| if (c == NULL) | |
| if (c == NULL) { | return(EINVAL); |
| return (EINVAL); | |
| } | |
| TAILQ_INIT(c); | TAILQ_INIT(c); |
| return (0); | return(0); |
| } | } |
| /* Free the context, and destroy all dynamic oids registered in this context */ | /* Free the context, and destroy all dynamic oids registered in this context */ |
| Line 188 sysctl_ctx_free(struct sysctl_ctx_list * | Line 201 sysctl_ctx_free(struct sysctl_ctx_list * |
| int error; | int error; |
| error = 0; | error = 0; |
| sysctl_ctx_lock(LK_EXCLUSIVE); | |
| /* | /* |
| * First perform a "dry run" to check if it's ok to remove oids. | * First perform a "dry run" to check if it's ok to remove oids. |
| * XXX FIXME | * XXX FIXME |
| Line 212 sysctl_ctx_free(struct sysctl_ctx_list * | Line 226 sysctl_ctx_free(struct sysctl_ctx_list * |
| sysctl_register_oid(e1->entry); | sysctl_register_oid(e1->entry); |
| e1 = TAILQ_PREV(e1, sysctl_ctx_list, link); | e1 = TAILQ_PREV(e1, sysctl_ctx_list, link); |
| } | } |
| if (error) | if (error) { |
| sysctl_ctx_unlock(); | |
| return(EBUSY); | return(EBUSY); |
| } | |
| /* Now really delete the entries */ | /* Now really delete the entries */ |
| e = TAILQ_FIRST(clist); | e = TAILQ_FIRST(clist); |
| while (e != NULL) { | while (e != NULL) { |
| Line 225 sysctl_ctx_free(struct sysctl_ctx_list * | Line 241 sysctl_ctx_free(struct sysctl_ctx_list * |
| free(e, M_SYSCTLOID); | free(e, M_SYSCTLOID); |
| e = e1; | e = e1; |
| } | } |
| sysctl_ctx_unlock(); | |
| return (error); | return (error); |
| } | } |
| Line 238 sysctl_ctx_entry_add(struct sysctl_ctx_l | Line 255 sysctl_ctx_entry_add(struct sysctl_ctx_l |
| return(NULL); | return(NULL); |
| e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK); | e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK); |
| e->entry = oidp; | e->entry = oidp; |
| sysctl_ctx_lock(LK_EXCLUSIVE); | |
| TAILQ_INSERT_HEAD(clist, e, link); | TAILQ_INSERT_HEAD(clist, e, link); |
| sysctl_ctx_unlock(); | |
| return (e); | return (e); |
| } | } |
| Line 250 sysctl_ctx_entry_find(struct sysctl_ctx_ | Line 269 sysctl_ctx_entry_find(struct sysctl_ctx_ |
| if (clist == NULL || oidp == NULL) | if (clist == NULL || oidp == NULL) |
| return(NULL); | return(NULL); |
| sysctl_ctx_lock(LK_SHARED); | |
| e = sysctl_ctx_entry_find_int(clist, oidp); | |
| sysctl_ctx_unlock(); | |
| return(e); | |
| } | |
| struct sysctl_ctx_entry * | |
| sysctl_ctx_entry_find_int(struct sysctl_ctx_list *clist, struct sysctl_oid *oidp) | |
| { | |
| struct sysctl_ctx_entry *e; | |
| KKASSERT(clist != NULL && oidp != NULL); | |
| for (e = TAILQ_FIRST(clist); e != NULL; e = TAILQ_NEXT(e, link)) { | for (e = TAILQ_FIRST(clist); e != NULL; e = TAILQ_NEXT(e, link)) { |
| if(e->entry == oidp) | if(e->entry == oidp) |
| return(e); | break; |
| } | } |
| return (e); | return (e); |
| } | } |
| Line 269 sysctl_ctx_entry_del(struct sysctl_ctx_l | Line 304 sysctl_ctx_entry_del(struct sysctl_ctx_l |
| if (clist == NULL || oidp == NULL) | if (clist == NULL || oidp == NULL) |
| return (EINVAL); | return (EINVAL); |
| e = sysctl_ctx_entry_find(clist, oidp); | |
| if (e != NULL) { | sysctl_ctx_lock(LK_EXCLUSIVE); |
| TAILQ_REMOVE(clist, e, link); | e = sysctl_ctx_entry_find_int(clist, oidp); |
| free(e, M_SYSCTLOID); | if (e == NULL) { |
| return (0); | sysctl_ctx_unlock(); |
| } else | |
| return (ENOENT); | return (ENOENT); |
| } | |
| TAILQ_REMOVE(clist, e, link); | |
| free(e, M_SYSCTLOID); | |
| sysctl_ctx_unlock(); | |
| return(0); | |
| } | } |
| /* | /* |
| Line 296 sysctl_remove_oid(struct sysctl_oid *oid | Line 336 sysctl_remove_oid(struct sysctl_oid *oid |
| printf("can't remove non-dynamic nodes!\n"); | printf("can't remove non-dynamic nodes!\n"); |
| return (EINVAL); | return (EINVAL); |
| } | } |
| sysctl_lock(LK_EXCLUSIVE | LK_CANRECURSE); | |
| /* | /* |
| * WARNING: normal method to do this should be through | * WARNING: normal method to do this should be through |
| * sysctl_ctx_free(). Use recursing as the last resort | * sysctl_ctx_free(). Use recursing as the last resort |
| Line 306 sysctl_remove_oid(struct sysctl_oid *oid | Line 347 sysctl_remove_oid(struct sysctl_oid *oid |
| if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { | if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { |
| if (oidp->oid_refcnt == 1) { | if (oidp->oid_refcnt == 1) { |
| SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) { | SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) { |
| if (!recurse) | if (!recurse) { |
| return (ENOTEMPTY); | sysctl_unlock(); |
| return(ENOTEMPTY); | |
| } | |
| error = sysctl_remove_oid(p, del, recurse); | error = sysctl_remove_oid(p, del, recurse); |
| if (error) | if (error) { |
| return (error); | sysctl_unlock(); |
| return(error); | |
| } | |
| } | } |
| if (del) | if (del) |
| free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID); | free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID); |
| Line 321 sysctl_remove_oid(struct sysctl_oid *oid | Line 366 sysctl_remove_oid(struct sysctl_oid *oid |
| } else { | } else { |
| if (oidp->oid_refcnt == 0) { | if (oidp->oid_refcnt == 0) { |
| printf("Warning: bad oid_refcnt=%u (%s)!\n", | printf("Warning: bad oid_refcnt=%u (%s)!\n", |
| oidp->oid_refcnt, oidp->oid_name); | oidp->oid_refcnt, oidp->oid_name); |
| return (EINVAL); | sysctl_unlock(); |
| return(EINVAL); | |
| } | } |
| sysctl_unregister_oid(oidp); | sysctl_unregister_oid_int(oidp); |
| if (del) { | if (del) { |
| if (oidp->oid_descr) | if (oidp->oid_descr) |
| free((void *)(uintptr_t)(const void *)oidp->oid_descr, M_SYSCTLOID); | free(__DECONST(char *,oidp->oid_descr), |
| free((void *)(uintptr_t)(const void *)oidp->oid_name, | M_SYSCTLOID); |
| M_SYSCTLOID); | free(__DECONST(char *, oidp->oid_name), M_SYSCTLOID); |
| free(oidp, M_SYSCTLOID); | free(oidp, M_SYSCTLOID); |
| } | } |
| } | } |
| return (0); | sysctl_unlock(); |
| return(0); | |
| } | } |
| /* | /* |
| Line 352 sysctl_add_oid(struct sysctl_ctx_list *c | Line 399 sysctl_add_oid(struct sysctl_ctx_list *c |
| /* You have to hook up somewhere.. */ | /* You have to hook up somewhere.. */ |
| if (parent == NULL) | if (parent == NULL) |
| return(NULL); | return(NULL); |
| sysctl_lock(LK_EXCLUSIVE); | |
| /* Check if the node already exists, otherwise create it */ | /* Check if the node already exists, otherwise create it */ |
| oidp = sysctl_find_oidname(name, parent); | oidp = sysctl_find_oidname(name, parent, 0); |
| if (oidp != NULL) { | if (oidp != NULL) { |
| if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { | if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { |
| oidp->oid_refcnt++; | oidp->oid_refcnt++; |
| /* Update the context */ | /* Update the context */ |
| if (clist != NULL) | if (clist != NULL) |
| sysctl_ctx_entry_add(clist, oidp); | sysctl_ctx_entry_add(clist, oidp); |
| sysctl_unlock(); | |
| return (oidp); | return (oidp); |
| } else { | } else { |
| printf("can't re-use a leaf (%s)!\n", name); | printf("can't re-use a leaf (%s)!\n", name); |
| sysctl_unlock(); | |
| return (NULL); | return (NULL); |
| } | } |
| } | } |
| oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK); | oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK | M_ZERO); |
| bzero(oidp, sizeof(struct sysctl_oid)); | |
| oidp->oid_parent = parent; | oidp->oid_parent = parent; |
| SLIST_NEXT(oidp, oid_link) = NULL; | SLIST_NEXT(oidp, oid_link) = NULL; |
| oidp->oid_number = number; | oidp->oid_number = number; |
| Line 399 sysctl_add_oid(struct sysctl_ctx_list *c | Line 448 sysctl_add_oid(struct sysctl_ctx_list *c |
| if (clist != NULL) | if (clist != NULL) |
| sysctl_ctx_entry_add(clist, oidp); | sysctl_ctx_entry_add(clist, oidp); |
| /* Register this oid */ | /* Register this oid */ |
| sysctl_register_oid(oidp); | sysctl_register_oid_int(oidp); |
| sysctl_unlock(); | |
| return (oidp); | return (oidp); |
| } | } |
| Line 412 static void sysctl_register_all(void *ar | Line 462 static void sysctl_register_all(void *ar |
| { | { |
| struct sysctl_oid **oidp; | struct sysctl_oid **oidp; |
| lockinit(&sysctl_lkp, 0, "sysctl", 0, 0); | |
| lockinit(&sysctl_ctx_lkp, 0, "sysctl ctx", 0, 0); | |
| SET_FOREACH(oidp, sysctl_set) | SET_FOREACH(oidp, sysctl_set) |
| sysctl_register_oid(*oidp); | sysctl_register_oid_int(*oidp); |
| } | } |
| SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0); | SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0); |
| Line 442 sysctl_sysctl_debug_dump_node(struct sys | Line 494 sysctl_sysctl_debug_dump_node(struct sys |
| int k; | int k; |
| struct sysctl_oid *oidp; | struct sysctl_oid *oidp; |
| sysctl_lock(LK_SHARED); | |
| SLIST_FOREACH(oidp, l, oid_link) { | SLIST_FOREACH(oidp, l, oid_link) { |
| for (k=0; k<i; k++) | for (k=0; k<i; k++) |
| Line 472 sysctl_sysctl_debug_dump_node(struct sys | Line 525 sysctl_sysctl_debug_dump_node(struct sys |
| } | } |
| } | } |
| sysctl_unlock(); | |
| } | } |
| static int | static int |
| Line 499 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) | Line 553 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) |
| struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; | struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; |
| char buf[10]; | char buf[10]; |
| sysctl_lock(LK_SHARED); | |
| while (namelen) { | while (namelen) { |
| if (!lsp) { | if (!lsp) { |
| snprintf(buf,sizeof(buf),"%d",*name); | snprintf(buf,sizeof(buf),"%d",*name); |
| Line 506 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) | Line 561 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) |
| error = SYSCTL_OUT(req, ".", 1); | error = SYSCTL_OUT(req, ".", 1); |
| if (!error) | if (!error) |
| error = SYSCTL_OUT(req, buf, strlen(buf)); | error = SYSCTL_OUT(req, buf, strlen(buf)); |
| if (error) | if (error) { |
| sysctl_unlock(); | |
| return (error); | return (error); |
| } | |
| namelen--; | namelen--; |
| name++; | name++; |
| continue; | continue; |
| Line 522 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) | Line 579 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) |
| if (!error) | if (!error) |
| error = SYSCTL_OUT(req, oid->oid_name, | error = SYSCTL_OUT(req, oid->oid_name, |
| strlen(oid->oid_name)); | strlen(oid->oid_name)); |
| if (error) | if (error) { |
| sysctl_unlock(); | |
| return (error); | return (error); |
| } | |
| namelen--; | namelen--; |
| name++; | name++; |
| Line 539 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) | Line 598 sysctl_sysctl_name(SYSCTL_HANDLER_ARGS) |
| } | } |
| lsp = lsp2; | lsp = lsp2; |
| } | } |
| sysctl_unlock(); | |
| return (SYSCTL_OUT(req, "", 1)); | return (SYSCTL_OUT(req, "", 1)); |
| } | } |
| Line 551 sysctl_sysctl_next_ls(struct sysctl_oid_ | Line 611 sysctl_sysctl_next_ls(struct sysctl_oid_ |
| struct sysctl_oid *oidp; | struct sysctl_oid *oidp; |
| *len = level; | *len = level; |
| sysctl_lock(LK_SHARED); | |
| SLIST_FOREACH(oidp, lsp, oid_link) { | SLIST_FOREACH(oidp, lsp, oid_link) { |
| *next = oidp->oid_number; | *next = oidp->oid_number; |
| *oidpp = oidp; | *oidpp = oidp; |
| if (!namelen) { | if (!namelen) { |
| if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) | if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) { |
| sysctl_unlock(); | |
| return 0; | return 0; |
| if (oidp->oid_handler) | } |
| if (oidp->oid_handler) { | |
| /* We really should call the handler here...*/ | /* We really should call the handler here...*/ |
| sysctl_unlock(); | |
| return 0; | return 0; |
| } | |
| lsp = (struct sysctl_oid_list *)oidp->oid_arg1; | lsp = (struct sysctl_oid_list *)oidp->oid_arg1; |
| if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, | if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, |
| len, level+1, oidpp)) | len, level+1, oidpp)) { |
| sysctl_unlock(); | |
| return 0; | return 0; |
| } | |
| goto emptynode; | goto emptynode; |
| } | } |
| Line 572 sysctl_sysctl_next_ls(struct sysctl_oid_ | Line 639 sysctl_sysctl_next_ls(struct sysctl_oid_ |
| continue; | continue; |
| if (oidp->oid_number > *name) { | if (oidp->oid_number > *name) { |
| if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) | if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) { |
| sysctl_unlock(); | |
| return 0; | return 0; |
| if (oidp->oid_handler) | } |
| if (oidp->oid_handler) { | |
| sysctl_unlock(); | |
| return 0; | return 0; |
| } | |
| lsp = (struct sysctl_oid_list *)oidp->oid_arg1; | lsp = (struct sysctl_oid_list *)oidp->oid_arg1; |
| if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, | if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, |
| next+1, len, level+1, oidpp)) | next+1, len, level+1, oidpp)) { |
| sysctl_unlock(); | |
| return (0); | return (0); |
| } | |
| goto next; | goto next; |
| } | } |
| if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) | if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) |
| Line 590 sysctl_sysctl_next_ls(struct sysctl_oid_ | Line 663 sysctl_sysctl_next_ls(struct sysctl_oid_ |
| lsp = (struct sysctl_oid_list *)oidp->oid_arg1; | lsp = (struct sysctl_oid_list *)oidp->oid_arg1; |
| if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, | if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, |
| len, level+1, oidpp)) | len, level+1, oidpp)) { |
| sysctl_unlock(); | |
| return (0); | return (0); |
| } | |
| next: | next: |
| namelen = 1; | namelen = 1; |
| *len = level; | *len = level; |
| emptynode: | emptynode: |
| *len = level; | *len = level; |
| } | } |
| sysctl_unlock(); | |
| return 1; | return 1; |
| } | } |
| Line 643 name2oid (char *name, int *oid, int *len | Line 719 name2oid (char *name, int *oid, int *len |
| if (i == '.') | if (i == '.') |
| *p = '\0'; | *p = '\0'; |
| sysctl_lock(LK_SHARED); | |
| oidp = SLIST_FIRST(lsp); | oidp = SLIST_FIRST(lsp); |
| while (oidp && *len < CTL_MAXNAME) { | while (oidp && *len < CTL_MAXNAME) { |
| Line 656 name2oid (char *name, int *oid, int *len | Line 733 name2oid (char *name, int *oid, int *len |
| if (!i) { | if (!i) { |
| if (oidpp) | if (oidpp) |
| *oidpp = oidp; | *oidpp = oidp; |
| sysctl_unlock(); | |
| return (0); | return (0); |
| } | } |
| Line 674 name2oid (char *name, int *oid, int *len | Line 752 name2oid (char *name, int *oid, int *len |
| if (i == '.') | if (i == '.') |
| *p = '\0'; | *p = '\0'; |
| } | } |
| sysctl_unlock(); | |
| return ENOENT; | return ENOENT; |
| } | } |
| Line 934 kernel_sysctl(int *name, u_int namelen, | Line 1013 kernel_sysctl(int *name, u_int namelen, |
| req.newfunc = sysctl_new_kernel; | req.newfunc = sysctl_new_kernel; |
| req.lock = 1; | req.lock = 1; |
| /* XXX this should probably be done in a general way */ | sysctl_lock(LK_SHARED); |
| while (memlock.sl_lock) { | |
| memlock.sl_want = 1; | |
| (void) tsleep((caddr_t)&memlock, 0, "sysctl", 0); | |
| memlock.sl_locked++; | |
| } | |
| memlock.sl_lock = 1; | |
| error = sysctl_root(0, name, namelen, &req); | error = sysctl_root(0, name, namelen, &req); |
| if (req.lock == 2) | if (req.lock == 2) |
| vsunlock(req.oldptr, req.oldlen); | vsunlock(req.oldptr, req.oldlen); |
| memlock.sl_lock = 0; | sysctl_unlock(); |
| if (memlock.sl_want) { | |
| memlock.sl_want = 0; | |
| wakeup((caddr_t)&memlock); | |
| } | |
| if (error && error != ENOMEM) | if (error && error != ENOMEM) |
| return (error); | return (error); |
| Line 1038 sysctl_find_oid(int *name, u_int namelen | Line 1106 sysctl_find_oid(int *name, u_int namelen |
| struct sysctl_oid *oid; | struct sysctl_oid *oid; |
| int indx; | int indx; |
| sysctl_lock(LK_SHARED); | |
| oid = SLIST_FIRST(&sysctl__children); | oid = SLIST_FIRST(&sysctl__children); |
| indx = 0; | indx = 0; |
| while (oid && indx < CTL_MAXNAME) { | while (oid && indx < CTL_MAXNAME) { |
| Line 1051 sysctl_find_oid(int *name, u_int namelen | Line 1120 sysctl_find_oid(int *name, u_int namelen |
| *noid = oid; | *noid = oid; |
| if (nindx != NULL) | if (nindx != NULL) |
| *nindx = indx; | *nindx = indx; |
| sysctl_unlock(); | |
| return (0); | return (0); |
| } | } |
| oid = SLIST_FIRST( | oid = SLIST_FIRST( |
| Line 1059 sysctl_find_oid(int *name, u_int namelen | Line 1129 sysctl_find_oid(int *name, u_int namelen |
| *noid = oid; | *noid = oid; |
| if (nindx != NULL) | if (nindx != NULL) |
| *nindx = indx; | *nindx = indx; |
| sysctl_unlock(); | |
| return (0); | return (0); |
| } else { | } else { |
| sysctl_unlock(); | |
| return (ENOTDIR); | return (ENOTDIR); |
| } | } |
| } else { | } else { |
| oid = SLIST_NEXT(oid, oid_link); | oid = SLIST_NEXT(oid, oid_link); |
| } | } |
| } | } |
| sysctl_unlock(); | |
| return (ENOENT); | return (ENOENT); |
| } | } |
| Line 1186 userland_sysctl(int *name, u_int namelen | Line 1259 userland_sysctl(int *name, u_int namelen |
| req.lock = 1; | req.lock = 1; |
| req.td = curthread; | req.td = curthread; |
| /* XXX this should probably be done in a general way */ | sysctl_lock(LK_SHARED); |
| while (memlock.sl_lock) { | |
| memlock.sl_want = 1; | |
| (void) tsleep((caddr_t)&memlock, 0, "sysctl", 0); | |
| memlock.sl_locked++; | |
| } | |
| memlock.sl_lock = 1; | |
| do { | do { |
| req2 = req; | req2 = req; |
| Line 1203 userland_sysctl(int *name, u_int namelen | Line 1270 userland_sysctl(int *name, u_int namelen |
| if (req.lock == 2) | if (req.lock == 2) |
| vsunlock(req.oldptr, req.oldlen); | vsunlock(req.oldptr, req.oldlen); |
| memlock.sl_lock = 0; | sysctl_unlock(); |
| if (memlock.sl_want) { | |
| memlock.sl_want = 0; | |
| wakeup((caddr_t)&memlock); | |
| } | |
| if (error && error != ENOMEM) | if (error && error != ENOMEM) |
| return (error); | return (error); |
| Line 1221 userland_sysctl(int *name, u_int namelen | Line 1283 userland_sysctl(int *name, u_int namelen |
| } | } |
| return (error); | return (error); |
| } | } |
| static void | |
| sysctl_lock(int flag) | |
| { | |
| lockmgr(&sysctl_lkp, flag, NULL, curthread); | |
| } | |
| static void | |
| sysctl_unlock(void) | |
| { | |
| lockmgr(&sysctl_lkp, LK_RELEASE, NULL, curthread); | |
| } | |
| static void | |
| sysctl_ctx_lock(int flag) | |
| { | |
| lockmgr(&sysctl_ctx_lkp, flag, NULL, curthread); | |
| } | |
| static void | |
| sysctl_ctx_unlock(void) | |
| { | |
| lockmgr(&sysctl_ctx_lkp, LK_RELEASE, NULL, curthread); | |
| } |