DF-4529 / nvmedetach.c
/* * nvmedetach.c -- DF-4528/DF-4529 PoC trigger (TEST ONLY, never for sys/). * * MOD_LOAD: device_detach() nvme unit 0 -> runs nvme_pci_detach() * MOD_UNLOAD: device_attach() nvme unit 0 -> re-runs the full attach * (identify controller / make queues / identify namespaces * admin-command storm) * * This simulates, deterministically, what a PCI hot-unplug / surprise * removal (or hot-plug) does to the driver while user processes hold the * namespace devices open and are issuing NVMEIOCGETLOG ioctls. */ #include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/bus.h> static devclass_t nvme_dc; static int nvmedetach_handler(module_t mod, int what, void *arg) { device_t dev; int error; switch (what) { case MOD_LOAD: nvme_dc = devclass_find("nvme"); if (nvme_dc == NULL) { kprintf("nvmedetach: devclass 'nvme' not found\n"); return (ENOENT); } dev = devclass_get_device(nvme_dc, 0); if (dev == NULL) { kprintf("nvmedetach: nvme0 not present\n"); return (ENOENT); } kprintf("nvmedetach: DETACH %s%d ...\n", device_get_name(dev), device_get_unit(dev)); error = device_detach(dev); kprintf("nvmedetach: DETACH done error=%d\n", error); return (0); case MOD_UNLOAD: if (nvme_dc == NULL) { kprintf("nvmedetach: no devclass on unload\n"); return (0); } dev = devclass_get_device(nvme_dc, 0); if (dev == NULL) { kprintf("nvmedetach: no unit 0 on unload\n"); return (0); } kprintf("nvmedetach: ATTACH %s%d ...\n", device_get_name(dev), device_get_unit(dev)); error = device_probe_and_attach(dev); kprintf("nvmedetach: ATTACH done error=%d\n", error); return (0); default: return (0); } /* NOTREACHED */ } static moduledata_t nvmedetach_mod = { "nvmedetach", nvmedetach_handler, NULL }; DECLARE_MODULE(nvmedetach, nvmedetach_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); MODULE_VERSION(nvmedetach, 1); |