Get SIM lock in several places while calling CAM functions.

This fixes several use-after-free panics on systems with SAS enclosures.

Submitted by:	ken@, mav@
This commit is contained in:
Alexander Motin 2012-10-12 18:21:31 +00:00
parent 6884b66275
commit 24a1ba9110
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=241488

View File

@ -886,6 +886,7 @@ ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
struct device_match_result *device_match;
struct device_match_pattern *device_pattern;
ses_path_iter_args_t *args;
struct cam_sim *sim;
args = (ses_path_iter_args_t *)arg;
match_pattern.type = DEV_MATCH_DEVICE;
@ -920,14 +921,18 @@ ses_path_iter_devid_callback(enc_softc_t *enc, enc_element_t *elem,
return;
device_match = &match_result.result.device_result;
if (xpt_create_path(&cdm.ccb_h.path, /*periph*/NULL,
device_match->path_id,
device_match->target_id,
device_match->target_lun) != CAM_REQ_CMP)
if (xpt_create_path_unlocked(&cdm.ccb_h.path, /*periph*/NULL,
device_match->path_id,
device_match->target_id,
device_match->target_lun) != CAM_REQ_CMP)
return;
args->callback(enc, elem, cdm.ccb_h.path, args->callback_arg);
sim = xpt_path_sim(cdm.ccb_h.path);
CAM_SIM_LOCK(sim);
xpt_free_path(cdm.ccb_h.path);
CAM_SIM_UNLOCK(sim);
}
/**
@ -999,7 +1004,7 @@ ses_setphyspath_callback(enc_softc_t *enc, enc_element_t *elm,
args = (ses_setphyspath_callback_args_t *)arg;
old_physpath = malloc(MAXPATHLEN, M_SCSIENC, M_WAITOK|M_ZERO);
cam_periph_lock(enc->periph);
xpt_setup_ccb(&cdai.ccb_h, path, CAM_PRIORITY_NORMAL);
cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
cdai.buftype = CDAI_TYPE_PHYS_PATH;
@ -1024,6 +1029,7 @@ ses_setphyspath_callback(enc_softc_t *enc, enc_element_t *elm,
if (cdai.ccb_h.status == CAM_REQ_CMP)
args->num_set++;
}
cam_periph_unlock(enc->periph);
free(old_physpath, M_SCSIENC);
}
@ -1063,9 +1069,11 @@ ses_set_physpath(enc_softc_t *enc, enc_element_t *elm,
ret = ENOMEM;
goto out;
}
cam_periph_lock(enc->periph);
xpt_action((union ccb *)&cdai);
if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
cam_periph_unlock(enc->periph);
if (cdai.ccb_h.status != CAM_REQ_CMP)
goto out;