Module Name: src
Committed By: riastradh
Date: Mon Mar 28 12:33:50 UTC 2022
Modified Files:
src/sys/kern: subr_devsw.c
src/sys/sys: conf.h
Log Message:
driver(9): New devsw members d_cfdriver, d_devtounit.
If set, then bdev_open/cdev_open will use d_devtounit to map the
dev_t to an autoconf instance (e.g., /dev/wd0a -> wd0) and hold a
reference with device_lookup_acquire across the call to d_open.
This guarantees that the autoconf instance cannot be detached while
the devsw's d_open function is trying to open it (and also that the
autoconf instance has finished *_attach before anyone can open it).
Of course, if the underlying hardware has gone away, there will be
I/O errors, but this avoids software synchronization bugs between
open and detach for drivers that opt into it. It's up to the driver
and bus to figure out how to deal with I/O errors from operations on
hardware that has gone away while the software hasn't finished
notifying everything that it's gone yet.
XXX kernel ABI change to struct bdevsw/cdevsw requires bump
To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/kern/subr_devsw.c
cvs rdiff -u -r1.155 -r1.156 src/sys/sys/conf.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_devsw.c
diff -u src/sys/kern/subr_devsw.c:1.40 src/sys/kern/subr_devsw.c:1.41
--- src/sys/kern/subr_devsw.c:1.40 Mon Mar 28 12:33:32 2022
+++ src/sys/kern/subr_devsw.c Mon Mar 28 12:33:50 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_devsw.c,v 1.40 2022/03/28 12:33:32 riastradh Exp $ */
+/* $NetBSD: subr_devsw.c,v 1.41 2022/03/28 12:33:50 riastradh Exp $ */
/*-
* Copyright (c) 2001, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.40 2022/03/28 12:33:32 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_devsw.c,v 1.41 2022/03/28 12:33:50 riastradh Exp $");
#ifdef _KERNEL_OPT
#include "opt_dtrace.h"
@@ -89,6 +89,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_devsw.c
#include <sys/localcount.h>
#include <sys/pserialize.h>
#include <sys/xcall.h>
+#include <sys/device.h>
#ifdef DEVSW_DEBUG
#define DPRINTF(x) printf x
@@ -895,16 +896,38 @@ bdev_open(dev_t dev, int flag, int devty
{
const struct bdevsw *d;
struct localcount *lc;
- int rv, mpflag;
+ device_t dv = NULL/*XXXGCC*/;
+ int unit, rv, mpflag;
d = bdevsw_lookup_acquire(dev, &lc);
if (d == NULL)
return ENXIO;
+ if (d->d_devtounit) {
+ /*
+ * If the device node corresponds to an autoconf device
+ * instance, acquire a reference to it so that during
+ * d_open, device_lookup is stable.
+ *
+ * XXX This should also arrange to instantiate cloning
+ * pseudo-devices if appropriate, but that requires
+ * reviewing them all to find and verify a common
+ * pattern.
+ */
+ if ((unit = (*d->d_devtounit)(dev)) == -1)
+ return ENXIO;
+ if ((dv = device_lookup_acquire(d->d_cfdriver, unit)) == NULL)
+ return ENXIO;
+ }
+
DEV_LOCK(d);
rv = (*d->d_open)(dev, flag, devtype, l);
DEV_UNLOCK(d);
+ if (d->d_devtounit) {
+ device_release(dv);
+ }
+
bdevsw_release(d, lc);
return rv;
@@ -1050,16 +1073,38 @@ cdev_open(dev_t dev, int flag, int devty
{
const struct cdevsw *d;
struct localcount *lc;
- int rv, mpflag;
+ device_t dv = NULL/*XXXGCC*/;
+ int unit, rv, mpflag;
d = cdevsw_lookup_acquire(dev, &lc);
if (d == NULL)
return ENXIO;
+ if (d->d_devtounit) {
+ /*
+ * If the device node corresponds to an autoconf device
+ * instance, acquire a reference to it so that during
+ * d_open, device_lookup is stable.
+ *
+ * XXX This should also arrange to instantiate cloning
+ * pseudo-devices if appropriate, but that requires
+ * reviewing them all to find and verify a common
+ * pattern.
+ */
+ if ((unit = (*d->d_devtounit)(dev)) == -1)
+ return ENXIO;
+ if ((dv = device_lookup_acquire(d->d_cfdriver, unit)) == NULL)
+ return ENXIO;
+ }
+
DEV_LOCK(d);
rv = (*d->d_open)(dev, flag, devtype, l);
DEV_UNLOCK(d);
+ if (d->d_devtounit) {
+ device_release(dv);
+ }
+
cdevsw_release(d, lc);
return rv;
Index: src/sys/sys/conf.h
diff -u src/sys/sys/conf.h:1.155 src/sys/sys/conf.h:1.156
--- src/sys/sys/conf.h:1.155 Mon Mar 28 12:33:22 2022
+++ src/sys/sys/conf.h Mon Mar 28 12:33:50 2022
@@ -1,4 +1,4 @@
-/* $NetBSD: conf.h,v 1.155 2022/03/28 12:33:22 riastradh Exp $ */
+/* $NetBSD: conf.h,v 1.156 2022/03/28 12:33:50 riastradh Exp $ */
/*-
* Copyright (c) 1990, 1993
@@ -76,6 +76,8 @@ struct bdevsw {
int (*d_dump)(dev_t, daddr_t, void *, size_t);
int (*d_psize)(dev_t);
int (*d_discard)(dev_t, off_t, off_t);
+ int (*d_devtounit)(dev_t);
+ struct cfdriver *d_cfdriver;
int d_flag;
};
@@ -94,6 +96,8 @@ struct cdevsw {
paddr_t (*d_mmap)(dev_t, off_t, int);
int (*d_kqfilter)(dev_t, struct knote *);
int (*d_discard)(dev_t, off_t, off_t);
+ int (*d_devtounit)(dev_t);
+ struct cfdriver *d_cfdriver;
int d_flag;
};