Index: kern/kern_jail.c =================================================================== --- src/sys/kern/kern_jail.c (.../current/src/sys) (revision 84) +++ src/sys/kern/kern_jail.c (.../sysctl/src/sys) (revision 84) @@ -451,18 +451,18 @@ { struct xprison *xp, *sxp; struct prison *pr; - int count, error; + int count, error = 0; - mtx_assert(&Giant, MA_OWNED); + mtx_lock(&Giant); if (jailed(req->td->td_ucred)) - return (0); + goto done; retry: mtx_lock(&allprison_mtx); count = prisoncount; mtx_unlock(&allprison_mtx); if (count == 0) - return (0); + goto done; sxp = xp = malloc(sizeof(*xp) * count, M_TEMP, M_WAITOK | M_ZERO); mtx_lock(&allprison_mtx); @@ -483,9 +483,11 @@ xp++; } mtx_unlock(&allprison_mtx); - + error = SYSCTL_OUT(req, sxp, sizeof(*sxp) * count); free(sxp, M_TEMP); +done: + mtx_unlock(&Giant); if (error) return (error); return (0); Index: kern/kern_sysctl.c =================================================================== --- src/sys/kern/kern_sysctl.c (.../current/src/sys) (revision 84) +++ src/sys/kern/kern_sysctl.c (.../sysctl/src/sys) (revision 84) @@ -62,21 +62,78 @@ /* * Locking - this locks the sysctl tree in memory. */ -static struct sx sysctllock; +static struct mtx sysctl_ctx_mtx; +static struct mtx sysctl_mtx; -#define SYSCTL_LOCK() sx_xlock(&sysctllock) -#define SYSCTL_UNLOCK() sx_xunlock(&sysctllock) -#define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock") +#define SYSCTL_LOCK() mtx_lock(&sysctl_mtx) +#define SYSCTL_UNLOCK() mtx_unlock(&sysctl_mtx) +#define SYSCTL_INIT() mtx_init(&sysctl_mtx, \ + "sysctl lock", \ + NULL, MTX_DEF | MTX_RECURSE) +#define SYSCTL_CTX_LOCK() mtx_lock(&sysctl_ctx_mtx) +#define SYSCTL_CTX_UNLOCK() mtx_unlock(&sysctl_ctx_mtx) +#define SYSCTL_CTX_INIT() mtx_init(&sysctl_ctx_mtx, \ + "sysctl context lock", \ + NULL, MTX_DEF) + +static void sysctl_oid_own(struct sysctl_oid *oid); +static void sysctl_oid_disown(struct sysctl_oid *oid); + static int sysctl_root(SYSCTL_HANDLER_ARGS); struct sysctl_oid_list sysctl__children; /* root list */ +static void +sysctl_oid_own(struct sysctl_oid *oid) +{ + struct thread *td = curthread; + + mtx_assert(&sysctl_mtx, MA_OWNED); + + oid->oid_wanted++; + + if (oid->oid_owner == NULL) + oid->oid_owner = td; + else if (oid->oid_owner != td) { + + while (oid->oid_owner != NULL) { + /* XXX Priority? */ + msleep(oid, + &sysctl_mtx, + PPAUSE, "oid", 0); + } + oid->oid_owner = td; + } + oid->oid_ownlevel++; +} + +static void +sysctl_oid_disown(struct sysctl_oid *oid) +{ + KASSERT(oid->oid_owner >= 0, ("oid_ownlevel < 0")); + KASSERT(oid->oid_owner != NULL, ("oid already disowned")); + KASSERT(oid->oid_owner == curthread, ("oid owner changed")); + + oid->oid_wanted--; + + if (--oid->oid_ownlevel == 0) { + oid->oid_owner = NULL; + if (!oid->oid_wanted) { + sysctl_remove_oid(oid, 1, 1); + } else if (oid->oid_wanted > 1) { + wakeup_one(oid); + } + } +} + static struct sysctl_oid * sysctl_find_oidname(const char *name, struct sysctl_oid_list *list) { struct sysctl_oid *oidp; + mtx_assert(&sysctl_mtx, MA_OWNED); + SLIST_FOREACH(oidp, list, oid_link) { if (strcmp(oidp->oid_name, name) == 0) { return (oidp); @@ -91,25 +148,37 @@ * Order by number in each list. */ -void +int sysctl_register_oid(struct sysctl_oid *oidp) { struct sysctl_oid_list *parent = oidp->oid_parent; struct sysctl_oid *p; struct sysctl_oid *q; + int error; /* * First check if another oid with the same name already * exists in the parent's list. */ + + SYSCTL_LOCK(); + sysctl_oid_own(oidp); + + if (parent == NULL) { /* The oid has no parent! */ + error = 1; + goto done; + } + p = sysctl_find_oidname(oidp->oid_name, parent); if (p != NULL) { if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) { p->oid_refcnt++; - return; + error = 1; + goto done; } else { printf("can't re-use a leaf (%s)!\n", p->oid_name); - return; + error = 1; + goto done; } } /* @@ -146,19 +215,28 @@ SLIST_INSERT_AFTER(q, oidp, oid_link); else SLIST_INSERT_HEAD(parent, oidp, oid_link); + error = 0; +done: + sysctl_oid_disown(oidp); + SYSCTL_UNLOCK(); + return (error); } void sysctl_unregister_oid(struct sysctl_oid *oidp) { struct sysctl_oid *p; + struct sysctl_oid_list *parent = oidp->oid_parent; int error; + SYSCTL_LOCK(); + sysctl_oid_own(oidp); + error = ENOENT; if (oidp->oid_number == OID_AUTO) { error = EINVAL; } else { - SLIST_FOREACH(p, oidp->oid_parent, oid_link) { + SLIST_FOREACH(p, parent, oid_link) { if (p == oidp) { SLIST_REMOVE(oidp->oid_parent, oidp, sysctl_oid, oid_link); @@ -167,7 +245,8 @@ } } } - + sysctl_oid_disown(oidp); + SYSCTL_UNLOCK(); /* * This can happen when a module fails to register and is * being unloaded afterwards. It should not be a panic() @@ -203,6 +282,8 @@ * XXX This algorithm is a hack. But I don't know any * XXX better solution for now... */ + + SYSCTL_CTX_LOCK(); TAILQ_FOREACH(e, clist, link) { error = sysctl_remove_oid(e->entry, 0, 0); if (error) @@ -221,8 +302,10 @@ sysctl_register_oid(e1->entry); e1 = TAILQ_PREV(e1, sysctl_ctx_list, link); } - if (error) + if (error) { + SYSCTL_CTX_UNLOCK(); return(EBUSY); + } /* Now really delete the entries */ e = TAILQ_FIRST(clist); while (e != NULL) { @@ -234,6 +317,7 @@ free(e, M_SYSCTLOID); e = e1; } + SYSCTL_CTX_UNLOCK(); return (error); } @@ -247,7 +331,9 @@ return(NULL); e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK); e->entry = oidp; + SYSCTL_CTX_LOCK(); TAILQ_INSERT_HEAD(clist, e, link); + SYSCTL_CTX_UNLOCK(); return (e); } @@ -278,17 +364,21 @@ if (clist == NULL || oidp == NULL) return (EINVAL); + SYSCTL_CTX_LOCK(); e = sysctl_ctx_entry_find(clist, oidp); if (e != NULL) { TAILQ_REMOVE(clist, e, link); free(e, M_SYSCTLOID); + SYSCTL_CTX_UNLOCK(); return (0); - } else + } else { + SYSCTL_CTX_UNLOCK(); return (ENOENT); + } } /* - * Remove dynamically created sysctl trees. + * Really remove dynamically created sysctl trees. * oidp - top of the tree to be removed * del - if 0 - just deregister, otherwise free up entries as well * recurse - if != 0 traverse the subtree to be deleted @@ -301,8 +391,23 @@ if (oidp == NULL) return(EINVAL); + + SYSCTL_LOCK(); + sysctl_oid_own(oidp); + SYSCTL_UNLOCK(); + oidp->oid_wanted--; + /* + * If we have to free the oid, and other threads want to own it, + * we free it later. Otherwise, we can free it immediately. + */ + if (del && (oidp->oid_wanted > 1)) { + sysctl_oid_disown(oidp); + return (0); + } + if ((oidp->oid_kind & CTLFLAG_DYN) == 0) { printf("can't remove non-dynamic nodes!\n"); + sysctl_oid_disown(oidp); return (EINVAL); } /* @@ -313,24 +418,34 @@ * it will panic. */ if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { + SYSCTL_LOCK(); if (oidp->oid_refcnt == 1) { SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) { - if (!recurse) + if (!recurse) { + sysctl_oid_disown(oidp); + SYSCTL_UNLOCK(); return (ENOTEMPTY); + } error = sysctl_remove_oid(p, del, recurse); - if (error) + if (error) { + sysctl_oid_disown(oidp); + SYSCTL_UNLOCK(); return (error); + } } if (del) free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID); + SYSCTL_UNLOCK(); } } - if (oidp->oid_refcnt > 1 ) { + if (oidp->oid_refcnt > 1) { oidp->oid_refcnt--; + sysctl_oid_disown(oidp); } else { if (oidp->oid_refcnt == 0) { printf("Warning: bad oid_refcnt=%u (%s)!\n", oidp->oid_refcnt, oidp->oid_name); + SYSCTL_UNLOCK(); return (EINVAL); } sysctl_unregister_oid(oidp); @@ -339,9 +454,11 @@ free((void *)(uintptr_t)(const void *)oidp->descr, M_SYSCTLOID); free((void *)(uintptr_t)(const void *)oidp->oid_name, M_SYSCTLOID); + sysctl_oid_disown(oidp); free(oidp, M_SYSCTLOID); } } + return (0); } @@ -361,8 +478,11 @@ /* You have to hook up somewhere.. */ if (parent == NULL) return(NULL); + + SYSCTL_LOCK(); /* Check if the node already exists, otherwise create it */ oidp = sysctl_find_oidname(name, parent); + SYSCTL_UNLOCK(); if (oidp != NULL) { if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { oidp->oid_refcnt++; @@ -403,11 +523,25 @@ if (oidp->descr) strcpy((char *)(uintptr_t)(const void *)oidp->descr, descr); } + oidp->oid_owner = NULL; + oidp->oid_wanted = 1; /* Initial reference */ + oidp->oid_ownlevel = 0; /* Update the context, if used */ if (clist != NULL) sysctl_ctx_entry_add(clist, oidp); /* Register this oid */ - sysctl_register_oid(oidp); + + if (sysctl_register_oid(oidp)) { + free((void *)(uintptr_t)(const void *)oidp->descr, + M_SYSCTLOID); + free((void *)(uintptr_t)(const void *)oidp->oid_name, + M_SYSCTLOID); + free(oidp->oid_arg1, M_SYSCTLOID); /* Children */ + free(newname, M_SYSCTLOID); + free(oidp, M_SYSCTLOID); + return (NULL); + } + return (oidp); } @@ -421,13 +555,17 @@ if (oid->oid_parent == parent) return (0); + SYSCTL_LOCK(); oidp = sysctl_find_oidname(oid->oid_name, parent); - if (oidp != NULL) + if (oidp != NULL) { + SYSCTL_UNLOCK(); return (EEXIST); + } sysctl_unregister_oid(oid); oid->oid_parent = parent; oid->oid_number = OID_AUTO; sysctl_register_oid(oid); + SYSCTL_UNLOCK(); return (0); } @@ -441,11 +579,12 @@ { struct sysctl_oid **oidp; + SYSCTL_CTX_INIT(); SYSCTL_INIT(); SET_FOREACH(oidp, sysctl_set) sysctl_register_oid(*oidp); } -SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_ANY, sysctl_register_all, 0); +SYSINIT(sysctl, SI_SUB_LOCK, SI_ORDER_ANY, sysctl_register_all, 0); /* * "Staff-functions" @@ -473,6 +612,8 @@ int k; struct sysctl_oid *oidp; + mtx_assert(&sysctl_mtx, MA_OWNED); + SLIST_FOREACH(oidp, l, oid_link) { for (k=0; koid_handler) { + mtx_pool_lock(mtxpool_sleep, + SYSCTL_CHILDREN(oidp)); sysctl_sysctl_debug_dump_node( oidp->oid_arg1, i+2); + mtx_pool_unlock(mtxpool_sleep, + SYSCTL_CHILDREN(oidp)); } break; case CTLTYPE_INT: printf(" Int\n"); break; @@ -513,7 +658,9 @@ error = suser(req->td); if (error) return error; + SYSCTL_LOCK(); sysctl_sysctl_debug_dump_node(&sysctl__children, 0); + SYSCTL_UNLOCK(); return ENOENT; } @@ -530,16 +677,23 @@ struct sysctl_oid *oid; struct sysctl_oid_list *lsp = &sysctl__children, *lsp2; char buf[10]; + int oldidx = 0; + char *b; + int l = MAXPATHLEN; + b = malloc(l, M_SYSCTL, M_WAITOK); + memset(b, 0, l); + + SYSCTL_LOCK(); while (namelen) { if (!lsp) { snprintf(buf,sizeof(buf),"%d",*name); - if (req->oldidx) - error = SYSCTL_OUT(req, ".", 1); - if (!error) - error = SYSCTL_OUT(req, buf, strlen(buf)); - if (error) - return (error); + if (oldidx) + strlcat(b, ".", l); + + oldidx++; + strlcat(b, buf, l); + namelen--; name++; continue; @@ -549,18 +703,16 @@ if (oid->oid_number != *name) continue; - if (req->oldidx) - error = SYSCTL_OUT(req, ".", 1); - if (!error) - error = SYSCTL_OUT(req, oid->oid_name, - strlen(oid->oid_name)); - if (error) - return (error); + if (oldidx) + strlcat(b, ".", l); + oldidx++; + strlcat(b, oid->oid_name, l); + namelen--; name++; - if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) + if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE) break; if (oid->oid_handler) @@ -571,6 +723,12 @@ } lsp = lsp2; } + SYSCTL_UNLOCK(); + error = SYSCTL_OUT(req, b, strlen(b)); + free(b, M_SYSCTL); + if (error) + return (error); + return (SYSCTL_OUT(req, "", 1)); } @@ -583,23 +741,28 @@ struct sysctl_oid *oidp; *len = level; + SYSCTL_LOCK(); SLIST_FOREACH(oidp, lsp, oid_link) { *next = oidp->oid_number; *oidpp = oidp; - if (oidp->oid_kind & CTLFLAG_SKIP) continue; - if (!namelen) { - if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) + if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) { + SYSCTL_UNLOCK(); return 0; - if (oidp->oid_handler) + } + if (oidp->oid_handler) { /* We really should call the handler here...*/ + SYSCTL_UNLOCK(); return 0; + } lsp = (struct sysctl_oid_list *)oidp->oid_arg1; if (!sysctl_sysctl_next_ls(lsp, 0, 0, next+1, - len, level+1, oidpp)) + len, level+1, oidpp)) { + SYSCTL_UNLOCK(); return 0; + } goto emptynode; } @@ -607,14 +770,20 @@ continue; if (oidp->oid_number > *name) { - if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) + if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) { + SYSCTL_UNLOCK(); return 0; - if (oidp->oid_handler) + } + if (oidp->oid_handler) { + SYSCTL_UNLOCK(); return 0; + } lsp = (struct sysctl_oid_list *)oidp->oid_arg1; 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); + } goto next; } if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE) @@ -625,13 +794,17 @@ lsp = (struct sysctl_oid_list *)oidp->oid_arg1; if (!sysctl_sysctl_next_ls(lsp, name+1, namelen-1, next+1, - len, level+1, oidpp)) + len, level+1, oidpp)) { + SYSCTL_UNLOCK(); return (0); + } + next: namelen = 1; emptynode: *len = level; } + SYSCTL_UNLOCK(); return 1; } @@ -644,7 +817,7 @@ struct sysctl_oid *oid; struct sysctl_oid_list *lsp = &sysctl__children; int newoid[CTL_MAXNAME]; - + i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid); if (i) return ENOENT; @@ -677,6 +850,7 @@ if (i == '.') *p = '\0'; + SYSCTL_LOCK(); oidp = SLIST_FIRST(lsp); while (oidp && *len < CTL_MAXNAME) { @@ -690,6 +864,7 @@ if (!i) { if (oidpp) *oidpp = oidp; + SYSCTL_UNLOCK(); return (0); } @@ -708,6 +883,7 @@ if (i == '.') *p = '\0'; } + SYSCTL_UNLOCK(); return ENOENT; } @@ -752,17 +928,22 @@ { struct sysctl_oid *oid; int error; - + error = sysctl_find_oid(arg1, arg2, &oid, NULL, req); if (error) return (error); - if (!oid->oid_fmt) + if (!oid->oid_fmt) { + sysctl_oid_disown(oid); return (ENOENT); + } error = SYSCTL_OUT(req, &oid->oid_kind, sizeof(oid->oid_kind)); - if (error) + if (error) { + sysctl_oid_disown(oid); return (error); + } error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1); + sysctl_oid_disown(oid); return (error); } @@ -779,9 +960,12 @@ if (error) return (error); - if (!oid->descr) + if (!oid->descr) { + sysctl_oid_disown(oid); return (ENOENT); + } error = SYSCTL_OUT(req, oid->descr, strlen(oid->descr) + 1); + sysctl_oid_disown(oid); return (error); } @@ -1010,15 +1194,11 @@ req.newfunc = sysctl_new_kernel; req.lock = REQ_LOCKED; - SYSCTL_LOCK(); - error = sysctl_root(0, name, namelen, &req); if (req.lock == REQ_WIRED && req.validlen > 0) vsunlock(req.oldptr, req.validlen); - SYSCTL_UNLOCK(); - if (error && error != ENOMEM) return (error); @@ -1062,6 +1242,9 @@ int error = 0; size_t i, len, origidx; + if (mtx_owned(&sysctl_mtx)) + panic("shouldn't be owned!"); + origidx = req->oldidx; req->oldidx += l; if (req->oldptr == NULL) @@ -1131,14 +1314,20 @@ return (0); } +/* + * If succesful, the returned oid will be already owned. + */ int sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid, int *nindx, struct sysctl_req *req) { struct sysctl_oid *oid; + struct sysctl_oid_list *lsp = &sysctl__children; + struct sysctl_oid_list *parent; int indx; - oid = SLIST_FIRST(&sysctl__children); + SYSCTL_LOCK(); + oid = SLIST_FIRST(lsp); indx = 0; while (oid && indx < CTL_MAXNAME) { if (oid->oid_number == name[indx]) { @@ -1151,22 +1340,33 @@ *noid = oid; if (nindx != NULL) *nindx = indx; + sysctl_oid_own(oid); + SYSCTL_UNLOCK(); return (0); } - oid = SLIST_FIRST( - (struct sysctl_oid_list *)oid->oid_arg1); + lsp = (struct sysctl_oid_list *)oid->oid_arg1; + oid = SLIST_FIRST(lsp); } else if (indx == namelen) { *noid = oid; if (nindx != NULL) *nindx = indx; + sysctl_oid_own(oid); + SYSCTL_UNLOCK(); return (0); } else { + SYSCTL_UNLOCK(); return (ENOTDIR); } } else { + parent = oid->oid_parent; oid = SLIST_NEXT(oid, oid_link); + if (!oid) { + SYSCTL_UNLOCK(); + return (ENOENT); + } } } + SYSCTL_UNLOCK(); return (ENOENT); } @@ -1185,19 +1385,26 @@ if (error) return (error); + if (mtx_owned(&sysctl_mtx)) + panic("sysctl_root: shouldn't be owned!"); + if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { /* * You can't call a sysctl when it's a node, but has * no handler. Inform the user that it's a node. * The indx may or may not be the same as namelen. */ - if (oid->oid_handler == NULL) + if (oid->oid_handler == NULL) { + sysctl_oid_disown(oid); return (EISDIR); + } } /* Is this sysctl writable? */ - if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) + if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) { + sysctl_oid_disown(oid); return (EPERM); + } KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL")); @@ -1205,8 +1412,10 @@ if (req->newptr && (oid->oid_kind & CTLFLAG_SECURE)) { lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE; error = securelevel_gt(req->td->td_ucred, lvl); - if (error) + if (error) { + sysctl_oid_disown(oid); return (error); + } } /* Is this sysctl writable by only privileged users? */ @@ -1218,12 +1427,16 @@ else flags = 0; error = suser_cred(req->td->td_ucred, flags); - if (error) + if (error) { + sysctl_oid_disown(oid); return (error); + } } - if (!oid->oid_handler) + if (!oid->oid_handler) { + sysctl_oid_disown(oid); return EINVAL; + } if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) { arg1 = (int *)arg1 + indx; @@ -1235,11 +1448,13 @@ #ifdef MAC error = mac_check_system_sysctl(req->td->td_ucred, oid, arg1, arg2, req); - if (error != 0) + if (error != 0) { + sysctl_oid_disown(oid); return (error); + } #endif error = oid->oid_handler(oid, arg1, arg2, req); - + sysctl_oid_disown(oid); return (error); } @@ -1270,8 +1485,6 @@ if (error) return (error); - mtx_lock(&Giant); - error = userland_sysctl(td, name, uap->namelen, uap->old, uap->oldlenp, 0, uap->new, uap->newlen, &j, 0); @@ -1283,7 +1496,6 @@ error = i; } done2: - mtx_unlock(&Giant); return (error); } @@ -1332,8 +1544,6 @@ req.newfunc = sysctl_new_user; req.lock = REQ_LOCKED; - SYSCTL_LOCK(); - do { req.oldidx = 0; req.newidx = 0; @@ -1343,8 +1553,6 @@ if (req.lock == REQ_WIRED && req.validlen > 0) vsunlock(req.oldptr, req.validlen); - SYSCTL_UNLOCK(); - if (error && error != ENOMEM) return (error); Index: vm/vm_meter.c =================================================================== --- src/sys/vm/vm_meter.c (.../current/src/sys) (revision 84) +++ src/sys/vm/vm_meter.c (.../sysctl/src/sys) (revision 84) @@ -118,10 +118,12 @@ totalp = &total; bzero(totalp, sizeof *totalp); + + mtx_lock(&Giant); + /* * Mark all objects as inactive. */ - GIANT_REQUIRED; mtx_lock(&vm_object_list_mtx); TAILQ_FOREACH(object, &vm_object_list, object_list) { if (!VM_OBJECT_TRYLOCK(object)) { @@ -237,6 +239,7 @@ } mtx_unlock(&vm_object_list_mtx); totalp->t_free = cnt.v_free_count + cnt.v_cache_count; + mtx_unlock(&Giant); return (sysctl_handle_opaque(oidp, totalp, sizeof total, req)); } Index: sys/sysctl.h =================================================================== --- src/sys/sys/sysctl.h (.../current/src/sys) (revision 84) +++ src/sys/sys/sysctl.h (.../sysctl/src/sys) (revision 84) @@ -162,6 +162,9 @@ const char *oid_fmt; int oid_refcnt; const char *descr; + struct thread *oid_owner; + int oid_wanted; + int oid_ownlevel; }; #define SYSCTL_IN(r, p, l) (r->newfunc)(r, p, l) @@ -176,7 +179,7 @@ /* * These functions are used to add/remove an oid from the mib. */ -void sysctl_register_oid(struct sysctl_oid *oidp); +int sysctl_register_oid(struct sysctl_oid *oidp); void sysctl_unregister_oid(struct sysctl_oid *oidp); /* Declare a static oid to allow child oids to be added to it. */ @@ -208,7 +211,8 @@ #define SYSCTL_OID(parent, nbr, name, kind, a1, a2, handler, fmt, descr) \ static struct sysctl_oid sysctl__##parent##_##name = { \ &sysctl_##parent##_children, { 0 }, \ - nbr, kind, a1, a2, #name, handler, fmt, 0, descr }; \ + nbr, kind, a1, a2, #name, handler, fmt, 0, descr, NULL, \ + 1, 0 }; \ DATA_SET(sysctl_set, sysctl__##parent##_##name) #define SYSCTL_ADD_OID(ctx, parent, nbr, name, kind, a1, a2, handler, fmt, descr) \