dk(4): Set .d_cfdriver and .d_devtounit to plug open/detach race.
This way, opening dkN or rdkN will wait if attach or detach is still in progress, and vdevgone will wake up such pending opens and make them fail. So it is no longer possible for a wedge to be detached after dkopen has already started using it. For now, we use a custom .d_devtounit function that looks up the autoconf unit number via the dkwedges array, which conceivably may use an independent unit numbering system -- nothing guarantees they match up. (In practice they will mostly match up, but concurrent wedge creation could lead to different numbering.) Eventually this should be changed so the two numbering systems match, which would let us delete the new dkunit function and just use dev_minor_unit like many other drivers can.
This commit is contained in:
parent
932706d0fa
commit
5f51c927dc
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: dk.c,v 1.143 2023/04/21 18:30:52 riastradh Exp $ */
|
||||
/* $NetBSD: dk.c,v 1.144 2023/04/21 18:31:00 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004, 2005, 2006, 2007 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.143 2023/04/21 18:30:52 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: dk.c,v 1.144 2023/04/21 18:31:00 riastradh Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_dkwedge.h"
|
||||
|
@ -114,6 +114,8 @@ static int dkwedge_del1(struct dkwedge_info *, int);
|
|||
static int dk_open_parent(dev_t, int, struct vnode **);
|
||||
static int dk_close_parent(struct vnode *, int);
|
||||
|
||||
static int dkunit(dev_t);
|
||||
|
||||
static dev_type_open(dkopen);
|
||||
static dev_type_close(dkclose);
|
||||
static dev_type_cancel(dkcancel);
|
||||
|
@ -139,6 +141,8 @@ const struct bdevsw dk_bdevsw = {
|
|||
.d_dump = dkdump,
|
||||
.d_psize = dksize,
|
||||
.d_discard = dkdiscard,
|
||||
.d_cfdriver = &dk_cd,
|
||||
.d_devtounit = dkunit,
|
||||
.d_flag = D_DISK | D_MPSAFE
|
||||
};
|
||||
|
||||
|
@ -155,6 +159,8 @@ const struct cdevsw dk_cdevsw = {
|
|||
.d_mmap = nommap,
|
||||
.d_kqfilter = nokqfilter,
|
||||
.d_discard = dkdiscard,
|
||||
.d_cfdriver = &dk_cd,
|
||||
.d_devtounit = dkunit,
|
||||
.d_flag = D_DISK | D_MPSAFE
|
||||
};
|
||||
|
||||
|
@ -1216,6 +1222,36 @@ dk_close_parent(struct vnode *vp, int mode)
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* dkunit: [devsw entry point]
|
||||
*
|
||||
* Return the autoconf device_t unit number of a wedge by its
|
||||
* devsw dev_t number, or -1 if there is none.
|
||||
*
|
||||
* XXX This is a temporary hack until dkwedge numbering is made to
|
||||
* correspond 1:1 to autoconf device numbering.
|
||||
*/
|
||||
static int
|
||||
dkunit(dev_t dev)
|
||||
{
|
||||
int mn = minor(dev);
|
||||
struct dkwedge_softc *sc;
|
||||
device_t dv;
|
||||
int unit = -1;
|
||||
|
||||
if (mn < 0)
|
||||
return -1;
|
||||
|
||||
rw_enter(&dkwedges_lock, RW_READER);
|
||||
if (mn < ndkwedges &&
|
||||
(sc = dkwedges[minor(dev)]) != NULL &&
|
||||
(dv = sc->sc_dev) != NULL)
|
||||
unit = device_unit(dv);
|
||||
rw_exit(&dkwedges_lock);
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
/*
|
||||
* dkopen: [devsw entry point]
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue