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; };