--- old/usr/src/cmd/stmfadm/stmfadm.c	Fri Dec  2 14:28:51 2011
+++ new/usr/src/cmd/stmfadm/stmfadm.c	Fri Dec  2 14:28:51 2011
@@ -80,7 +80,7 @@
 static void printGuid(stmfGuid *guid, FILE *printWhere);
 static void printTargetProps(stmfTargetProperties *);
 static void printSessionProps(stmfSessionList *);
-static int setLuPropFromInput(luResource, char *);
+static int setLuPropFromInput(luResource, char *, uint32_t *);
 static int convertCharToPropId(char *, uint32_t *);
 
 
@@ -130,6 +130,7 @@
 #define	SERIAL_NUMBER		    "SERIAL"
 #define	MGMT_URL		    "MGMT-URL"
 #define	HOST_ID			    "HOST-ID"
+#define	UNMAP			    "UNMAP"
 
 #define	STMFADM_SUCCESS		    0
 #define	STMFADM_FAILURE		    1
@@ -139,6 +140,7 @@
 "Valid properties for -p, --lu-prop are: \n" \
 "     alias    - alias for logical unit (up to 255 chars)\n" \
 "     mgmt-url - Management URL address\n" \
+"     unmap    - iSCSI UNMAP enabled (true, false)\n" \
 "     wcd      - write cache disabled (true, false)\n" \
 "     wp       - write protect (true, false)\n\n" \
 "-f alters the meaning of the operand to be a file name\n" \
@@ -159,6 +161,7 @@
 "                6 ascii hex characters of valid format\n" \
 "     pid      - product identifier (up to 16 chars)\n" \
 "     serial   - serial number (up to 252 chars)\n" \
+"     unmap    - iSCSI UNMAP enabled (true, false)\n" \
 "     vid      - vendor identifier (up to 8 chars)\n" \
 "     wcd      - write cache disabled (true, false)\n" \
 "     wp       - write protect (true, false)\n"
@@ -814,6 +817,8 @@
 	int stmfRet = 0;
 	char guidAsciiBuf[33];
 	stmfGuid createdGuid;
+	uint32_t propid;
+	boolean_t unmap_not_set = B_TRUE;
 
 	stmfRet = stmfCreateLuResource(STMF_DISK, &hdl);
 
@@ -826,7 +831,10 @@
 	for (; options->optval; options++) {
 		switch (options->optval) {
 			case 'p':
-				ret = setLuPropFromInput(hdl, options->optarg);
+				ret = setLuPropFromInput(hdl, options->optarg,
+				    &propid);
+				if (propid == STMF_LU_PROP_UNMAP)
+					unmap_not_set = B_FALSE;
 				if (ret != 0) {
 					(void) stmfFreeLuResource(hdl);
 					return (1);
@@ -851,6 +859,19 @@
 		}
 	}
 
+	if (unmap_not_set) {
+		/*
+		 * We "enable" unmap by default, but STMF is hostile toward
+		 * enable-by-default, so we enable it here if it hasn't
+		 * already been set.
+		 */
+		if (stmfSetLuProp(hdl, STMF_LU_PROP_UNMAP, "true") !=
+		    STMF_STATUS_SUCCESS) {
+			fprintf(stderr, "%s: %s\n", cmdName,
+			    gettext("Problems setting UNMAP default"));
+		}
+	}
+
 	stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
 
 	if (stmfRet != STMF_STATUS_SUCCESS) {
@@ -1233,12 +1254,11 @@
 }
 
 static int
-setLuPropFromInput(luResource hdl, char *optarg)
+setLuPropFromInput(luResource hdl, char *optarg, uint32_t *propId)
 {
 	char *prop = NULL;
 	char *propVal = NULL;
 	char *lasts = NULL;
-	uint32_t propId;
 	int ret = 0;
 
 	prop = strtok_r(optarg, "=", &lasts);
@@ -1249,7 +1269,7 @@
 		return (1);
 	}
 
-	ret = convertCharToPropId(prop, &propId);
+	ret = convertCharToPropId(prop, propId);
 	if (ret != 0) {
 		(void) fprintf(stderr, "%s: %s: %s\n",
 		    cmdName, gettext("invalid property specified"), prop);
@@ -1256,7 +1276,7 @@
 		return (1);
 	}
 
-	ret = stmfSetLuProp(hdl, propId, propVal);
+	ret = stmfSetLuProp(hdl, *propId, propVal);
 	if (ret != STMF_STATUS_SUCCESS) {
 		(void) fprintf(stderr, "%s: %s %s: ",
 		    cmdName, gettext("unable to set"), prop);
@@ -1304,6 +1324,8 @@
 		*propId = STMF_LU_PROP_MGMT_URL;
 	} else if (strcasecmp(prop, HOST_ID) == 0) {
 		*propId = STMF_LU_PROP_HOST_ID;
+	} else if (strcasecmp(prop, UNMAP) == 0) {
+		*propId = STMF_LU_PROP_UNMAP;
 	} else {
 		return (1);
 	}
@@ -2218,6 +2240,21 @@
 		    strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
 	} else if (stmfRet == STMF_ERROR_NO_PROP) {
 		(void) printf("not set\n");
+	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
+		(void) printf("prop unavailable in standby\n");
+	} else {
+		(void) printf("<error retrieving property>\n");
+		ret++;
+	}
+
+	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_UNMAP, propVal,
+	    &propValSize);
+	(void) printf(PROPS_FORMAT, "UNMAP support");
+	if (stmfRet == STMF_STATUS_SUCCESS) {
+		(void) printf("%s\n", (strcasecmp(propVal, "true") == 0) ?
+		    "Enabled" : "Disabled");
+	} else if (stmfRet == STMF_ERROR_NO_PROP) {
+		(void) printf("not set\n");
 	} else if (stmfRet == STMF_ERROR_NO_PROP_STANDBY) {
 		(void) printf("prop unavailable in standby\n");
 	} else {
--- old/usr/src/lib/libstmf/common/libstmf.h	Fri Dec  2 14:28:52 2011
+++ new/usr/src/lib/libstmf/common/libstmf.h	Fri Dec  2 14:28:52 2011
@@ -106,6 +106,7 @@
 #define	STMF_ERROR_META_CREATION	(STMF_STATUS_ERROR | 0x107)
 #define	STMF_ERROR_FILE_SIZE_INVALID	(STMF_STATUS_ERROR | 0x108)
 #define	STMF_ERROR_WRITE_CACHE_SET	(STMF_STATUS_ERROR | 0x109)
+#define	STMF_ERROR_UNMAP_SET		(STMF_STATUS_ERROR | 0x10a)
 
 /* Initiator Name Types */
 #define	STMF_FC_PORT_WWN	    1
@@ -149,7 +150,8 @@
 	STMF_LU_PROP_PID,
 	STMF_LU_PROP_SERIAL_NUM,
 	STMF_LU_PROP_ACCESS_STATE,
-	STMF_LU_PROP_HOST_ID
+	STMF_LU_PROP_HOST_ID,
+	STMF_LU_PROP_UNMAP
 };
 
 
--- old/usr/src/lib/libstmf/common/libstmf_impl.h	Fri Dec  2 14:28:53 2011
+++ new/usr/src/lib/libstmf/common/libstmf_impl.h	Fri Dec  2 14:28:52 2011
@@ -67,6 +67,8 @@
 	boolean_t   writeProtectEnable;
 	boolean_t   writebackCacheDisableValid;
 	boolean_t   writebackCacheDisable;
+	boolean_t   unmapValid;
+	boolean_t   unmap;
 	uint16_t    accessState;
 	uint32_t    hostId;
 	boolean_t   hostIdValid;
--- old/usr/src/lib/libstmf/common/stmf.c	Fri Dec  2 14:28:54 2011
+++ new/usr/src/lib/libstmf/common/stmf.c	Fri Dec  2 14:28:53 2011
@@ -1262,6 +1262,13 @@
 		}
 	}
 
+	if (disk->unmapValid) {
+		sbdLu->slu_unmap_valid = 1;
+		if (disk->unmap) {
+			sbdLu->slu_unmap = 1;
+		}
+	}
+
 	if (disk->writebackCacheDisableValid) {
 		sbdLu->slu_writeback_cache_disable_valid = 1;
 		if (disk->writebackCacheDisable) {
@@ -1513,6 +1520,9 @@
 		case SBD_RET_WRITE_CACHE_SET_FAILED:
 			*ret = STMF_ERROR_WRITE_CACHE_SET;
 			break;
+		case SBD_RET_UNMAP_SET_FAILED:
+			*ret = STMF_ERROR_UNMAP_SET;
+			break;
 		case SBD_RET_ACCESS_STATE_FAILED:
 			*ret = STMF_ERROR_ACCESS_STATE_SET;
 			break;
@@ -1822,6 +1832,7 @@
 		case STMF_LU_PROP_MGMT_URL:
 		case STMF_LU_PROP_WRITE_PROTECT:
 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
+		case STMF_LU_PROP_UNMAP:
 			return (STMF_STATUS_SUCCESS);
 			break;
 		default:
@@ -1906,6 +1917,12 @@
 		sbdLu->mlu_lu_size = disk->luSize;
 	}
 
+	if (disk->unmapValid) {
+		sbdLu->mlu_unmap_valid = 1;
+		if (disk->unmap)
+			sbdLu->mlu_unmap = 1;
+	}
+
 	if (disk->writeProtectEnableValid) {
 		sbdLu->mlu_write_protected_valid = 1;
 		if (disk->writeProtectEnable) {
@@ -2343,6 +2360,10 @@
 	diskLu->revValid = B_TRUE;
 	bcopy(sbdProps->slp_rev, diskLu->rev, sizeof (diskLu->rev));
 
+	diskLu->unmapValid = B_TRUE;
+	if (sbdProps->slp_unmap_cur)
+		diskLu->unmap = B_TRUE;
+
 	diskLu->writeProtectEnableValid = B_TRUE;
 	if (sbdProps->slp_write_protected) {
 		diskLu->writeProtectEnable = B_TRUE;
@@ -2817,6 +2838,23 @@
 				}
 			}
 			break;
+		case STMF_LU_PROP_UNMAP:
+			if (!diskLu->unmapValid)
+				return (STMF_ERROR_NO_PROP);
+			if (diskLu->unmap) {
+				if ((reqLen = strlcpy(propVal, "true",
+				    *propLen)) >= *propLen) {
+					*propLen = reqLen + 1;
+					return (STMF_ERROR_INVALID_ARG);
+				}
+			} else {
+				if ((reqLen = strlcpy(propVal, "false",
+				    *propLen)) >= *propLen) {
+					*propLen = reqLen + 1;
+					return (STMF_ERROR_INVALID_ARG);
+				}
+			}
+			break;
 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
 			if (diskLu->writebackCacheDisableValid == B_FALSE) {
 				return (STMF_ERROR_NO_PROP);
@@ -3036,6 +3074,16 @@
 			}
 			diskLu->writebackCacheDisableValid = B_TRUE;
 			break;
+		case STMF_LU_PROP_UNMAP:
+			if (strcasecmp(propVal, "TRUE") == 0) {
+				diskLu->unmap = B_TRUE;
+			} else if (strcasecmp(propVal, "FALSE") == 0) {
+				diskLu->unmap = B_FALSE;
+			} else {
+				return (STMF_ERROR_INVALID_ARG);
+			}
+			diskLu->unmapValid = B_TRUE;
+			break;
 		case STMF_LU_PROP_ACCESS_STATE:
 			ret = STMF_ERROR_INVALID_PROP;
 			break;
--- old/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Fri Dec  2 14:28:55 2011
+++ new/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Fri Dec  2 14:28:54 2011
@@ -1353,6 +1353,9 @@
 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
 		sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE;
 	}
+	if (sl->sl_flags & SL_SAVED_UNMAP_ENABLED) {
+		sli->sli_flags |= SLI_UNMAP_ENABLED;
+	}
 	if (sl->sl_flags & SL_VID_VALID) {
 		bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
 		sli->sli_flags |= SLI_VID_VALID;
@@ -1389,17 +1392,24 @@
 }
 
 /*
- * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
+ * Will scribble SL_UNMAP_ENABLED on or off in sl_flags if we succeed.
+ * Returns B_TRUE if the LU is UNMAP-capable.
  */
-static void
-do_unmap_setup(sbd_lu_t *sl)
+static boolean_t
+do_unmap_setup(sbd_lu_t *sl, boolean_t enable)
 {
-	ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
+	if ((sl->sl_flags & SL_ZFS_META) == 0) {
+		sl->sl_flags &= ~SL_SAVED_UNMAP_ENABLED;
+		ASSERT((sl->sl_flags & SL_UNMAP_ENABLED) == 0);
+		return (B_FALSE);	/* No UNMAP for you. */
+	}
 
-	if ((sl->sl_flags & SL_ZFS_META) == 0)
-		return;	/* No UNMAP for you. */
+	if (enable)
+		sl->sl_flags |= (SL_UNMAP_ENABLED | SL_SAVED_UNMAP_ENABLED);
+	else
+		sl->sl_flags &= ~(SL_UNMAP_ENABLED | SL_SAVED_UNMAP_ENABLED);
 
-	sl->sl_flags |= SL_UNMAP_ENABLED;
+	return (B_TRUE);
 }
 
 int
@@ -1408,7 +1418,10 @@
 	stmf_lu_t *lu = sl->sl_lu;
 	stmf_status_t ret;
 
-	do_unmap_setup(sl);
+#if 0
+	/* Always try and enable UNMAP upon bringup. */
+	(void) do_unmap_setup(sl, B_TRUE);
+#endif
 
 	lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
 	if (sl->sl_alias) {
@@ -1835,6 +1848,11 @@
 	if (slu->slu_write_protected) {
 		sl->sl_flags |= SL_WRITE_PROTECTED;
 	}
+
+	if (slu->slu_unmap) {
+		(void) do_unmap_setup(sl, B_TRUE);
+	}
+
 	if (slu->slu_writeback_cache_disable) {
 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
 		    SL_SAVED_WRITE_CACHE_DISABLE;
@@ -2477,6 +2495,9 @@
 	if (sli->sli_flags & SLI_WRITE_PROTECTED) {
 		sl->sl_flags |= SL_WRITE_PROTECTED;
 	}
+	if (sli->sli_flags & SLI_UNMAP_ENABLED) {
+		sl->sl_flags |= SL_UNMAP_ENABLED;
+	}
 	if (sli->sli_flags & SLI_VID_VALID) {
 		sl->sl_flags |= SL_VID_VALID;
 		bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
@@ -2697,6 +2718,17 @@
 		goto smm_err_out;
 	}
 
+	/* Change UNMAP status... */
+	if (mlu->mlu_unmap_valid) {
+		mutex_enter(&sl->sl_lock);
+		ASSERT(ret == 0);
+		if (!do_unmap_setup(sl, mlu->mlu_unmap))
+			ret = EINVAL;
+		mutex_exit(&sl->sl_lock);
+		if (ret != 0)
+			goto smm_err_out;
+	}
+
 	/* check for write cache change */
 	if (mlu->mlu_writeback_cache_disable_valid) {
 		/* set wce on device */
@@ -3331,6 +3363,10 @@
 	}
 	bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
 
+	if (sl->sl_flags & SL_UNMAP_ENABLED)
+		oslp->slp_unmap_cur = 1;
+	if (sl->sl_flags & SL_SAVED_UNMAP_ENABLED)
+		oslp->slp_unmap_saved = 1;
 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
 		oslp->slp_writeback_cache_disable_cur = 1;
 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
--- old/usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h	Fri Dec  2 14:28:55 2011
+++ new/usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h	Fri Dec  2 14:28:55 2011
@@ -176,6 +176,7 @@
 #define	SLI_WRITEBACK_CACHE_DISABLE		0x0200
 #define	SLI_ZFS_META				0x0400
 #define	SLI_MGMT_URL_VALID			0x0800
+#define	SLI_UNMAP_ENABLED			0x1000
 
 struct sbd_it_data;
 
@@ -270,6 +271,7 @@
 #define	SL_FLUSH_ON_DISABLED_WRITECACHE	    0x00040000
 #define	SL_CALL_ZVOL			    0x00080000
 #define	SL_UNMAP_ENABLED		    0x00100000
+#define	SL_SAVED_UNMAP_ENABLED		    0x00200000
 
 /*
  * sl_trans_op. LU is undergoing some transition and this field
--- old/usr/src/uts/common/sys/stmf_sbd_ioctl.h	Fri Dec  2 14:28:56 2011
+++ new/usr/src/uts/common/sys/stmf_sbd_ioctl.h	Fri Dec  2 14:28:56 2011
@@ -64,6 +64,7 @@
 	SBD_RET_INSUFFICIENT_BUF_SPACE,
 	SBD_RET_WRITE_CACHE_SET_FAILED,
 	SBD_RET_ACCESS_STATE_FAILED,
+	SBD_RET_UNMAP_SET_FAILED,
 
 	SBD_RET_MAX_VAL
 } sbd_ret_t;
@@ -82,7 +83,7 @@
 
 typedef struct sbd_create_and_reg_lu {
 	uint32_t	slu_struct_size;
-	uint16_t	slu_meta_fname_valid:1,
+	uint32_t	slu_meta_fname_valid:1,
 			slu_lu_size_valid:1,
 			slu_blksize_valid:1,
 			slu_vid_valid:1,
@@ -96,7 +97,11 @@
 			slu_host_id_valid:1,
 			slu_writeback_cache_disable_valid:1,
 			slu_writeback_cache_disable:1,
-			slu_write_protected:1;
+			slu_write_protected:1,
+			slu_unmap_valid:1,
+			slu_unmap:1;
+	uint32_t	slu_pad1;	/* To preserve 64-bit alignment */
+	uint16_t	slu_pad2;	/* for the following fields. */
 	uint16_t	slu_meta_fname_off;
 	uint64_t	slu_lu_size;
 	uint16_t	slu_data_fname_off;
@@ -163,7 +168,9 @@
 			mlu_by_guid:1,
 			mlu_by_fname:1,
 			mlu_standby_valid:1,
-			mlu_standby:1;
+			mlu_standby:1,
+			mlu_unmap_valid:1,
+			mlu_unmap:1;
 	uint64_t	mlu_lu_size;
 	uint16_t	mlu_alias_off;
 	uint16_t	mlu_mgmt_url_off;
@@ -205,6 +212,8 @@
 			slp_lu_pid:1,
 			slp_lu_rev:1,
 			slp_serial_valid:1,
+			slp_unmap_cur:1,
+			slp_unmap_saved:1,
 			slp_writeback_cache_disable_cur:1,
 			slp_writeback_cache_disable_saved:1,
 			slp_write_protected:1;
