summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-12-18 08:32:06 +0000
committermav <mav@FreeBSD.org>2014-12-18 08:32:06 +0000
commit510c6d695ec3a76a46b39d6c063d09af2a472322 (patch)
treed61ddc3414e7a1abf3485a49515b84ed269b32c5
parente998495ddf03720f4a0985e1e540e3a472dd88ef (diff)
downloadFreeBSD-src-510c6d695ec3a76a46b39d6c063d09af2a472322.zip
FreeBSD-src-510c6d695ec3a76a46b39d6c063d09af2a472322.tar.gz
MFC r275458:
Do not pre-allocate UNIT ATTENTIONs storage for every possible initiator. Abusing ability of major UAs cover minor ones we may not account UAs for inactive ports. Allocate UAs storage for port and start accounting only after some initiator from that port fetched its first POWER ON OCCURRED. This reduces per-LUN CTL memory usage from >1MB to less then 100K.
-rw-r--r--sys/cam/ctl/ctl.c230
-rw-r--r--sys/cam/ctl/ctl_error.c31
-rw-r--r--sys/cam/ctl/ctl_error.h6
-rw-r--r--sys/cam/ctl/ctl_private.h2
4 files changed, 141 insertions, 128 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index fca226d..c9d716e 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -964,12 +964,70 @@ ctl_copy_sense_data(union ctl_ha_msg *src, union ctl_io *dest)
dest->io_hdr.status = src->hdr.status;
}
+static void
+ctl_est_ua(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua)
+{
+ ctl_ua_type *pu;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ pu = lun->pending_ua[initidx / CTL_MAX_INIT_PER_PORT];
+ if (pu == NULL)
+ return;
+ pu[initidx % CTL_MAX_INIT_PER_PORT] |= ua;
+}
+
+static void
+ctl_est_ua_all(struct ctl_lun *lun, uint32_t except, ctl_ua_type ua)
+{
+ int i, j;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ for (i = 0; i < CTL_MAX_PORTS; i++) {
+ if (lun->pending_ua[i] == NULL)
+ continue;
+ for (j = 0; j < CTL_MAX_INIT_PER_PORT; j++) {
+ if (i * CTL_MAX_INIT_PER_PORT + j == except)
+ continue;
+ lun->pending_ua[i][j] |= ua;
+ }
+ }
+}
+
+static void
+ctl_clr_ua(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua)
+{
+ ctl_ua_type *pu;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ pu = lun->pending_ua[initidx / CTL_MAX_INIT_PER_PORT];
+ if (pu == NULL)
+ return;
+ pu[initidx % CTL_MAX_INIT_PER_PORT] &= ~ua;
+}
+
+static void
+ctl_clr_ua_all(struct ctl_lun *lun, uint32_t except, ctl_ua_type ua)
+{
+ int i, j;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ for (i = 0; i < CTL_MAX_PORTS; i++) {
+ if (lun->pending_ua[i] == NULL)
+ continue;
+ for (j = 0; j < CTL_MAX_INIT_PER_PORT; j++) {
+ if (i * CTL_MAX_INIT_PER_PORT + j == except)
+ continue;
+ lun->pending_ua[i][j] &= ~ua;
+ }
+ }
+}
+
static int
ctl_ha_state_sysctl(SYSCTL_HANDLER_ARGS)
{
struct ctl_softc *softc = (struct ctl_softc *)arg1;
struct ctl_lun *lun;
- int error, value, i;
+ int error, value;
if (softc->flags & CTL_FLAG_ACTIVE_SHELF)
value = 0;
@@ -987,8 +1045,7 @@ ctl_ha_state_sysctl(SYSCTL_HANDLER_ARGS)
softc->flags &= ~CTL_FLAG_ACTIVE_SHELF;
STAILQ_FOREACH(lun, &softc->lun_list, links) {
mtx_lock(&lun->lun_lock);
- for (i = 0; i < CTL_MAX_INITIATORS; i++)
- lun->pending_ua[i] |= CTL_UA_ASYM_ACC_CHANGE;
+ ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
mtx_unlock(&lun->lun_lock);
}
mtx_unlock(&softc->ctl_lock);
@@ -4549,19 +4606,13 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
ctl_init_log_page_index(lun);
/*
- * Set the poweron UA for all initiators on this LUN only.
- */
- for (i = 0; i < CTL_MAX_INITIATORS; i++)
- lun->pending_ua[i] = CTL_UA_POWERON;
-
- /*
* Now, before we insert this lun on the lun list, set the lun
* inventory changed UA for all other luns.
*/
STAILQ_FOREACH(nlun, &ctl_softc->lun_list, links) {
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- nlun->pending_ua[i] |= CTL_UA_LUN_CHANGE;
- }
+ mtx_lock(&nlun->lun_lock);
+ ctl_est_ua_all(nlun, -1, CTL_UA_LUN_CHANGE);
+ mtx_unlock(&nlun->lun_lock);
}
STAILQ_INSERT_TAIL(&ctl_softc->lun_list, lun, links);
@@ -4696,18 +4747,18 @@ ctl_free_lun(struct ctl_lun *lun)
ctl_tpc_lun_shutdown(lun);
mtx_destroy(&lun->lun_lock);
free(lun->lun_devid, M_CTL);
- for (i = 0; i < 2 * CTL_MAX_PORTS; i++) {
- if (lun->pr_keys[i] != NULL)
- free(lun->pr_keys[i], M_CTL);
- }
+ for (i = 0; i < CTL_MAX_PORTS; i++)
+ free(lun->pending_ua[i], M_CTL);
+ for (i = 0; i < 2 * CTL_MAX_PORTS; i++)
+ free(lun->pr_keys[i], M_CTL);
free(lun->write_buffer, M_CTL);
if (lun->flags & CTL_LUN_MALLOCED)
free(lun, M_CTL);
STAILQ_FOREACH(nlun, &softc->lun_list, links) {
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- nlun->pending_ua[i] |= CTL_UA_LUN_CHANGE;
- }
+ mtx_lock(&nlun->lun_lock);
+ ctl_est_ua_all(nlun, -1, CTL_UA_LUN_CHANGE);
+ mtx_unlock(&nlun->lun_lock);
}
return (0);
@@ -4985,19 +5036,10 @@ ctl_lun_operable(struct ctl_be_lun *be_lun)
void
ctl_lun_capacity_changed(struct ctl_be_lun *be_lun)
{
- struct ctl_lun *lun;
- struct ctl_softc *softc;
- int i;
-
- softc = control_softc;
-
- lun = (struct ctl_lun *)be_lun->ctl_lun;
+ struct ctl_lun *lun = (struct ctl_lun *)be_lun->ctl_lun;
mtx_lock(&lun->lun_lock);
-
- for (i = 0; i < CTL_MAX_INITIATORS; i++)
- lun->pending_ua[i] |= CTL_UA_CAPACITY_CHANGED;
-
+ ctl_est_ua_all(lun, -1, CTL_UA_CAPACITY_CHANGED);
mtx_unlock(&lun->lun_lock);
}
@@ -6045,19 +6087,8 @@ ctl_control_page_handler(struct ctl_scsiio *ctsio,
saved_cp->eca_and_aen |= user_cp->eca_and_aen & SCP_SWP;
set_ua = 1;
}
- if (set_ua != 0) {
- int i;
- /*
- * Let other initiators know that the mode
- * parameters for this LUN have changed.
- */
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- if (i == initidx)
- continue;
-
- lun->pending_ua[i] |= CTL_UA_MODE_CHANGE;
- }
- }
+ if (set_ua != 0)
+ ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE);
mtx_unlock(&lun->lun_lock);
return (0);
@@ -6093,19 +6124,8 @@ ctl_caching_sp_handler(struct ctl_scsiio *ctsio,
saved_cp->flags1 |= user_cp->flags1 & (SCP_WCE | SCP_RCD);
set_ua = 1;
}
- if (set_ua != 0) {
- int i;
- /*
- * Let other initiators know that the mode
- * parameters for this LUN have changed.
- */
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- if (i == initidx)
- continue;
-
- lun->pending_ua[i] |= CTL_UA_MODE_CHANGE;
- }
- }
+ if (set_ua != 0)
+ ctl_est_ua_all(lun, initidx, CTL_UA_MODE_CHANGE);
mtx_unlock(&lun->lun_lock);
return (0);
@@ -7893,7 +7913,7 @@ ctl_set_res_ua(struct ctl_lun *lun, uint32_t residx, ctl_ua_type ua)
int off = lun->ctl_softc->persis_offset;
if (residx >= off && residx < off + CTL_MAX_INITIATORS)
- lun->pending_ua[residx - off] |= ua;
+ ctl_est_ua(lun, residx - off, ua);
}
/*
@@ -8435,8 +8455,8 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
if (ctl_get_prkey(lun, i +
softc->persis_offset) == 0)
continue;
- lun->pending_ua[i] |=
- CTL_UA_RES_RELEASE;
+ ctl_est_ua(lun, i,
+ CTL_UA_RES_RELEASE);
}
}
lun->res_type = 0;
@@ -8584,7 +8604,7 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
ctl_get_prkey(lun,
i + softc->persis_offset) == 0)
continue;
- lun->pending_ua[i] |= CTL_UA_RES_RELEASE;
+ ctl_est_ua(lun, i, CTL_UA_RES_RELEASE);
}
}
mtx_unlock(&lun->lun_lock);
@@ -8703,8 +8723,7 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
softc->persis_offset) == 0)
continue;
- lun->pending_ua[i] |=
- CTL_UA_RES_RELEASE;
+ ctl_est_ua(lun, i, CTL_UA_RES_RELEASE);
}
}
lun->res_type = 0;
@@ -8734,8 +8753,7 @@ ctl_hndl_per_res_out_on_other_sc(union ctl_ha_msg *msg)
&& lun->res_type != SPR_TYPE_WR_EX) {
for (i = 0; i < CTL_MAX_INITIATORS; i++)
if (ctl_get_prkey(lun, i + softc->persis_offset) != 0)
- lun->pending_ua[i] |=
- CTL_UA_RES_RELEASE;
+ ctl_est_ua(lun, i, CTL_UA_RES_RELEASE);
}
lun->flags &= ~CTL_LUN_PR_RESERVED;
@@ -9308,7 +9326,7 @@ ctl_report_luns(struct ctl_scsiio *ctsio)
*/
if (request_lun != NULL) {
mtx_lock(&lun->lun_lock);
- lun->pending_ua[initidx] &= ~CTL_UA_LUN_CHANGE;
+ ctl_clr_ua(lun, initidx, CTL_UA_RES_RELEASE);
mtx_unlock(&lun->lun_lock);
}
}
@@ -9363,6 +9381,7 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
uint32_t initidx;
int have_error;
scsi_sense_data_type sense_format;
+ ctl_ua_type ua_type;
cdb = (struct scsi_request_sense *)ctsio->cdb;
@@ -9447,11 +9466,8 @@ ctl_request_sense(struct ctl_scsiio *ctsio)
have_error = 1;
} else
#endif
- if (lun->pending_ua[initidx] != CTL_UA_NONE) {
- ctl_ua_type ua_type;
-
- ua_type = ctl_build_ua(&lun->pending_ua[initidx],
- sense_ptr, sense_format);
+ {
+ ua_type = ctl_build_ua(lun, initidx, sense_ptr, sense_format);
if (ua_type != CTL_UA_NONE)
have_error = 1;
}
@@ -11122,7 +11138,6 @@ ctl_failover(void)
union ctl_io *next_io, *pending_io;
union ctl_io *io;
int lun_idx;
- int i;
ctl_softc = control_softc;
@@ -11257,13 +11272,7 @@ ctl_failover(void)
}
}
- /*
- * Build Unit Attention
- */
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- lun->pending_ua[i] |=
- CTL_UA_ASYM_ACC_CHANGE;
- }
+ ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
} else if (((lun->flags & CTL_LUN_PRIMARY_SC) == 0)
&& (ctl_softc->ha_mode == CTL_HA_MODE_SER_ONLY)) {
printf("FAILOVER: secondary lun %d\n", lun_idx);
@@ -11352,13 +11361,7 @@ ctl_failover(void)
}
}
- /*
- * Build Unit Attention
- */
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- lun->pending_ua[i] |=
- CTL_UA_ASYM_ACC_CHANGE;
- }
+ ctl_est_ua_all(lun, -1, CTL_UA_ASYM_ACC_CHANGE);
} else {
panic("Unhandled HA mode failover, LUN flags = %#x, "
"ha_mode = #%x", lun->flags, ctl_softc->ha_mode);
@@ -11494,28 +11497,22 @@ ctl_scsiio_precheck(struct ctl_softc *ctl_softc, struct ctl_scsiio *ctsio)
*/
if ((entry->flags & CTL_CMD_FLAG_NO_SENSE) == 0) {
ctl_ua_type ua_type;
+ scsi_sense_data_type sense_format;
- if (lun->pending_ua[initidx] != CTL_UA_NONE) {
- scsi_sense_data_type sense_format;
+ if (lun->flags & CTL_LUN_SENSE_DESC)
+ sense_format = SSD_TYPE_DESC;
+ else
+ sense_format = SSD_TYPE_FIXED;
- if (lun != NULL)
- sense_format = (lun->flags &
- CTL_LUN_SENSE_DESC) ? SSD_TYPE_DESC :
- SSD_TYPE_FIXED;
- else
- sense_format = SSD_TYPE_FIXED;
-
- ua_type = ctl_build_ua(&lun->pending_ua[initidx],
- &ctsio->sense_data, sense_format);
- if (ua_type != CTL_UA_NONE) {
- ctsio->scsi_status = SCSI_STATUS_CHECK_COND;
- ctsio->io_hdr.status = CTL_SCSI_ERROR |
- CTL_AUTOSENSE;
- ctsio->sense_len = SSD_FULL_SIZE;
- mtx_unlock(&lun->lun_lock);
- ctl_done((union ctl_io *)ctsio);
- return (retval);
- }
+ ua_type = ctl_build_ua(lun, initidx, &ctsio->sense_data,
+ sense_format);
+ if (ua_type != CTL_UA_NONE) {
+ mtx_unlock(&lun->lun_lock);
+ ctsio->scsi_status = SCSI_STATUS_CHECK_COND;
+ ctsio->io_hdr.status = CTL_SCSI_ERROR | CTL_AUTOSENSE;
+ ctsio->sense_len = SSD_FULL_SIZE;
+ ctl_done((union ctl_io *)ctsio);
+ return (retval);
}
}
@@ -11794,7 +11791,9 @@ ctl_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
#if 0
uint32_t initidx;
#endif
+#ifdef CTL_WITH_CA
int i;
+#endif
mtx_lock(&lun->lun_lock);
/*
@@ -11813,11 +11812,9 @@ ctl_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
*/
#if 0
initidx = ctl_get_initindex(&io->io_hdr.nexus);
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
- if (initidx == i)
- continue;
- lun->pending_ua[i] |= ua_type;
- }
+ ctl_est_ua_all(lun, initidx, ua_type);
+#else
+ ctl_est_ua_all(lun, -1, ua_type);
#endif
/*
@@ -11830,12 +11827,10 @@ ctl_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
*/
lun->flags &= ~CTL_LUN_RESERVED;
- for (i = 0; i < CTL_MAX_INITIATORS; i++) {
#ifdef CTL_WITH_CA
+ for (i = 0; i < CTL_MAX_INITIATORS; i++)
ctl_clear_mask(lun->have_ca, i);
#endif
- lun->pending_ua[i] |= ua_type;
- }
mtx_unlock(&lun->lun_lock);
return (0);
@@ -11937,7 +11932,7 @@ ctl_i_t_nexus_reset(union ctl_io *io)
#endif
if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == residx))
lun->flags &= ~CTL_LUN_RESERVED;
- lun->pending_ua[initidx] |= CTL_UA_I_T_NEXUS_LOSS;
+ ctl_est_ua(lun, initidx, CTL_UA_I_T_NEXUS_LOSS);
mtx_unlock(&lun->lun_lock);
}
mtx_unlock(&softc->ctl_lock);
@@ -13953,14 +13948,11 @@ ctl_thresh_thread(void *arg)
if (lun->lasttpt == 0 ||
time_uptime - lun->lasttpt >= CTL_LBP_UA_PERIOD) {
lun->lasttpt = time_uptime;
- for (i = 0; i < CTL_MAX_INITIATORS; i++)
- lun->pending_ua[i] |=
- CTL_UA_THIN_PROV_THRES;
+ ctl_est_ua_all(lun, -1, CTL_UA_THIN_PROV_THRES);
}
} else {
lun->lasttpt = 0;
- for (i = 0; i < CTL_MAX_INITIATORS; i++)
- lun->pending_ua[i] &= ~CTL_UA_THIN_PROV_THRES;
+ ctl_clr_ua_all(lun, -1, CTL_UA_THIN_PROV_THRES);
}
mtx_unlock(&lun->lun_lock);
}
diff --git a/sys/cam/ctl/ctl_error.c b/sys/cam/ctl/ctl_error.c
index 370af63..d4d7f79 100644
--- a/sys/cam/ctl/ctl_error.c
+++ b/sys/cam/ctl/ctl_error.c
@@ -367,16 +367,35 @@ ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq)
}
ctl_ua_type
-ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
- scsi_sense_data_type sense_format)
+ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
+ struct scsi_sense_data *sense, scsi_sense_data_type sense_format)
{
+ ctl_ua_type *ua;
ctl_ua_type ua_to_build, ua_to_clear;
int asc, ascq;
-
- if (*ua_type == CTL_UA_NONE)
+ uint32_t p, i;
+
+ mtx_assert(&lun->lun_lock, MA_OWNED);
+ p = initidx / CTL_MAX_INIT_PER_PORT;
+ if ((ua = lun->pending_ua[p]) == NULL) {
+ mtx_unlock(&lun->lun_lock);
+ ua = malloc(sizeof(ctl_ua_type) * CTL_MAX_INIT_PER_PORT,
+ M_CTL, M_WAITOK);
+ mtx_lock(&lun->lun_lock);
+ if (lun->pending_ua[p] == NULL) {
+ lun->pending_ua[p] = ua;
+ for (i = 0; i < CTL_MAX_INIT_PER_PORT; i++)
+ ua[i] = CTL_UA_POWERON;
+ } else {
+ free(ua, M_CTL);
+ ua = lun->pending_ua[p];
+ }
+ }
+ i = initidx % CTL_MAX_INIT_PER_PORT;
+ if (ua[i] == CTL_UA_NONE)
return (CTL_UA_NONE);
- ua_to_build = (1 << (ffs(*ua_type) - 1));
+ ua_to_build = (1 << (ffs(ua[i]) - 1));
ua_to_clear = ua_to_build;
switch (ua_to_build) {
@@ -482,7 +501,7 @@ ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
SSD_ELEM_NONE);
/* We're reporting this UA, so clear it */
- *ua_type &= ~ua_to_clear;
+ ua[i] &= ~ua_to_clear;
return (ua_to_build);
}
diff --git a/sys/cam/ctl/ctl_error.h b/sys/cam/ctl/ctl_error.h
index d7d82aa..8430eef 100644
--- a/sys/cam/ctl/ctl_error.h
+++ b/sys/cam/ctl/ctl_error.h
@@ -42,6 +42,8 @@
#ifndef _CTL_ERROR_H_
#define _CTL_ERROR_H_
+struct ctl_lun;
+
void ctl_set_sense_data_va(struct scsi_sense_data *sense_data, void *lun,
scsi_sense_data_type sense_format, int current_error,
int sense_key, int asc, int ascq, va_list ap);
@@ -55,8 +57,8 @@ void ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src,
void ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src,
struct scsi_sense_data_fixed *sense_dest);
void ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq);
-ctl_ua_type ctl_build_ua(ctl_ua_type *ua_type, struct scsi_sense_data *sense,
- scsi_sense_data_type sense_format);
+ctl_ua_type ctl_build_ua(struct ctl_lun *lun, uint32_t initidx,
+ struct scsi_sense_data *sense, scsi_sense_data_type sense_format);
void ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio);
void ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag);
void ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command,
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index f6f7d6e..dac8123 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -403,7 +403,7 @@ struct ctl_lun {
uint32_t have_ca[CTL_MAX_INITIATORS >> 5];
struct scsi_sense_data pending_sense[CTL_MAX_INITIATORS];
#endif
- ctl_ua_type pending_ua[CTL_MAX_INITIATORS];
+ ctl_ua_type *pending_ua[CTL_MAX_PORTS];
time_t lasttpt;
struct ctl_mode_pages mode_pages;
struct ctl_log_pages log_pages;
OpenPOWER on IntegriCloud