summaryrefslogtreecommitdiffstats
path: root/sys/cam/cam_xpt.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2013-10-09 12:09:01 +0000
committermav <mav@FreeBSD.org>2013-10-09 12:09:01 +0000
commitc05499893942c2cd7104f917c5f6ddc9e789d867 (patch)
treef23b86ab0243d0ba21c222a05337c797ec16be42 /sys/cam/cam_xpt.c
parent06b2736d4dfaa5318b8ede11b53fd03efe9e59b1 (diff)
downloadFreeBSD-src-c05499893942c2cd7104f917c5f6ddc9e789d867.zip
FreeBSD-src-c05499893942c2cd7104f917c5f6ddc9e789d867.tar.gz
Close the race on path ID allocation in xpt_bus_register() if two buses are
registered simultaneously. Due to topology unlock between the ID allocation and the bus registration there is a chance that two buses may get the same IDs. That is supposed reason of lock assertion panic in CAM during initial bus scanning after new iscsid initiates two sessions same time. Reported by: trasz Approved by: re (glebus, marius) MFC after: 2 weeks
Diffstat (limited to 'sys/cam/cam_xpt.c')
-rw-r--r--sys/cam/cam_xpt.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 142195b..01025ff 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -2415,7 +2415,7 @@ xptsetasyncbusfunc(struct cam_eb *bus, void *arg)
struct ccb_setasync *csa = (struct ccb_setasync *)arg;
xpt_compile_path(&path, /*periph*/NULL,
- bus->sim->path_id,
+ bus->path_id,
CAM_TARGET_WILDCARD,
CAM_LUN_WILDCARD);
xpt_setup_ccb(&cpi.ccb_h, &path, CAM_PRIORITY_NORMAL);
@@ -3840,13 +3840,8 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
/* Couldn't satisfy request */
return (CAM_RESRC_UNAVAIL);
}
- if (strcmp(sim->sim_name, "xpt") != 0) {
- sim->path_id =
- xptpathid(sim->sim_name, sim->unit_number, sim->bus_id);
- }
TAILQ_INIT(&new_bus->et_entries);
- new_bus->path_id = sim->path_id;
cam_sim_hold(sim);
new_bus->sim = sim;
timevalclear(&new_bus->last_reset);
@@ -3855,6 +3850,8 @@ xpt_bus_register(struct cam_sim *sim, device_t parent, u_int32_t bus)
new_bus->generation = 0;
xpt_lock_buses();
+ sim->path_id = new_bus->path_id =
+ xptpathid(sim->sim_name, sim->unit_number, sim->bus_id);
old_bus = TAILQ_FIRST(&xsoftc.xpt_busses);
while (old_bus != NULL
&& old_bus->path_id < new_bus->path_id)
@@ -3958,8 +3955,8 @@ xptnextfreepathid(void)
path_id_t pathid;
const char *strval;
+ mtx_assert(&xsoftc.xpt_topo_lock, MA_OWNED);
pathid = 0;
- xpt_lock_buses();
bus = TAILQ_FIRST(&xsoftc.xpt_busses);
retry:
/* Find an unoccupied pathid */
@@ -3968,7 +3965,6 @@ retry:
pathid++;
bus = TAILQ_NEXT(bus, links);
}
- xpt_unlock_buses();
/*
* Ensure that this pathid is not reserved for
@@ -3977,7 +3973,6 @@ retry:
if (resource_string_value("scbus", pathid, "at", &strval) == 0) {
++pathid;
/* Start the search over */
- xpt_lock_buses();
goto retry;
}
return (pathid);
@@ -3993,6 +3988,8 @@ xptpathid(const char *sim_name, int sim_unit, int sim_bus)
pathid = CAM_XPT_PATH_ID;
snprintf(buf, sizeof(buf), "%s%d", sim_name, sim_unit);
+ if (strcmp(buf, "xpt0") == 0 && sim_bus == 0)
+ return (pathid);
i = 0;
while ((resource_find_match(&i, &dname, &dunit, "at", buf)) == 0) {
if (strcmp(dname, "scbus")) {
OpenPOWER on IntegriCloud