From 1da659edbaf30e8c96e76831ef92f93392e01aa8 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 2 Jan 2017 18:48:11 -0800 Subject: [PATCH] cam - Fix bus registration race * Fix bus registration race. This race could only occur when hw.ahci.synchronous_boot is set to 0 (it defaults to 1). --- sys/bus/cam/cam_xpt.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sys/bus/cam/cam_xpt.c b/sys/bus/cam/cam_xpt.c index 6d47429aa2..5f339c55c4 100644 --- a/sys/bus/cam/cam_xpt.c +++ b/sys/bus/cam/cam_xpt.c @@ -4294,6 +4294,11 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus) sim->bus_id = bus; new_bus = kmalloc(sizeof(*new_bus), M_CAMXPT, M_INTWAIT); + /* + * Must hold topo lock across xptpathid() through installation of + * new_bus to avoid duplication due to SMP races. + */ + lockmgr(&xsoftc.xpt_topo_lock, LK_EXCLUSIVE); if (strcmp(sim->sim_name, "xpt") != 0) { sim->path_id = xptpathid(sim->sim_name, sim->unit_number, sim->bus_id); @@ -4308,10 +4313,8 @@ xpt_bus_register(struct cam_sim *sim, u_int32_t bus) new_bus->refcount = 1; /* Held until a bus_deregister event */ new_bus->generation = 0; new_bus->counted_to_config = 0; - lockmgr(&xsoftc.xpt_topo_lock, LK_EXCLUSIVE); old_bus = TAILQ_FIRST(&xsoftc.xpt_busses); - while (old_bus != NULL - && old_bus->path_id < new_bus->path_id) + while (old_bus != NULL && old_bus->path_id < new_bus->path_id) old_bus = TAILQ_NEXT(old_bus, links); if (old_bus != NULL) TAILQ_INSERT_BEFORE(old_bus, new_bus, links); @@ -4469,6 +4472,9 @@ again: return (CAM_REQ_CMP); } +/* + * Must be called with xpt_topo_lock held. + */ static path_id_t xptnextfreepathid(void) { @@ -4477,7 +4483,6 @@ xptnextfreepathid(void) const char *strval; pathid = 0; - lockmgr(&xsoftc.xpt_topo_lock, LK_EXCLUSIVE); bus = TAILQ_FIRST(&xsoftc.xpt_busses); retry: /* Find an unoccupied pathid */ @@ -4486,7 +4491,6 @@ retry: pathid++; bus = TAILQ_NEXT(bus, links); } - lockmgr(&xsoftc.xpt_topo_lock, LK_RELEASE); /* * Ensure that this pathid is not reserved for @@ -4495,12 +4499,14 @@ retry: if (resource_string_value("scbus", pathid, "at", &strval) == 0) { ++pathid; /* Start the search over */ - lockmgr(&xsoftc.xpt_topo_lock, LK_EXCLUSIVE); goto retry; } return (pathid); } +/* + * Must be called with xpt_topo_lock held. + */ static path_id_t xptpathid(const char *sim_name, int sim_unit, int sim_bus) { -- 2.41.0