svn commit: r275888 - stable/10/sys/cam/ctl

Alexander Motin mav at FreeBSD.org
Thu Dec 18 08:32:08 UTC 2014


Author: mav
Date: Thu Dec 18 08:32:06 2014
New Revision: 275888
URL: https://svnweb.freebsd.org/changeset/base/275888

Log:
  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.

Modified:
  stable/10/sys/cam/ctl/ctl.c
  stable/10/sys/cam/ctl/ctl_error.c
  stable/10/sys/cam/ctl/ctl_error.h
  stable/10/sys/cam/ctl/ctl_private.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/cam/ctl/ctl.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl.c	Thu Dec 18 08:31:13 2014	(r275887)
+++ stable/10/sys/cam/ctl/ctl.c	Thu Dec 18 08:32:06 2014	(r275888)
@@ -964,12 +964,70 @@ ctl_copy_sense_data(union ctl_ha_msg *sr
 	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_soft
 	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_l
 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_scsi
 		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
 		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, uint
 	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_sc
 						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_sc
 				    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 c
 					    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 c
 		 && 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 *cts
 	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 *cts
 		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 *ct
 	 */
 	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 != NULL)
-				sense_format = (lun->flags &
-				    CTL_LUN_SENSE_DESC) ? SSD_TYPE_DESC :
-				    SSD_TYPE_FIXED;
-			else
-				sense_format = SSD_TYPE_FIXED;
+		if (lun->flags & CTL_LUN_SENSE_DESC)
+			sense_format = SSD_TYPE_DESC;
+		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
 #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
 	 */
 #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
 	 */
 	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);
 		}

Modified: stable/10/sys/cam/ctl/ctl_error.c
==============================================================================
--- stable/10/sys/cam/ctl/ctl_error.c	Thu Dec 18 08:31:13 2014	(r275887)
+++ stable/10/sys/cam/ctl/ctl_error.c	Thu Dec 18 08:32:06 2014	(r275888)
@@ -367,16 +367,35 @@ ctl_set_ua(struct ctl_scsiio *ctsio, int
 }
 
 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;
+	uint32_t p, i;
 
-	if (*ua_type == CTL_UA_NONE)
+	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, struc
 			   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);
 }

Modified: stable/10/sys/cam/ctl/ctl_error.h
==============================================================================
--- stable/10/sys/cam/ctl/ctl_error.h	Thu Dec 18 08:31:13 2014	(r275887)
+++ stable/10/sys/cam/ctl/ctl_error.h	Thu Dec 18 08:32:06 2014	(r275888)
@@ -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
 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,

Modified: stable/10/sys/cam/ctl/ctl_private.h
==============================================================================
--- stable/10/sys/cam/ctl/ctl_private.h	Thu Dec 18 08:31:13 2014	(r275887)
+++ stable/10/sys/cam/ctl/ctl_private.h	Thu Dec 18 08:32:06 2014	(r275888)
@@ -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;


More information about the svn-src-all mailing list