Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160251207
D36500.id110401.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D36500.id110401.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D36500: Fix O(n^2) behavior in sysctl
Attached
Detach File
Event Timeline
Log In to Comment