changeset 10113:045148591643

6812611 Add Management Network Address VPD (85h) support to sbd 6856759 groupMemberListIoctl() frees memory it hasn't allocated 6855914 fw_63 iSCSI failing SCSI compliance WHQL test 6840755 page_length for VPD page 80 isn't set for all conditions in sbd inquiry handler
author Nattuvetty Bhavyan <Nattuvetty.Bhavyan@Sun.COM>
date Fri, 17 Jul 2009 11:20:16 -0700
parents ca9cb52b0505
children 023993413f11
files usr/src/cmd/stmfadm/stmfadm.c usr/src/lib/libstmf/common/libstmf.h usr/src/lib/libstmf/common/libstmf_impl.h usr/src/lib/libstmf/common/stmf.c usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h usr/src/uts/common/sys/stmf_sbd_ioctl.h
diffstat 8 files changed, 387 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/stmfadm/stmfadm.c	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/cmd/stmfadm/stmfadm.c	Fri Jul 17 11:20:16 2009 -0700
@@ -126,13 +126,15 @@
 #define	COMPANY_ID		    "OUI"
 #define	BLOCK_SIZE		    "BLK"
 #define	SERIAL_NUMBER		    "SERIAL"
+#define	MGMT_URL		    "MGMT-URL"
 
 #define	MODIFY_HELP "\n"\
 "Description: Modify properties of a logical unit. \n" \
 "Valid properties for -p, --lu-prop are: \n" \
-"     alias - alias for logical unit (up to 255 chars)\n" \
-"     wcd   - write cache disabled (true, false)\n" \
-"     wp    - write protect (true, false)\n\n" \
+"     alias    - alias for logical unit (up to 255 chars)\n" \
+"     mgmt-url - Management URL address\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" \
 "rather than a LU name. This allows for modification\n" \
 "of a logical unit that is not yet imported into stmf\n"
@@ -140,17 +142,18 @@
 #define	CREATE_HELP "\n"\
 "Description: Create a logical unit. \n" \
 "Valid properties for -p, --lu-prop are: \n" \
-"     alias - alias for logical unit (up to 255 chars)\n" \
-"     blk   - block size in bytes in 2^n\n" \
-"     guid  - 32 ascii hex characters in NAA format \n" \
-"     meta  - separate meta data file name\n" \
-"     oui   - organizational unique identifier\n" \
-"             6 ascii hex characters of valid format\n" \
-"     pid   - product identifier (up to 16 chars)\n" \
-"     serial- serial number (up to 252 chars)\n" \
-"     vid   - vendor identifier (up to 8 chars)\n" \
-"     wp    - write protect (true, false)\n" \
-"     wcd   - write cache disabled (true, false)\n"
+"     alias    - alias for logical unit (up to 255 chars)\n" \
+"     blk      - block size in bytes in 2^n\n" \
+"     guid     - 32 ascii hex characters in NAA format \n" \
+"     meta     - separate meta data file name\n" \
+"     mgmt-url - Management URL address\n" \
+"     oui      - organizational unique identifier\n" \
+"                6 ascii hex characters of valid format\n" \
+"     pid      - product identifier (up to 16 chars)\n" \
+"     serial   - serial number (up to 252 chars)\n" \
+"     vid      - vendor identifier (up to 8 chars)\n" \
+"     wcd      - write cache disabled (true, false)\n" \
+"     wp       - write protect (true, false)\n"
 #define	ADD_VIEW_HELP "\n"\
 "Description: Add a view entry to a logical unit. \n" \
 "A view entry is comprised of three elements; the \n" \
@@ -991,14 +994,7 @@
 		switch (options->optval) {
 			case 'p':
 				prop = strtok_r(options->optarg, "=", &lasts);
-				if ((propVal = strtok_r(NULL, "=", &lasts))
-				    == NULL) {
-					(void) fprintf(stderr, "%s: %s: %s\n",
-					    cmdName, options->optarg,
-					gettext("invalid property specifier"
-					    "- prop=val\n"));
-					return (1);
-				}
+				propVal = strtok_r(NULL, "=", &lasts);
 				ret = convertCharToPropId(prop, &propId);
 				if (ret != 0) {
 					(void) fprintf(stderr, "%s: %s: %s\n",
@@ -1007,8 +1003,22 @@
 					    prop);
 					return (1);
 				}
-				if (callModify(fname, &inGuid, propId, propVal,
-				    prop) != 0) {
+				if (propVal ==  NULL &&
+				    propId != STMF_LU_PROP_MGMT_URL) {
+					(void) fprintf(stderr, "%s: %s: %s\n",
+					    cmdName, options->optarg,
+					    gettext("invalid property specifier"
+					    "- prop=val\n"));
+					return (1);
+				}
+				if (propVal ==  NULL) {
+					ret = callModify(fname, &inGuid, propId,
+					    "", prop);
+				} else {
+					ret = callModify(fname, &inGuid, propId,
+					    propVal, prop);
+				}
+				if (ret != 0) {
 					return (1);
 				}
 				break;
@@ -1270,6 +1280,8 @@
 		*propId = STMF_LU_PROP_COMPANY_ID;
 	} else if (strcasecmp(prop, META_FILE) == 0) {
 		*propId = STMF_LU_PROP_META_FILENAME;
+	} else if (strcasecmp(prop, MGMT_URL) == 0) {
+		*propId = STMF_LU_PROP_MGMT_URL;
 	} else {
 		return (1);
 	}
@@ -2092,6 +2104,18 @@
 		ret++;
 	}
 
+	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_MGMT_URL, propVal,
+	    &propValSize);
+	(void) printf(PROPS_FORMAT, "Management URL");
+	if (stmfRet == STMF_STATUS_SUCCESS) {
+		(void) printf("%s\n", propVal);
+	} else if (stmfRet == STMF_ERROR_NO_PROP) {
+		(void) printf("not set\n");
+	} else {
+		(void) printf("<error retrieving property>\n");
+		ret++;
+	}
+
 	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
 	    &propValSize);
 	(void) printf(PROPS_FORMAT, "Vendor ID");
--- a/usr/src/lib/libstmf/common/libstmf.h	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/lib/libstmf/common/libstmf.h	Fri Jul 17 11:20:16 2009 -0700
@@ -129,6 +129,7 @@
 	STMF_LU_PROP_FILENAME,
 	STMF_LU_PROP_GUID,
 	STMF_LU_PROP_META_FILENAME,
+	STMF_LU_PROP_MGMT_URL,
 	STMF_LU_PROP_NEW,
 	STMF_LU_PROP_SIZE,
 	STMF_LU_PROP_WRITE_PROTECT,
--- a/usr/src/lib/libstmf/common/libstmf_impl.h	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/lib/libstmf/common/libstmf_impl.h	Fri Jul 17 11:20:16 2009 -0700
@@ -55,6 +55,8 @@
 	uint32_t    companyId;
 	boolean_t   luAliasValid;
 	char	    luAlias[256];
+	boolean_t   luMgmtUrlValid;
+	char	    luMgmtUrl[1024];
 	boolean_t   vidValid;
 	char	    vid[8];
 	boolean_t   pidValid;
--- a/usr/src/lib/libstmf/common/stmf.c	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/lib/libstmf/common/stmf.c	Fri Jul 17 11:20:16 2009 -0700
@@ -1078,6 +1078,7 @@
 	int metaFileNameLen = 0;
 	int serialNumLen = 0;
 	int luAliasLen = 0;
+	int luMgmtUrlLen = 0;
 	int sluBufSize = 0;
 	int bufOffset = 0;
 	int fd = 0;
@@ -1117,6 +1118,11 @@
 		sluBufSize += luAliasLen + 1;
 	}
 
+	if (disk->luMgmtUrlValid) {
+		luMgmtUrlLen = strlen(disk->luMgmtUrl);
+		sluBufSize += luMgmtUrlLen + 1;
+	}
+
 	/*
 	 * 8 is the size of the buffer set aside for
 	 * concatenation of variable length fields
@@ -1161,6 +1167,14 @@
 		bufOffset += luAliasLen + 1;
 	}
 
+	if (disk->luMgmtUrlValid) {
+		sbdLu->slu_mgmt_url_valid = 1;
+		sbdLu->slu_mgmt_url_off = bufOffset;
+		bcopy(disk->luMgmtUrl, &(sbdLu->slu_buf[bufOffset]),
+		    luMgmtUrlLen + 1);
+		bufOffset += luMgmtUrlLen + 1;
+	}
+
 	if (disk->luSizeValid) {
 		sbdLu->slu_lu_size_valid = 1;
 		sbdLu->slu_lu_size = disk->luSize;
@@ -1665,6 +1679,7 @@
 	switch (prop) {
 		case STMF_LU_PROP_ALIAS:
 		case STMF_LU_PROP_SIZE:
+		case STMF_LU_PROP_MGMT_URL:
 		case STMF_LU_PROP_WRITE_PROTECT:
 		case STMF_LU_PROP_WRITE_CACHE_DISABLE:
 			return (STMF_STATUS_SUCCESS);
@@ -1680,6 +1695,7 @@
 {
 	int ret = STMF_STATUS_SUCCESS;
 	int luAliasLen = 0;
+	int luMgmtUrlLen = 0;
 	int mluBufSize = 0;
 	int bufOffset = 0;
 	int fd = 0;
@@ -1710,6 +1726,11 @@
 		mluBufSize += luAliasLen + 1;
 	}
 
+	if (disk->luMgmtUrlValid) {
+		luMgmtUrlLen = strlen(disk->luMgmtUrl);
+		mluBufSize += luMgmtUrlLen + 1;
+	}
+
 	/*
 	 * 8 is the size of the buffer set aside for
 	 * concatenation of variable length fields
@@ -1732,6 +1753,14 @@
 		bufOffset += luAliasLen + 1;
 	}
 
+	if (disk->luMgmtUrlValid) {
+		sbdLu->mlu_mgmt_url_valid = 1;
+		sbdLu->mlu_mgmt_url_off = bufOffset;
+		bcopy(disk->luMgmtUrl, &(sbdLu->mlu_buf[bufOffset]),
+		    luMgmtUrlLen + 1);
+		bufOffset += luMgmtUrlLen + 1;
+	}
+
 	if (disk->luSizeValid) {
 		sbdLu->mlu_lu_size_valid = 1;
 		sbdLu->mlu_lu_size = disk->luSize;
@@ -2123,6 +2152,16 @@
 		    diskLu->serialNum, sbdProps->slp_serial_size);
 	}
 
+	if (sbdProps->slp_mgmt_url_valid) {
+		diskLu->luMgmtUrlValid = B_TRUE;
+		if (strlcpy(diskLu->luMgmtUrl,
+		    (char *)&(sbdProps->slp_buf[sbdProps->slp_mgmt_url_off]),
+		    sizeof (diskLu->luMgmtUrl)) >=
+		    sizeof (diskLu->luMgmtUrl)) {
+			return (STMF_STATUS_ERROR);
+		}
+	}
+
 	if (sbdProps->slp_alias_valid) {
 		diskLu->luAliasValid = B_TRUE;
 		if (strlcpy(diskLu->luAlias,
@@ -2250,6 +2289,16 @@
 				return (STMF_ERROR_INVALID_ARG);
 			}
 			break;
+		case STMF_LU_PROP_MGMT_URL:
+			if (diskLu->luMgmtUrlValid == B_FALSE) {
+				return (STMF_ERROR_NO_PROP);
+			}
+			if ((reqLen = strlcpy(propVal, diskLu->luMgmtUrl,
+			    *propLen)) >= *propLen) {
+				*propLen = reqLen + 1;
+				return (STMF_ERROR_INVALID_ARG);
+			}
+			break;
 		case STMF_LU_PROP_GUID:
 			if (diskLu->luGuidValid == B_FALSE) {
 				return (STMF_ERROR_NO_PROP);
@@ -2463,6 +2512,14 @@
 			}
 			diskLu->luMetaFileNameValid = B_TRUE;
 			break;
+		case STMF_LU_PROP_MGMT_URL:
+			if ((strlcpy(diskLu->luMgmtUrl, propVal,
+			    sizeof (diskLu->luMgmtUrl))) >=
+			    sizeof (diskLu->luMgmtUrl)) {
+				return (STMF_ERROR_INVALID_PROPSIZE);
+			}
+			diskLu->luMgmtUrlValid = B_TRUE;
+			break;
 		case STMF_LU_PROP_PID:
 			if ((propSize = strlen(propVal)) >
 			    sizeof (diskLu->pid)) {
@@ -3076,9 +3133,8 @@
 	}
 	(*groupList)->cnt = stmfIoctl.stmf_obuf_nentries;
 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
-		bcopy(iGroupList->name, (*groupList)->name[i],
+		bcopy(iGroupList[i].name, (*groupList)->name[i],
 		    sizeof (stmfGroupName));
-		iGroupList++;
 	}
 
 done:
@@ -3224,10 +3280,9 @@
 	(*groupProps)->cnt = stmfIoctl.stmf_obuf_nentries;
 	for (i = 0; i < stmfIoctl.stmf_obuf_nentries; i++) {
 		(*groupProps)->name[i].identLength =
-		    iGroupMembers->ident_size;
-		bcopy(iGroupMembers->ident, (*groupProps)->name[i].ident,
-		    iGroupMembers->ident_size);
-		iGroupMembers++;
+		    iGroupMembers[i].ident_size;
+		bcopy(iGroupMembers[i].ident, (*groupProps)->name[i].ident,
+		    iGroupMembers[i].ident_size);
 	}
 
 done:
--- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c	Fri Jul 17 11:20:16 2009 -0700
@@ -1066,6 +1066,9 @@
 	if (sl->sl_alias) {
 		s += strlen(sl->sl_alias) + 1;
 	}
+	if (sl->sl_mgmt_url) {
+		s += strlen(sl->sl_mgmt_url) + 1;
+	}
 	sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP);
 	p = sli->sli_buf;
 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
@@ -1092,6 +1095,13 @@
 		sli->sli_flags |= SLI_ALIAS_VALID;
 		p += strlen(sl->sl_alias) + 1;
 	}
+	if (sl->sl_mgmt_url) {
+		(void) strcpy((char *)p, sl->sl_mgmt_url);
+		sli->sli_mgmt_url_offset =
+		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
+		sli->sli_flags |= SLI_MGMT_URL_VALID;
+		p += strlen(sl->sl_mgmt_url) + 1;
+	}
 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
 		sli->sli_flags |= SLI_WRITE_PROTECTED;
 	}
@@ -1338,6 +1348,9 @@
 	if (sl->sl_alias_alloc_size) {
 		kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
 	}
+	if (sl->sl_mgmt_url_alloc_size) {
+		kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
+	}
 	stmf_free(sl->sl_lu);
 	return (ret);
 }
@@ -1368,6 +1381,8 @@
 	    (slu->slu_data_fname_off >= sz) ||
 	    ((slu->slu_alias_valid) &&
 	    (slu->slu_alias_off >= sz)) ||
+	    ((slu->slu_mgmt_url_valid) &&
+	    (slu->slu_mgmt_url_off >= sz)) ||
 	    ((slu->slu_serial_valid) &&
 	    ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
 		return (EINVAL);
@@ -1385,6 +1400,9 @@
 	if (slu->slu_alias_valid) {
 		alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
 	}
+	if (slu->slu_mgmt_url_valid) {
+		alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1;
+	}
 	if (slu->slu_serial_valid) {
 		alloc_sz += slu->slu_serial_size;
 	}
@@ -1428,6 +1446,11 @@
 		(void) strcpy(p, namebuf + slu->slu_alias_off);
 		p += strlen(sl->sl_alias) + 1;
 	}
+	if (slu->slu_mgmt_url_valid) {
+		sl->sl_mgmt_url = p;
+		(void) strcpy(p, namebuf + slu->slu_mgmt_url_off);
+		p += strlen(sl->sl_mgmt_url) + 1;
+	}
 	if (slu->slu_serial_valid) {
 		sl->sl_serial_no = (uint8_t *)p;
 		bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
@@ -1784,6 +1807,8 @@
 	    (sli->sli_meta_fname_offset > sli_buf_sz)) ||
 	    ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
 	    (sli->sli_data_fname_offset > sli_buf_sz)) ||
+	    ((sli->sli_flags & SLI_MGMT_URL_VALID) &&
+	    (sli->sli_mgmt_url_offset > sli_buf_sz)) ||
 	    ((sli->sli_flags & SLI_SERIAL_VALID) &&
 	    ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
 	    ((sli->sli_flags & SLI_ALIAS_VALID) &&
@@ -1855,6 +1880,14 @@
 		(void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
 		    sli->sli_alias_offset);
 	}
+	if (sli->sli_flags & SLI_MGMT_URL_VALID) {
+		sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy +
+		    sli->sli_mgmt_url_offset) + 1;
+		sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size,
+		    KM_SLEEP);
+		(void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy +
+		    sli->sli_mgmt_url_offset);
+	}
 	if (sli->sli_flags & SLI_WRITE_PROTECTED) {
 		sl->sl_flags |= SL_WRITE_PROTECTED;
 	}
@@ -1958,7 +1991,7 @@
 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
 {
 	sbd_lu_t *sl = NULL;
-	int alias_sz;
+	uint16_t alias_sz;
 	int ret = 0;
 	sbd_it_data_t *it;
 	sbd_status_t sret;
@@ -1982,6 +2015,8 @@
 	/* Lets validate offsets */
 	if (((mlu->mlu_alias_valid) &&
 	    (mlu->mlu_alias_off >= sz)) ||
+	    ((mlu->mlu_mgmt_url_valid) &&
+	    (mlu->mlu_mgmt_url_off >= sz)) ||
 	    (mlu->mlu_by_fname) &&
 	    (mlu->mlu_fname_off >= sz)) {
 		return (EINVAL);
@@ -2088,6 +2123,35 @@
 		mutex_exit(&sl->sl_lock);
 	}
 
+	if (mlu->mlu_mgmt_url_valid) {
+		uint16_t url_sz;
+
+		url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
+		if (url_sz > 0)
+			url_sz++;
+
+		mutex_enter(&sl->sl_lock);
+		if (sl->sl_mgmt_url_alloc_size > 0 &&
+		    (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) {
+			kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
+			sl->sl_mgmt_url = NULL;
+			sl->sl_mgmt_url_alloc_size = 0;
+		}
+		if (url_sz > 0) {
+			if (sl->sl_mgmt_url_alloc_size == 0) {
+				sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
+				sl->sl_mgmt_url_alloc_size = url_sz;
+			}
+			(void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf +
+			    mlu->mlu_mgmt_url_off);
+		}
+		for (it = sl->sl_it_list; it != NULL;
+		    it = it->sbd_it_next) {
+			it->sbd_it_ua_conditions |=
+			    SBD_UA_MODE_PARAMETERS_CHANGED;
+		}
+		mutex_exit(&sl->sl_lock);
+	}
 
 	if (mlu->mlu_write_protected_valid) {
 		mutex_enter(&sl->sl_lock);
@@ -2368,6 +2432,9 @@
 		sz += strlen(sl->sl_alias) + 1;
 	}
 
+	if (sl->sl_mgmt_url) {
+		sz += strlen(sl->sl_mgmt_url) + 1;
+	}
 	bzero(oslp, sizeof (*oslp) - 8);
 	oslp->slp_buf_size_needed = sz;
 
@@ -2404,6 +2471,12 @@
 		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
 		off += strlen(sl->sl_alias) + 1;
 	}
+	if (sl->sl_mgmt_url) {
+		oslp->slp_mgmt_url_valid = 1;
+		oslp->slp_mgmt_url_off = off;
+		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url);
+		off += strlen(sl->sl_mgmt_url) + 1;
+	}
 	if (sl->sl_serial_no_size) {
 		oslp->slp_serial_off = off;
 		bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
--- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_scsi.c	Fri Jul 17 11:20:16 2009 -0700
@@ -1070,15 +1070,56 @@
 	    STMF_SAA_INVALID_FIELD_IN_PARAM_LIST);
 }
 
+/*
+ * This function parse through a string, passed to it as a pointer to a string,
+ * by adjusting the pointer to the first non-space character and returns
+ * the count/length of the first bunch of non-space characters. Multiple
+ * Management URLs are stored as a space delimited string in sl_mgmt_url
+ * field of sbd_lu_t. This function is used to retrieve one url at a time.
+ *
+ * i/p : pointer to pointer to a url string
+ * o/p : Adjust the pointer to the url to the first non white character
+ *       and returns the length of the URL
+ */
+uint16_t
+sbd_parse_mgmt_url(char **url_addr) {
+	uint16_t url_length = 0;
+	char *url;
+	url = *url_addr;
+
+	while (*url != '\0') {
+		if (*url == ' ' || *url == '\t' || *url == '\n') {
+			(*url_addr)++;
+			url = *url_addr;
+		} else {
+			break;
+		}
+	}
+
+	while (*url != '\0') {
+		if (*url == ' ' || *url == '\t' ||
+		    *url == '\n' || *url == '\0') {
+			break;
+		}
+		url++;
+		url_length++;
+	}
+	return (url_length);
+}
+
 void
-sbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf,
-			uint8_t *p, int bsize)
+sbd_handle_inquiry(struct scsi_task *task, struct stmf_data_buf *initial_dbuf)
 {
 	sbd_lu_t *sl = (sbd_lu_t *)task->task_lu->lu_provider_private;
 	uint8_t *cdbp = (uint8_t *)&task->task_cdb[0];
-	uint32_t cmd_size;
+	uint8_t *p;
+	uint8_t byte0;
 	uint8_t page_length;
-	uint8_t byte0;
+	uint16_t bsize = 512;
+	uint16_t cmd_size;
+	uint32_t xfer_size = 4;
+	uint32_t mgmt_url_size = 0;
+
 
 	byte0 = DTYPE_DIRECT;
 	/*
@@ -1096,7 +1137,7 @@
 	 * return success.
 	 */
 
-	cmd_size = (((uint32_t)cdbp[3]) << 8) | cdbp[4];
+	cmd_size = (((uint16_t)cdbp[3]) << 8) | cdbp[4];
 
 	if (cmd_size == 0) {
 		task->task_cmd_xfer_length = 0;
@@ -1108,15 +1149,23 @@
 		return;
 	}
 
+	if (sl->sl_mgmt_url) {
+		mgmt_url_size = strlen(sl->sl_mgmt_url);
+	}
+
 	/*
 	 * Standard inquiry
 	 */
 
 	if ((cdbp[1] & 1) == 0) {
-		struct scsi_inquiry *inq = (struct scsi_inquiry *)p;
+		int	i;
+		struct scsi_inquiry *inq;
 
-		page_length = 31;
-		bzero(inq, page_length + 5);
+		p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
+		inq = (struct scsi_inquiry *)p;
+
+		page_length = 69;
+		xfer_size = page_length + 5;
 
 		inq->inq_dtype = DTYPE_DIRECT;
 		inq->inq_ansi = 5;	/* SPC-3 */
@@ -1124,7 +1173,7 @@
 		inq->inq_rdf = 2;	/* Response data format for SPC-3 */
 		inq->inq_len = page_length;
 
-		inq->inq_tpgs = 1;
+		inq->inq_tpgs = TPGS_FAILOVER_IMPLICIT;
 		inq->inq_cmdque = 1;
 
 		if (sl->sl_flags & SL_VID_VALID) {
@@ -1145,8 +1194,59 @@
 			bcopy(sbd_revision, inq->inq_revision, 4);
 		}
 
+		/* Adding Version Descriptors */
+		i = 0;
+		/* SAM-3 no version */
+		inq->inq_vd[i].inq_vd_msb = 0x00;
+		inq->inq_vd[i].inq_vd_lsb = 0x60;
+		i++;
+
+		/* transport */
+		switch (task->task_lport->lport_id->protocol_id) {
+		case PROTOCOL_FIBRE_CHANNEL:
+			inq->inq_vd[i].inq_vd_msb = 0x09;
+			inq->inq_vd[i].inq_vd_lsb = 0x00;
+			i++;
+			break;
+
+		case PROTOCOL_PARALLEL_SCSI:
+		case PROTOCOL_SSA:
+		case PROTOCOL_IEEE_1394:
+			/* Currently no claims of conformance */
+			break;
+
+		case PROTOCOL_SRP:
+			inq->inq_vd[i].inq_vd_msb = 0x09;
+			inq->inq_vd[i].inq_vd_lsb = 0x40;
+			i++;
+			break;
+
+		case PROTOCOL_iSCSI:
+			inq->inq_vd[i].inq_vd_msb = 0x09;
+			inq->inq_vd[i].inq_vd_lsb = 0x60;
+			i++;
+			break;
+
+		case PROTOCOL_SAS:
+		case PROTOCOL_ADT:
+		case PROTOCOL_ATAPI:
+		default:
+			/* Currently no claims of conformance */
+			break;
+		}
+
+		/* SPC-3 no version */
+		inq->inq_vd[i].inq_vd_msb = 0x03;
+		inq->inq_vd[i].inq_vd_lsb = 0x00;
+		i++;
+
+		/* SBC-2 no version */
+		inq->inq_vd[i].inq_vd_msb = 0x03;
+		inq->inq_vd[i].inq_vd_lsb = 0x20;
+
 		sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
-		    min(cmd_size, page_length + 5));
+		    min(cmd_size, xfer_size));
+		kmem_free(p, bsize);
 
 		return;
 	}
@@ -1155,18 +1255,30 @@
 	 * EVPD handling
 	 */
 
+	/* Default 512 bytes may not be enough, increase bsize if necessary */
+	if (cdbp[2] == 0x83 || cdbp[2] == 0x85) {
+		if (bsize <  cmd_size)
+			bsize = cmd_size;
+	}
+	p = (uint8_t *)kmem_zalloc(bsize, KM_SLEEP);
+
 	switch (cdbp[2]) {
 	case 0x00:
-		page_length = 4;
-
-		bzero(p, page_length + 4);
+		page_length = 4 + (mgmt_url_size ? 1 : 0);
 
 		p[0] = byte0;
 		p[3] = page_length;
-		p[5] = 0x80;
-		p[6] = 0x83;
-		p[7] = 0x86;
+		/* Supported VPD pages in ascending order */
+		{
+			uint8_t i = 5;
 
+			p[i++] = 0x80;
+			p[i++] = 0x83;
+			if (mgmt_url_size != 0)
+				p[i++] = 0x85;
+			p[i++] = 0x86;
+		}
+		xfer_size = page_length + 4;
 		break;
 
 	case 0x80:
@@ -1174,25 +1286,74 @@
 			page_length = sl->sl_serial_no_size;
 			bcopy(sl->sl_serial_no, p + 4, sl->sl_serial_no_size);
 		} else {
+			/* if no serial num is specified set 4 spaces */
+			page_length = 4;
 			bcopy("    ", p + 4, 4);
 		}
 		p[0] = byte0;
 		p[1] = 0x80;
 		p[3] = page_length;
+		xfer_size = page_length + 4;
 		break;
 
 	case 0x83:
-
-		page_length = stmf_scsilib_prepare_vpd_page83(task, p,
+		xfer_size = stmf_scsilib_prepare_vpd_page83(task, p,
 		    bsize, byte0, STMF_VPD_LU_ID|STMF_VPD_TARGET_ID|
-		    STMF_VPD_TP_GROUP|STMF_VPD_RELATIVE_TP_ID) - 4;
+		    STMF_VPD_TP_GROUP|STMF_VPD_RELATIVE_TP_ID);
 		break;
 
+	case 0x85:
+		if (mgmt_url_size == 0) {
+			stmf_scsilib_send_status(task, STATUS_CHECK,
+			    STMF_SAA_INVALID_FIELD_IN_CDB);
+			kmem_free(p, bsize);
+			return;
+		}
+		{
+			uint16_t idx, newidx, sz, url_size;
+			char *url;
+
+			p[0] = byte0;
+			p[1] = 0x85;
+
+			idx = 4;
+			url = sl->sl_mgmt_url;
+			url_size = sbd_parse_mgmt_url(&url);
+			/* Creating Network Service Descriptors */
+			while (url_size != 0) {
+				/* Null terminated and 4 Byte aligned */
+				sz = url_size + 1;
+				sz += (sz % 4) ? 4 - (sz % 4) : 0;
+				newidx = idx + sz + 4;
+
+				if (newidx < bsize) {
+					/*
+					 * SPC-3r23 : Table 320  (Sec 7.6.5)
+					 * (Network service descriptor format
+					 *
+					 * Note: Hard coding service type as
+					 * "Storage Configuration Service".
+					 */
+					p[idx] = 1;
+					SCSI_WRITE16(p + idx + 2, sz);
+					bcopy(url, p + idx + 4, url_size);
+					xfer_size = newidx + 4;
+				}
+				idx = newidx;
+
+				/* skip to next mgmt url if any */
+				url += url_size;
+				url_size = sbd_parse_mgmt_url(&url);
+			}
+
+			/* Total descriptor length */
+			SCSI_WRITE16(p + 2, idx - 4);
+			break;
+		}
+
 	case 0x86:
 		page_length = 0x3c;
 
-		bzero(p, page_length + 4);
-
 		p[0] = byte0;
 		p[1] = 0x86;		/* Page 86 response */
 		p[3] = page_length;
@@ -1204,17 +1365,19 @@
 		 * to claim support only for Simple TA.
 		 */
 		p[5] = 1;
-
+		xfer_size = page_length + 4;
 		break;
 
 	default:
 		stmf_scsilib_send_status(task, STATUS_CHECK,
 		    STMF_SAA_INVALID_FIELD_IN_CDB);
+		kmem_free(p, bsize);
 		return;
 	}
 
 	sbd_handle_short_read_transfers(task, initial_dbuf, p, cmd_size,
-	    min(cmd_size, page_length + 4));
+	    min(cmd_size, xfer_size));
+	kmem_free(p, bsize);
 }
 
 stmf_status_t
@@ -1424,11 +1587,7 @@
 	cdb1 = task->task_cdb[1];
 
 	if (cdb0 == SCMD_INQUIRY) {		/* Inquiry */
-		uint8_t *p;
-
-		p = (uint8_t *)kmem_zalloc(512, KM_SLEEP);
-		sbd_handle_inquiry(task, initial_dbuf, p, 512);
-		kmem_free(p, 512);
+		sbd_handle_inquiry(task, initial_dbuf);
 		return;
 	}
 
--- a/usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/uts/common/io/comstar/lu/stmf_sbd/stmf_sbd.h	Fri Jul 17 11:20:16 2009 -0700
@@ -145,7 +145,8 @@
 	uint8_t			sli_serial_size;
 	uint8_t			sli_rsvd1;
 	uint8_t			sli_device_id[20];
-	uint8_t			sli_rsvd2[256];
+	uint64_t		sli_mgmt_url_offset;
+	uint8_t			sli_rsvd2[248];
 
 	/*
 	 * In case there is no separate meta, sli_meta_fname_offset wont
@@ -169,6 +170,7 @@
 #define	SLI_ALIAS_VALID				0x0100
 #define	SLI_WRITEBACK_CACHE_DISABLE		0x0200
 #define	SLI_ZFS_META				0x0400
+#define	SLI_MGMT_URL_VALID			0x0800
 
 struct sbd_it_data;
 
@@ -189,6 +191,7 @@
 	/* Metadata */
 	char		*sl_alias;
 	char		*sl_meta_filename;	/* If applicable */
+	char		*sl_mgmt_url;
 	vnode_t		*sl_meta_vp;
 	vtype_t		sl_meta_vtype;
 	uint8_t		sl_device_id[20];	/* 4(hdr) + 16(GUID) */
@@ -203,7 +206,8 @@
 	char		sl_product_id[16];
 	char		sl_revision[4];
 	uint32_t	sl_data_fname_alloc_size; /* for an explicit alloc */
-	uint32_t	sl_alias_alloc_size;
+	uint16_t	sl_alias_alloc_size;
+	uint16_t	sl_mgmt_url_alloc_size;
 	uint8_t		sl_serial_no_alloc_size;
 	uint64_t	sl_meta_offset;
 
--- a/usr/src/uts/common/sys/stmf_sbd_ioctl.h	Fri Jul 17 12:06:50 2009 -0500
+++ b/usr/src/uts/common/sys/stmf_sbd_ioctl.h	Fri Jul 17 11:20:16 2009 -0700
@@ -83,6 +83,7 @@
 			slu_rev_valid:1,
 			slu_serial_valid:1,
 			slu_alias_valid:1,
+			slu_mgmt_url_valid:1,
 			slu_guid_valid:1,
 			slu_company_id_valid:1,
 			slu_writeback_cache_disable_valid:1,
@@ -98,8 +99,7 @@
 	uint16_t	slu_blksize;
 	uint32_t	slu_company_id;
 	uint16_t	slu_alias_off;
-	uint8_t		slu_rsvd2;
-	uint8_t		slu_rsvd;
+	uint16_t	slu_mgmt_url_off;
 	uint32_t	slu_rsvd1;
 	char		slu_rev[4];
 	char		slu_vid[8];
@@ -120,6 +120,7 @@
 	uint32_t	mlu_lu_size_valid:1,
 			mlu_serial_valid:1,
 			mlu_alias_valid:1,
+			mlu_mgmt_url_valid:1,
 			mlu_writeback_cache_disable_valid:1,
 			mlu_writeback_cache_disable:1,
 			mlu_write_protected_valid:1,
@@ -128,9 +129,12 @@
 			mlu_by_fname:1;
 	uint64_t	mlu_lu_size;
 	uint16_t	mlu_alias_off;
+	uint16_t	mlu_mgmt_url_off;
 	uint16_t	mlu_serial_off;
 	uint16_t	mlu_serial_size;
 	uint16_t	mlu_fname_off;
+	uint16_t	mlu_rsvd1;
+	uint32_t	mlu_rsvd2;
 	uint8_t		mlu_input_guid[16];
 	char		mlu_buf[8]; /* can be more than 8 */
 } sbd_modify_lu_t;
@@ -151,6 +155,7 @@
 			slp_data_fname_valid:1,
 			slp_zfs_meta:1,
 			slp_alias_valid:1,
+			slp_mgmt_url_valid:1,
 			slp_lu_vid:1,
 			slp_lu_pid:1,
 			slp_lu_rev:1,
@@ -165,6 +170,7 @@
 	uint16_t	slp_serial_off;
 	uint16_t	slp_blksize;
 	uint16_t	slp_alias_off;
+	uint16_t	slp_mgmt_url_off;
 	uint32_t	slp_buf_size_needed;	/* Upon return */
 	uint16_t	slp_serial_size;
 	uint16_t	slp_rsvd;