Page MenuHomeFreeBSD

D36500.id110401.diff
No OneTemporary

D36500.id110401.diff

diff --git a/sys/compat/linuxkpi/common/include/linux/sysfs.h b/sys/compat/linuxkpi/common/include/linux/sysfs.h
--- a/sys/compat/linuxkpi/common/include/linux/sysfs.h
+++ b/sys/compat/linuxkpi/common/include/linux/sysfs.h
@@ -246,7 +246,7 @@
struct attribute **attr;
struct sysctl_oid *oidp;
- SLIST_FOREACH(oidp, SYSCTL_CHILDREN(kobj->oidp), oid_link) {
+ SPLAY_FOREACH(oidp, sysctl_oid_list, SYSCTL_CHILDREN(kobj->oidp)) {
if (strcmp(oidp->oid_name, grp->name) != 0)
continue;
for (attr = grp->attrs; *attr != NULL; attr++) {
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -59,7 +59,6 @@
#include <sys/kdb.h>
#include <sys/lock.h>
#include <sys/mutex.h>
-#include <sys/rmlock.h>
#include <sys/sbuf.h>
#include <sys/sx.h>
#include <sys/sysproto.h>
@@ -84,6 +83,8 @@
static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids");
static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer");
+SPLAY_GENERATE(sysctl_oid_list, sysctl_oid, oid_link, cmp_splay_oid);
+
/*
* The sysctllock protects the MIB tree. It also protects sysctl
* contexts used with dynamic sysctls. The sysctl_register_oid() and
@@ -100,27 +101,26 @@
* The sysctlstringlock is used to protect concurrent access to writable
* string nodes in sysctl_handle_string().
*/
-static struct rmlock sysctllock;
+/* Even though we never lock it for reading, sysctllock needs to be an sx lock
+ * instead of a mutex to support sleeping.
+ */
+static struct sx sysctllock;
static struct sx __exclusive_cache_line sysctlmemlock;
static struct sx sysctlstringlock;
-#define SYSCTL_WLOCK() rm_wlock(&sysctllock)
-#define SYSCTL_WUNLOCK() rm_wunlock(&sysctllock)
-#define SYSCTL_RLOCK(tracker) rm_rlock(&sysctllock, (tracker))
-#define SYSCTL_RUNLOCK(tracker) rm_runlock(&sysctllock, (tracker))
-#define SYSCTL_WLOCKED() rm_wowned(&sysctllock)
-#define SYSCTL_ASSERT_LOCKED() rm_assert(&sysctllock, RA_LOCKED)
-#define SYSCTL_ASSERT_WLOCKED() rm_assert(&sysctllock, RA_WLOCKED)
-#define SYSCTL_ASSERT_RLOCKED() rm_assert(&sysctllock, RA_RLOCKED)
-#define SYSCTL_INIT() rm_init_flags(&sysctllock, "sysctl lock", \
- RM_SLEEPABLE)
+#define SYSCTL_LOCK() sx_xlock(&sysctllock)
+#define SYSCTL_UNLOCK() sx_xunlock(&sysctllock)
+#define SYSCTL_RLOCK(tracker) sx_xlock(&sysctllock)
+#define SYSCTL_RUNLOCK(tracker) sx_xunlock(&sysctllock)
+#define SYSCTL_ASSERT_LOCKED() sx_assert(&sysctllock, SA_XLOCKED)
+#define SYSCTL_INIT() sx_init(&sysctllock, "sysctl lock")
#define SYSCTL_SLEEP(ch, wmesg, timo) \
- rm_sleep(ch, &sysctllock, 0, wmesg, timo)
+ sx_sleep(ch, &sysctllock, 0, wmesg, timo)
static int sysctl_root(SYSCTL_HANDLER_ARGS);
/* Root list */
-struct sysctl_oid_list sysctl__children = SLIST_HEAD_INITIALIZER(&sysctl__children);
+struct sysctl_oid_list sysctl__children = SPLAY_INITIALIZER(&sysctl__children);
static char* sysctl_escape_name(const char*);
static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del,
@@ -134,7 +134,7 @@
struct sysctl_oid *oidp;
SYSCTL_ASSERT_LOCKED();
- SLIST_FOREACH(oidp, list, oid_link) {
+ SPLAY_FOREACH(oidp, sysctl_oid_list, list) {
if (strcmp(oidp->oid_name, name) == 0) {
return (oidp);
}
@@ -151,29 +151,26 @@
sysctl_wlock(void)
{
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
}
void
sysctl_wunlock(void)
{
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
}
static int
sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intmax_t arg2,
- struct sysctl_req *req, struct rm_priotracker *tracker)
+ struct sysctl_req *req)
{
int error;
if (oid->oid_kind & CTLFLAG_DYN)
atomic_add_int(&oid->oid_running, 1);
- if (tracker != NULL)
- SYSCTL_RUNLOCK(tracker);
- else
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
/*
* Treat set CTLFLAG_NEEDGIANT and unset CTLFLAG_MPSAFE flags the same,
@@ -189,10 +186,7 @@
KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
- if (tracker != NULL)
- SYSCTL_RLOCK(tracker);
- else
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
if (oid->oid_kind & CTLFLAG_DYN) {
if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
@@ -335,7 +329,7 @@
return;
}
error = sysctl_root_handler_locked(oidp, oidp->oid_arg1,
- oidp->oid_arg2, &req, NULL);
+ oidp->oid_arg2, &req);
if (error != 0)
printf("Setting sysctl %s failed: %d\n", path + rem, error);
if (penv != NULL)
@@ -356,11 +350,14 @@
indx = 0;
while (indx < CTL_MAXNAME && indx >= 0) {
if (nodes[indx] == NULL && indx == 0)
- nodes[indx] = SLIST_FIRST(&sysctl__children);
+ nodes[indx] = SPLAY_MIN(sysctl_oid_list,
+ &sysctl__children);
else if (nodes[indx] == NULL)
- nodes[indx] = SLIST_FIRST(&nodes[indx - 1]->oid_children);
+ nodes[indx] = SPLAY_MIN(sysctl_oid_list,
+ &nodes[indx - 1]->oid_children);
else
- nodes[indx] = SLIST_NEXT(nodes[indx], oid_link);
+ nodes[indx] = SPLAY_NEXT(sysctl_oid_list,
+ &nodes[indx - 1]->oid_children, nodes[indx]);
if (nodes[indx] == needle)
return (indx + 1);
@@ -409,11 +406,9 @@
static int
sysctl_reuse_test(SYSCTL_HANDLER_ARGS)
{
- struct rm_priotracker tracker;
-
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
sysctl_warn_reuse(__func__, oidp);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (0);
}
SYSCTL_PROC(_sysctl, OID_AUTO, reuse_test,
@@ -425,8 +420,7 @@
sysctl_register_oid(struct sysctl_oid *oidp)
{
struct sysctl_oid_list *parent = oidp->oid_parent;
- struct sysctl_oid *p;
- struct sysctl_oid *q;
+ struct sysctl_oid *p, key;
int oid_number;
int timeout = 2;
@@ -434,7 +428,7 @@
* First check if another oid with the same name already
* exists in the parent's list.
*/
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_LOCKED();
p = sysctl_find_oidname(oidp->oid_name, parent);
if (p != NULL) {
if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
@@ -476,25 +470,21 @@
* Insert the OID into the parent's list sorted by OID number.
*/
retry:
- q = NULL;
- SLIST_FOREACH(p, parent, oid_link) {
- /* check if the current OID number is in use */
- if (oid_number == p->oid_number) {
- /* get the next valid OID number */
- if (oid_number < CTL_AUTO_START ||
- oid_number == 0x7fffffff) {
- /* wraparound - restart */
- oid_number = CTL_AUTO_START;
- /* don't loop forever */
- if (!timeout--)
- panic("sysctl: Out of OID numbers\n");
- goto retry;
- } else {
- oid_number++;
- }
- } else if (oid_number < p->oid_number)
- break;
- q = p;
+ key.oid_number = oid_number;
+ p = SPLAY_FIND(sysctl_oid_list, parent, &key);
+ if (p) {
+ /* get the next valid OID number */
+ if (oid_number < CTL_AUTO_START ||
+ oid_number == 0x7fffffff) {
+ /* wraparound - restart */
+ oid_number = CTL_AUTO_START;
+ /* don't loop forever */
+ if (!timeout--)
+ panic("sysctl: Out of OID numbers\n");
+ goto retry;
+ } else {
+ oid_number++;
+ }
}
/* check for non-auto OID number collision */
if (oidp->oid_number >= 0 && oidp->oid_number < CTL_AUTO_START &&
@@ -504,10 +494,7 @@
}
/* update the OID number, if any */
oidp->oid_number = oid_number;
- if (q != NULL)
- SLIST_INSERT_AFTER(q, oidp, oid_link);
- else
- SLIST_INSERT_HEAD(parent, oidp, oid_link);
+ SPLAY_INSERT(sysctl_oid_list, parent, oidp);
if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
#ifdef VIMAGE
@@ -542,7 +529,7 @@
sysctl_enable_oid(struct sysctl_oid *oidp)
{
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_LOCKED();
if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
("sysctl node is marked as dormant"));
@@ -556,22 +543,15 @@
void
sysctl_unregister_oid(struct sysctl_oid *oidp)
{
- struct sysctl_oid *p;
int error;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_LOCKED();
if (oidp->oid_number == OID_AUTO) {
error = EINVAL;
} else {
error = ENOENT;
- SLIST_FOREACH(p, oidp->oid_parent, oid_link) {
- if (p == oidp) {
- SLIST_REMOVE(oidp->oid_parent, oidp,
- sysctl_oid, oid_link);
- error = 0;
- break;
- }
- }
+ if (SPLAY_REMOVE(sysctl_oid_list, oidp->oid_parent, oidp))
+ error = 0;
}
/*
@@ -617,7 +597,7 @@
* XXX This algorithm is a hack. But I don't know any
* XXX better solution for now...
*/
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
TAILQ_FOREACH(e, clist, link) {
error = sysctl_remove_oid_locked(e->entry, 0, 0);
if (error)
@@ -637,7 +617,7 @@
e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
}
if (error) {
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return(EBUSY);
}
/* Now really delete the entries */
@@ -651,7 +631,7 @@
free(e, M_SYSCTLOID);
e = e1;
}
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (error);
}
@@ -661,7 +641,7 @@
{
struct sysctl_ctx_entry *e;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_LOCKED();
if (clist == NULL || oidp == NULL)
return(NULL);
e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
@@ -676,7 +656,7 @@
{
struct sysctl_ctx_entry *e;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_LOCKED();
if (clist == NULL || oidp == NULL)
return(NULL);
TAILQ_FOREACH(e, clist, link) {
@@ -698,15 +678,15 @@
if (clist == NULL || oidp == NULL)
return (EINVAL);
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
e = sysctl_ctx_entry_find(clist, oidp);
if (e != NULL) {
TAILQ_REMOVE(clist, e, link);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
free(e, M_SYSCTLOID);
return (0);
} else {
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (ENOENT);
}
}
@@ -722,9 +702,9 @@
{
int error;
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
error = sysctl_remove_oid_locked(oidp, del, recurse);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (error);
}
@@ -732,18 +712,15 @@
sysctl_remove_name(struct sysctl_oid *parent, const char *name,
int del, int recurse)
{
- struct sysctl_oid *p, *tmp;
+ struct sysctl_oid *p;
int error;
error = ENOENT;
- SYSCTL_WLOCK();
- SLIST_FOREACH_SAFE(p, SYSCTL_CHILDREN(parent), oid_link, tmp) {
- if (strcmp(p->oid_name, name) == 0) {
- error = sysctl_remove_oid_locked(p, del, recurse);
- break;
- }
- }
- SYSCTL_WUNLOCK();
+ SYSCTL_LOCK();
+ p = sysctl_find_oidname(name, &parent->oid_children);
+ if (p)
+ error = sysctl_remove_oid_locked(p, del, recurse);
+ SYSCTL_UNLOCK();
return (error);
}
@@ -794,7 +771,7 @@
struct sysctl_oid *p, *tmp;
int error;
- SYSCTL_ASSERT_WLOCKED();
+ SYSCTL_ASSERT_LOCKED();
if (oidp == NULL)
return(EINVAL);
if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
@@ -811,14 +788,16 @@
*/
if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
if (oidp->oid_refcnt == 1) {
- SLIST_FOREACH_SAFE(p,
- SYSCTL_CHILDREN(oidp), oid_link, tmp) {
+ for(p = SPLAY_MIN(sysctl_oid_list, &oidp->oid_children);
+ p != NULL; p = tmp) {
if (!recurse) {
printf("Warning: failed attempt to "
"remove oid %s with child %s\n",
oidp->oid_name, p->oid_name);
return (ENOTEMPTY);
}
+ tmp = SPLAY_NEXT(sysctl_oid_list,
+ &oidp->oid_children, p);
error = sysctl_remove_oid_locked(p, del,
recurse);
if (error)
@@ -876,7 +855,7 @@
return(NULL);
escaped = sysctl_escape_name(name);
/* Check if the node already exists, otherwise create it */
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
oidp = sysctl_find_oidname(escaped, parent);
if (oidp != NULL) {
free(escaped, M_SYSCTLOID);
@@ -885,17 +864,17 @@
/* Update the context */
if (clist != NULL)
sysctl_ctx_entry_add(clist, oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (oidp);
} else {
sysctl_warn_reuse(__func__, oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (NULL);
}
}
oidp = malloc(sizeof(struct sysctl_oid), M_SYSCTLOID, M_WAITOK|M_ZERO);
oidp->oid_parent = parent;
- SLIST_INIT(&oidp->oid_children);
+ SPLAY_INIT(&oidp->oid_children);
oidp->oid_number = number;
oidp->oid_refcnt = 1;
oidp->oid_name = escaped;
@@ -913,7 +892,7 @@
sysctl_ctx_entry_add(clist, oidp);
/* Register this oid */
sysctl_register_oid(oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (oidp);
}
@@ -927,10 +906,10 @@
char *oldname;
newname = strdup(name, M_SYSCTLOID);
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
oldname = __DECONST(char *, oidp->oid_name);
oidp->oid_name = newname;
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
free(oldname, M_SYSCTLOID);
}
@@ -942,21 +921,21 @@
{
struct sysctl_oid *oidp;
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
if (oid->oid_parent == parent) {
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (0);
}
oidp = sysctl_find_oidname(oid->oid_name, parent);
if (oidp != NULL) {
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (EEXIST);
}
sysctl_unregister_oid(oid);
oid->oid_parent = parent;
oid->oid_number = OID_AUTO;
sysctl_register_oid(oid);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
return (0);
}
@@ -973,10 +952,10 @@
sx_init(&sysctlmemlock, "sysctl mem");
sx_init(&sysctlstringlock, "sysctl string handler");
SYSCTL_INIT();
- SYSCTL_WLOCK();
+ SYSCTL_LOCK();
SET_FOREACH(oidp, sysctl_set)
sysctl_register_oid(*oidp);
- SYSCTL_WUNLOCK();
+ SYSCTL_UNLOCK();
}
SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
@@ -1016,7 +995,7 @@
struct sysctl_oid *oidp;
SYSCTL_ASSERT_LOCKED();
- SLIST_FOREACH(oidp, l, oid_link) {
+ SPLAY_FOREACH(oidp, sysctl_oid_list, l) {
for (k=0; k<i; k++)
printf(" ");
@@ -1059,15 +1038,14 @@
static int
sysctl_sysctl_debug(SYSCTL_HANDLER_ARGS)
{
- struct rm_priotracker tracker;
int error;
error = priv_check(req->td, PRIV_SYSCTL_DEBUG);
if (error)
return (error);
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (ENOENT);
}
@@ -1081,16 +1059,15 @@
int *name = (int *) arg1;
u_int namelen = arg2;
int error;
- struct sysctl_oid *oid;
+ struct sysctl_oid *oid, key;
struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
- struct rm_priotracker tracker;
char buf[10];
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
while (namelen) {
if (!lsp) {
snprintf(buf,sizeof(buf),"%d",*name);
@@ -1105,10 +1082,9 @@
continue;
}
lsp2 = NULL;
- SLIST_FOREACH(oid, lsp, oid_link) {
- if (oid->oid_number != *name)
- continue;
-
+ key.oid_number = *name;
+ oid = SPLAY_FIND(sysctl_oid_list, lsp, &key);
+ if (oid) {
if (req->oldidx)
error = SYSCTL_OUT(req, ".", 1);
if (!error)
@@ -1120,20 +1096,15 @@
namelen--;
name++;
- if ((oid->oid_kind & CTLTYPE) != CTLTYPE_NODE)
- break;
-
- if (oid->oid_handler)
- break;
-
- lsp2 = SYSCTL_CHILDREN(oid);
- break;
+ if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE &&
+ !oid->oid_handler)
+ lsp2 = SYSCTL_CHILDREN(oid);
}
lsp = lsp2;
}
error = SYSCTL_OUT(req, "", 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (error);
}
@@ -1239,13 +1210,25 @@
sysctl_sysctl_next_action(struct sysctl_oid_list *lsp, int *name, u_int namelen,
int *next, int *len, int level, bool honor_skip)
{
- struct sysctl_oid *oidp;
+ struct sysctl_oid_list *next_lsp;
+ struct sysctl_oid *oidp = NULL, key;
bool success = false;
enum sysctl_iter_action action;
SYSCTL_ASSERT_LOCKED();
- SLIST_FOREACH(oidp, lsp, oid_link) {
- action = sysctl_sysctl_next_node(oidp, name, namelen, honor_skip);
+ /*
+ * Start the search at the requested oid. But if not found, then scan
+ * through all children.
+ */
+ if (namelen > 0) {
+ key.oid_number = *name;
+ oidp = SPLAY_FIND(sysctl_oid_list, lsp, &key);
+ }
+ if (!oidp)
+ oidp = SPLAY_MIN(sysctl_oid_list, lsp);
+ for(; oidp != NULL; oidp = SPLAY_NEXT(sysctl_oid_list, lsp, oidp)) {
+ action = sysctl_sysctl_next_node(oidp, name, namelen,
+ honor_skip);
if (action == ITER_SIBLINGS)
continue;
if (action == ITER_FOUND) {
@@ -1254,13 +1237,13 @@
}
KASSERT((action== ITER_CHILDREN), ("ret(%d)!=ITER_CHILDREN", action));
- lsp = SYSCTL_CHILDREN(oidp);
+ next_lsp = SYSCTL_CHILDREN(oidp);
if (namelen == 0) {
- success = sysctl_sysctl_next_action(lsp, NULL, 0,
+ success = sysctl_sysctl_next_action(next_lsp, NULL, 0,
next + 1, len, level + 1, honor_skip);
} else {
- success = sysctl_sysctl_next_action(lsp, name + 1, namelen - 1,
- next + 1, len, level + 1, honor_skip);
+ success = sysctl_sysctl_next_action(next_lsp, name + 1,
+ namelen - 1, next + 1, len, level + 1, honor_skip);
if (!success) {
/*
@@ -1296,14 +1279,13 @@
int len, error;
bool success;
struct sysctl_oid_list *lsp = &sysctl__children;
- struct rm_priotracker tracker;
int next[CTL_MAXNAME];
len = 0;
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
success = sysctl_sysctl_next_action(lsp, name, namelen, next, &len, 1,
oidp->oid_number == CTL_SYSCTL_NEXT);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
if (!success)
return (ENOENT);
error = SYSCTL_OUT(req, next, len * sizeof (int));
@@ -1332,13 +1314,12 @@
for (*len = 0; *len < CTL_MAXNAME;) {
p = strsep(&name, ".");
- oidp = SLIST_FIRST(lsp);
- for (;; oidp = SLIST_NEXT(oidp, oid_link)) {
- if (oidp == NULL)
- return (ENOENT);
+ SPLAY_FOREACH(oidp, sysctl_oid_list, lsp) {
if (strcmp(p, oidp->oid_name) == 0)
break;
}
+ if (oidp == NULL)
+ return (ENOENT);
*oid++ = oidp->oid_number;
(*len)++;
@@ -1365,7 +1346,6 @@
char *p;
int error, oid[CTL_MAXNAME], len = 0;
struct sysctl_oid *op = NULL;
- struct rm_priotracker tracker;
char buf[32];
if (!req->newlen)
@@ -1386,9 +1366,9 @@
p [req->newlen] = '\0';
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
error = name2oid(p, oid, &len, &op);
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
if (p != buf)
free(p, M_SYSCTL);
@@ -1412,14 +1392,13 @@
sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error;
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
goto out;
@@ -1433,7 +1412,7 @@
goto out;
error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (error);
}
@@ -1444,14 +1423,13 @@
sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error;
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
goto out;
@@ -1462,7 +1440,7 @@
}
error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (error);
}
@@ -1473,14 +1451,13 @@
sysctl_sysctl_oidlabel(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error;
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
if (error)
goto out;
@@ -1491,7 +1468,7 @@
}
error = SYSCTL_OUT(req, oid->oid_label, strlen(oid->oid_label) + 1);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (error);
}
@@ -2162,16 +2139,15 @@
{
struct sysctl_oid_list *lsp;
struct sysctl_oid *oid;
+ struct sysctl_oid key;
int indx;
SYSCTL_ASSERT_LOCKED();
lsp = &sysctl__children;
indx = 0;
while (indx < CTL_MAXNAME) {
- SLIST_FOREACH(oid, lsp, oid_link) {
- if (oid->oid_number == name[indx])
- break;
- }
+ key.oid_number = name[indx];
+ oid = SPLAY_FIND(sysctl_oid_list, lsp, &key);
if (oid == NULL)
return (ENOENT);
@@ -2211,10 +2187,9 @@
sysctl_root(SYSCTL_HANDLER_ARGS)
{
struct sysctl_oid *oid;
- struct rm_priotracker tracker;
int error, indx, lvl;
- SYSCTL_RLOCK(&tracker);
+ SYSCTL_LOCK();
error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
if (error)
@@ -2302,10 +2277,10 @@
if ((oid->oid_kind & CTLFLAG_VNET) && arg1 != NULL)
arg1 = (void *)(curvnet->vnet_data_base + (uintptr_t)arg1);
#endif
- error = sysctl_root_handler_locked(oid, arg1, arg2, req, &tracker);
+ error = sysctl_root_handler_locked(oid, arg1, arg2, req);
out:
- SYSCTL_RUNLOCK(&tracker);
+ SYSCTL_UNLOCK();
return (error);
}
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -525,7 +525,7 @@
* number.
*/
sysctl_wlock();
- SLIST_FOREACH(oidp, SYSCTL_CHILDREN(&sysctl___vfs), oid_link) {
+ SPLAY_FOREACH(oidp, sysctl_oid_list, SYSCTL_CHILDREN(&sysctl___vfs)) {
if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) {
sysctl_unregister_oid(oidp);
oidp->oid_number = vfc->vfc_typenum;
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -39,7 +39,8 @@
#define _SYS_SYSCTL_H_
#ifdef _KERNEL
-#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/systm.h>
#endif
/*
@@ -173,20 +174,25 @@
int flags;
};
-SLIST_HEAD(sysctl_oid_list, sysctl_oid);
+struct sysctl_oid;
+
+/* Splay handling */
+SPLAY_HEAD(sysctl_oid_list, sysctl_oid);
/*
* This describes one "oid" in the MIB tree. Potentially more nodes can
* be hidden behind it, expanded by the handler.
*/
struct sysctl_oid {
- struct sysctl_oid_list oid_children;
- struct sysctl_oid_list *oid_parent;
- SLIST_ENTRY(sysctl_oid) oid_link;
+ struct sysctl_oid_list oid_children;
+ struct sysctl_oid_list* oid_parent;
+ SPLAY_ENTRY(sysctl_oid) oid_link;
+ /* Sort key for all siblings, and lookup key for userland */
int oid_number;
u_int oid_kind;
void *oid_arg1;
intmax_t oid_arg2;
+ /* Must be unique amongst all siblings. */
const char *oid_name;
int (*oid_handler)(SYSCTL_HANDLER_ARGS);
const char *oid_fmt;
@@ -196,6 +202,19 @@
const char *oid_label;
};
+static inline int
+cmp_splay_oid(struct sysctl_oid *a, struct sysctl_oid *b)
+{
+ if (a->oid_number > b->oid_number)
+ return (1);
+ else if (a->oid_number < b->oid_number)
+ return (-1);
+ else
+ return (0);
+}
+
+SPLAY_PROTOTYPE(sysctl_oid_list, sysctl_oid, oid_link, cmp_splay_oid);
+
#define SYSCTL_IN(r, p, l) (r->newfunc)(r, p, l)
#define SYSCTL_OUT(r, p, l) (r->oldfunc)(r, p, l)
#define SYSCTL_OUT_STR(r, p) (r->oldfunc)(r, p, strlen(p) + 1)
@@ -275,7 +294,7 @@
#define SYSCTL_OID_RAW(id, parent_child_head, nbr, name, kind, a1, a2, handler, fmt, descr, label) \
struct sysctl_oid id = { \
.oid_parent = (parent_child_head), \
- .oid_children = SLIST_HEAD_INITIALIZER(&id.oid_children), \
+ .oid_children = SPLAY_INITIALIZER(&id.oid_children), \
.oid_number = (nbr), \
.oid_kind = (kind), \
.oid_arg1 = (a1), \

File Metadata

Mime Type
text/plain
Expires
Tue, Jun 23, 2:00 PM (4 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34249636
Default Alt Text
D36500.id110401.diff (22 KB)

Event Timeline