Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys autoconf(9): New function config_detach_commit.
details: https://anonhg.NetBSD.org/src/rev/3e4a95c8adcf
branches: trunk
changeset: 364522:3e4a95c8adcf
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Mar 28 12:38:15 2022 +0000
description:
autoconf(9): New function config_detach_commit.
When a driver's .ca_detach function has committed to detaching -- it
definitely won't back out with EBUSY, for instance -- it can call
this to wake all pending calls to device_lookup_acquire and make them
fail immediately.
This is necessary to break a deadlock if the device_lookup_acquire
calls happen inside I/O operations which the driver's .ca_detach
function waits for the completion of -- without config_detach_commit,
I/O operations would be stuck in device_lookup_acquire waiting for
.ca_detach and .ca_detach would be stuck waiting for I/O operations
to return.
Most drivers won't need to call this: for autoconf drivers used the
traditional way by devsw for userland device nodes, the .ca_detach
routine uses vdevgone, and we will arrange to make vdevgone call
config_detach_commit automagically in such drivers anyway.
XXX kernel ABI change to struct device requires bump -- later change
will make struct device opaque to ABI, but we're not there yet
diffstat:
sys/kern/subr_autoconf.c | 49 ++++++++++++++++++++++++++++++++++++++++-------
sys/sys/device.h | 4 ++-
2 files changed, 44 insertions(+), 9 deletions(-)
diffs (116 lines):
diff -r 8652f02d3f00 -r 3e4a95c8adcf sys/kern/subr_autoconf.c
--- a/sys/kern/subr_autoconf.c Mon Mar 28 12:38:04 2022 +0000
+++ b/sys/kern/subr_autoconf.c Mon Mar 28 12:38:15 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_autoconf.c,v 1.298 2022/03/28 12:33:41 riastradh Exp $ */
+/* $NetBSD: subr_autoconf.c,v 1.299 2022/03/28 12:38:15 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.298 2022/03/28 12:33:41 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_autoconf.c,v 1.299 2022/03/28 12:38:15 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "opt_ddb.h"
@@ -2039,10 +2039,17 @@
* If it was possible to detach the device, ensure that the
* device is deactivated.
*/
- if (rv == 0)
- dev->dv_flags &= ~DVF_ACTIVE;
- else if ((flags & DETACH_FORCE) == 0) {
- /* Detach failed -- likely EBUSY. */
+ if (rv == 0) {
+ config_detach_commit(dev);
+ dev->dv_flags &= ~DVF_ACTIVE; /* XXXSMP */
+ } else if ((flags & DETACH_FORCE) == 0) {
+ /*
+ * Detach failed -- likely EBUSY. Driver must not have
+ * called config_detach_commit.
+ */
+ KASSERTMSG(!dev->dv_detached,
+ "%s committed to detaching and then backed out",
+ device_xname(dev));
goto out;
} else {
panic("config_detach: forced detach of %s failed (%d)",
@@ -2059,7 +2066,8 @@
* responsibility of .ca_detach to ensure anything with open
* references will be interrupted and release them promptly,
* not block indefinitely. All new attempts to acquire
- * references will block until dv_detaching clears.
+ * references will fail, as config_detach_commit has arranged
+ * by now.
*/
mutex_enter(&config_misc_lock);
localcount_drain(dev->dv_localcount,
@@ -2133,6 +2141,30 @@
return rv;
}
+/*
+ * config_detach_commit(dev)
+ *
+ * Issued by a driver's .ca_detach routine to notify anyone
+ * waiting in device_lookup_acquire that the driver is committed
+ * to detaching the device, which allows device_lookup_acquire to
+ * wake up and fail immediately.
+ *
+ * Safe to call multiple times -- idempotent. Must be called
+ * during config_detach_enter/exit. Safe to use with
+ * device_lookup because the device is not actually removed from
+ * the table until after config_detach_exit.
+ */
+void
+config_detach_commit(device_t dev)
+{
+
+ mutex_enter(&config_misc_lock);
+ KASSERT(dev->dv_detaching == curlwp);
+ dev->dv_detached = true;
+ cv_broadcast(&config_misc_cv);
+ mutex_exit(&config_misc_lock);
+}
+
int
config_detach_children(device_t parent, int flags)
{
@@ -2640,7 +2672,8 @@
mutex_enter(&alldevs_lock);
retry: if (unit < 0 || unit >= cd->cd_ndevs ||
(dv = cd->cd_devs[unit]) == NULL ||
- dv->dv_del_gen != 0) {
+ dv->dv_del_gen != 0 ||
+ dv->dv_detached) {
dv = NULL;
} else {
/*
diff -r 8652f02d3f00 -r 3e4a95c8adcf sys/sys/device.h
--- a/sys/sys/device.h Mon Mar 28 12:38:04 2022 +0000
+++ b/sys/sys/device.h Mon Mar 28 12:38:15 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: device.h,v 1.180 2022/03/28 12:33:41 riastradh Exp $ */
+/* $NetBSD: device.h,v 1.181 2022/03/28 12:38:15 riastradh Exp $ */
/*
* Copyright (c) 2021 The NetBSD Foundation, Inc.
@@ -281,6 +281,7 @@
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 */
size_t dv_activity_count;
void (**dv_activity_handlers)(device_t, devactive_t);
@@ -631,6 +632,7 @@
int config_detach(device_t, int);
int config_detach_children(device_t, int flags);
+void config_detach_commit(device_t);
bool config_detach_all(int);
int config_deactivate(device_t);
void config_defer(device_t, void (*)(device_t));
Home |
Main Index |
Thread Index |
Old Index