DF-2478 / fix.diff
--- /home/maxx/dfbsd/dfbsd/sys/dev/disk/md/md.c 2026-06-29 12:51:18.000000000 +0000 +++ /tmp/opencode/fixtree/sys/dev/disk/md/md.c 2026-10-24 09:24:22.917124000 +0000 @@ -132,7 +132,9 @@ sc = dev->si_drv1; lwkt_gettoken(&sc->tok); - if (sc->unit + 1 == mdunits) + /* cap the auto-create-on-open convenience; explicit creation + * via the ioctls remains unlimited for root */ + if (sc->unit + 1 == mdunits && mdunits < 256) mdcreate_malloc(); atomic_add_int(&refcnt, 1); lwkt_reltoken(&sc->tok); @@ -478,6 +480,20 @@ * itself. */ TAILQ_FOREACH_MUTABLE(sc, &mdlist, link, sc_temp) { + /* + * Drain the device FIRST: destroy_dev() blocks until racing + * mdopen/mdclose have completed and prevents any new open. + * Only then re-check refcnt before freeing -- an mdopen that + * slipped past the unlocked check above either completes + * before the drain (refcnt!=0 -> EBUSY, nothing freed) or is + * rejected by the destroyed cdev. + */ + if (sc->dev != NULL) { + destroy_dev(sc->dev); + sc->dev = NULL; + } + if (atomic_fetchadd_int(&refcnt, 0) != 0) + return EBUSY; for (secno = 0; secno < sc->nsecp; secno++) { if ((u_int)(uintptr_t)sc->secp[secno] > 255) kfree(sc->secp[secno], M_MDSECT); |