aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Motin <mav@FreeBSD.org>2014-12-03 15:16:18 +0000
committerAlexander Motin <mav@FreeBSD.org>2014-12-03 15:16:18 +0000
commit9e52565344f48fbd9bec44f9d72c5a1c639e32c6 (patch)
treea2523f5c7e49f9e413a5831c8a6e8791872e229a
parent672aa7f472bb9397aee52462b6a8cb23425d3bf9 (diff)
downloadsrc-9e52565344f48fbd9bec44f9d72c5a1c639e32c6.tar.gz
src-9e52565344f48fbd9bec44f9d72c5a1c639e32c6.zip
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. MFC after: 1 month
Notes
Notes: svn path=/head/; revision=275458
-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 499a085d9673..290ebefcf136 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -962,12 +962,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;
@@ -985,8 +1043,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);
@@ -4547,19 +4604,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);
@@ -4694,18 +4745,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);
@@ -4983,19 +5034,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);
}
@@ -6043,19 +6085,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);
@@ -6091,19 +6122,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);
@@ -7891,7 +7911,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);
}
/*
@@ -8433,8 +8453,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;
@@ -8582,7 +8602,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);
@@ -8701,8 +8721,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;
@@ -8732,8 +8751,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;
@@ -9306,7 +9324,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);
}
}
@@ -9361,6 +9379,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;
@@ -9445,11 +9464,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;
}
@@ -11120,7 +11136,6 @@ ctl_failover(void)
union ctl_io *next_io, *pending_io;
union ctl_io *io;
int lun_idx;
- int i;
ctl_softc = control_softc;
@@ -11255,13 +11270,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);
@@ -11350,13 +11359,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);
@@ -11492,28 +11495,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);
}
}
@@ -11792,7 +11789,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);
/*
@@ -11811,11 +11810,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
/*
@@ -11828,12 +11825,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);
@@ -11935,7 +11930,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);
@@ -13951,14 +13946,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 370af630f2c9..d4d7f79f2018 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 d7d82aa392a0..8430eef0bb02 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 f6f7d6e26b3c..dac812321572 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;