Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 11 Aug 2001 15:22:21 +0900
From:      neckpain@nettaxi.com
To:        current@FreeBSD.ORG
Subject:   Re: panic kldunload'ing: static sysctl oid too high
Message-ID:  <200108110622.XAA21343@taxismtp1.alchemyfx.com>
In-Reply-To: <200108102252.PAA03031@taxismtp1.alchemyfx.com>
References:  <200108102252.PAA03031@taxismtp1.alchemyfx.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--zhXaljGHf11kAtnf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sat, Aug 11, 2001 at 07:53:05AM +0900, I wrote:
> Hello.
> I'm running current as of 2001.08.01.00.00.00 (plus John Baldwin's patch
> against kern_lock.c; without this patch I couldn't get the crash dump),
> and had a panic kldunload'ing snd_ds1 module. I'm not sure what's going on,
> but confirmed the following:
> 
>  - unloading snd_ds1 always panics(either when it's loaded from
>     /boot/loader.conf, or from the command line by kldload).
>  - loading and unloading snd_pcm alone does not panic(snd_pcm is a driver
>     loaded as dependency when snd_ds1 is loaded).
>  - unloading some other modules does not panic.
>  - the last kernel I remember that didn't panic was from 2001.07.20.00.00.00 .

And attached is a patch to kern_sysctl.c I'm using currently as a workaround.
It just adds a test mode to internal sysctl_remove_oid() and avoid
reregistering removed oid in sysctl_ctx_free().

--zhXaljGHf11kAtnf
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=workaround

Index: src/sys/kern/kern_sysctl.c
===================================================================
RCS file: /home/cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.112
diff -u -u -r1.112 kern_sysctl.c
--- src/sys/kern/kern_sysctl.c	2001/07/25 17:21:15	1.112
+++ src/sys/kern/kern_sysctl.c	2001/08/11 05:57:32
@@ -65,6 +65,8 @@
 } memlock;
 
 static int sysctl_root(SYSCTL_HANDLER_ARGS);
+static int sysctl_remove_oid_internal(struct sysctl_oid *oidp, int del,
+    int recurse, int test);
 
 struct sysctl_oid_list sysctl__children; /* root list */
 
@@ -173,10 +175,11 @@
 	 * XXX better solution for now...
 	 */
 	TAILQ_FOREACH(e, clist, link) {
-		error = sysctl_remove_oid(e->entry, 0, 0);
+		error = sysctl_remove_oid_internal(e->entry, 0, 0, 1);
 		if (error)
 			break;
 	}
+#if 0
 	/*
 	 * Restore deregistered entries, either from the end,
 	 * or from the place where error occured.
@@ -190,6 +193,7 @@
 		sysctl_register_oid(e1->entry);
 		e1 = TAILQ_PREV(e1, sysctl_ctx_list, link);
 	}
+#endif
 	if (error)
 		return(EBUSY);
 	/* Now really delete the entries */
@@ -261,9 +265,12 @@
  * 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
+ * test - if != 0 traverse the tree to see if it can be removed,
+ *	but don't do anything.
  */
-int
-sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
+static int
+sysctl_remove_oid_internal(struct sysctl_oid *oidp, int del, int recurse,
+    int test)
 {
 	struct sysctl_oid *p;
 	int error;
@@ -286,30 +293,38 @@
 			SLIST_FOREACH(p, SYSCTL_CHILDREN(oidp), oid_link) {
 				if (!recurse)
 					return (ENOTEMPTY);
-				error = sysctl_remove_oid(p, del, recurse);
+				error = sysctl_remove_oid_internal(p, del,
+				    recurse, test);
 				if (error)
 					return (error);
 			}
-			if (del)
+			if (del && !test)
 				free(SYSCTL_CHILDREN(oidp), M_SYSCTLOID);
 		}
 	}
-	if (oidp->oid_refcnt > 1 ) {
-		oidp->oid_refcnt--;
+	if (oidp->oid_refcnt > 1) {
+		if (!test)
+			oidp->oid_refcnt--;
 	} else {
 		if (oidp->oid_refcnt == 0) {
 			printf("Warning: bad oid_refcnt=%u (%s)!\n",
 				oidp->oid_refcnt, oidp->oid_name);
 			return (EINVAL);
 		}
-		sysctl_unregister_oid(oidp);
-		if (del) {
+		if (!test)
+			sysctl_unregister_oid(oidp);
+		if (del && !test) {
 			free((void *)(uintptr_t)(const void *)oidp->oid_name,
 			     M_SYSCTLOID);
 			free(oidp, M_SYSCTLOID);
 		}
 	}
 	return (0);
+}
+int
+sysctl_remove_oid(struct sysctl_oid *oidp, int del, int recurse)
+{
+	return sysctl_remove_oid_internal(oidp, del, recurse, 0);
 }
 
 /*

--zhXaljGHf11kAtnf--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




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