cgd(4): Fix criterion for detach when wedgies are held.
The somewhat confusingly named DK_BUSY(dksc, pmask) answers the following question: Suppose I hold either the character or the block device (but not both) of all of the partitions in pmask. Is anyone else using the disk, rendering it unsafe to detach? This is useful for ioctls like CGDIOCCLR and VNDIOCCLR, which must be issued on open file descriptors for the disk, so the question cannot simply be answered by testing whether dk_openmask != 0. Instead, DK_BUSY breaks the question into the following criteria: 1. Are there any _other_ partitions than those in pmask open at all? If so, it must be someone else, since I only hold partitions in pmask -- hence the disk is busy. 2. Are any of the partitions in pmask open _both_ as a block device _and_ as a character device? If so, it must be someone else, since I only hold _either_ the character _or_ the block device open but not both -- hence the disk is busy. When config_detach_all runs at shutdown time, it tries to detach cgd(4), which has DVF_DETACH_SHUTDOWN; this is important so we submit queued writes to the underlying disk and wait for them to complete with dk_drain. If cgd(4) has any dk wedges with file systems mounted still configured on it, it isn't ready to detach yet. But asking DK_BUSY(dksc, 1 << RAW_PART) returns false, because the dk wedges only hold RAW_PART open as a block device -- so if nobody has RAW_PART open as a character device, or any other partitions open, cgd_detach blithely goes on its way to forcibly detach the wedges. Instead, ask DK_BUSY(dksc, 0), because the caller -- cgd_detach issued by config_detach_all -- does not, in fact, hold any partitions open, so it doesn't need to work around them like ioctl(CGDIOCCLR) does. Fixes hang in zfs on dk on cgd during shutdown (and probably also zfs on cgd without any intervening dk but I haven't tested). (This change might have the side effect that `drvctl -d cgdN' doesn't work, but I don't care.) XXX pullup-9 XXX pullup-8 (...-7, -6, -5...)
This commit is contained in:
parent
069962538c
commit
4a85b256a6
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: cgd.c,v 1.141 2021/12/13 21:15:26 riastradh Exp $ */
|
||||
/* $NetBSD: cgd.c,v 1.142 2021/12/27 22:57:19 riastradh Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
|
@ -30,7 +30,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.141 2021/12/13 21:15:26 riastradh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.142 2021/12/27 22:57:19 riastradh Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -529,11 +529,10 @@ static int
|
|||
cgd_detach(device_t self, int flags)
|
||||
{
|
||||
int ret;
|
||||
const int pmask = 1 << RAW_PART;
|
||||
struct cgd_softc *sc = device_private(self);
|
||||
struct dk_softc *dksc = &sc->sc_dksc;
|
||||
|
||||
if (DK_BUSY(dksc, pmask))
|
||||
if (DK_BUSY(dksc, 0))
|
||||
return EBUSY;
|
||||
|
||||
if (DK_ATTACHED(dksc) &&
|
||||
|
|
Loading…
Reference in New Issue