diff --git a/sys/dev/disk/nata/atapi-fd.c b/sys/dev/disk/nata/atapi-fd.c --- a/sys/dev/disk/nata/atapi-fd.c +++ b/sys/dev/disk/nata/atapi-fd.c @@ -173,6 +173,16 @@ if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) || ((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) { + /* The device vanished during channel reset. Previously this only did + * device_set_ivars(NULL)+kfree(), orphaning the disk, devstat and + * /dev/afdN cdev with dangling pointers into freed memory (the later + * afd_detach early-returns ENXIO on the NULL ivars and skips all + * cleanup). Tear down properly here, mirroring afd_detach, so nothing + * references the freed softc. See DF-2507. */ + disk_invalidate(&fdp->disk); + disk_destroy(&fdp->disk); + ata_fail_requests(dev); + devstat_remove_entry(&fdp->stats); device_set_ivars(dev, NULL); kfree(fdp, M_AFD); return 1;