diff options
| author | hannken <hannken@NetBSD.org> | 2021-05-07 09:54:43 +0000 |
|---|---|---|
| committer | hannken <hannken@NetBSD.org> | 2021-05-07 09:54:43 +0000 |
| commit | aab45de7dcbd7ffd55af5588d190c41166c3418e (patch) | |
| tree | f138be22b626718c145b5cdab587446c7e3d5e8b /sys/dev | |
| parent | 6aca380d1ffb70376609f44d541ac9f312dfbe24 (diff) | |
Track the number of cdev and bdev opens and fail dm_detach()
on open devices unless detach is forced.
PR kern/54969 (Disk cache is no longer flushed on shutdown)
Diffstat (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/dm/device-mapper.c | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/sys/dev/dm/device-mapper.c b/sys/dev/dm/device-mapper.c index 22f6e2db6fb..bdd17f60f62 100644 --- a/sys/dev/dm/device-mapper.c +++ b/sys/dev/dm/device-mapper.c @@ -1,4 +1,4 @@ -/* $NetBSD: device-mapper.c,v 1.61 2020/07/08 15:07:13 thorpej Exp $ */ +/* $NetBSD: device-mapper.c,v 1.62 2021/05/07 09:54:43 hannken Exp $ */ /* * Copyright (c) 2010 The NetBSD Foundation, Inc. @@ -260,8 +260,17 @@ dm_attach(device_t parent, device_t self, void *aux) static int dm_detach(device_t self, int flags) { + bool busy; dm_dev_t *dmv; + dmv = dm_dev_lookup(NULL, NULL, device_unit(self)); + mutex_enter(&dmv->diskp->dk_openlock); + busy = (dmv->diskp->dk_openmask != 0 && (flags & DETACH_FORCE) == 0); + mutex_exit(&dmv->diskp->dk_openlock); + dm_dev_unbusy(dmv); + if (busy) + return EBUSY; + pmf_device_deregister(self); /* Detach device from global device list */ @@ -334,6 +343,25 @@ dmdestroy(void) static int dmopen(dev_t dev, int flags, int mode, struct lwp *l) { + dm_dev_t *dmv; + struct disk *dk; + + dmv = dm_dev_lookup(NULL, NULL, minor(dev)); + if (dmv) { + dk = dmv->diskp; + mutex_enter(&dk->dk_openlock); + switch (mode) { + case S_IFCHR: + dk->dk_copenmask |= 1; + break; + case S_IFBLK: + dk->dk_bopenmask |= 1; + break; + } + dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; + mutex_exit(&dk->dk_openlock); + dm_dev_unbusy(dmv); + } aprint_debug("dm open routine called %" PRIu32 "\n", minor(dev)); return 0; @@ -342,8 +370,27 @@ dmopen(dev_t dev, int flags, int mode, struct lwp *l) static int dmclose(dev_t dev, int flags, int mode, struct lwp *l) { + dm_dev_t *dmv; + struct disk *dk; aprint_debug("dm close routine called %" PRIu32 "\n", minor(dev)); + + dmv = dm_dev_lookup(NULL, NULL, minor(dev)); + if (dmv) { + dk = dmv->diskp; + mutex_enter(&dk->dk_openlock); + switch (mode) { + case S_IFCHR: + dk->dk_copenmask &= ~1; + break; + case S_IFBLK: + dk->dk_bopenmask &= ~1; + break; + } + dk->dk_openmask = dk->dk_copenmask | dk->dk_bopenmask; + mutex_exit(&dk->dk_openlock); + dm_dev_unbusy(dmv); + } return 0; } |
