DF-4751 / fix.diff
--- a/sys/dev/disk/dm/device-mapper.c +++ b/sys/dev/disk/dm/device-mapper.c @@ -153,14 +153,19 @@ case MOD_UNLOAD: /* - * Disable unloading of dm module if there are any devices - * defined in driver. This is probably too strong we need - * to disable auto-unload only if there is mounted dm device - * present. + * Quiesce the control device first: destroy_dev() drains + * in-flight ioctls, so once it returns no NETBSD_DM_IOCTL + * can be running and dm_dev_counter is stable for the + * check below. */ - if (dm_dev_counter > 0) + destroy_dev(dmcdev); + sync_devs(); + if (dm_dev_counter > 0) { + /* A device snuck in before/during the drain: re-arm. */ + dmcdev = make_dev(&dmctl_ops, 0, UID_ROOT, + GID_OPERATOR, 0640, "mapper/control"); return EBUSY; - /* race window here */ + } error = dmdestroy(); if (error) @@ -187,12 +192,16 @@ static int dmdestroy(void) { - destroy_dev(dmcdev); - + /* dmcdev was already destroyed by MOD_UNLOAD before the counter + * check, so in-flight control ioctls have drained. */ dm_dev_uninit(); dm_pdev_uninit(); dm_target_uninit(); + /* wait for async devfs destroy of the block devices' cdevsw + * revectors before the module text goes away */ + sync_devs(); + return 0; } |