Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 30 Jul 2015 19:52:44 +0000 (UTC)
From:      Mateusz Guzik <mjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286094 - in head/sys: kern sys
Message-ID:  <201507301952.t6UJqiPK003032@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mjg
Date: Thu Jul 30 19:52:43 2015
New Revision: 286094
URL: https://svnweb.freebsd.org/changeset/base/286094

Log:
  Revert r285125 until rmlocks get fixed.
  
  Right now there is a chance that sysctl unregister will cause reader to
  block on the sx lock associated with sysctl rmlock, in which case kernels
  with debug enabled will panic.

Modified:
  head/sys/kern/kern_linker.c
  head/sys/kern/kern_sysctl.c
  head/sys/kern/vfs_init.c
  head/sys/sys/sysctl.h

Modified: head/sys/kern/kern_linker.c
==============================================================================
--- head/sys/kern/kern_linker.c	Thu Jul 30 19:44:46 2015	(r286093)
+++ head/sys/kern/kern_linker.c	Thu Jul 30 19:52:43 2015	(r286094)
@@ -292,10 +292,10 @@ linker_file_register_sysctls(linker_file
 		return;
 
 	sx_xunlock(&kld_sx);
-	sysctl_wlock();
+	sysctl_xlock();
 	for (oidp = start; oidp < stop; oidp++)
 		sysctl_register_oid(*oidp);
-	sysctl_wunlock();
+	sysctl_xunlock();
 	sx_xlock(&kld_sx);
 }
 
@@ -313,10 +313,10 @@ linker_file_unregister_sysctls(linker_fi
 		return;
 
 	sx_xunlock(&kld_sx);
-	sysctl_wlock();
+	sysctl_xlock();
 	for (oidp = start; oidp < stop; oidp++)
 		sysctl_unregister_oid(*oidp);
-	sysctl_wunlock();
+	sysctl_xunlock();
 	sx_xlock(&kld_sx);
 }
 

Modified: head/sys/kern/kern_sysctl.c
==============================================================================
--- head/sys/kern/kern_sysctl.c	Thu Jul 30 19:44:46 2015	(r286093)
+++ head/sys/kern/kern_sysctl.c	Thu Jul 30 19:52:43 2015	(r286094)
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/jail.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>
@@ -78,7 +77,7 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysct
  * The sysctllock protects the MIB tree.  It also protects sysctl
  * contexts used with dynamic sysctls.  The sysctl_register_oid() and
  * sysctl_unregister_oid() routines require the sysctllock to already
- * be held, so the sysctl_wlock() and sysctl_wunlock() routines are
+ * be held, so the sysctl_xlock() and sysctl_xunlock() routines are
  * provided for the few places in the kernel which need to use that
  * API rather than using the dynamic API.  Use of the dynamic API is
  * strongly encouraged for most code.
@@ -87,21 +86,20 @@ static MALLOC_DEFINE(M_SYSCTLTMP, "sysct
  * sysctl requests.  This is implemented by serializing any userland
  * sysctl requests larger than a single page via an exclusive lock.
  */
-static struct rmlock sysctllock;
+static struct sx sysctllock;
 static struct sx sysctlmemlock;
 
-#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_XLOCK()		sx_xlock(&sysctllock)
+#define	SYSCTL_XUNLOCK()	sx_xunlock(&sysctllock)
+#define	SYSCTL_SLOCK()		sx_slock(&sysctllock)
+#define	SYSCTL_SUNLOCK()	sx_sunlock(&sysctllock)
+#define	SYSCTL_XLOCKED()	sx_xlocked(&sysctllock)
+#define	SYSCTL_ASSERT_LOCKED()	sx_assert(&sysctllock, SA_LOCKED)
+#define	SYSCTL_ASSERT_XLOCKED()	sx_assert(&sysctllock, SA_XLOCKED)
+#define	SYSCTL_ASSERT_SLOCKED()	sx_assert(&sysctllock, SA_SLOCKED)
+#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);
 
@@ -113,6 +111,29 @@ static int	sysctl_remove_oid_locked(stru
 static int	sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
 static int	sysctl_new_kernel(struct sysctl_req *, void *, size_t);
 
+static void
+sysctl_lock(bool xlock)
+{
+
+	if (xlock)
+		SYSCTL_XLOCK();
+	else
+		SYSCTL_SLOCK();
+}
+
+static bool
+sysctl_unlock(void)
+{
+	bool xlocked;
+
+	xlocked = SYSCTL_XLOCKED();
+	if (xlocked)
+		SYSCTL_XUNLOCK();
+	else
+		SYSCTL_SUNLOCK();
+	return (xlocked);
+}
+
 static struct sysctl_oid *
 sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
 {
@@ -133,32 +154,29 @@ sysctl_find_oidname(const char *name, st
  * Order by number in each list.
  */
 void
-sysctl_wlock(void)
+sysctl_xlock(void)
 {
 
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 }
 
 void
-sysctl_wunlock(void)
+sysctl_xunlock(void)
 {
 
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 }
 
 static int
 sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1, intptr_t arg2,
-    struct sysctl_req *req, struct rm_priotracker *tracker)
+    struct sysctl_req *req)
 {
 	int error;
+	bool xlocked;
 
 	if (oid->oid_kind & CTLFLAG_DYN)
 		atomic_add_int(&oid->oid_running, 1);
-
-	if (tracker != NULL)
-		SYSCTL_RUNLOCK(tracker);
-	else
-		SYSCTL_WUNLOCK();
+	xlocked = sysctl_unlock();
 
 	if (!(oid->oid_kind & CTLFLAG_MPSAFE))
 		mtx_lock(&Giant);
@@ -166,11 +184,7 @@ sysctl_root_handler_locked(struct sysctl
 	if (!(oid->oid_kind & CTLFLAG_MPSAFE))
 		mtx_unlock(&Giant);
 
-	if (tracker != NULL)
-		SYSCTL_RLOCK(tracker);
-	else
-		SYSCTL_WLOCK();
-
+	sysctl_lock(xlocked);
 	if (oid->oid_kind & CTLFLAG_DYN) {
 		if (atomic_fetchadd_int(&oid->oid_running, -1) == 1 &&
 		    (oid->oid_kind & CTLFLAG_DYING) != 0)
@@ -269,7 +283,7 @@ sysctl_load_tunable_by_oid_locked(struct
 		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)
@@ -289,7 +303,7 @@ sysctl_register_oid(struct sysctl_oid *o
 	 * First check if another oid with the same name already
 	 * exists in the parent's list.
 	 */
-	SYSCTL_ASSERT_WLOCKED();
+	SYSCTL_ASSERT_XLOCKED();
 	p = sysctl_find_oidname(oidp->oid_name, parent);
 	if (p != NULL) {
 		if ((p->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
@@ -383,7 +397,7 @@ sysctl_unregister_oid(struct sysctl_oid 
 	struct sysctl_oid *p;
 	int error;
 
-	SYSCTL_ASSERT_WLOCKED();
+	SYSCTL_ASSERT_XLOCKED();
 	error = ENOENT;
 	if (oidp->oid_number == OID_AUTO) {
 		error = EINVAL;
@@ -439,7 +453,7 @@ sysctl_ctx_free(struct sysctl_ctx_list *
 	 * XXX This algorithm is a hack. But I don't know any
 	 * XXX better solution for now...
 	 */
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	TAILQ_FOREACH(e, clist, link) {
 		error = sysctl_remove_oid_locked(e->entry, 0, 0);
 		if (error)
@@ -459,7 +473,7 @@ sysctl_ctx_free(struct sysctl_ctx_list *
 		e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
 	}
 	if (error) {
-		SYSCTL_WUNLOCK();
+		SYSCTL_XUNLOCK();
 		return(EBUSY);
 	}
 	/* Now really delete the entries */
@@ -473,7 +487,7 @@ sysctl_ctx_free(struct sysctl_ctx_list *
 		free(e, M_SYSCTLOID);
 		e = e1;
 	}
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 	return (error);
 }
 
@@ -483,7 +497,7 @@ sysctl_ctx_entry_add(struct sysctl_ctx_l
 {
 	struct sysctl_ctx_entry *e;
 
-	SYSCTL_ASSERT_WLOCKED();
+	SYSCTL_ASSERT_XLOCKED();
 	if (clist == NULL || oidp == NULL)
 		return(NULL);
 	e = malloc(sizeof(struct sysctl_ctx_entry), M_SYSCTLOID, M_WAITOK);
@@ -498,7 +512,7 @@ sysctl_ctx_entry_find(struct sysctl_ctx_
 {
 	struct sysctl_ctx_entry *e;
 
-	SYSCTL_ASSERT_WLOCKED();
+	SYSCTL_ASSERT_XLOCKED();
 	if (clist == NULL || oidp == NULL)
 		return(NULL);
 	TAILQ_FOREACH(e, clist, link) {
@@ -520,15 +534,15 @@ sysctl_ctx_entry_del(struct sysctl_ctx_l
 
 	if (clist == NULL || oidp == NULL)
 		return (EINVAL);
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	e = sysctl_ctx_entry_find(clist, oidp);
 	if (e != NULL) {
 		TAILQ_REMOVE(clist, e, link);
-		SYSCTL_WUNLOCK();
+		SYSCTL_XUNLOCK();
 		free(e, M_SYSCTLOID);
 		return (0);
 	} else {
-		SYSCTL_WUNLOCK();
+		SYSCTL_XUNLOCK();
 		return (ENOENT);
 	}
 }
@@ -544,9 +558,9 @@ sysctl_remove_oid(struct sysctl_oid *oid
 {
 	int error;
 
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	error = sysctl_remove_oid_locked(oidp, del, recurse);
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 	return (error);
 }
 
@@ -558,14 +572,14 @@ sysctl_remove_name(struct sysctl_oid *pa
 	int error;
 
 	error = ENOENT;
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	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_XUNLOCK();
 
 	return (error);
 }
@@ -577,7 +591,7 @@ sysctl_remove_oid_locked(struct sysctl_o
 	struct sysctl_oid *p, *tmp;
 	int error;
 
-	SYSCTL_ASSERT_WLOCKED();
+	SYSCTL_ASSERT_XLOCKED();
 	if (oidp == NULL)
 		return(EINVAL);
 	if ((oidp->oid_kind & CTLFLAG_DYN) == 0) {
@@ -652,7 +666,7 @@ sysctl_add_oid(struct sysctl_ctx_list *c
 	if (parent == NULL)
 		return(NULL);
 	/* Check if the node already exists, otherwise create it */
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	oidp = sysctl_find_oidname(name, parent);
 	if (oidp != NULL) {
 		if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
@@ -660,10 +674,10 @@ sysctl_add_oid(struct sysctl_ctx_list *c
 			/* Update the context */
 			if (clist != NULL)
 				sysctl_ctx_entry_add(clist, oidp);
-			SYSCTL_WUNLOCK();
+			SYSCTL_XUNLOCK();
 			return (oidp);
 		} else {
-			SYSCTL_WUNLOCK();
+			SYSCTL_XUNLOCK();
 			printf("can't re-use a leaf (%s)!\n", name);
 			return (NULL);
 		}
@@ -686,7 +700,7 @@ sysctl_add_oid(struct sysctl_ctx_list *c
 		sysctl_ctx_entry_add(clist, oidp);
 	/* Register this oid */
 	sysctl_register_oid(oidp);
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 	return (oidp);
 }
 
@@ -700,10 +714,10 @@ sysctl_rename_oid(struct sysctl_oid *oid
 	char *oldname;
 
 	newname = strdup(name, M_SYSCTLOID);
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	oldname = __DECONST(char *, oidp->oid_name);
 	oidp->oid_name = newname;
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 	free(oldname, M_SYSCTLOID);
 }
 
@@ -715,21 +729,21 @@ sysctl_move_oid(struct sysctl_oid *oid, 
 {
 	struct sysctl_oid *oidp;
 
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	if (oid->oid_parent == parent) {
-		SYSCTL_WUNLOCK();
+		SYSCTL_XUNLOCK();
 		return (0);
 	}
 	oidp = sysctl_find_oidname(oid->oid_name, parent);
 	if (oidp != NULL) {
-		SYSCTL_WUNLOCK();
+		SYSCTL_XUNLOCK();
 		return (EEXIST);
 	}
 	sysctl_unregister_oid(oid);
 	oid->oid_parent = parent;
 	oid->oid_number = OID_AUTO;
 	sysctl_register_oid(oid);
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 	return (0);
 }
 
@@ -745,10 +759,10 @@ sysctl_register_all(void *arg)
 
 	sx_init(&sysctlmemlock, "sysctl mem");
 	SYSCTL_INIT();
-	SYSCTL_WLOCK();
+	SYSCTL_XLOCK();
 	SET_FOREACH(oidp, sysctl_set)
 		sysctl_register_oid(*oidp);
-	SYSCTL_WUNLOCK();
+	SYSCTL_XUNLOCK();
 }
 SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, 0);
 
@@ -818,15 +832,14 @@ sysctl_sysctl_debug_dump_node(struct sys
 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_SLOCK();
 	sysctl_sysctl_debug_dump_node(&sysctl__children, 0);
-	SYSCTL_RUNLOCK(&tracker);
+	SYSCTL_SUNLOCK();
 	return (ENOENT);
 }
 
@@ -842,10 +855,9 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
 	int error = 0;
 	struct sysctl_oid *oid;
 	struct sysctl_oid_list *lsp = &sysctl__children, *lsp2;
-	struct rm_priotracker tracker;
 	char buf[10];
 
-	SYSCTL_RLOCK(&tracker);
+	SYSCTL_SLOCK();
 	while (namelen) {
 		if (!lsp) {
 			snprintf(buf,sizeof(buf),"%d",*name);
@@ -888,7 +900,7 @@ sysctl_sysctl_name(SYSCTL_HANDLER_ARGS)
 	}
 	error = SYSCTL_OUT(req, "", 1);
  out:
-	SYSCTL_RUNLOCK(&tracker);
+	SYSCTL_SUNLOCK();
 	return (error);
 }
 
@@ -967,12 +979,11 @@ sysctl_sysctl_next(SYSCTL_HANDLER_ARGS)
 	int i, j, error;
 	struct sysctl_oid *oid;
 	struct sysctl_oid_list *lsp = &sysctl__children;
-	struct rm_priotracker tracker;
 	int newoid[CTL_MAXNAME];
 
-	SYSCTL_RLOCK(&tracker);
+	SYSCTL_SLOCK();
 	i = sysctl_sysctl_next_ls(lsp, name, namelen, newoid, &j, 1, &oid);
-	SYSCTL_RUNLOCK(&tracker);
+	SYSCTL_SUNLOCK();
 	if (i)
 		return (ENOENT);
 	error = SYSCTL_OUT(req, newoid, j * sizeof (int));
@@ -1031,7 +1042,6 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_AR
 	char *p;
 	int error, oid[CTL_MAXNAME], len = 0;
 	struct sysctl_oid *op = 0;
-	struct rm_priotracker tracker;
 
 	if (!req->newlen) 
 		return (ENOENT);
@@ -1048,9 +1058,9 @@ sysctl_sysctl_name2oid(SYSCTL_HANDLER_AR
 
 	p [req->newlen] = '\0';
 
-	SYSCTL_RLOCK(&tracker);
+	SYSCTL_SLOCK();
 	error = name2oid(p, oid, &len, &op);
-	SYSCTL_RUNLOCK(&tracker);
+	SYSCTL_SUNLOCK();
 
 	free(p, M_SYSCTL);
 
@@ -1073,10 +1083,9 @@ static int
 sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS)
 {
 	struct sysctl_oid *oid;
-	struct rm_priotracker tracker;
 	int error;
 
-	SYSCTL_RLOCK(&tracker);
+	SYSCTL_SLOCK();
 	error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
 	if (error)
 		goto out;
@@ -1090,7 +1099,7 @@ sysctl_sysctl_oidfmt(SYSCTL_HANDLER_ARGS
 		goto out;
 	error = SYSCTL_OUT(req, oid->oid_fmt, strlen(oid->oid_fmt) + 1);
  out:
-	SYSCTL_RUNLOCK(&tracker);
+	SYSCTL_SUNLOCK();
 	return (error);
 }
 
@@ -1102,10 +1111,9 @@ static int
 sysctl_sysctl_oiddescr(SYSCTL_HANDLER_ARGS)
 {
 	struct sysctl_oid *oid;
-	struct rm_priotracker tracker;
 	int error;
 
-	SYSCTL_RLOCK(&tracker);
+	SYSCTL_SLOCK();
 	error = sysctl_find_oid(arg1, arg2, &oid, NULL, req);
 	if (error)
 		goto out;
@@ -1116,7 +1124,7 @@ sysctl_sysctl_oiddescr(SYSCTL_HANDLER_AR
 	}
 	error = SYSCTL_OUT(req, oid->oid_descr, strlen(oid->oid_descr) + 1);
  out:
-	SYSCTL_RUNLOCK(&tracker);
+	SYSCTL_SUNLOCK();
 	return (error);
 }
 
@@ -1421,7 +1429,9 @@ kernel_sysctl(struct thread *td, int *na
 	req.newfunc = sysctl_new_kernel;
 	req.lock = REQ_UNWIRED;
 
+	SYSCTL_SLOCK();
 	error = sysctl_root(0, name, namelen, &req);
+	SYSCTL_SUNLOCK();
 
 	if (req.lock == REQ_WIRED && req.validlen > 0)
 		vsunlock(req.oldptr, req.validlen);
@@ -1598,14 +1608,13 @@ static int
 sysctl_root(SYSCTL_HANDLER_ARGS)
 {
 	struct sysctl_oid *oid;
-	struct rm_priotracker tracker;
 	int error, indx, lvl;
 
-	SYSCTL_RLOCK(&tracker);
+	SYSCTL_ASSERT_SLOCKED();
 
 	error = sysctl_find_oid(arg1, arg2, &oid, &indx, req);
 	if (error)
-		goto out;
+		return (error);
 
 	if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
 		/*
@@ -1613,17 +1622,13 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
 		 * 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) {
-			error = EISDIR;
-			goto out;
-		}
+		if (oid->oid_handler == NULL)
+			return (EISDIR);
 	}
 
 	/* Is this sysctl writable? */
-	if (req->newptr && !(oid->oid_kind & CTLFLAG_WR)) {
-		error = EPERM;
-		goto out;
-	}
+	if (req->newptr && !(oid->oid_kind & CTLFLAG_WR))
+		return (EPERM);
 
 	KASSERT(req->td != NULL, ("sysctl_root(): req->td == NULL"));
 
@@ -1633,11 +1638,10 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
 	 * writing unless specifically granted for the node.
 	 */
 	if (IN_CAPABILITY_MODE(req->td)) {
-		if ((req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD)) ||
-		    (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))) {
-			error = EPERM;
-			goto out;
-		}
+		if (req->oldptr && !(oid->oid_kind & CTLFLAG_CAPRD))
+			return (EPERM);
+		if (req->newptr && !(oid->oid_kind & CTLFLAG_CAPWR))
+			return (EPERM);
 	}
 #endif
 
@@ -1646,7 +1650,7 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
 		lvl = (oid->oid_kind & CTLMASK_SECURE) >> CTLSHIFT_SECURE;
 		error = securelevel_gt(req->td->td_ucred, lvl);
 		if (error)
-			goto out;
+			return (error);
 	}
 
 	/* Is this sysctl writable by only privileged users? */
@@ -1664,13 +1668,11 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
 			priv = PRIV_SYSCTL_WRITE;
 		error = priv_check(req->td, priv);
 		if (error)
-			goto out;
+			return (error);
 	}
 
-	if (!oid->oid_handler) {
-		error = EINVAL;
-		goto out;
-	}
+	if (!oid->oid_handler)
+		return (EINVAL);
 
 	if ((oid->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
 		arg1 = (int *)arg1 + indx;
@@ -1683,18 +1685,16 @@ sysctl_root(SYSCTL_HANDLER_ARGS)
 	error = mac_system_check_sysctl(req->td->td_ucred, oid, arg1, arg2,
 	    req);
 	if (error != 0)
-		goto out;
+		return (error);
 #endif
 #ifdef VIMAGE
 	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);
 
 	KFAIL_POINT_ERROR(_debug_fail_point, sysctl_running, error);
 
-out:
-	SYSCTL_RUNLOCK(&tracker);
 	return (error);
 }
 
@@ -1794,7 +1794,9 @@ userland_sysctl(struct thread *td, int *
 	for (;;) {
 		req.oldidx = 0;
 		req.newidx = 0;
+		SYSCTL_SLOCK();
 		error = sysctl_root(0, name, namelen, &req);
+		SYSCTL_SUNLOCK();
 		if (error != EAGAIN)
 			break;
 		kern_yield(PRI_USER);

Modified: head/sys/kern/vfs_init.c
==============================================================================
--- head/sys/kern/vfs_init.c	Thu Jul 30 19:44:46 2015	(r286093)
+++ head/sys/kern/vfs_init.c	Thu Jul 30 19:52:43 2015	(r286094)
@@ -291,7 +291,7 @@ vfs_register(struct vfsconf *vfc)
 	 * preserved by re-registering the oid after modifying its
 	 * number.
 	 */
-	sysctl_wlock();
+	sysctl_xlock();
 	SLIST_FOREACH(oidp, SYSCTL_CHILDREN(&sysctl___vfs), oid_link) {
 		if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) {
 			sysctl_unregister_oid(oidp);
@@ -300,7 +300,7 @@ vfs_register(struct vfsconf *vfc)
 			break;
 		}
 	}
-	sysctl_wunlock();
+	sysctl_xunlock();
 
 	return (0);
 }

Modified: head/sys/sys/sysctl.h
==============================================================================
--- head/sys/sys/sysctl.h	Thu Jul 30 19:44:46 2015	(r286093)
+++ head/sys/sys/sysctl.h	Thu Jul 30 19:52:43 2015	(r286094)
@@ -807,8 +807,8 @@ int	userland_sysctl(struct thread *td, i
 	    size_t *retval, int flags);
 int	sysctl_find_oid(int *name, u_int namelen, struct sysctl_oid **noid,
 	    int *nindx, struct sysctl_req *req);
-void	sysctl_wlock(void);
-void	sysctl_wunlock(void);
+void	sysctl_xlock(void);
+void	sysctl_xunlock(void);
 int	sysctl_wire_old_buffer(struct sysctl_req *req, size_t len);
 
 struct sbuf;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507301952.t6UJqiPK003032>