summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2015-10-05 09:02:13 +0000
committermav <mav@FreeBSD.org>2015-10-05 09:02:13 +0000
commit94d3cb685bf100c20ee43b91af4d8a3a02a01550 (patch)
treed99e3d2ceb611f8767450c51b61d5b7f8eb497b0 /sys/cam
parent2ae17b4970a1c781d41117245fe9d5c4719962e3 (diff)
downloadFreeBSD-src-94d3cb685bf100c20ee43b91af4d8a3a02a01550.zip
FreeBSD-src-94d3cb685bf100c20ee43b91af4d8a3a02a01550.tar.gz
MFC r287711: Some HA polishing.
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/ctl/ctl.c145
1 files changed, 89 insertions, 56 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 36cadfd..2c0f49a 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -675,7 +675,10 @@ ctl_isc_ha_link_down(struct ctl_softc *softc)
mtx_lock(&softc->ctl_lock);
STAILQ_FOREACH(lun, &softc->lun_list, links) {
mtx_lock(&lun->lun_lock);
- lun->flags &= ~CTL_LUN_PEER_SC_PRIMARY;
+ if (lun->flags & CTL_LUN_PEER_SC_PRIMARY) {
+ lun->flags &= ~CTL_LUN_PEER_SC_PRIMARY;
+ ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
+ }
mtx_unlock(&lun->lun_lock);
mtx_unlock(&softc->ctl_lock);
@@ -702,8 +705,11 @@ ctl_isc_ua(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
struct ctl_lun *lun;
uint32_t iid = ctl_get_initindex(&msg->hdr.nexus);
+ mtx_lock(&softc->ctl_lock);
if (msg->hdr.nexus.targ_lun < CTL_MAX_LUNS &&
- (lun = softc->ctl_luns[msg->hdr.nexus.targ_lun]) != NULL) {
+ (lun = softc->ctl_luns[msg->hdr.nexus.targ_mapped_lun]) != NULL) {
+ mtx_lock(&lun->lun_lock);
+ mtx_unlock(&softc->ctl_lock);
if (msg->ua.ua_all) {
if (msg->ua.ua_set)
ctl_est_ua_all(lun, iid, msg->ua.ua_type);
@@ -715,7 +721,9 @@ ctl_isc_ua(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
else
ctl_clr_ua(lun, iid, msg->ua.ua_type);
}
- }
+ mtx_unlock(&lun->lun_lock);
+ } else
+ mtx_unlock(&softc->ctl_lock);
}
static void
@@ -724,58 +732,69 @@ ctl_isc_lun_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
struct ctl_lun *lun;
struct ctl_ha_msg_lun_pr_key pr_key;
int i, k;
+ ctl_lun_flags oflags;
+ uint32_t targ_lun;
- lun = softc->ctl_luns[msg->hdr.nexus.targ_lun];
- if (lun == NULL) {
- CTL_DEBUG_PRINT(("%s: Unknown LUN %d\n", __func__,
- msg->hdr.nexus.targ_lun));
+ targ_lun = msg->hdr.nexus.targ_mapped_lun;
+ mtx_lock(&softc->ctl_lock);
+ if ((targ_lun >= CTL_MAX_LUNS) ||
+ ((lun = softc->ctl_luns[targ_lun]) == NULL)) {
+ mtx_unlock(&softc->ctl_lock);
+ return;
+ }
+ mtx_lock(&lun->lun_lock);
+ mtx_unlock(&softc->ctl_lock);
+ if (lun->flags & CTL_LUN_DISABLED) {
+ mtx_unlock(&lun->lun_lock);
+ return;
+ }
+ i = (lun->lun_devid != NULL) ? lun->lun_devid->len : 0;
+ if (msg->lun.lun_devid_len != i || (i > 0 &&
+ memcmp(&msg->lun.data[0], lun->lun_devid->data, i) != 0)) {
+ mtx_unlock(&lun->lun_lock);
+ printf("%s: Received conflicting HA LUN %d\n",
+ __func__, msg->hdr.nexus.targ_lun);
+ return;
} else {
- mtx_lock(&lun->lun_lock);
- i = (lun->lun_devid != NULL) ? lun->lun_devid->len : 0;
- if (msg->lun.lun_devid_len != i || (i > 0 &&
- memcmp(&msg->lun.data[0], lun->lun_devid->data, i) != 0)) {
- mtx_unlock(&lun->lun_lock);
- printf("%s: Received conflicting HA LUN %d\n",
- __func__, msg->hdr.nexus.targ_lun);
- return;
- } else {
- /* Record whether peer is primary. */
- if ((msg->lun.flags & CTL_LUN_PRIMARY_SC) &&
- (msg->lun.flags & CTL_LUN_DISABLED) == 0)
- lun->flags |= CTL_LUN_PEER_SC_PRIMARY;
- else
- lun->flags &= ~CTL_LUN_PEER_SC_PRIMARY;
-
- /* If peer is primary and we are not -- use data */
- if ((lun->flags & CTL_LUN_PRIMARY_SC) == 0 &&
- (lun->flags & CTL_LUN_PEER_SC_PRIMARY)) {
- lun->PRGeneration = msg->lun.pr_generation;
- lun->pr_res_idx = msg->lun.pr_res_idx;
- lun->res_type = msg->lun.pr_res_type;
- lun->pr_key_count = msg->lun.pr_key_count;
- for (k = 0; k < CTL_MAX_INITIATORS; k++)
- ctl_clr_prkey(lun, k);
- for (k = 0; k < msg->lun.pr_key_count; k++) {
- memcpy(&pr_key, &msg->lun.data[i],
- sizeof(pr_key));
- ctl_alloc_prkey(lun, pr_key.pr_iid);
- ctl_set_prkey(lun, pr_key.pr_iid,
- pr_key.pr_key);
- i += sizeof(pr_key);
- }
+ /* Record whether peer is primary. */
+ oflags = lun->flags;
+ if ((msg->lun.flags & CTL_LUN_PRIMARY_SC) &&
+ (msg->lun.flags & CTL_LUN_DISABLED) == 0)
+ lun->flags |= CTL_LUN_PEER_SC_PRIMARY;
+ else
+ lun->flags &= ~CTL_LUN_PEER_SC_PRIMARY;
+ if (oflags != lun->flags)
+ ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
+
+ /* If peer is primary and we are not -- use data */
+ if ((lun->flags & CTL_LUN_PRIMARY_SC) == 0 &&
+ (lun->flags & CTL_LUN_PEER_SC_PRIMARY)) {
+ lun->PRGeneration = msg->lun.pr_generation;
+ lun->pr_res_idx = msg->lun.pr_res_idx;
+ lun->res_type = msg->lun.pr_res_type;
+ lun->pr_key_count = msg->lun.pr_key_count;
+ for (k = 0; k < CTL_MAX_INITIATORS; k++)
+ ctl_clr_prkey(lun, k);
+ for (k = 0; k < msg->lun.pr_key_count; k++) {
+ memcpy(&pr_key, &msg->lun.data[i],
+ sizeof(pr_key));
+ ctl_alloc_prkey(lun, pr_key.pr_iid);
+ ctl_set_prkey(lun, pr_key.pr_iid,
+ pr_key.pr_key);
+ i += sizeof(pr_key);
}
+ }
- mtx_unlock(&lun->lun_lock);
- CTL_DEBUG_PRINT(("%s: Known LUN %d, peer is %s\n",
- __func__, msg->hdr.nexus.targ_lun,
- (msg->lun.flags & CTL_LUN_PRIMARY_SC) ?
- "primary" : "secondary"));
+ mtx_unlock(&lun->lun_lock);
+ CTL_DEBUG_PRINT(("%s: Known LUN %d, peer is %s\n",
+ __func__, msg->hdr.nexus.targ_lun,
+ (msg->lun.flags & CTL_LUN_PRIMARY_SC) ?
+ "primary" : "secondary"));
- /* If we are primary but peer doesn't know -- notify */
- if ((lun->flags & CTL_LUN_PRIMARY_SC) &&
- (msg->lun.flags & CTL_LUN_PEER_SC_PRIMARY) == 0)
- ctl_isc_announce_lun(lun);
- }
+ /* If we are primary but peer doesn't know -- notify */
+ if ((lun->flags & CTL_LUN_PRIMARY_SC) &&
+ (msg->lun.flags & CTL_LUN_PEER_SC_PRIMARY) == 0)
+ ctl_isc_announce_lun(lun);
}
}
@@ -1732,20 +1751,24 @@ ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio)
softc = control_softc;
targ_lun = ctsio->io_hdr.nexus.targ_mapped_lun;
+ mtx_lock(&softc->ctl_lock);
if ((targ_lun < CTL_MAX_LUNS) &&
((lun = softc->ctl_luns[targ_lun]) != NULL)) {
+ mtx_lock(&lun->lun_lock);
+ mtx_unlock(&softc->ctl_lock);
/*
* If the LUN is invalid, pretend that it doesn't exist.
* It will go away as soon as all pending I/O has been
* completed.
*/
- mtx_lock(&lun->lun_lock);
if (lun->flags & CTL_LUN_DISABLED) {
mtx_unlock(&lun->lun_lock);
lun = NULL;
}
- } else
+ } else {
+ mtx_unlock(&softc->ctl_lock);
lun = NULL;
+ }
if (lun == NULL) {
/*
* The other node would not send this request to us unless
@@ -2516,6 +2539,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
if (lun == NULL) {
mtx_unlock(&softc->ctl_lock);
sync_info->status = CTL_GS_SYNC_NO_LUN;
+ break;
}
/*
* Get or set the sync interval. We're not bounds checking
@@ -4533,8 +4557,8 @@ ctl_lun_primary(struct ctl_be_lun *be_lun)
mtx_lock(&lun->lun_lock);
lun->flags |= CTL_LUN_PRIMARY_SC;
- mtx_unlock(&lun->lun_lock);
ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
+ mtx_unlock(&lun->lun_lock);
ctl_isc_announce_lun(lun);
return (0);
}
@@ -4546,8 +4570,8 @@ ctl_lun_secondary(struct ctl_be_lun *be_lun)
mtx_lock(&lun->lun_lock);
lun->flags &= ~CTL_LUN_PRIMARY_SC;
- mtx_unlock(&lun->lun_lock);
ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
+ mtx_unlock(&lun->lun_lock);
ctl_isc_announce_lun(lun);
return (0);
}
@@ -8385,10 +8409,19 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
uint32_t targ_lun;
softc = control_softc;
-
targ_lun = msg->hdr.nexus.targ_mapped_lun;
- lun = softc->ctl_luns[targ_lun];
+ mtx_lock(&softc->ctl_lock);
+ if ((targ_lun >= CTL_MAX_LUNS) ||
+ ((lun = softc->ctl_luns[targ_lun]) == NULL)) {
+ mtx_unlock(&softc->ctl_lock);
+ return;
+ }
mtx_lock(&lun->lun_lock);
+ mtx_unlock(&softc->ctl_lock);
+ if (lun->flags & CTL_LUN_DISABLED) {
+ mtx_unlock(&lun->lun_lock);
+ return;
+ }
switch(msg->pr.pr_info.action) {
case CTL_PR_REG_KEY:
ctl_alloc_prkey(lun, msg->pr.pr_info.residx);
OpenPOWER on IntegriCloud