Module Name:    src
Committed By:   riastradh
Date:           Tue Sep 13 09:43:33 UTC 2022

Modified Files:
        src/sys/kern: subr_autoconf.c
        src/sys/sys: device_impl.h

Log Message:
autoconf(9): New diagnostic to detect double-detach.

- Rename dv_detached -> dv_detach_committed.
- Add dv_detach_done, asserted false and then set in config_detach.

dv_detach_done may appear redundant with dv_del_gen, but dv_del_gen
will be used to safely detect config_detach on two valid references
to a device (e.g., a bus detaching its child concurrently with drvctl
detaching the same child), while dv_detach_done is strictly a
diagnostic to detect races in the config_detach API.

Currently the config_detach API itself is unsafe, but we can add a
config_detach_release function that simultaneously releases and
detaches a referenced device_t; this will continue to use dv_del_gen
to safely avoid multiple detach, and dv_detach_done to check for
races in usage.


To generate a diff of this commit:
cvs rdiff -u -r1.305 -r1.306 src/sys/kern/subr_autoconf.c
cvs rdiff -u -r1.4 -r1.5 src/sys/sys/device_impl.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/subr_autoconf.c
diff -u src/sys/kern/subr_autoconf.c:1.305 src/sys/kern/subr_autoconf.c:1.306
--- src/sys/kern/subr_autoconf.c:1.305	Tue Sep 13 09:40:38 2022
+++ src/sys/kern/subr_autoconf.c	Tue Sep 13 09:43:33 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.305 2022/09/13 09:40:38 riastradh Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.306 2022/09/13 09:43:33 riastradh Exp $ */
 
 /*
  * Copyright (c) 1996, 2000 Christopher G. Demetriou
@@ -77,7 +77,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.305 2022/09/13 09:40:38 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.306 2022/09/13 09:43:33 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ddb.h"
@@ -2051,6 +2051,9 @@ config_detach(device_t dev, int flags)
 	} else
 		rv = EOPNOTSUPP;
 
+	KASSERTMSG(!dev->dv_detach_done, "%s detached twice, error=%d",
+	    device_xname(dev), rv);
+
 	/*
 	 * If it was not possible to detach the device, then we either
 	 * panic() (for the forced but failed case), or return an error.
@@ -2060,9 +2063,9 @@ config_detach(device_t dev, int flags)
 		 * Detach failed -- likely EOPNOTSUPP or EBUSY.  Driver
 		 * must not have called config_detach_commit.
 		 */
-		KASSERTMSG(!dev->dv_detached,
-		    "%s committed to detaching and then backed out",
-		    device_xname(dev));
+		KASSERTMSG(!dev->dv_detach_committed,
+		    "%s committed to detaching and then backed out, error=%d",
+		    device_xname(dev), rv);
 		if (flags & DETACH_FORCE) {
 			panic("config_detach: forced detach of %s failed (%d)",
 			    device_xname(dev), rv);
@@ -2073,6 +2076,7 @@ config_detach(device_t dev, int flags)
 	/*
 	 * The device has now been successfully detached.
 	 */
+	dev->dv_detach_done = true;
 
 	/*
 	 * If .ca_detach didn't commit to detach, then do that for it.
@@ -2193,7 +2197,7 @@ config_detach_commit(device_t dev)
 	    "lwp %ld [%s] @ %p detaching %s",
 	    (long)l->l_lid, (l->l_name ? l->l_name : l->l_proc->p_comm), l,
 	    device_xname(dev));
-	dev->dv_detached = true;
+	dev->dv_detach_committed = true;
 	cv_broadcast(&config_misc_cv);
 	mutex_exit(&config_misc_lock);
 }
@@ -2706,7 +2710,7 @@ device_lookup_acquire(cfdriver_t cd, int
 retry:	if (unit < 0 || unit >= cd->cd_ndevs ||
 	    (dv = cd->cd_devs[unit]) == NULL ||
 	    dv->dv_del_gen != 0 ||
-	    dv->dv_detached) {
+	    dv->dv_detach_committed) {
 		dv = NULL;
 	} else {
 		/*

Index: src/sys/sys/device_impl.h
diff -u src/sys/sys/device_impl.h:1.4 src/sys/sys/device_impl.h:1.5
--- src/sys/sys/device_impl.h:1.4	Wed Aug 24 11:47:52 2022
+++ src/sys/sys/device_impl.h	Tue Sep 13 09:43:33 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: device_impl.h,v 1.4 2022/08/24 11:47:52 riastradh Exp $	*/
+/*	$NetBSD: device_impl.h,v 1.5 2022/09/13 09:43:33 riastradh Exp $	*/
 
 /*
  * Copyright (c) 2022 The NetBSD Foundation, Inc.
@@ -147,7 +147,8 @@ struct device {
 
 	struct lwp	*dv_attaching;	/* thread not yet finished in attach */
 	struct lwp	*dv_detaching;	/* detach lock (config_misc_lock/cv) */
-	bool		dv_detached;	/* config_misc_lock */
+	bool		dv_detach_committed;	/* config_misc_lock */
+	bool		dv_detach_done;		/* dv_detaching */
 
 	size_t		dv_activity_count;
 	void		(**dv_activity_handlers)(device_t, devactive_t);

Reply via email to