6795089 COMSTAR sbd lun provider should support PGR
authortim szeto <Tim.Szeto@Sun.COM>
Fri May 08 16:22:42 2009 -0600 (10 months ago)
changeset 9585bf09620212ab
parent 95845536d6df764d
child 9586bd5e99a50121
6795089 COMSTAR sbd lun provider should support PGR
6808269 Add interfaces for support of create/delete/modify logical unit
6824910 Allow persistence of configuration data to be optional
6794362 Add support for the SCSI direct-access block device Caching mode page
6749644 stmf/sbd getinfo(9E) entry point needs to be fixed
PSARC 2009/251 libstmf/stmfadm enhancements for COMSTAR
usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c
usr/src/cmd/sbdadm/Makefile
usr/src/cmd/sbdadm/sbdadm.c
usr/src/cmd/stmfadm/stmfadm.c
usr/src/common/cmdparse/cmdparse.c
usr/src/common/cmdparse/cmdparse.h
usr/src/lib/libstmf/Makefile.com
usr/src/lib/libstmf/common/libstmf.h
usr/src/lib/libstmf/common/libstmf_impl.h
usr/src/lib/libstmf/common/mapfile-vers
usr/src/lib/libstmf/common/stmf.c
usr/src/lib/libstmf/common/store.c
usr/src/lib/libstmf/common/store.h
usr/src/uts/common/Makefile.files
usr/src/uts/common/io/comstar/lu/stmf_sbd/filedisk.c
usr/src/uts/common/io/comstar/lu/stmf_sbd/memdisk.c
usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c
usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_impl.h
usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd_pgr.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/io/comstar/port/fct/fct.c
usr/src/uts/common/io/comstar/stmf/stmf.c
usr/src/uts/common/io/comstar/stmf/stmf_impl.h
usr/src/uts/common/sys/scsi/generic/persist.h
usr/src/uts/common/sys/stmf.h
usr/src/uts/common/sys/stmf_defines.h
usr/src/uts/common/sys/stmf_ioctl.h
usr/src/uts/common/sys/stmf_sbd_ioctl.h
       1 --- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c	Fri May 08 13:31:23 2009 -0700
       2 +++ b/usr/src/cmd/iscsi/iscsitgtd/t10_spc_pr.c	Fri May 08 16:22:42 2009 -0600
       3 @@ -674,6 +674,7 @@
       4  	int			i = 0, max_buf_rsrv, hsize;
       5  	spc_pr_rsrv_t		*rsrv;
       6  	scsi_prin_full_status_t	*buf = (scsi_prin_full_status_t *)bp;
       7 +	iscsi_transport_id_t	*tptid;
       8  
       9  	hsize = sizeof (buf->PRgeneration) + sizeof (buf->add_len);
      10  	max_buf_rsrv = ((int)alloc_len - hsize) /
      11 @@ -694,15 +695,15 @@
      12  			buf->full_desc[i].type = rsrv->r_type;
      13  			SCSI_WRITE16(buf->full_desc[i].rel_tgt_port_id, 0);
      14  			SCSI_WRITE32(buf->full_desc[i].add_len,
      15 -			    sizeof (scsi_transport_id_t));
      16 +			    sizeof (iscsi_transport_id_t));
      17  			buf->full_desc[i].trans_id.protocol_id =
      18  			    iSCSI_PROTOCOL_ID;
      19  			buf->full_desc[i].trans_id.format_code =
      20  			    WW_UID_DEVICE_NAME;
      21 -			SCSI_WRITE16(buf->full_desc[i].trans_id.add_len, 0);
      22 -			(void) sprintf(buf->full_desc[i].trans_id.iscsi_name,
      23 -			    "");
      24 -
      25 +			tptid = (iscsi_transport_id_t *)
      26 +			    &(buf->full_desc[i].trans_id);
      27 +			SCSI_WRITE16(tptid->add_len, 0);
      28 +			(void) sprintf(tptid->iscsi_name, "");
      29  			i++;
      30  		}
      31  		else
     1.1 --- a/usr/src/cmd/sbdadm/Makefile	Fri May 08 13:31:23 2009 -0700
     1.2 +++ b/usr/src/cmd/sbdadm/Makefile	Fri May 08 16:22:42 2009 -0600
     1.3 @@ -20,7 +20,7 @@
     1.4  #
     1.5  
     1.6  #
     1.7 -# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     1.8 +# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     1.9  # Use is subject to license terms.
    1.10  #
    1.11  
    1.12 @@ -41,7 +41,7 @@
    1.13  POFILES = $(LOCAL_OBJS:%.o=%.po)
    1.14   
    1.15  CPPFLAGS += -I. -I$(COMMONBASE)/cmdparse
    1.16 -LDLIBS += -lstmf -lnvpair
    1.17 +LDLIBS += -lstmf
    1.18  LINTFLAGS += -xerroff=E_BAD_PTR_CAST_ALIGN
    1.19  
    1.20  .KEEP_STATE:
     2.1 --- a/usr/src/cmd/sbdadm/sbdadm.c	Fri May 08 13:31:23 2009 -0700
     2.2 +++ b/usr/src/cmd/sbdadm/sbdadm.c	Fri May 08 16:22:42 2009 -0600
     2.3 @@ -19,7 +19,7 @@
     2.4   * CDDL HEADER END
     2.5   */
     2.6  /*
     2.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     2.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     2.9   * Use is subject to license terms.
    2.10   */
    2.11  #include <stdlib.h>
    2.12 @@ -36,48 +36,35 @@
    2.13  #include <strings.h>
    2.14  #include <ctype.h>
    2.15  #include <libnvpair.h>
    2.16 +#include <locale.h>
    2.17  
    2.18  #include <cmdparse.h>
    2.19  #include <sys/stmf_defines.h>
    2.20  #include <libstmf.h>
    2.21  #include <sys/stmf_sbd_ioctl.h>
    2.22  
    2.23 -#define	BIG_BUF_SIZE	512
    2.24  #define	MAX_LU_LIST	8192
    2.25  #define	LU_LIST_MAX_RETRIES 3
    2.26 +#define	GUID_INPUT  32
    2.27  
    2.28 -uint8_t big_buf[BIG_BUF_SIZE];
    2.29 +#define	VERSION_STRING_MAJOR	    "1"
    2.30 +#define	VERSION_STRING_MINOR	    "0"
    2.31 +#define	VERSION_STRING_MAX_LEN	    10
    2.32  
    2.33 +
    2.34 +char *cmdName;
    2.35 +
    2.36 +static char *getExecBasename(char *);
    2.37  int delete_lu(int argc, char *argv[], cmdOptions_t *options,
    2.38      void *callData);
    2.39  int create_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
    2.40 -int import_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
    2.41  int list_lus(int argc, char *argv[], cmdOptions_t *options, void *callData);
    2.42  int modify_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
    2.43 -static int persist_lu_register(char *, char *);
    2.44 -int print_lu_attr(uint64_t handle, char **s);
    2.45 +int import_lu(int argc, char *argv[], cmdOptions_t *options, void *callData);
    2.46 +static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
    2.47 +int print_lu_attr(stmfGuid *);
    2.48  void print_guid(uint8_t *g, FILE *f);
    2.49  void print_attr_header();
    2.50 -
    2.51 -char	*rlc_ret[] = {	"", "Metadata creation failed",
    2.52 -	"LU is not initialized",
    2.53 -	"File is already loaded",
    2.54 -	"GUID in the file is already registered",
    2.55 -	"Registration with framework failed",
    2.56 -	"Deregistration with stmf failed",
    2.57 -	"Unable to lookup file",
    2.58 -	"Incorrect file type to export as LU. Only regular \n"
    2.59 -	    "files and raw storage devices (disks/volumes) can be exported "
    2.60 -	    "as LUs",
    2.61 -	"Unable to open file",
    2.62 -	"Unable to get file attributes",
    2.63 -	"File size has to be at least 1M",
    2.64 -	"File size is not a multiple of blocksize",
    2.65 -	"LU size is out of range",
    2.66 -	"LU size is not supported by underlying Filesystem"
    2.67 -};
    2.68 -
    2.69 -char sbdadm_ver[] = "sbdadm version 1.0";
    2.70  
    2.71  optionTbl_t options[] = {
    2.72  	{ "disk-size", required_argument, 's',
    2.73 @@ -103,590 +90,445 @@
    2.74  	{ NULL, 0, 0, NULL, 0, NULL}
    2.75  };
    2.76  
    2.77 -int sbd_fd;
    2.78 +/*ARGSUSED*/
    2.79 +int
    2.80 +create_lu(int argc, char *operands[], cmdOptions_t *options, void *callData)
    2.81 +{
    2.82 +	luResource hdl = NULL;
    2.83 +	int ret = 0;
    2.84 +	stmfGuid createdGuid;
    2.85  
    2.86 -int
    2.87 -main(int argc, char *argv[])
    2.88 -{
    2.89 -	int ret, func_ret;
    2.90 -	synTables_t sbdt = { sbdadm_ver, options, subCommands };
    2.91 +	ret = stmfCreateLuResource(STMF_DISK, &hdl);
    2.92  
    2.93 -	sbd_fd = open("/devices/pseudo/stmf_sbd@0:admin", O_RDONLY);
    2.94 -	if (sbd_fd < 0) {
    2.95 -		if (errno == EPERM) {
    2.96 -			(void) fprintf(stderr, "Not enough permissions to open "
    2.97 -			    "device\n");
    2.98 -		} else {
    2.99 -			(void) fprintf(stderr,
   2.100 -			    "Unable to open device. Is the driver "
   2.101 -			    "attached ?\n");
   2.102 -		}
   2.103 -		exit(1);
   2.104 +	if (ret != STMF_STATUS_SUCCESS) {
   2.105 +		(void) fprintf(stderr, "%s: %s\n",
   2.106 +		    cmdName, gettext("Failure to create lu resource\n"));
   2.107 +		return (1);
   2.108  	}
   2.109 -	ret = cmdParse(argc, argv, sbdt, NULL, &func_ret);
   2.110  
   2.111 -	if (ret)
   2.112 -		return (ret);
   2.113 -	return (func_ret);
   2.114 -}
   2.115 -
   2.116 -/*
   2.117 - * Supports upto 8 Exabytes.
   2.118 - *
   2.119 - * Returns zero upon success and the size in sizep.
   2.120 - * returns 2 if the string format is invalid.
   2.121 - * returns 1 if the specified size is out of range.
   2.122 - */
   2.123 -int
   2.124 -str_to_size(char *str, uint64_t *sizep)
   2.125 -{
   2.126 -	uint64_t cur_size, m;
   2.127 -	uint64_t new_cur_size;
   2.128 -	int i;
   2.129 -	char c;
   2.130 -
   2.131 -	m = 1;
   2.132 -	cur_size = 0;
   2.133 -
   2.134 -	for (i = 0; str[i] != NULL; i++) {
   2.135 -		if (m != 1) {
   2.136 -			/* We should have been done after the modifier */
   2.137 -			return (2);
   2.138 -		}
   2.139 -		c = str[i];
   2.140 -		if (isdigit(c)) {
   2.141 -			new_cur_size = (cur_size * 10) +
   2.142 -			    (((uint64_t)c) - '0');
   2.143 -			if (new_cur_size < cur_size) {
   2.144 -				/* Overflow */
   2.145 +	for (; options->optval; options++) {
   2.146 +		switch (options->optval) {
   2.147 +			case 's':
   2.148 +				ret = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
   2.149 +				    options->optarg);
   2.150 +				if (ret != STMF_STATUS_SUCCESS) {
   2.151 +					(void) fprintf(stderr, "%s: %c: %s\n",
   2.152 +					    cmdName, options->optval,
   2.153 +					    gettext("size param invalid"));
   2.154 +					(void) stmfFreeLuResource(hdl);
   2.155 +					return (1);
   2.156 +				}
   2.157 +				break;
   2.158 +			default:
   2.159 +				(void) fprintf(stderr, "%s: %c: %s\n",
   2.160 +				    cmdName, options->optval,
   2.161 +				    gettext("unknown option"));
   2.162  				return (1);
   2.163 -			}
   2.164 -			cur_size = new_cur_size;
   2.165 -			continue;
   2.166 -		}
   2.167 -		if (cur_size == 0) {
   2.168 -			/* Direct format modifier ?? */
   2.169 -			return (2);
   2.170 -		}
   2.171 -		c = toupper(c);
   2.172 -		if (c == 'K') {
   2.173 -			m = 1024;
   2.174 -		} else if (c == 'M') {
   2.175 -			m = 1024 * 1024;
   2.176 -		} else if (c == 'G') {
   2.177 -			m = 1024 * 1024 * 1024;
   2.178 -		} else if (c == 'T') {
   2.179 -			m = 1024ll * 1024 * 1024 * 1024;
   2.180 -		} else if (c == 'P') {
   2.181 -			m = 1024ll * 1024 * 1024 * 1024 * 1024;
   2.182 -		} else if (c == 'E') {
   2.183 -			m = 1024ll * 1024 * 1024 * 1024 * 1024 * 1024;
   2.184 -		} else {
   2.185 -			return (2);
   2.186  		}
   2.187  	}
   2.188  
   2.189 -	while (m > 1) {
   2.190 -		if (cur_size & 0x8000000000000000ull) {
   2.191 -			/* Overflow */
   2.192 -			return (1);
   2.193 -		}
   2.194 -		cur_size <<= 1;
   2.195 -		m >>= 1;
   2.196 -	}
   2.197 +	ret = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
   2.198  
   2.199 -	if (cur_size > 0x8000000000000000ull) {
   2.200 -		/* We cannot allow more than 8 Exabytes */
   2.201 +	if (ret != STMF_STATUS_SUCCESS) {
   2.202 +		(void) fprintf(stderr, "%s: %s\n",
   2.203 +		    cmdName, gettext("could not set filename"));
   2.204  		return (1);
   2.205  	}
   2.206  
   2.207 -	*sizep = cur_size;
   2.208 +	ret = stmfCreateLu(hdl, &createdGuid);
   2.209 +	switch (ret) {
   2.210 +		case STMF_STATUS_SUCCESS:
   2.211 +			break;
   2.212 +		case STMF_ERROR_BUSY:
   2.213 +		case STMF_ERROR_LU_BUSY:
   2.214 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.215 +			    gettext("resource busy"));
   2.216 +			ret++;
   2.217 +			break;
   2.218 +		case STMF_ERROR_PERM:
   2.219 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.220 +			    gettext("permission denied"));
   2.221 +			ret++;
   2.222 +			break;
   2.223 +		case STMF_ERROR_FILE_IN_USE:
   2.224 +			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
   2.225 +			    operands[0], gettext("in use"));
   2.226 +			ret++;
   2.227 +			break;
   2.228 +		case STMF_ERROR_INVALID_BLKSIZE:
   2.229 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.230 +			    gettext("invalid block size"));
   2.231 +			ret++;
   2.232 +			break;
   2.233 +		case STMF_ERROR_GUID_IN_USE:
   2.234 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.235 +			    gettext("guid in use"));
   2.236 +			ret++;
   2.237 +			break;
   2.238 +		case STMF_ERROR_META_FILE_NAME:
   2.239 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.240 +			    gettext("meta file error"));
   2.241 +			ret++;
   2.242 +			break;
   2.243 +		case STMF_ERROR_DATA_FILE_NAME:
   2.244 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.245 +			    gettext("data file error"));
   2.246 +			ret++;
   2.247 +			break;
   2.248 +		case STMF_ERROR_SIZE_OUT_OF_RANGE:
   2.249 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.250 +			    gettext("invalid size"));
   2.251 +			ret++;
   2.252 +			break;
   2.253 +		case STMF_ERROR_META_CREATION:
   2.254 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.255 +			    gettext("could not create meta file"));
   2.256 +			ret++;
   2.257 +			break;
   2.258 +		default:
   2.259 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.260 +			    gettext("unknown error"));
   2.261 +			ret++;
   2.262 +			break;
   2.263 +	}
   2.264  
   2.265 -	return (0);
   2.266 -}
   2.267 +	if (ret != STMF_STATUS_SUCCESS) {
   2.268 +		goto done;
   2.269 +	}
   2.270  
   2.271 -static int
   2.272 -persist_lu_register(char *guid, char *filename)
   2.273 -{
   2.274 -	int ret = 0;
   2.275 -	nvlist_t *nvl = NULL;
   2.276 -	uint64_t setToken;
   2.277 -	boolean_t		retryGetProviderData;
   2.278 +	(void) printf("Created the following LU:\n");
   2.279 +	print_attr_header();
   2.280 +	ret = print_lu_attr(&createdGuid);
   2.281  
   2.282 -	do {
   2.283 -		retryGetProviderData = B_FALSE;
   2.284 -		ret = stmfGetProviderDataProt("sbd", &nvl,
   2.285 -		    STMF_LU_PROVIDER_TYPE, &setToken);
   2.286 -		if (ret != STMF_STATUS_SUCCESS) {
   2.287 -			if (ret == STMF_ERROR_NOT_FOUND) {
   2.288 -				(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
   2.289 -			} else {
   2.290 -				(void) fprintf(stderr,
   2.291 -				    "could not access persistent store\n");
   2.292 -				ret = 1;
   2.293 -				goto out;
   2.294 -			}
   2.295 -		}
   2.296 -
   2.297 -		ret = nvlist_add_string(nvl, guid, filename);
   2.298 -		if (ret != 0) {
   2.299 -			(void) fprintf(stderr,
   2.300 -			    "could not add data to nvlist\n");
   2.301 -			ret = 1;
   2.302 -			goto out;
   2.303 -		}
   2.304 -
   2.305 -		ret = stmfSetProviderDataProt("sbd", nvl, STMF_LU_PROVIDER_TYPE,
   2.306 -		    &setToken);
   2.307 -		if (ret != STMF_STATUS_SUCCESS) {
   2.308 -			if (ret == STMF_ERROR_BUSY) {
   2.309 -				(void) fprintf(stderr,
   2.310 -				    "stmf framework resource busy\n");
   2.311 -			} else if (ret == STMF_ERROR_PROV_DATA_STALE) {
   2.312 -				nvlist_free(nvl);
   2.313 -				nvl = NULL;
   2.314 -				retryGetProviderData = B_TRUE;
   2.315 -				continue;
   2.316 -			} else {
   2.317 -				(void) fprintf(stderr,
   2.318 -				    "unable to set persistent store data\n");
   2.319 -			}
   2.320 -			ret = 1;
   2.321 -			goto out;
   2.322 -		}
   2.323 -	} while (retryGetProviderData);
   2.324 -out:
   2.325 -	nvlist_free(nvl);
   2.326 +done:
   2.327 +	(void) stmfFreeLuResource(hdl);
   2.328  	return (ret);
   2.329  }
   2.330  
   2.331  /*ARGSUSED*/
   2.332  int
   2.333 -create_lu(int argc, char *argv[], cmdOptions_t *options, void *callData)
   2.334 +import_lu(int argc, char *operands[], cmdOptions_t *options, void *callData)
   2.335  {
   2.336 -	register_lu_cmd_t *rlc;
   2.337 -	uint32_t fl;
   2.338 -	int ret = 0, err;
   2.339 -	uint64_t size;
   2.340 -	char guidAsciiBuf[33];
   2.341 +	int ret = 0;
   2.342 +	stmfGuid createdGuid;
   2.343  
   2.344 -	/* Check whether this file path is absolute path */
   2.345 -	if (argv[argc - 1][0] != '/') {
   2.346 -		(void) fprintf(stderr, "File name should be an absolute path"
   2.347 -		    " i.e. it should start with a /\n");
   2.348 -		return (1);
   2.349 +	ret = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
   2.350 +	switch (ret) {
   2.351 +		case STMF_STATUS_SUCCESS:
   2.352 +			break;
   2.353 +		case STMF_ERROR_BUSY:
   2.354 +		case STMF_ERROR_LU_BUSY:
   2.355 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.356 +			    gettext("resource busy"));
   2.357 +			ret++;
   2.358 +			break;
   2.359 +		case STMF_ERROR_PERM:
   2.360 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.361 +			    gettext("permission denied"));
   2.362 +			ret++;
   2.363 +			break;
   2.364 +		case STMF_ERROR_FILE_IN_USE:
   2.365 +			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
   2.366 +			    operands[0], gettext("in use"));
   2.367 +			ret++;
   2.368 +			break;
   2.369 +		case STMF_ERROR_GUID_IN_USE:
   2.370 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.371 +			    gettext("guid in use"));
   2.372 +			ret++;
   2.373 +			break;
   2.374 +		case STMF_ERROR_META_FILE_NAME:
   2.375 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.376 +			    gettext("meta file error"));
   2.377 +			ret++;
   2.378 +			break;
   2.379 +		case STMF_ERROR_DATA_FILE_NAME:
   2.380 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.381 +			    gettext("data file error"));
   2.382 +			ret++;
   2.383 +			break;
   2.384 +		case STMF_ERROR_SIZE_OUT_OF_RANGE:
   2.385 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.386 +			    gettext("invalid size"));
   2.387 +			ret++;
   2.388 +			break;
   2.389 +		case STMF_ERROR_META_CREATION:
   2.390 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.391 +			    gettext("could not create meta file"));
   2.392 +			ret++;
   2.393 +			break;
   2.394 +		default:
   2.395 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.396 +			    gettext("unknown error"));
   2.397 +			ret++;
   2.398 +			break;
   2.399  	}
   2.400  
   2.401 -	fl = strlen(argv[argc - 1]) + 1;
   2.402 -	rlc = (register_lu_cmd_t *)malloc(sizeof (register_lu_cmd_t) + fl - 8);
   2.403 -	if (rlc == NULL) {
   2.404 -		(void) fprintf(stderr, "Unable to allocate memory\n");
   2.405 -		return (1);
   2.406 -	}
   2.407 -	bzero(rlc, sizeof (register_lu_cmd_t));
   2.408 -	rlc->total_struct_size = sizeof (register_lu_cmd_t) + fl - 8;
   2.409 -
   2.410 -	rlc->flags = RLC_LU_TYPE_FILEDISK | RLC_CREATE_LU | RLC_REGISTER_LU;
   2.411 -	for (; options->optval; options++) {
   2.412 -		if (options->optval == 's') {
   2.413 -			err = str_to_size(options->optarg, &size);
   2.414 -			if (err == 1) {
   2.415 -				(void) fprintf(stderr,
   2.416 -				    "Size out of range: maximum"
   2.417 -				    " supported size is 9223372036854710272"
   2.418 -				    " (8 Exabytes - 64 Kilobytes)\n");
   2.419 -				ret = 1;
   2.420 -				goto create_lu_done;
   2.421 -			} else if (err == 2) {
   2.422 -				(void) fprintf(stderr,
   2.423 -				    "Invalid size specified\n");
   2.424 -				ret = 1;
   2.425 -				goto create_lu_done;
   2.426 -			}
   2.427 -			rlc->lu_size = size;
   2.428 -		}
   2.429 -	}
   2.430 -	(void) strcpy(rlc->name, argv[argc-1]);
   2.431 -	if ((ioctl(sbd_fd, SBD_REGISTER_LU, rlc) < 0) ||
   2.432 -	    (rlc->return_code != 0) || (rlc->op_ret != STMF_SUCCESS)) {
   2.433 -		if (rlc->return_code && (rlc->return_code < RLC_RET_MAX_VAL)) {
   2.434 -			(void) fprintf(stderr, "LU Create failed : %s.\n",
   2.435 -			    rlc_ret[rlc->return_code]);
   2.436 -			if (rlc->return_code ==
   2.437 -			    RLC_RET_SIZE_NOT_SUPPORTED_BY_FS) {
   2.438 -				(void) fprintf(stderr, "Maximum LU size on "
   2.439 -				    "the underlying filesystem can be %llu "
   2.440 -				    "bytes.\n",
   2.441 -				    ((((uint64_t)1) << rlc->filesize_nbits)
   2.442 -				    - 1 - 64 * 1024) & 0xfffffffffffffe00ull);
   2.443 -			}
   2.444 -			if (rlc->return_code ==
   2.445 -			    RLC_RET_GUID_ALREADY_REGISTERED) {
   2.446 -				(void) fprintf(stderr, "Registered GUID is ");
   2.447 -				print_guid(rlc->guid, stderr);
   2.448 -				(void) fprintf(stderr, "\n");
   2.449 -			}
   2.450 -		} else {
   2.451 -			(void) fprintf(stderr, "LU Create failed(%llx) : %s.\n",
   2.452 -			    rlc->op_ret, strerror(errno));
   2.453 -		}
   2.454 -		ret = 1;
   2.455 -	} else {
   2.456 -		if (rlc->flags & RLC_REGISTER_LU) {
   2.457 -			(void) printf("\nCreated the following LU:\n");
   2.458 -			print_attr_header();
   2.459 -			(void) print_lu_attr(rlc->lu_handle, NULL);
   2.460 -			(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
   2.461 -			    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
   2.462 -			    "%02x%02x%02x%02x%02x%02x",
   2.463 -			    rlc->guid[0], rlc->guid[1], rlc->guid[2],
   2.464 -			    rlc->guid[3], rlc->guid[4], rlc->guid[5],
   2.465 -			    rlc->guid[6], rlc->guid[7], rlc->guid[8],
   2.466 -			    rlc->guid[9], rlc->guid[10], rlc->guid[11],
   2.467 -			    rlc->guid[12], rlc->guid[13], rlc->guid[14],
   2.468 -			    rlc->guid[15]);
   2.469 -
   2.470 -			ret = persist_lu_register(guidAsciiBuf, argv[argc - 1]);
   2.471 -		}
   2.472 +	if (ret != STMF_STATUS_SUCCESS) {
   2.473 +		goto done;
   2.474  	}
   2.475  
   2.476 -create_lu_done:;
   2.477 -	free(rlc);
   2.478 +	(void) printf("Imported the following LU:\n");
   2.479 +	print_attr_header();
   2.480 +	ret = print_lu_attr(&createdGuid);
   2.481 +
   2.482 +done:
   2.483  	return (ret);
   2.484  }
   2.485  
   2.486  /*ARGSUSED*/
   2.487  int
   2.488 -import_lu(int argc, char *argv[], cmdOptions_t *options, void *callData)
   2.489 +delete_lu(int operandLen, char *operands[], cmdOptions_t *options,
   2.490 +    void *callData)
   2.491  {
   2.492 -	register_lu_cmd_t *rlc;
   2.493 -	uint32_t fl;
   2.494 +	int i, j;
   2.495  	int ret = 0;
   2.496 -	char guidAsciiBuf[33];
   2.497 +	int stmfRet;
   2.498 +	unsigned int inGuid[sizeof (stmfGuid)];
   2.499 +	stmfGuid delGuid;
   2.500 +	boolean_t keepViews = B_FALSE;
   2.501 +	boolean_t viewEntriesRemoved = B_FALSE;
   2.502 +	boolean_t noLunFound = B_FALSE;
   2.503 +	boolean_t views = B_FALSE;
   2.504 +	char sGuid[GUID_INPUT + 1];
   2.505 +	stmfViewEntryList *viewEntryList = NULL;
   2.506  
   2.507 -	/* Check whether this file path is absolute path */
   2.508 -	if (argv[argc - 1][0] != '/') {
   2.509 -		(void) fprintf(stderr, "File name should be an absolute path"
   2.510 -		    " i.e. it should start with a /\n");
   2.511 -		return (1);
   2.512 -	}
   2.513 -
   2.514 -	fl = strlen(argv[argc - 1]) + 1;
   2.515 -	rlc = (register_lu_cmd_t *)malloc(sizeof (register_lu_cmd_t) + fl - 8);
   2.516 -	if (rlc == NULL) {
   2.517 -		(void) fprintf(stderr, "Unable to allocate memory\n");
   2.518 -		return (1);
   2.519 -	}
   2.520 -	bzero(rlc, sizeof (register_lu_cmd_t));
   2.521 -	rlc->total_struct_size = sizeof (register_lu_cmd_t) + fl - 8;
   2.522 -
   2.523 -	rlc->flags = RLC_LU_TYPE_FILEDISK | RLC_REGISTER_LU;
   2.524 -	(void) strcpy(rlc->name, argv[argc-1]);
   2.525 -	if ((ioctl(sbd_fd, SBD_REGISTER_LU, rlc) < 0) ||
   2.526 -	    (rlc->return_code != 0) || (rlc->op_ret != STMF_SUCCESS)) {
   2.527 -		if (rlc->return_code && (rlc->return_code < RLC_RET_MAX_VAL)) {
   2.528 -			(void) fprintf(stderr, "LU import failed : %s.\n",
   2.529 -			    rlc_ret[rlc->return_code]);
   2.530 -			if (rlc->return_code ==
   2.531 -			    RLC_RET_SIZE_NOT_SUPPORTED_BY_FS) {
   2.532 -				(void) fprintf(stderr, "Maximum LU size on "
   2.533 -				    "the underlying filesystem can be %llu "
   2.534 -				    "bytes.\n",
   2.535 -				    ((((uint64_t)1) << rlc->filesize_nbits)
   2.536 -				    - 1 - 64 * 1024) & 0xfffffffffffffe00ull);
   2.537 -			}
   2.538 -			if (rlc->return_code ==
   2.539 -			    RLC_RET_GUID_ALREADY_REGISTERED) {
   2.540 -				(void) fprintf(stderr, "Registered GUID is ");
   2.541 -				print_guid(rlc->guid, stderr);
   2.542 -				(void) fprintf(stderr, "\n");
   2.543 -			}
   2.544 -		} else {
   2.545 -			(void) fprintf(stderr, "LU import failed(%llx) : %s.\n",
   2.546 -			    rlc->op_ret, strerror(errno));
   2.547 -		}
   2.548 -		ret = 1;
   2.549 -	} else {
   2.550 -		if (rlc->flags & RLC_REGISTER_LU) {
   2.551 -			(void) printf("\nImported the following LU:\n");
   2.552 -			print_attr_header();
   2.553 -			(void) print_lu_attr(rlc->lu_handle, NULL);
   2.554 -			(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
   2.555 -			    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
   2.556 -			    "%02x%02x%02x%02x%02x%02x",
   2.557 -			    rlc->guid[0], rlc->guid[1], rlc->guid[2],
   2.558 -			    rlc->guid[3], rlc->guid[4], rlc->guid[5],
   2.559 -			    rlc->guid[6], rlc->guid[7], rlc->guid[8],
   2.560 -			    rlc->guid[9], rlc->guid[10], rlc->guid[11],
   2.561 -			    rlc->guid[12], rlc->guid[13], rlc->guid[14],
   2.562 -			    rlc->guid[15]);
   2.563 -
   2.564 -			ret = persist_lu_register(guidAsciiBuf, argv[argc - 1]);
   2.565 +	for (; options->optval; options++) {
   2.566 +		switch (options->optval) {
   2.567 +			/* Keep views for logical unit */
   2.568 +			case 'k':
   2.569 +				keepViews = B_TRUE;
   2.570 +				break;
   2.571 +			default:
   2.572 +				(void) fprintf(stderr, "%s: %c: %s\n",
   2.573 +				    cmdName, options->optval,
   2.574 +				    gettext("unknown option"));
   2.575 +				return (1);
   2.576  		}
   2.577  	}
   2.578  
   2.579 -import_lu_done:;
   2.580 -	free(rlc);
   2.581 +
   2.582 +	for (i = 0; i < operandLen; i++) {
   2.583 +		for (j = 0; j < GUID_INPUT; j++) {
   2.584 +			if (!isxdigit(operands[i][j])) {
   2.585 +				break;
   2.586 +			}
   2.587 +			sGuid[j] = tolower(operands[i][j]);
   2.588 +		}
   2.589 +		if (j != GUID_INPUT) {
   2.590 +			(void) fprintf(stderr, "%s: %s: %s%d%s\n",
   2.591 +			    cmdName, operands[i], gettext("must be "),
   2.592 +			    GUID_INPUT,
   2.593 +			    gettext(" hexadecimal digits long"));
   2.594 +			ret++;
   2.595 +			continue;
   2.596 +		}
   2.597 +
   2.598 +		sGuid[j] = 0;
   2.599 +
   2.600 +		(void) sscanf(sGuid,
   2.601 +		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   2.602 +		    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
   2.603 +		    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
   2.604 +		    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
   2.605 +		    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
   2.606 +
   2.607 +		for (j = 0; j < sizeof (stmfGuid); j++) {
   2.608 +			delGuid.guid[j] = inGuid[j];
   2.609 +		}
   2.610 +
   2.611 +		stmfRet = stmfDeleteLu(&delGuid);
   2.612 +		switch (stmfRet) {
   2.613 +			case STMF_STATUS_SUCCESS:
   2.614 +				break;
   2.615 +			case STMF_ERROR_NOT_FOUND:
   2.616 +				noLunFound = B_TRUE;
   2.617 +				break;
   2.618 +			case STMF_ERROR_BUSY:
   2.619 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.620 +				    gettext("resource busy"));
   2.621 +				ret++;
   2.622 +				break;
   2.623 +			case STMF_ERROR_PERM:
   2.624 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.625 +				    gettext("permission denied"));
   2.626 +				ret++;
   2.627 +				break;
   2.628 +			default:
   2.629 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.630 +				    gettext("unknown error"));
   2.631 +				ret++;
   2.632 +				break;
   2.633 +		}
   2.634 +
   2.635 +		if (!keepViews) {
   2.636 +			stmfRet = stmfGetViewEntryList(&delGuid,
   2.637 +			    &viewEntryList);
   2.638 +			if (stmfRet == STMF_STATUS_SUCCESS) {
   2.639 +				for (j = 0; j < viewEntryList->cnt; j++) {
   2.640 +					(void) stmfRemoveViewEntry(&delGuid,
   2.641 +					    viewEntryList->ve[j].veIndex);
   2.642 +				}
   2.643 +				viewEntriesRemoved = B_TRUE;
   2.644 +				stmfFreeMemory(viewEntryList);
   2.645 +			} else if (stmfRet != STMF_ERROR_NOT_FOUND) {
   2.646 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.647 +				    gettext("unable to remove view entries\n"));
   2.648 +				ret++;
   2.649 +			} /* No view entries to remove */
   2.650 +		}
   2.651 +		if (keepViews) {
   2.652 +			stmfRet = stmfGetViewEntryList(&delGuid,
   2.653 +			    &viewEntryList);
   2.654 +			if (stmfRet == STMF_STATUS_SUCCESS) {
   2.655 +				views = B_TRUE;
   2.656 +				stmfFreeMemory(viewEntryList);
   2.657 +			}
   2.658 +		}
   2.659 +
   2.660 +		if ((!viewEntriesRemoved && noLunFound && !views) ||
   2.661 +		    (!views && keepViews && noLunFound)) {
   2.662 +			(void) fprintf(stderr, "%s: %s: %s\n",
   2.663 +			    cmdName, sGuid,
   2.664 +			    gettext("not found"));
   2.665 +			ret++;
   2.666 +		}
   2.667 +		noLunFound = viewEntriesRemoved = views = B_FALSE;
   2.668 +	}
   2.669  	return (ret);
   2.670  }
   2.671  
   2.672  /*ARGSUSED*/
   2.673  int
   2.674 -delete_lu(int argc, char *argv[], cmdOptions_t *options, void *callData)
   2.675 +modify_lu(int operandLen, char *operands[], cmdOptions_t *options,
   2.676 +    void *callData)
   2.677  {
   2.678 -	deregister_lu_cmd_t	drlc;
   2.679 -	int			ret = 0, i;
   2.680 -	char			chstr[3], *pend = NULL;
   2.681 -	uint32_t		ch, off = 0;
   2.682 -	int			exists = 0;
   2.683 -	char			guidAsciiBuf[33];
   2.684 -	nvlist_t		*nvl = NULL;
   2.685 +	stmfGuid inGuid;
   2.686 +	unsigned int guid[sizeof (stmfGuid)];
   2.687 +	int ret = 0;
   2.688 +	int i;
   2.689 +	char *fname = NULL;
   2.690 +	char sGuid[GUID_INPUT + 1];
   2.691 +	boolean_t fnameUsed = B_FALSE;
   2.692  
   2.693 -	int			stmf_ret;
   2.694 -	int			keep_view = 0;
   2.695 -	uint64_t		setToken;
   2.696 -	stmfGuid		inGuid;
   2.697 -	stmfViewEntryList	*viewEntryList;
   2.698 -	boolean_t		retryGetProviderData;
   2.699 +	if (operands[0][0] == '/') {
   2.700 +		fnameUsed = B_TRUE;
   2.701 +		fname = operands[0];
   2.702 +	}
   2.703 +
   2.704 +	/* check input length */
   2.705 +	if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
   2.706 +		(void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
   2.707 +		    gettext("must be "), GUID_INPUT,
   2.708 +		    gettext(" hexadecimal digits"));
   2.709 +		return (1);
   2.710 +	}
   2.711 +
   2.712 +	if (!fnameUsed) {
   2.713 +		/* convert to lower case for scan */
   2.714 +		for (i = 0; i < 32; i++)
   2.715 +			sGuid[i] = tolower(operands[0][i]);
   2.716 +		sGuid[i] = 0;
   2.717 +		(void) sscanf(sGuid,
   2.718 +		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   2.719 +		    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
   2.720 +		    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
   2.721 +		    &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
   2.722 +
   2.723 +		for (i = 0; i < sizeof (stmfGuid); i++) {
   2.724 +			inGuid.guid[i] = guid[i];
   2.725 +		}
   2.726 +	}
   2.727  
   2.728  	for (; options->optval; options++) {
   2.729  		switch (options->optval) {
   2.730 -		case 'k':
   2.731 -			keep_view = 1;
   2.732 -			break;
   2.733 +			case 's':
   2.734 +				if (callModify(fname, &inGuid,
   2.735 +				    STMF_LU_PROP_SIZE, options->optarg,
   2.736 +				    "size") != 0) {
   2.737 +					return (1);
   2.738 +				}
   2.739 +				break;
   2.740 +			default:
   2.741 +				(void) fprintf(stderr, "%s: %c: %s\n",
   2.742 +				    cmdName, options->optval,
   2.743 +				    gettext("unknown option"));
   2.744 +				return (1);
   2.745  		}
   2.746  	}
   2.747 -
   2.748 -	if (strlen(argv[argc - 1]) != 32) {
   2.749 -		(void) fprintf(stderr, "GUID must be 32 characters\n");
   2.750 -		ret = 1;
   2.751 -		goto delete_lu_done;
   2.752 -	}
   2.753 -
   2.754 -	for (i = 0; i < 32; i++) {
   2.755 -		guidAsciiBuf[i] = tolower(argv[argc - 1][i]);
   2.756 -	}
   2.757 -
   2.758 -	guidAsciiBuf[i] = 0;
   2.759 -
   2.760 -	do {
   2.761 -		retryGetProviderData = B_FALSE;
   2.762 -		stmf_ret = stmfGetProviderDataProt("sbd", &nvl,
   2.763 -		    STMF_LU_PROVIDER_TYPE, &setToken);
   2.764 -		if (stmf_ret != STMF_STATUS_SUCCESS) {
   2.765 -			(void) fprintf(stderr,
   2.766 -			    "Could not access persistent store\n");
   2.767 -			ret = 1;
   2.768 -			goto delete_lu_done;
   2.769 -		}
   2.770 -		ret = nvlist_remove(nvl, guidAsciiBuf, DATA_TYPE_STRING);
   2.771 -		if (ret == 0) {
   2.772 -			exists = 1;
   2.773 -			stmf_ret = stmfSetProviderDataProt("sbd", nvl,
   2.774 -			    STMF_LU_PROVIDER_TYPE, &setToken);
   2.775 -			if (stmf_ret != STMF_STATUS_SUCCESS) {
   2.776 -				if (stmf_ret == STMF_ERROR_BUSY) {
   2.777 -					(void) fprintf(stderr,
   2.778 -					    "stmf framework resource busy\n");
   2.779 -				} else if (stmf_ret ==
   2.780 -				    STMF_ERROR_PROV_DATA_STALE) {
   2.781 -					/*
   2.782 -					 * update failed, try again
   2.783 -					 */
   2.784 -					nvlist_free(nvl);
   2.785 -					nvl = NULL;
   2.786 -					retryGetProviderData = B_TRUE;
   2.787 -					continue;
   2.788 -				} else {
   2.789 -					(void) fprintf(stderr,
   2.790 -					    "unable to set persistent store "
   2.791 -					    "data\n");
   2.792 -				}
   2.793 -				ret = 1;
   2.794 -				goto delete_lu_done;
   2.795 -			}
   2.796 -		}
   2.797 -	} while (retryGetProviderData);
   2.798 -
   2.799 -	bzero(&drlc, sizeof (drlc));
   2.800 -	drlc.total_struct_size = sizeof (drlc);
   2.801 -	drlc.flags = RLC_DEREGISTER_LU;
   2.802 -
   2.803 -	chstr[2] = 0;
   2.804 -	i = 0;
   2.805 -	while ((off + 2) <= strlen(argv[argc - 1])) {
   2.806 -		bcopy(argv[argc -1] + off, chstr, 2);
   2.807 -		off += 2;
   2.808 -
   2.809 -		if (!isxdigit(chstr[0]) || !isxdigit(chstr[1])) {
   2.810 -			(void) fprintf(stderr, "Invalid LU GUID specified.\n");
   2.811 -			ret = 1;
   2.812 -			goto delete_lu_done;
   2.813 -		}
   2.814 -		errno = 0;
   2.815 -		ch = strtoul(chstr, &pend, 16);
   2.816 -		if (errno != 0) {
   2.817 -			(void) fprintf(stderr, "Invalid LU GUID specified.\n");
   2.818 -			ret = 1;
   2.819 -			goto delete_lu_done;
   2.820 -		}
   2.821 -		drlc.guid[i++] = ch;
   2.822 -
   2.823 -	}
   2.824 -
   2.825 -	if (ioctl(sbd_fd, SBD_DEREGISTER_LU, &drlc) < 0) {
   2.826 -		if (errno != ENODEV) {
   2.827 -			(void) fprintf(stderr,
   2.828 -			    "Request to delete LU failed: %s\n",
   2.829 -			    strerror(errno));
   2.830 -			ret = 1;
   2.831 -			goto delete_lu_done;
   2.832 -		}
   2.833 -	} else if (drlc.return_code != 0) {
   2.834 -		(void) fprintf(stderr, "LU deregister failed: ret_code-%x",
   2.835 -		    drlc.return_code);
   2.836 -		ret = 1;
   2.837 -		goto delete_lu_done;
   2.838 -	} else {
   2.839 -		exists = 1;
   2.840 -	}
   2.841 -
   2.842 -	if (!keep_view) {
   2.843 -		for (i = 0; i < 16; i++)
   2.844 -			inGuid.guid[i] = drlc.guid[i];
   2.845 -
   2.846 -		if ((stmf_ret = stmfGetViewEntryList(&inGuid,
   2.847 -		    &viewEntryList)) == STMF_STATUS_SUCCESS) {
   2.848 -			for (i = 0; i < viewEntryList->cnt; i++) {
   2.849 -				(void) stmfRemoveViewEntry(&inGuid,
   2.850 -				    viewEntryList->ve[i].veIndex);
   2.851 -			}
   2.852 -		} else if (stmf_ret != STMF_ERROR_NOT_FOUND) {
   2.853 -			(void) fprintf(stderr,
   2.854 -			    "unable to remove view entries\n");
   2.855 -			ret = 1;
   2.856 -		}
   2.857 -	}
   2.858 -
   2.859 -	if (!exists) {
   2.860 -		(void) fprintf(stderr, "GUID not found.\n");
   2.861 -		ret = 1;
   2.862 -		goto delete_lu_done;
   2.863 -	}
   2.864 -
   2.865 -delete_lu_done:;
   2.866  	return (ret);
   2.867  }
   2.868  
   2.869 -/*ARGSUSED*/
   2.870 -int
   2.871 -modify_lu(int argc, char *argv[], cmdOptions_t *options, void *callData)
   2.872 +static int
   2.873 +callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
   2.874 +    const char *propString)
   2.875  {
   2.876 -	modify_lu_cmd_t *mlc;
   2.877 -	uint32_t fl = 0, struct_size;
   2.878 -	int ret = 0, err;
   2.879 -	int i = 0;
   2.880 -	uint64_t size;
   2.881 -	int is_filename = 0;
   2.882 -	char chstr[3], *pend = NULL;
   2.883 -	uint32_t ch;
   2.884 -	uint32_t off = 0;
   2.885 +	int ret = 0;
   2.886 +	int stmfRet = 0;
   2.887  
   2.888 -	if (argv[argc - 1][0] == '/') {
   2.889 -		is_filename = 1;
   2.890 -		fl = strlen(argv[argc - 1]) + 1;
   2.891 -		struct_size = sizeof (modify_lu_cmd_t) + fl - 8;
   2.892 +	if (!fname) {
   2.893 +		stmfRet = stmfModifyLu(luGuid, prop, propVal);
   2.894  	} else {
   2.895 -		struct_size = sizeof (modify_lu_cmd_t);
   2.896 +		stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
   2.897 +		    propVal);
   2.898  	}
   2.899 -	mlc = (modify_lu_cmd_t *)malloc(struct_size);
   2.900 -	if (mlc == NULL) {
   2.901 -		(void) fprintf(stderr, "Unable to allocate memory\n");
   2.902 -		return (1);
   2.903 -	}
   2.904 -	bzero(mlc, sizeof (modify_lu_cmd_t));
   2.905 -	mlc->total_struct_size = struct_size;
   2.906 -
   2.907 -	mlc->flags = RLC_LU_TYPE_FILEDISK | RLC_CREATE_LU;
   2.908 -	for (; options->optval; options++) {
   2.909 -		if (options->optval == 's') {
   2.910 -			err = str_to_size(options->optarg, &size);
   2.911 -			if (err == 1) {
   2.912 -				(void) fprintf(stderr,
   2.913 -				    "Size out of range: maximum"
   2.914 -				    " supported size is 9223372036854775808"
   2.915 -				    " (8 Exabytes)\n");
   2.916 -				ret = 1;
   2.917 -				goto modify_lu_done;
   2.918 -			} else if (err == 2) {
   2.919 -				(void) fprintf(stderr,
   2.920 -				    "Invalid size specified\n");
   2.921 -				ret = 1;
   2.922 -				goto modify_lu_done;
   2.923 -			}
   2.924 -			mlc->lu_size = size;
   2.925 -		}
   2.926 -	}
   2.927 -	if (is_filename) {
   2.928 -		(void) strcpy(mlc->name, argv[argc-1]);
   2.929 -		(void) memset(mlc->guid, 0, 16);
   2.930 -	} else {
   2.931 -		if (strlen(argv[argc - 1]) != 32) {
   2.932 -			(void) fprintf(stderr,
   2.933 -			    "Invalid device identifier or filename"
   2.934 -			    " specified.\nIf it is a filename, it should be an"
   2.935 -			    " absolute path i.e. it should start with a /\n");
   2.936 -			goto modify_lu_done;
   2.937 -		}
   2.938 -		chstr[2] = 0;
   2.939 -		i = 0;
   2.940 -		while ((off + 2) <= strlen(argv[argc - 1])) {
   2.941 -			bcopy(argv[argc -1] + off, chstr, 2);
   2.942 -			off += 2;
   2.943 -
   2.944 -			ch = strtoul(chstr, &pend, 16);
   2.945 -			if (errno != 0) {
   2.946 -				(void) fprintf(stderr,
   2.947 -				    "Invalid device identifier or"
   2.948 -				    " filename specified.\nIf it is a"
   2.949 -				    " filename, it should be an absolute path"
   2.950 -				    " i.e. it should start with a /\n");
   2.951 -				ret = 1;
   2.952 -				goto modify_lu_done;
   2.953 -			}
   2.954 -			mlc->guid[i++] = ch;
   2.955 -
   2.956 -		}
   2.957 -		mlc->name[0] = '\0';
   2.958 -	}
   2.959 -	if ((ioctl(sbd_fd, SBD_MODIFY_LU, mlc) < 0) ||
   2.960 -	    (mlc->return_code != 0) || (mlc->op_ret |= STMF_SUCCESS)) {
   2.961 -		if (mlc->return_code && (mlc->return_code < RLC_RET_MAX_VAL)) {
   2.962 -			(void) fprintf(stderr, "LU modify failed : %s.\n",
   2.963 -			    rlc_ret[mlc->return_code]);
   2.964 -			if (mlc->return_code ==
   2.965 -			    RLC_RET_SIZE_NOT_SUPPORTED_BY_FS) {
   2.966 -				(void) fprintf(stderr, "Maximum LU size on "
   2.967 -				    "the underlying filesystem can be %llu "
   2.968 -				    "bytes.\n",
   2.969 -				    ((((uint64_t)1) << mlc->filesize_nbits)
   2.970 -				    - 1) & 0xfffffffffffffe00ull);
   2.971 -			} else if (mlc->return_code ==
   2.972 -			    RLC_RET_LU_NOT_INITIALIZED) {
   2.973 -				(void) fprintf(stderr, "Use 'sbdadm lu-create' "
   2.974 -				    "to initialize the LU.\n");
   2.975 -			}
   2.976 -		} else {
   2.977 -			(void) fprintf(stderr, "LU modify failed(%llx) : %s.\n",
   2.978 -			    mlc->op_ret, strerror(errno));
   2.979 -		}
   2.980 -		ret = 1;
   2.981 -	} else {
   2.982 -		(void) printf("LU modified Successfully.\n");
   2.983 +	switch (stmfRet) {
   2.984 +		case STMF_STATUS_SUCCESS:
   2.985 +			break;
   2.986 +		case STMF_ERROR_BUSY:
   2.987 +		case STMF_ERROR_LU_BUSY:
   2.988 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.989 +			    gettext("resource busy"));
   2.990 +			ret++;
   2.991 +			break;
   2.992 +		case STMF_ERROR_PERM:
   2.993 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.994 +			    gettext("permission denied"));
   2.995 +			ret++;
   2.996 +			break;
   2.997 +		case STMF_ERROR_INVALID_BLKSIZE:
   2.998 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   2.999 +			    gettext("invalid block size"));
  2.1000 +			ret++;
  2.1001 +			break;
  2.1002 +		case STMF_ERROR_GUID_IN_USE:
  2.1003 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1004 +			    gettext("guid in use"));
  2.1005 +			ret++;
  2.1006 +			break;
  2.1007 +		case STMF_ERROR_META_FILE_NAME:
  2.1008 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1009 +			    gettext("meta file error"));
  2.1010 +			ret++;
  2.1011 +			break;
  2.1012 +		case STMF_ERROR_DATA_FILE_NAME:
  2.1013 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1014 +			    gettext("data file error"));
  2.1015 +			ret++;
  2.1016 +			break;
  2.1017 +		case STMF_ERROR_FILE_SIZE_INVALID:
  2.1018 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1019 +			    gettext("file size invalid"));
  2.1020 +			ret++;
  2.1021 +			break;
  2.1022 +		case STMF_ERROR_SIZE_OUT_OF_RANGE:
  2.1023 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1024 +			    gettext("invalid size"));
  2.1025 +			ret++;
  2.1026 +			break;
  2.1027 +		case STMF_ERROR_META_CREATION:
  2.1028 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1029 +			    gettext("could not create meta file"));
  2.1030 +			ret++;
  2.1031 +			break;
  2.1032 +		default:
  2.1033 +			(void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
  2.1034 +			    gettext("could not set property"), propString,
  2.1035 +			    stmfRet);
  2.1036 +			ret++;
  2.1037 +			break;
  2.1038  	}
  2.1039  
  2.1040 -modify_lu_done:;
  2.1041 -	free(mlc);
  2.1042  	return (ret);
  2.1043  }
  2.1044  
  2.1045 @@ -695,88 +537,71 @@
  2.1046  int
  2.1047  list_lus(int argc, char *argv[], cmdOptions_t *options, void *callData)
  2.1048  {
  2.1049 -	sbd_lu_list_t *sll;
  2.1050 -	uint32_t i;
  2.1051 -	ssize_t list_size;
  2.1052 -	int retry_count = 0;
  2.1053 -	uint32_t lu_count_in = MAX_LU_LIST;
  2.1054 -	int ret;
  2.1055 -	nvlist_t *nvl = NULL;
  2.1056 -	nvpair_t *np;
  2.1057 -	char *s;
  2.1058 +	int stmfRet;
  2.1059 +	stmfGuidList *luList;
  2.1060 +	stmfLogicalUnitProperties luProps;
  2.1061 +	int sbdLuCnt = 0;
  2.1062 +	int i;
  2.1063  
  2.1064 -	ret = stmfGetProviderDataProt("sbd", &nvl, STMF_LU_PROVIDER_TYPE,
  2.1065 -	    NULL);
  2.1066 -	if (ret != STMF_STATUS_SUCCESS) {
  2.1067 -		if (ret == STMF_ERROR_NOT_FOUND) {
  2.1068 -			(void) nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
  2.1069 -		} else {
  2.1070 -			(void) fprintf(stderr,
  2.1071 -			    "Could not access persistent store\n");
  2.1072 +	if ((stmfRet = stmfGetLogicalUnitList(&luList))
  2.1073 +	    != STMF_STATUS_SUCCESS) {
  2.1074 +		switch (stmfRet) {
  2.1075 +			case STMF_ERROR_SERVICE_NOT_FOUND:
  2.1076 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1077 +				    gettext("STMF service not found"));
  2.1078 +				break;
  2.1079 +			case STMF_ERROR_BUSY:
  2.1080 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1081 +				    gettext("resource busy"));
  2.1082 +				break;
  2.1083 +			case STMF_ERROR_PERM:
  2.1084 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1085 +				    gettext("permission denied"));
  2.1086 +				break;
  2.1087 +			case STMF_ERROR_SERVICE_DATA_VERSION:
  2.1088 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1089 +				    gettext("STMF service version incorrect"));
  2.1090 +				break;
  2.1091 +			default:
  2.1092 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1093 +				    gettext("list failed"));
  2.1094 +				break;
  2.1095 +		}
  2.1096 +		return (1);
  2.1097 +	}
  2.1098 +
  2.1099 +	for (i = 0; i < luList->cnt; i++) {
  2.1100 +		stmfRet = stmfGetLogicalUnitProperties(&luList->guid[i],
  2.1101 +		    &luProps);
  2.1102 +		if (stmfRet != STMF_STATUS_SUCCESS) {
  2.1103 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1104 +			    gettext("list failed"));
  2.1105  			return (1);
  2.1106 +		}
  2.1107 +		if (strcmp(luProps.providerName, "sbd") == 0) {
  2.1108 +			sbdLuCnt++;
  2.1109  		}
  2.1110  	}
  2.1111  
  2.1112 -retry_get_lu_list:
  2.1113 -	list_size = (lu_count_in * 8) + sizeof (sbd_lu_list_t) - 8;
  2.1114 -	sll = (sbd_lu_list_t *)calloc(1, list_size);
  2.1115 -	if (sll == NULL) {
  2.1116 -		(void) fprintf(stderr, "Memory allocation failure\n");
  2.1117 -		nvlist_free(nvl);
  2.1118 -		return (1);
  2.1119 -	}
  2.1120  
  2.1121 -	sll->total_struct_size = list_size;
  2.1122 +	if (sbdLuCnt == 0)
  2.1123 +		return (0);
  2.1124  
  2.1125 -	sll->count_in = lu_count_in;
  2.1126 -	if (ioctl(sbd_fd, SBD_GET_LU_LIST, sll) < 0) {
  2.1127 -		(void) fprintf(stderr, "Unable to get LU list : %s\n",
  2.1128 -		    strerror(errno));
  2.1129 -		free(sll);
  2.1130 -		nvlist_free(nvl);
  2.1131 -		return (1);
  2.1132 -	}
  2.1133 -	if (sll->count_out > sll->count_in) {
  2.1134 -		lu_count_in = sll->count_out;
  2.1135 -		free(sll);
  2.1136 -		if (retry_count < LU_LIST_MAX_RETRIES) {
  2.1137 -			retry_count++;
  2.1138 -			goto retry_get_lu_list;
  2.1139 -		} else {
  2.1140 -			(void) fprintf(stderr, "Unable to get LU list after %d"
  2.1141 -			    " retries\n", retry_count);
  2.1142 -			nvlist_free(nvl);
  2.1143 +	(void) printf("\nFound %d LU(s)\n", sbdLuCnt);
  2.1144 +	print_attr_header();
  2.1145 +
  2.1146 +	for (i = 0; i < luList->cnt; i++) {
  2.1147 +		stmfRet = stmfGetLogicalUnitProperties(&luList->guid[i],
  2.1148 +		    &luProps);
  2.1149 +		if (stmfRet != STMF_STATUS_SUCCESS) {
  2.1150 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1151 +			    gettext("list failed"));
  2.1152  			return (1);
  2.1153  		}
  2.1154 -	}
  2.1155 -
  2.1156 -	(void) printf("\nFound %d LU(s)\n", sll->count_out);
  2.1157 -	if (sll->count_out == 0)
  2.1158 -		goto over_print_attr;
  2.1159 -
  2.1160 -	print_attr_header();
  2.1161 -	for (i = 0; i < sll->count_out; i++) {
  2.1162 -		if (!print_lu_attr(sll->handles[i], &s))
  2.1163 -			continue;
  2.1164 -		if (nvlist_remove(nvl, s, DATA_TYPE_STRING) != 0) {
  2.1165 -			(void) fprintf(stderr,
  2.1166 -			    "Error: GUID %s does not exist in "
  2.1167 -			    "persistent store\n", s);
  2.1168 +		if (strcmp(luProps.providerName, "sbd") == 0) {
  2.1169 +			(void) print_lu_attr(&luList->guid[i]);
  2.1170  		}
  2.1171  	}
  2.1172 -over_print_attr:
  2.1173 -	free(sll);
  2.1174 -	np = NULL;
  2.1175 -	while ((np = nvlist_next_nvpair(nvl, np)) != NULL) {
  2.1176 -		if (nvpair_type(np) != DATA_TYPE_STRING)
  2.1177 -			continue;
  2.1178 -		if (nvpair_value_string(np, &s) != 0)
  2.1179 -			continue;
  2.1180 -
  2.1181 -		(void) fprintf(stderr, "%s   <Failed to load>    %s\n",
  2.1182 -		    nvpair_name(np), s);
  2.1183 -	}
  2.1184 -	nvlist_free(nvl);
  2.1185  	return (0);
  2.1186  }
  2.1187  
  2.1188 @@ -801,47 +626,121 @@
  2.1189  }
  2.1190  
  2.1191  int
  2.1192 -print_lu_attr(uint64_t handle, char **s)
  2.1193 +print_lu_attr(stmfGuid *guid)
  2.1194  {
  2.1195 -	sbd_lu_attr_t *sla;
  2.1196 +	luResource hdl = NULL;
  2.1197 +	int stmfRet = 0;
  2.1198 +	int ret = 0;
  2.1199 +	char propVal[MAXPATHLEN];
  2.1200 +	size_t propValSize = sizeof (propVal);
  2.1201  
  2.1202 -	sla = (sbd_lu_attr_t *)big_buf;
  2.1203 -
  2.1204 -	bzero(sla, BIG_BUF_SIZE);
  2.1205 -
  2.1206 -	sla->lu_handle = handle;
  2.1207 -	sla->total_struct_size = BIG_BUF_SIZE;
  2.1208 -	sla->max_name_length = BIG_BUF_SIZE - sizeof (*sla) + 7;
  2.1209 -
  2.1210 -	if (ioctl(sbd_fd, SBD_GET_LU_ATTR, sla) < 0) {
  2.1211 -		(void) fprintf(stderr, "Request to get LU attr failed: %s\n",
  2.1212 -		    strerror(errno));
  2.1213 -		return (0);
  2.1214 +	if ((stmfRet = stmfGetLuResource(guid, &hdl)) != STMF_STATUS_SUCCESS) {
  2.1215 +		switch (stmfRet) {
  2.1216 +			case STMF_ERROR_BUSY:
  2.1217 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1218 +				    gettext("resource busy"));
  2.1219 +				break;
  2.1220 +			case STMF_ERROR_PERM:
  2.1221 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1222 +				    gettext("permission denied"));
  2.1223 +				break;
  2.1224 +			case STMF_ERROR_NOT_FOUND:
  2.1225 +				/* No error here */
  2.1226 +				return (0);
  2.1227 +				break;
  2.1228 +			default:
  2.1229 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
  2.1230 +				    gettext("get extended properties failed"));
  2.1231 +				break;
  2.1232 +		}
  2.1233 +		return (1);
  2.1234  	}
  2.1235  
  2.1236 -	print_guid(sla->guid, stdout);
  2.1237 +	print_guid((uint8_t *)guid, stdout);
  2.1238  
  2.1239 -	if (sla->data_size > 9999999999999ull)
  2.1240 -		(void) printf("  %-19llu  ", sla->data_size);
  2.1241 -	else
  2.1242 -		(void) printf("      %-13llu    ", sla->data_size);
  2.1243 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
  2.1244 +	    &propValSize);
  2.1245 +	if (stmfRet == STMF_STATUS_SUCCESS) {
  2.1246 +		(void) printf("  %-19s  ", propVal);
  2.1247 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
  2.1248 +		(void) printf("not set\n");
  2.1249 +	} else {
  2.1250 +		(void) printf("<error retrieving property>");
  2.1251 +		ret++;
  2.1252 +	}
  2.1253  
  2.1254 -	if (sla->flags & RLC_LU_TYPE_MEMDISK) {
  2.1255 -		(void) printf("<RAM : %llu bytes>\n", sla->total_size);
  2.1256 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
  2.1257 +	    &propValSize);
  2.1258 +	if (stmfRet == STMF_STATUS_SUCCESS) {
  2.1259 +		(void) printf("%s\n", propVal);
  2.1260 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
  2.1261 +		(void) printf("not set\n");
  2.1262  	} else {
  2.1263 -		(void) printf("%s\n", sla->name);
  2.1264 +		(void) printf("<error retrieving property>");
  2.1265 +		ret++;
  2.1266  	}
  2.1267 -	if (s != NULL) {
  2.1268 -		(void) snprintf((char *)big_buf, sizeof (big_buf),
  2.1269 -		    "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
  2.1270 -		    "%02x%02x%02x%02x%02x%02x",
  2.1271 -		    sla->guid[0], sla->guid[1], sla->guid[2],
  2.1272 -		    sla->guid[3], sla->guid[4], sla->guid[5],
  2.1273 -		    sla->guid[6], sla->guid[7], sla->guid[8],
  2.1274 -		    sla->guid[9], sla->guid[10], sla->guid[11],
  2.1275 -		    sla->guid[12], sla->guid[13], sla->guid[14],
  2.1276 -		    sla->guid[15]);
  2.1277 -		*s = (char *)big_buf;
  2.1278 +
  2.1279 +
  2.1280 +	(void) stmfFreeLuResource(hdl);
  2.1281 +	return (ret);
  2.1282 +}
  2.1283 +
  2.1284 +/*
  2.1285 + * input:
  2.1286 + *  execFullName - exec name of program (argv[0])
  2.1287 + *
  2.1288 + *  copied from usr/src/cmd/zoneadm/zoneadm.c in OS/Net
  2.1289 + *  (changed name to lowerCamelCase to keep consistent with this file)
  2.1290 + *
  2.1291 + * Returns:
  2.1292 + *  command name portion of execFullName
  2.1293 + */
  2.1294 +static char *
  2.1295 +getExecBasename(char *execFullname)
  2.1296 +{
  2.1297 +	char *lastSlash, *execBasename;
  2.1298 +
  2.1299 +	/* guard against '/' at end of command invocation */
  2.1300 +	for (;;) {
  2.1301 +		lastSlash = strrchr(execFullname, '/');
  2.1302 +		if (lastSlash == NULL) {
  2.1303 +			execBasename = execFullname;
  2.1304 +			break;
  2.1305 +		} else {
  2.1306 +			execBasename = lastSlash + 1;
  2.1307 +			if (*execBasename == '\0') {
  2.1308 +				*lastSlash = '\0';
  2.1309 +				continue;
  2.1310 +			}
  2.1311 +			break;
  2.1312 +		}
  2.1313  	}
  2.1314 -	return (1);
  2.1315 +	return (execBasename);
  2.1316  }
  2.1317 +int
  2.1318 +main(int argc, char *argv[])
  2.1319 +{
  2.1320 +	synTables_t synTables;
  2.1321 +	char versionString[VERSION_STRING_MAX_LEN];
  2.1322 +	int ret;
  2.1323 +	int funcRet;
  2.1324 +	void *subcommandArgs = NULL;
  2.1325 +
  2.1326 +	(void) setlocale(LC_ALL, "");
  2.1327 +	(void) textdomain(TEXT_DOMAIN);
  2.1328 +	/* set global command name */
  2.1329 +	cmdName = getExecBasename(argv[0]);
  2.1330 +
  2.1331 +	(void) snprintf(versionString, VERSION_STRING_MAX_LEN, "%s.%s",
  2.1332 +	    VERSION_STRING_MAJOR, VERSION_STRING_MINOR);
  2.1333 +	synTables.versionString = versionString;
  2.1334 +	synTables.longOptionTbl = options;
  2.1335 +	synTables.subCommandPropsTbl = subCommands;
  2.1336 +
  2.1337 +	ret = cmdParse(argc, argv, synTables, subcommandArgs, &funcRet);
  2.1338 +	if (ret != 0) {
  2.1339 +		return (ret);
  2.1340 +	}
  2.1341 +
  2.1342 +	return (funcRet);
  2.1343 +} /* end main */
     3.1 --- a/usr/src/cmd/stmfadm/stmfadm.c	Fri May 08 13:31:23 2009 -0700
     3.2 +++ b/usr/src/cmd/stmfadm/stmfadm.c	Fri May 08 16:22:42 2009 -0600
     3.3 @@ -46,6 +46,10 @@
     3.4  static int addTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
     3.5  static int addViewFunc(int, char **, cmdOptions_t *, void *);
     3.6  static int createHostGroupFunc(int, char **, cmdOptions_t *, void *);
     3.7 +static int createLuFunc(int, char **, cmdOptions_t *, void *);
     3.8 +static int modifyLuFunc(int, char **, cmdOptions_t *, void *);
     3.9 +static int importLuFunc(int, char **, cmdOptions_t *, void *);
    3.10 +static int deleteLuFunc(int, char **, cmdOptions_t *, void *);
    3.11  static int createTargetGroupFunc(int, char **, cmdOptions_t *, void *);
    3.12  static int deleteHostGroupFunc(int, char **, cmdOptions_t *, void *);
    3.13  static int deleteTargetGroupFunc(int, char **, cmdOptions_t *, void *);
    3.14 @@ -63,6 +67,7 @@
    3.15  static int onlineOfflineLu(char *, int);
    3.16  static int removeHostGroupMemberFunc(int, char **, cmdOptions_t *, void *);
    3.17  static int removeTargetGroupMemberFunc(int, char **, cmdOptions_t *, void *);
    3.18 +static int callModify(char *, stmfGuid *, uint32_t, const char *, const char *);
    3.19  static int removeViewFunc(int, char **, cmdOptions_t *, void *);
    3.20  static char *getExecBasename(char *);
    3.21  static int parseDevid(char *input, stmfDevid *devid);
    3.22 @@ -71,9 +76,12 @@
    3.23  static int checkHexUpper(char *);
    3.24  static int checkIscsiName(wchar_t *);
    3.25  static void printLuProps(stmfLogicalUnitProperties *luProps);
    3.26 +static int printExtLuProps(stmfGuid *guid);
    3.27  static void printGuid(stmfGuid *guid, FILE *printWhere);
    3.28  static void printTargetProps(stmfTargetProperties *);
    3.29  static void printSessionProps(stmfSessionList *);
    3.30 +static int setLuPropFromInput(luResource, char *);
    3.31 +static int convertCharToPropId(char *, uint32_t *);
    3.32  
    3.33  
    3.34  
    3.35 @@ -107,21 +115,68 @@
    3.36  #define	SNS_WWN_16		    16
    3.37  #define	SNS_IQN_223		    223
    3.38  
    3.39 +/* LU Property strings */
    3.40 +#define	GUID			    "GUID"
    3.41 +#define	ALIAS			    "ALIAS"
    3.42 +#define	VID			    "VID"
    3.43 +#define	PID			    "PID"
    3.44 +#define	META_FILE		    "META"
    3.45 +#define	WRITE_PROTECT		    "WP"
    3.46 +#define	WRITEBACK_CACHE_DISABLE	    "WCD"
    3.47 +#define	COMPANY_ID		    "OUI"
    3.48 +#define	BLOCK_SIZE		    "BLK"
    3.49 +#define	SERIAL_NUMBER		    "SERIAL"
    3.50 +
    3.51 +#define	MODIFY_HELP "\n"\
    3.52 +"Description: Modify properties of a logical unit. \n" \
    3.53 +"Valid properties for -p, --lu-prop are: \n" \
    3.54 +"     alias - alias for logical unit (up to 255 chars)\n" \
    3.55 +"     wcd   - write cache disabled (true, false)\n" \
    3.56 +"     wp    - write protect (true, false)\n\n" \
    3.57 +"-f alters the meaning of the operand to be a file name\n" \
    3.58 +"rather than a LU name. This allows for modification\n" \
    3.59 +"of a logical unit that is not yet imported into stmf\n"
    3.60 +
    3.61 +#define	CREATE_HELP "\n"\
    3.62 +"Description: Create a logical unit. \n" \
    3.63 +"Valid properties for -p, --lu-prop are: \n" \
    3.64 +"     alias - alias for logical unit (up to 255 chars)\n" \
    3.65 +"     blk   - block size in bytes in 2^n\n" \
    3.66 +"     guid  - 32 ascii hex characters in NAA format \n" \
    3.67 +"     meta  - separate meta data file name\n" \
    3.68 +"     oui   - organizational unique identifier\n" \
    3.69 +"             6 ascii hex characters of valid format\n" \
    3.70 +"     pid   - product identifier (up to 16 chars)\n" \
    3.71 +"     serial- serial number (up to 252 chars)\n" \
    3.72 +"     vid   - vendor identifier (up to 8 chars)\n" \
    3.73 +"     wp    - write protect (true, false)\n" \
    3.74 +"     wcd   - write cache disabled (true, false)\n"
    3.75 +#define	ADD_VIEW_HELP "\n"\
    3.76 +"Description: Add a view entry to a logical unit. \n" \
    3.77 +"A view entry is comprised of three elements; the \n" \
    3.78 +"logical unit number, the target group name and the\n" \
    3.79 +"host group name. These three elements combine together\n" \
    3.80 +"to form a view for a given COMSTAR logical unit.\n" \
    3.81 +"This view is realized by a client, a SCSI initiator,\n" \
    3.82 +"via a REPORT LUNS command. \n"
    3.83 +
    3.84 +
    3.85 +
    3.86  /* tables set up based on cmdparse instructions */
    3.87  
    3.88  /* add new options here */
    3.89  optionTbl_t longOptions[] = {
    3.90  	{"all", no_arg, 'a', NULL},
    3.91  	{"group-name", required_arg, 'g', "group-name"},
    3.92 -	{"secure-data", no_arg, 's', NULL},
    3.93 +	{"keep-views", no_arg, 'k', NULL},
    3.94  	{"lu-name", required_arg, 'l', "LU-Name"},
    3.95  	{"lun", required_arg, 'n', "logical-unit-number"},
    3.96 -	{"verbose", no_arg, 'v', NULL},
    3.97 +	{"lu-prop", required_arg, 'p', "logical-unit-property=value"},
    3.98 +	{"file", no_arg, 'f', "filename"},
    3.99 +	{"size", required_arg, 's', "size K/M/G/T/P"},
   3.100  	{"target-group", required_arg, 't', "group-name"},
   3.101  	{"host-group", required_arg, 'h', "group-name"},
   3.102 -	{"size", required_arg, 's', "size (k/M/G)"},
   3.103 -	{"force", no_arg, 'r', NULL},
   3.104 -	{"new", no_arg, 'n', NULL},
   3.105 +	{"verbose", no_arg, 'v', NULL},
   3.106  	{NULL, 0, 0, 0}
   3.107  };
   3.108  
   3.109 @@ -130,45 +185,53 @@
   3.110   */
   3.111  subCommandProps_t subcommands[] = {
   3.112  	{"add-hg-member", addHostGroupMemberFunc, "g", "g", NULL,
   3.113 -		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER},
   3.114 +		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
   3.115  	{"add-tg-member", addTargetGroupMemberFunc, "g", "g", NULL,
   3.116 -		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER},
   3.117 +		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
   3.118  	{"add-view", addViewFunc, "nth", NULL, NULL,
   3.119 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU},
   3.120 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, ADD_VIEW_HELP},
   3.121  	{"create-hg", createHostGroupFunc, NULL, NULL, NULL,
   3.122 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME},
   3.123 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
   3.124  	{"create-tg", createTargetGroupFunc, NULL, NULL, NULL,
   3.125 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME},
   3.126 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
   3.127 +	{"create-lu", createLuFunc, "ps", NULL, NULL, OPERAND_MANDATORY_SINGLE,
   3.128 +		"lu file", CREATE_HELP},
   3.129  	{"delete-hg", deleteHostGroupFunc, NULL, NULL, NULL,
   3.130 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME},
   3.131 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
   3.132 +	{"modify-lu", modifyLuFunc, "psf", NULL, NULL, OPERAND_MANDATORY_SINGLE,
   3.133 +		OPERANDSTRING_LU, MODIFY_HELP},
   3.134 +	{"delete-lu", deleteLuFunc, "k", NULL, NULL,
   3.135 +		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_LU, NULL},
   3.136  	{"delete-tg", deleteTargetGroupFunc, NULL, NULL, NULL,
   3.137 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME},
   3.138 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_GROUP_NAME, NULL},
   3.139 +	{"import-lu", importLuFunc, NULL, NULL, NULL,
   3.140 +		OPERAND_MANDATORY_SINGLE, "file name", NULL},
   3.141  	{"list-hg", listHostGroupFunc, "v", NULL, NULL,
   3.142 -		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME},
   3.143 +		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
   3.144  	{"list-lu", listLuFunc, "v", NULL, NULL, OPERAND_OPTIONAL_MULTIPLE,
   3.145 -		OPERANDSTRING_LU},
   3.146 +		OPERANDSTRING_LU, NULL},
   3.147  	{"list-state", listStateFunc, NULL, NULL, NULL, OPERAND_NONE, NULL},
   3.148  	{"list-target", listTargetFunc, "v", NULL, NULL,
   3.149 -		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_TARGET},
   3.150 +		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_TARGET, NULL},
   3.151  	{"list-tg", listTargetGroupFunc, "v", NULL, NULL,
   3.152 -		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME},
   3.153 +		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_GROUP_NAME, NULL},
   3.154  	{"list-view", listViewFunc, "l", "l", NULL,
   3.155 -		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY},
   3.156 +		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
   3.157  	{"online-lu", onlineLuFunc, NULL, NULL, NULL,
   3.158 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU},
   3.159 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
   3.160  	{"offline-lu", offlineLuFunc, NULL, NULL, NULL,
   3.161 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU},
   3.162 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_LU, NULL},
   3.163  	{"online-target", onlineTargetFunc, NULL, NULL, NULL,
   3.164 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET},
   3.165 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
   3.166  	{"offline-target", offlineTargetFunc, NULL, NULL, NULL,
   3.167 -		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET},
   3.168 +		OPERAND_MANDATORY_SINGLE, OPERANDSTRING_TARGET, NULL},
   3.169  	{"remove-hg-member", removeHostGroupMemberFunc, "g", "g", NULL,
   3.170 -		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER},
   3.171 +		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
   3.172  	{"remove-tg-member", removeTargetGroupMemberFunc, "g", "g", NULL,
   3.173 -		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER},
   3.174 +		OPERAND_MANDATORY_MULTIPLE, OPERANDSTRING_GROUP_MEMBER, NULL},
   3.175  	{"remove-view", removeViewFunc, "la", "l", NULL,
   3.176 -		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY},
   3.177 -	{NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
   3.178 +		OPERAND_OPTIONAL_MULTIPLE, OPERANDSTRING_VIEW_ENTRY, NULL},
   3.179 +	{NULL, 0, NULL, NULL, 0, NULL, 0, NULL, NULL}
   3.180  };
   3.181  
   3.182  /* globals */
   3.183 @@ -716,6 +779,630 @@
   3.184  
   3.185  	return (ret);
   3.186  }
   3.187 +
   3.188 +/*
   3.189 + * createLuFunc
   3.190 + *
   3.191 + * Create a logical unit
   3.192 + *
   3.193 + */
   3.194 +/*ARGSUSED*/
   3.195 +static int
   3.196 +createLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   3.197 +    void *args)
   3.198 +{
   3.199 +	luResource hdl = NULL;
   3.200 +	int ret = 0;
   3.201 +	int stmfRet = 0;
   3.202 +	char guidAsciiBuf[33];
   3.203 +	stmfGuid createdGuid;
   3.204 +
   3.205 +	stmfRet = stmfCreateLuResource(STMF_DISK, &hdl);
   3.206 +
   3.207 +	if (stmfRet != STMF_STATUS_SUCCESS) {
   3.208 +		(void) fprintf(stderr, "%s: %s\n",
   3.209 +		    cmdName, gettext("Failure to create lu resource\n"));
   3.210 +		return (1);
   3.211 +	}
   3.212 +
   3.213 +	for (; options->optval; options++) {
   3.214 +		switch (options->optval) {
   3.215 +			case 'p':
   3.216 +				ret = setLuPropFromInput(hdl, options->optarg);
   3.217 +				if (ret != 0) {
   3.218 +					(void) stmfFreeLuResource(hdl);
   3.219 +					return (1);
   3.220 +				}
   3.221 +				break;
   3.222 +			case 's':
   3.223 +				stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_SIZE,
   3.224 +				    options->optarg);
   3.225 +				if (stmfRet != STMF_STATUS_SUCCESS) {
   3.226 +					(void) fprintf(stderr, "%s: %c: %s\n",
   3.227 +					    cmdName, options->optval,
   3.228 +					    gettext("size param invalid"));
   3.229 +					(void) stmfFreeLuResource(hdl);
   3.230 +					return (1);
   3.231 +				}
   3.232 +				break;
   3.233 +			default:
   3.234 +				(void) fprintf(stderr, "%s: %c: %s\n",
   3.235 +				    cmdName, options->optval,
   3.236 +				    gettext("unknown option"));
   3.237 +				return (1);
   3.238 +		}
   3.239 +	}
   3.240 +
   3.241 +	stmfRet = stmfSetLuProp(hdl, STMF_LU_PROP_FILENAME, operands[0]);
   3.242 +
   3.243 +	if (stmfRet != STMF_STATUS_SUCCESS) {
   3.244 +		(void) fprintf(stderr, "%s: %s\n",
   3.245 +		    cmdName, gettext("could not set filename"));
   3.246 +		return (1);
   3.247 +	}
   3.248 +
   3.249 +	stmfRet = stmfCreateLu(hdl, &createdGuid);
   3.250 +	switch (stmfRet) {
   3.251 +		case STMF_STATUS_SUCCESS:
   3.252 +			break;
   3.253 +		case STMF_ERROR_BUSY:
   3.254 +		case STMF_ERROR_LU_BUSY:
   3.255 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.256 +			    gettext("resource busy"));
   3.257 +			ret++;
   3.258 +			break;
   3.259 +		case STMF_ERROR_PERM:
   3.260 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.261 +			    gettext("permission denied"));
   3.262 +			ret++;
   3.263 +			break;
   3.264 +		case STMF_ERROR_FILE_IN_USE:
   3.265 +			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
   3.266 +			    operands[0], gettext("in use"));
   3.267 +			ret++;
   3.268 +			break;
   3.269 +		case STMF_ERROR_INVALID_BLKSIZE:
   3.270 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.271 +			    gettext("invalid block size"));
   3.272 +			ret++;
   3.273 +			break;
   3.274 +		case STMF_ERROR_GUID_IN_USE:
   3.275 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.276 +			    gettext("guid in use"));
   3.277 +			ret++;
   3.278 +			break;
   3.279 +		case STMF_ERROR_META_FILE_NAME:
   3.280 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.281 +			    gettext("meta file error"));
   3.282 +			ret++;
   3.283 +			break;
   3.284 +		case STMF_ERROR_DATA_FILE_NAME:
   3.285 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.286 +			    gettext("data file error"));
   3.287 +			ret++;
   3.288 +			break;
   3.289 +		case STMF_ERROR_FILE_SIZE_INVALID:
   3.290 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.291 +			    gettext("file size invalid"));
   3.292 +			ret++;
   3.293 +			break;
   3.294 +		case STMF_ERROR_SIZE_OUT_OF_RANGE:
   3.295 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.296 +			    gettext("invalid size"));
   3.297 +			ret++;
   3.298 +			break;
   3.299 +		case STMF_ERROR_META_CREATION:
   3.300 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.301 +			    gettext("could not create meta file"));
   3.302 +			ret++;
   3.303 +			break;
   3.304 +		case STMF_ERROR_WRITE_CACHE_SET:
   3.305 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.306 +			    gettext("could not set write cache"));
   3.307 +			ret++;
   3.308 +			break;
   3.309 +		default:
   3.310 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.311 +			    gettext("unknown error"));
   3.312 +			ret++;
   3.313 +			break;
   3.314 +	}
   3.315 +
   3.316 +	if (ret != 0) {
   3.317 +		goto done;
   3.318 +	}
   3.319 +
   3.320 +	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
   3.321 +	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
   3.322 +	    "%02X%02X%02X%02X%02X%02X",
   3.323 +	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
   3.324 +	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
   3.325 +	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
   3.326 +	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
   3.327 +	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
   3.328 +	    createdGuid.guid[15]);
   3.329 +	(void) printf("Logical unit created: %s\n", guidAsciiBuf);
   3.330 +
   3.331 +done:
   3.332 +	(void) stmfFreeLuResource(hdl);
   3.333 +	return (ret);
   3.334 +}
   3.335 +
   3.336 +/*
   3.337 + * createLuFunc
   3.338 + *
   3.339 + * Create a logical unit
   3.340 + *
   3.341 + */
   3.342 +/*ARGSUSED*/
   3.343 +static int
   3.344 +modifyLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   3.345 +    void *args)
   3.346 +{
   3.347 +	stmfGuid inGuid;
   3.348 +	unsigned int guid[sizeof (stmfGuid)];
   3.349 +	int ret = 0;
   3.350 +	int i;
   3.351 +	char *fname = NULL;
   3.352 +	char *lasts = NULL;
   3.353 +	char sGuid[GUID_INPUT + 1];
   3.354 +	char *prop = NULL;
   3.355 +	char *propVal = NULL;
   3.356 +	boolean_t fnameUsed = B_FALSE;
   3.357 +	uint32_t propId;
   3.358 +	cmdOptions_t *optionStart = options;
   3.359 +
   3.360 +
   3.361 +	for (; options->optval; options++) {
   3.362 +		switch (options->optval) {
   3.363 +			case 'f':
   3.364 +				fnameUsed = B_TRUE;
   3.365 +				fname = operands[0];
   3.366 +				break;
   3.367 +		}
   3.368 +	}
   3.369 +	options = optionStart;
   3.370 +
   3.371 +	/* check input length */
   3.372 +	if (!fnameUsed && strlen(operands[0]) != GUID_INPUT) {
   3.373 +		(void) fprintf(stderr, "%s: %s: %s%d%s\n", cmdName, operands[0],
   3.374 +		    gettext("must be "), GUID_INPUT,
   3.375 +		    gettext(" hexadecimal digits"));
   3.376 +		return (1);
   3.377 +	}
   3.378 +
   3.379 +	if (!fnameUsed) {
   3.380 +		/* convert to lower case for scan */
   3.381 +		for (i = 0; i < 32; i++)
   3.382 +			sGuid[i] = tolower(operands[0][i]);
   3.383 +		sGuid[i] = 0;
   3.384 +		(void) sscanf(sGuid,
   3.385 +		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   3.386 +		    &guid[0], &guid[1], &guid[2], &guid[3], &guid[4], &guid[5],
   3.387 +		    &guid[6], &guid[7], &guid[8], &guid[9], &guid[10],
   3.388 +		    &guid[11], &guid[12], &guid[13], &guid[14], &guid[15]);
   3.389 +
   3.390 +		for (i = 0; i < sizeof (stmfGuid); i++) {
   3.391 +			inGuid.guid[i] = guid[i];
   3.392 +		}
   3.393 +	}
   3.394 +
   3.395 +	for (; options->optval; options++) {
   3.396 +		switch (options->optval) {
   3.397 +			case 'p':
   3.398 +				prop = strtok_r(options->optarg, "=", &lasts);
   3.399 +				if ((propVal = strtok_r(NULL, "=", &lasts))
   3.400 +				    == NULL) {
   3.401 +					(void) fprintf(stderr, "%s: %s: %s\n",
   3.402 +					    cmdName, options->optarg,
   3.403 +					gettext("invalid property specifier"
   3.404 +					    "- prop=val\n"));
   3.405 +					return (1);
   3.406 +				}
   3.407 +				ret = convertCharToPropId(prop, &propId);
   3.408 +				if (ret != 0) {
   3.409 +					(void) fprintf(stderr, "%s: %s: %s\n",
   3.410 +					    cmdName,
   3.411 +					gettext("invalid property specified"),
   3.412 +					    prop);
   3.413 +					return (1);
   3.414 +				}
   3.415 +				if (callModify(fname, &inGuid, propId, propVal,
   3.416 +				    prop) != 0) {
   3.417 +					return (1);
   3.418 +				}
   3.419 +				break;
   3.420 +			case 's':
   3.421 +				if (callModify(fname, &inGuid,
   3.422 +				    STMF_LU_PROP_SIZE, options->optarg,
   3.423 +				    "size") != 0) {
   3.424 +					return (1);
   3.425 +				}
   3.426 +				break;
   3.427 +			case 'f':
   3.428 +				break;
   3.429 +			default:
   3.430 +				(void) fprintf(stderr, "%s: %c: %s\n",
   3.431 +				    cmdName, options->optval,
   3.432 +				    gettext("unknown option"));
   3.433 +				return (1);
   3.434 +		}
   3.435 +	}
   3.436 +	return (ret);
   3.437 +}
   3.438 +
   3.439 +static int
   3.440 +callModify(char *fname, stmfGuid *luGuid, uint32_t prop, const char *propVal,
   3.441 +    const char *propString)
   3.442 +{
   3.443 +	int ret = 0;
   3.444 +	int stmfRet = 0;
   3.445 +
   3.446 +	if (!fname) {
   3.447 +		stmfRet = stmfModifyLu(luGuid, prop, propVal);
   3.448 +	} else {
   3.449 +		stmfRet = stmfModifyLuByFname(STMF_DISK, fname, prop,
   3.450 +		    propVal);
   3.451 +	}
   3.452 +	switch (stmfRet) {
   3.453 +		case STMF_STATUS_SUCCESS:
   3.454 +			break;
   3.455 +		case STMF_ERROR_BUSY:
   3.456 +		case STMF_ERROR_LU_BUSY:
   3.457 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.458 +			    gettext("resource busy"));
   3.459 +			ret++;
   3.460 +			break;
   3.461 +		case STMF_ERROR_PERM:
   3.462 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.463 +			    gettext("permission denied"));
   3.464 +			ret++;
   3.465 +			break;
   3.466 +		case STMF_ERROR_INVALID_BLKSIZE:
   3.467 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.468 +			    gettext("invalid block size"));
   3.469 +			ret++;
   3.470 +			break;
   3.471 +		case STMF_ERROR_GUID_IN_USE:
   3.472 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.473 +			    gettext("guid in use"));
   3.474 +			ret++;
   3.475 +			break;
   3.476 +		case STMF_ERROR_META_FILE_NAME:
   3.477 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.478 +			    gettext("meta file error"));
   3.479 +			ret++;
   3.480 +			break;
   3.481 +		case STMF_ERROR_DATA_FILE_NAME:
   3.482 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.483 +			    gettext("data file error"));
   3.484 +			ret++;
   3.485 +			break;
   3.486 +		case STMF_ERROR_FILE_SIZE_INVALID:
   3.487 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.488 +			    gettext("file size invalid"));
   3.489 +			ret++;
   3.490 +			break;
   3.491 +		case STMF_ERROR_SIZE_OUT_OF_RANGE:
   3.492 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.493 +			    gettext("invalid size"));
   3.494 +			ret++;
   3.495 +			break;
   3.496 +		case STMF_ERROR_META_CREATION:
   3.497 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.498 +			    gettext("could not create meta file"));
   3.499 +			ret++;
   3.500 +			break;
   3.501 +		case STMF_ERROR_INVALID_PROP:
   3.502 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.503 +			    gettext("invalid property for modify"));
   3.504 +			ret++;
   3.505 +			break;
   3.506 +		case STMF_ERROR_WRITE_CACHE_SET:
   3.507 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.508 +			    gettext("could not set write cache"));
   3.509 +			ret++;
   3.510 +			break;
   3.511 +		default:
   3.512 +			(void) fprintf(stderr, "%s: %s: %s: %d\n", cmdName,
   3.513 +			    gettext("could not set property"), propString,
   3.514 +			    stmfRet);
   3.515 +			ret++;
   3.516 +			break;
   3.517 +	}
   3.518 +
   3.519 +	return (ret);
   3.520 +}
   3.521 +
   3.522 +
   3.523 +/*
   3.524 + * importLuFunc
   3.525 + *
   3.526 + * Create a logical unit
   3.527 + *
   3.528 + */
   3.529 +/*ARGSUSED*/
   3.530 +static int
   3.531 +importLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   3.532 +    void *args)
   3.533 +{
   3.534 +	int stmfRet = 0;
   3.535 +	int ret = 0;
   3.536 +	char guidAsciiBuf[33];
   3.537 +	stmfGuid createdGuid;
   3.538 +
   3.539 +	stmfRet = stmfImportLu(STMF_DISK, operands[0], &createdGuid);
   3.540 +	switch (stmfRet) {
   3.541 +		case STMF_STATUS_SUCCESS:
   3.542 +			break;
   3.543 +		case STMF_ERROR_BUSY:
   3.544 +		case STMF_ERROR_LU_BUSY:
   3.545 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.546 +			    gettext("resource busy"));
   3.547 +			ret++;
   3.548 +			break;
   3.549 +		case STMF_ERROR_PERM:
   3.550 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.551 +			    gettext("permission denied"));
   3.552 +			ret++;
   3.553 +			break;
   3.554 +		case STMF_ERROR_FILE_IN_USE:
   3.555 +			(void) fprintf(stderr, "%s: filename %s: %s\n", cmdName,
   3.556 +			    operands[0], gettext("in use"));
   3.557 +			ret++;
   3.558 +			break;
   3.559 +		case STMF_ERROR_GUID_IN_USE:
   3.560 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.561 +			    gettext("guid in use"));
   3.562 +			ret++;
   3.563 +			break;
   3.564 +		case STMF_ERROR_META_FILE_NAME:
   3.565 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.566 +			    gettext("meta file error"));
   3.567 +			ret++;
   3.568 +			break;
   3.569 +		case STMF_ERROR_DATA_FILE_NAME:
   3.570 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.571 +			    gettext("data file error"));
   3.572 +			ret++;
   3.573 +			break;
   3.574 +		case STMF_ERROR_META_CREATION:
   3.575 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.576 +			    gettext("could not create meta file"));
   3.577 +			ret++;
   3.578 +			break;
   3.579 +		case STMF_ERROR_WRITE_CACHE_SET:
   3.580 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.581 +			    gettext("could not set write cache"));
   3.582 +			ret++;
   3.583 +			break;
   3.584 +		default:
   3.585 +			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.586 +			    gettext("unknown error"));
   3.587 +			ret++;
   3.588 +			break;
   3.589 +	}
   3.590 +
   3.591 +	if (ret != STMF_STATUS_SUCCESS) {
   3.592 +		goto done;
   3.593 +	}
   3.594 +
   3.595 +	(void) snprintf(guidAsciiBuf, sizeof (guidAsciiBuf),
   3.596 +	    "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X"
   3.597 +	    "%02X%02X%02X%02X%02X%02X",
   3.598 +	    createdGuid.guid[0], createdGuid.guid[1], createdGuid.guid[2],
   3.599 +	    createdGuid.guid[3], createdGuid.guid[4], createdGuid.guid[5],
   3.600 +	    createdGuid.guid[6], createdGuid.guid[7], createdGuid.guid[8],
   3.601 +	    createdGuid.guid[9], createdGuid.guid[10], createdGuid.guid[11],
   3.602 +	    createdGuid.guid[12], createdGuid.guid[13], createdGuid.guid[14],
   3.603 +	    createdGuid.guid[15]);
   3.604 +	(void) printf("Logical unit imported: %s\n", guidAsciiBuf);
   3.605 +
   3.606 +done:
   3.607 +	return (ret);
   3.608 +}
   3.609 +
   3.610 +static int
   3.611 +setLuPropFromInput(luResource hdl, char *optarg)
   3.612 +{
   3.613 +	char *prop = NULL;
   3.614 +	char *propVal = NULL;
   3.615 +	char *lasts = NULL;
   3.616 +	uint32_t propId;
   3.617 +	int ret = 0;
   3.618 +
   3.619 +	prop = strtok_r(optarg, "=", &lasts);
   3.620 +	if ((propVal = strtok_r(NULL, "=", &lasts)) == NULL) {
   3.621 +		(void) fprintf(stderr, "%s: %s: %s\n",
   3.622 +		    cmdName, optarg,
   3.623 +		    gettext("invalid property specifier - prop=val\n"));
   3.624 +		return (1);
   3.625 +	}
   3.626 +
   3.627 +	ret = convertCharToPropId(prop, &propId);
   3.628 +	if (ret != 0) {
   3.629 +		(void) fprintf(stderr, "%s: %s: %s\n",
   3.630 +		    cmdName, gettext("invalid property specified"), prop);
   3.631 +		return (1);
   3.632 +	}
   3.633 +
   3.634 +	ret = stmfSetLuProp(hdl, propId, propVal);
   3.635 +	if (ret != STMF_STATUS_SUCCESS) {
   3.636 +		(void) fprintf(stderr, "%s: %s %s: ",
   3.637 +		    cmdName, gettext("unable to set"), prop);
   3.638 +		switch (ret) {
   3.639 +			case STMF_ERROR_INVALID_PROPSIZE:
   3.640 +				(void) fprintf(stderr, "invalid length\n");
   3.641 +				break;
   3.642 +			case STMF_ERROR_INVALID_ARG:
   3.643 +				(void) fprintf(stderr, "bad format\n");
   3.644 +				break;
   3.645 +			default:
   3.646 +				(void) fprintf(stderr, "\n");
   3.647 +				break;
   3.648 +		}
   3.649 +		return (1);
   3.650 +	}
   3.651 +
   3.652 +	return (0);
   3.653 +}
   3.654 +
   3.655 +static int
   3.656 +convertCharToPropId(char *prop, uint32_t *propId)
   3.657 +{
   3.658 +	if (strcasecmp(prop, GUID) == 0) {
   3.659 +		*propId = STMF_LU_PROP_GUID;
   3.660 +	} else if (strcasecmp(prop, ALIAS) == 0) {
   3.661 +		*propId = STMF_LU_PROP_ALIAS;
   3.662 +	} else if (strcasecmp(prop, VID) == 0) {
   3.663 +		*propId = STMF_LU_PROP_VID;
   3.664 +	} else if (strcasecmp(prop, PID) == 0) {
   3.665 +		*propId = STMF_LU_PROP_PID;
   3.666 +	} else if (strcasecmp(prop, WRITE_PROTECT) == 0) {
   3.667 +		*propId = STMF_LU_PROP_WRITE_PROTECT;
   3.668 +	} else if (strcasecmp(prop, WRITEBACK_CACHE_DISABLE) == 0) {
   3.669 +		*propId = STMF_LU_PROP_WRITE_CACHE_DISABLE;
   3.670 +	} else if (strcasecmp(prop, BLOCK_SIZE) == 0) {
   3.671 +		*propId = STMF_LU_PROP_BLOCK_SIZE;
   3.672 +	} else if (strcasecmp(prop, SERIAL_NUMBER) == 0) {
   3.673 +		*propId = STMF_LU_PROP_SERIAL_NUM;
   3.674 +	} else if (strcasecmp(prop, COMPANY_ID) == 0) {
   3.675 +		*propId = STMF_LU_PROP_COMPANY_ID;
   3.676 +	} else if (strcasecmp(prop, META_FILE) == 0) {
   3.677 +		*propId = STMF_LU_PROP_META_FILENAME;
   3.678 +	} else {
   3.679 +		return (1);
   3.680 +	}
   3.681 +	return (0);
   3.682 +}
   3.683 +
   3.684 +/*
   3.685 + * deleteLuFunc
   3.686 + *
   3.687 + * Delete a logical unit
   3.688 + *
   3.689 + */
   3.690 +/*ARGSUSED*/
   3.691 +static int
   3.692 +deleteLuFunc(int operandLen, char *operands[], cmdOptions_t *options,
   3.693 +    void *args)
   3.694 +{
   3.695 +	int i, j;
   3.696 +	int ret = 0;
   3.697 +	int stmfRet;
   3.698 +	unsigned int inGuid[sizeof (stmfGuid)];
   3.699 +	stmfGuid delGuid;
   3.700 +	boolean_t keepViews = B_FALSE;
   3.701 +	boolean_t viewEntriesRemoved = B_FALSE;
   3.702 +	boolean_t noLunFound = B_FALSE;
   3.703 +	boolean_t views = B_FALSE;
   3.704 +	char sGuid[GUID_INPUT + 1];
   3.705 +	stmfViewEntryList *viewEntryList = NULL;
   3.706 +
   3.707 +	for (; options->optval; options++) {
   3.708 +		switch (options->optval) {
   3.709 +			/* Keep views for logical unit */
   3.710 +			case 'k':
   3.711 +				keepViews = B_TRUE;
   3.712 +				break;
   3.713 +			default:
   3.714 +				(void) fprintf(stderr, "%s: %c: %s\n",
   3.715 +				    cmdName, options->optval,
   3.716 +				    gettext("unknown option"));
   3.717 +				return (1);
   3.718 +		}
   3.719 +	}
   3.720 +
   3.721 +
   3.722 +	for (i = 0; i < operandLen; i++) {
   3.723 +		for (j = 0; j < GUID_INPUT; j++) {
   3.724 +			if (!isxdigit(operands[i][j])) {
   3.725 +				break;
   3.726 +			}
   3.727 +			sGuid[j] = tolower(operands[i][j]);
   3.728 +		}
   3.729 +		if (j != GUID_INPUT) {
   3.730 +			(void) fprintf(stderr, "%s: %s: %s%d%s\n",
   3.731 +			    cmdName, operands[i], gettext("must be "),
   3.732 +			    GUID_INPUT,
   3.733 +			    gettext(" hexadecimal digits long"));
   3.734 +			continue;
   3.735 +		}
   3.736 +
   3.737 +		sGuid[j] = 0;
   3.738 +
   3.739 +		(void) sscanf(sGuid,
   3.740 +		    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
   3.741 +		    &inGuid[0], &inGuid[1], &inGuid[2], &inGuid[3],
   3.742 +		    &inGuid[4], &inGuid[5], &inGuid[6], &inGuid[7],
   3.743 +		    &inGuid[8], &inGuid[9], &inGuid[10], &inGuid[11],
   3.744 +		    &inGuid[12], &inGuid[13], &inGuid[14], &inGuid[15]);
   3.745 +
   3.746 +		for (j = 0; j < sizeof (stmfGuid); j++) {
   3.747 +			delGuid.guid[j] = inGuid[j];
   3.748 +		}
   3.749 +
   3.750 +		stmfRet = stmfDeleteLu(&delGuid);
   3.751 +		switch (stmfRet) {
   3.752 +			case STMF_STATUS_SUCCESS:
   3.753 +				break;
   3.754 +			case STMF_ERROR_NOT_FOUND:
   3.755 +				noLunFound = B_TRUE;
   3.756 +				break;
   3.757 +			case STMF_ERROR_BUSY:
   3.758 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.759 +				    gettext("resource busy"));
   3.760 +				ret++;
   3.761 +				break;
   3.762 +			case STMF_ERROR_PERM:
   3.763 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.764 +				    gettext("permission denied"));
   3.765 +				ret++;
   3.766 +				break;
   3.767 +			default:
   3.768 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.769 +				    gettext("unknown error"));
   3.770 +				ret++;
   3.771 +				break;
   3.772 +		}
   3.773 +
   3.774 +		if (!keepViews) {
   3.775 +			stmfRet = stmfGetViewEntryList(&delGuid,
   3.776 +			    &viewEntryList);
   3.777 +			if (stmfRet == STMF_STATUS_SUCCESS) {
   3.778 +				for (j = 0; j < viewEntryList->cnt; j++) {
   3.779 +					(void) stmfRemoveViewEntry(&delGuid,
   3.780 +					    viewEntryList->ve[j].veIndex);
   3.781 +				}
   3.782 +				viewEntriesRemoved = B_TRUE;
   3.783 +				stmfFreeMemory(viewEntryList);
   3.784 +			} else if (stmfRet != STMF_ERROR_NOT_FOUND) {
   3.785 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.786 +				    gettext("unable to remove view entries\n"));
   3.787 +				ret++;
   3.788 +			} /* No view entries to remove */
   3.789 +		}
   3.790 +		if (keepViews) {
   3.791 +			stmfRet = stmfGetViewEntryList(&delGuid,
   3.792 +			    &viewEntryList);
   3.793 +			if (stmfRet == STMF_STATUS_SUCCESS) {
   3.794 +				views = B_TRUE;
   3.795 +				stmfFreeMemory(viewEntryList);
   3.796 +			}
   3.797 +		}
   3.798 +
   3.799 +		if ((!viewEntriesRemoved && noLunFound && !views) ||
   3.800 +		    (!views && keepViews && noLunFound)) {
   3.801 +			(void) fprintf(stderr, "%s: %s: %s\n",
   3.802 +			    cmdName, sGuid,
   3.803 +			    gettext("not found"));
   3.804 +			ret++;
   3.805 +		}
   3.806 +		noLunFound = viewEntriesRemoved = views = B_FALSE;
   3.807 +	}
   3.808 +	return (ret);
   3.809 +}
   3.810 +
   3.811  
   3.812  /*
   3.813   * createTargetGroupFunc
   3.814 @@ -1235,6 +1922,7 @@
   3.815  				    cmdName, operands[i], gettext("must be "),
   3.816  				    GUID_INPUT,
   3.817  				    gettext(" hexadecimal digits long"));
   3.818 +				invalidInput = B_FALSE;
   3.819  				continue;
   3.820  			}
   3.821  
   3.822 @@ -1296,6 +1984,8 @@
   3.823  						(void) printf("unknown");
   3.824  					}
   3.825  					(void) printf("\n");
   3.826 +					ret = printExtLuProps(
   3.827 +					    &(luList->guid[j]));
   3.828  				}
   3.829  				if (found && operandEntered) {
   3.830  					break;
   3.831 @@ -1320,6 +2010,154 @@
   3.832  	for (i = 0; i < 16; i++) {
   3.833  		(void) fprintf(stream, "%02X", guid->guid[i]);
   3.834  	}
   3.835 +}
   3.836 +
   3.837 +static int
   3.838 +printExtLuProps(stmfGuid *guid)
   3.839 +{
   3.840 +	int stmfRet;
   3.841 +	luResource hdl = NULL;
   3.842 +	int ret = 0;
   3.843 +	char propVal[MAXNAMELEN];
   3.844 +	size_t propValSize = sizeof (propVal);
   3.845 +
   3.846 +	if ((stmfRet = stmfGetLuResource(guid, &hdl))
   3.847 +	    != STMF_STATUS_SUCCESS) {
   3.848 +		switch (stmfRet) {
   3.849 +			case STMF_ERROR_BUSY:
   3.850 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.851 +				    gettext("resource busy"));
   3.852 +				break;
   3.853 +			case STMF_ERROR_PERM:
   3.854 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.855 +				    gettext("permission denied"));
   3.856 +				break;
   3.857 +			case STMF_ERROR_NOT_FOUND:
   3.858 +				/* No error here */
   3.859 +				return (0);
   3.860 +				break;
   3.861 +			default:
   3.862 +				(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.863 +				    gettext("get extended properties failed"));
   3.864 +				break;
   3.865 +		}
   3.866 +		return (1);
   3.867 +	}
   3.868 +
   3.869 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_FILENAME, propVal,
   3.870 +	    &propValSize);
   3.871 +	(void) printf(PROPS_FORMAT, "Data File");
   3.872 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.873 +		(void) printf("%s\n", propVal);
   3.874 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.875 +		(void) printf("not set\n");
   3.876 +	} else {
   3.877 +		(void) printf("<error retrieving property>\n");
   3.878 +		ret++;
   3.879 +	}
   3.880 +
   3.881 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_META_FILENAME, propVal,
   3.882 +	    &propValSize);
   3.883 +	(void) printf(PROPS_FORMAT, "Meta File");
   3.884 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.885 +		(void) printf("%s\n", propVal);
   3.886 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.887 +		(void) printf("not set\n");
   3.888 +	} else {
   3.889 +		(void) printf("<error retrieving property>\n");
   3.890 +		ret++;
   3.891 +	}
   3.892 +
   3.893 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SIZE, propVal,
   3.894 +	    &propValSize);
   3.895 +	(void) printf(PROPS_FORMAT, "Size");
   3.896 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.897 +		(void) printf("%s\n", propVal);
   3.898 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.899 +		(void) printf("not set\n");
   3.900 +	} else {
   3.901 +		(void) printf("<error retrieving property>\n");
   3.902 +		ret++;
   3.903 +	}
   3.904 +
   3.905 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_BLOCK_SIZE, propVal,
   3.906 +	    &propValSize);
   3.907 +	(void) printf(PROPS_FORMAT, "Block Size");
   3.908 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.909 +		(void) printf("%s\n", propVal);
   3.910 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.911 +		(void) printf("not set\n");
   3.912 +	} else {
   3.913 +		(void) printf("<error retrieving property>\n");
   3.914 +		ret++;
   3.915 +	}
   3.916 +
   3.917 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_VID, propVal,
   3.918 +	    &propValSize);
   3.919 +	(void) printf(PROPS_FORMAT, "Vendor ID");
   3.920 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.921 +		(void) printf("%s\n", propVal);
   3.922 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.923 +		(void) printf("not set\n");
   3.924 +	} else {
   3.925 +		(void) printf("<error retrieving property>\n");
   3.926 +		ret++;
   3.927 +	}
   3.928 +
   3.929 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_PID, propVal,
   3.930 +	    &propValSize);
   3.931 +	(void) printf(PROPS_FORMAT, "Product ID");
   3.932 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.933 +		(void) printf("%s\n", propVal);
   3.934 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.935 +		(void) printf("not set\n");
   3.936 +	} else {
   3.937 +		(void) printf("<error retrieving property>\n");
   3.938 +		ret++;
   3.939 +	}
   3.940 +
   3.941 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_SERIAL_NUM, propVal,
   3.942 +	    &propValSize);
   3.943 +	(void) printf(PROPS_FORMAT, "Serial Num");
   3.944 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.945 +		(void) printf("%s\n", propVal);
   3.946 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.947 +		(void) printf("not set\n");
   3.948 +	} else {
   3.949 +		(void) printf("<error retrieving property>\n");
   3.950 +		ret++;
   3.951 +	}
   3.952 +
   3.953 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_PROTECT, propVal,
   3.954 +	    &propValSize);
   3.955 +	(void) printf(PROPS_FORMAT, "Write Protect");
   3.956 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.957 +		(void) printf("%s\n",
   3.958 +		    strcasecmp(propVal, "true") ? "Disabled" : "Enabled");
   3.959 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.960 +		(void) printf("not set\n");
   3.961 +	} else {
   3.962 +		(void) printf("<error retrieving property>\n");
   3.963 +		ret++;
   3.964 +	}
   3.965 +
   3.966 +	stmfRet = stmfGetLuProp(hdl, STMF_LU_PROP_WRITE_CACHE_DISABLE, propVal,
   3.967 +	    &propValSize);
   3.968 +	(void) printf(PROPS_FORMAT, "Writeback Cache");
   3.969 +	if (stmfRet == STMF_STATUS_SUCCESS) {
   3.970 +		(void) printf("%s\n",
   3.971 +		    strcasecmp(propVal, "true") ? "Enabled" : "Disabled");
   3.972 +	} else if (stmfRet == STMF_ERROR_NO_PROP) {
   3.973 +		(void) printf("not set\n");
   3.974 +	} else {
   3.975 +		(void) printf("<error retrieving property>\n");
   3.976 +		ret++;
   3.977 +	}
   3.978 +
   3.979 +
   3.980 +	(void) stmfFreeLuResource(hdl);
   3.981 +	return (ret);
   3.982 +
   3.983  }
   3.984  
   3.985  
   3.986 @@ -1479,8 +2317,8 @@
   3.987  			    gettext("STMF service version incorrect"));
   3.988  			break;
   3.989  		default:
   3.990 -			(void) fprintf(stderr, "%s: %s\n", cmdName,
   3.991 -			    gettext("unknown error"));
   3.992 +			(void) fprintf(stderr, "%s: %s: %d\n", cmdName,
   3.993 +			    gettext("unknown error"), ret);
   3.994  			break;
   3.995  	}
   3.996  	return (ret);
     4.1 --- a/usr/src/common/cmdparse/cmdparse.c	Fri May 08 13:31:23 2009 -0700
     4.2 +++ b/usr/src/common/cmdparse/cmdparse.c	Fri May 08 16:22:42 2009 -0600
     4.3 @@ -19,7 +19,7 @@
     4.4   * CDDL HEADER END
     4.5   */
     4.6  /*
     4.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     4.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     4.9   * Use is subject to license terms.
    4.10   */
    4.11  
    4.12 @@ -250,6 +250,9 @@
    4.13  		}
    4.14  	}
    4.15  	(void) fprintf(stdout, "\n");
    4.16 +	if (subcommand->helpText) {
    4.17 +		(void) printf("%s\n", subcommand->helpText);
    4.18 +	}
    4.19  }
    4.20  
    4.21  /*
     5.1 --- a/usr/src/common/cmdparse/cmdparse.h	Fri May 08 13:31:23 2009 -0700
     5.2 +++ b/usr/src/common/cmdparse/cmdparse.h	Fri May 08 16:22:42 2009 -0600
     5.3 @@ -19,7 +19,7 @@
     5.4   * CDDL HEADER END
     5.5   */
     5.6  /*
     5.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     5.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     5.9   * Use is subject to license terms.
    5.10   */
    5.11  
    5.12 @@ -126,7 +126,8 @@
    5.13  	char *exclusive;
    5.14  	int operand;
    5.15  	char *operandDefinition;
    5.16 -	uint8_t reserved[64];
    5.17 +	char *helpText;
    5.18 +	uint8_t reserved[60];
    5.19  } subCommandProps_t;
    5.20  
    5.21  
     6.1 --- a/usr/src/lib/libstmf/Makefile.com	Fri May 08 13:31:23 2009 -0700
     6.2 +++ b/usr/src/lib/libstmf/Makefile.com	Fri May 08 16:22:42 2009 -0600
     6.3 @@ -19,7 +19,7 @@
     6.4  # CDDL HEADER END
     6.5  #
     6.6  #
     6.7 -# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     6.8 +# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     6.9  # Use is subject to license terms.
    6.10  #
    6.11  
    6.12 @@ -38,7 +38,7 @@
    6.13  
    6.14  C99MODE=	-xc99=%all
    6.15  C99LMODE=	-Xc99=%all
    6.16 -LDLIBS +=	-lc -lnvpair -lscf
    6.17 +LDLIBS +=	-lc -lnvpair -lscf -lm
    6.18  CPPFLAGS +=	$(INCS) -D_REENTRANT
    6.19  
    6.20  $(LINTLIB) := SRCS=	$(SRCDIR)/$(LINTSRC)
     7.1 --- a/usr/src/lib/libstmf/common/libstmf.h	Fri May 08 13:31:23 2009 -0700
     7.2 +++ b/usr/src/lib/libstmf/common/libstmf.h	Fri May 08 16:22:42 2009 -0600
     7.3 @@ -19,7 +19,7 @@
     7.4   * CDDL HEADER END
     7.5   */
     7.6  /*
     7.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     7.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     7.9   * Use is subject to license terms.
    7.10   */
    7.11  
    7.12 @@ -80,17 +80,62 @@
    7.13  #define	STMF_ERROR_INVALID_HG		(STMF_STATUS_ERROR | 0x11)
    7.14  #define	STMF_ERROR_INVALID_TG		(STMF_STATUS_ERROR | 0x12)
    7.15  #define	STMF_ERROR_PROV_DATA_STALE	(STMF_STATUS_ERROR | 0x13)
    7.16 +#define	STMF_ERROR_NO_PROP		(STMF_STATUS_ERROR | 0x14)
    7.17 +#define	STMF_ERROR_NO_PROP_VAL		(STMF_STATUS_ERROR | 0x15)
    7.18 +#define	STMF_ERROR_MISSING_PROP_VAL	(STMF_STATUS_ERROR | 0x16)
    7.19 +#define	STMF_ERROR_INVALID_BLOCKSIZE	(STMF_STATUS_ERROR | 0x17)
    7.20 +#define	STMF_ERROR_FILE_ALREADY		(STMF_STATUS_ERROR | 0x18)
    7.21 +#define	STMF_ERROR_INVALID_PROPSIZE	(STMF_STATUS_ERROR | 0x19)
    7.22 +#define	STMF_ERROR_INVALID_PROP		(STMF_STATUS_ERROR | 0x20)
    7.23 +#define	STMF_ERROR_PERSIST_TYPE		(STMF_STATUS_ERROR | 0x21)
    7.24 +
    7.25 +/* Failures for stmfCreateLu */
    7.26 +#define	STMF_ERROR_FILE_IN_USE		(STMF_STATUS_ERROR | 0x100)
    7.27 +#define	STMF_ERROR_INVALID_BLKSIZE	(STMF_STATUS_ERROR | 0x101)
    7.28 +#define	STMF_ERROR_GUID_IN_USE		(STMF_STATUS_ERROR | 0x102)
    7.29 +#define	STMF_ERROR_META_FILE_NAME	(STMF_STATUS_ERROR | 0x103)
    7.30 +#define	STMF_ERROR_DATA_FILE_NAME	(STMF_STATUS_ERROR | 0x104)
    7.31 +#define	STMF_ERROR_SIZE_OUT_OF_RANGE	(STMF_STATUS_ERROR | 0x105)
    7.32 +#define	STMF_ERROR_LU_BUSY		(STMF_STATUS_ERROR | 0x106)
    7.33 +#define	STMF_ERROR_META_CREATION	(STMF_STATUS_ERROR | 0x107)
    7.34 +#define	STMF_ERROR_FILE_SIZE_INVALID	(STMF_STATUS_ERROR | 0x108)
    7.35 +#define	STMF_ERROR_WRITE_CACHE_SET	(STMF_STATUS_ERROR | 0x109)
    7.36  
    7.37  /* Initiator Name Types */
    7.38  #define	STMF_FC_PORT_WWN	    1
    7.39  #define	STMF_ISCSI_NAME		    2
    7.40  
    7.41 -/* protected data flag for provider store */
    7.42 -#define	STMF_PROTECTED_DATA	0x0001
    7.43  
    7.44  /* provider types */
    7.45  #define	STMF_LU_PROVIDER_TYPE	1
    7.46  #define	STMF_PORT_PROVIDER_TYPE	2
    7.47 +
    7.48 +/* LU Resource types */
    7.49 +#define	STMF_DISK   0
    7.50 +
    7.51 +/* Persistence methods */
    7.52 +#define	STMF_PERSIST_SMF	1
    7.53 +#define	STMF_PERSIST_NONE	2
    7.54 +
    7.55 +/*
    7.56 + * LU Disk Properties
    7.57 + */
    7.58 +
    7.59 +enum {
    7.60 +	STMF_LU_PROP_ALIAS = 1,
    7.61 +	STMF_LU_PROP_BLOCK_SIZE,
    7.62 +	STMF_LU_PROP_COMPANY_ID,
    7.63 +	STMF_LU_PROP_FILENAME,
    7.64 +	STMF_LU_PROP_GUID,
    7.65 +	STMF_LU_PROP_META_FILENAME,
    7.66 +	STMF_LU_PROP_NEW,
    7.67 +	STMF_LU_PROP_SIZE,
    7.68 +	STMF_LU_PROP_WRITE_PROTECT,
    7.69 +	STMF_LU_PROP_WRITE_CACHE_DISABLE,
    7.70 +	STMF_LU_PROP_VID,
    7.71 +	STMF_LU_PROP_PID,
    7.72 +	STMF_LU_PROP_SERIAL_NUM
    7.73 +};
    7.74  
    7.75  
    7.76  /* devid code set and name types */
    7.77 @@ -224,6 +269,8 @@
    7.78  	stmfGuid    luid;
    7.79  } stmfLogicalUnitProperties;
    7.80  
    7.81 +typedef void * luResource;
    7.82 +
    7.83  typedef struct _stmfLogicalUnitProviderProperties
    7.84  {
    7.85  	char	    providerName[MAXPATHLEN];
    7.86 @@ -247,11 +294,15 @@
    7.87  int stmfAddViewEntry(stmfGuid *lu, stmfViewEntry *viewEntry);
    7.88  int stmfClearProviderData(char *providerName, int providerType);
    7.89  int stmfCreateHostGroup(stmfGroupName *hostGroupName);
    7.90 +int stmfCreateLu(luResource hdl, stmfGuid *luGuid);
    7.91 +int stmfCreateLuResource(uint16_t dType, luResource *hdl);
    7.92  int stmfCreateTargetGroup(stmfGroupName *targetGroupName);
    7.93  int stmfDeleteHostGroup(stmfGroupName *hostGroupName);
    7.94 +int stmfDeleteLu(stmfGuid *luGuid);
    7.95  int stmfDeleteTargetGroup(stmfGroupName *targetGroupName);
    7.96  int stmfDevidFromIscsiName(char *iscsiName, stmfDevid *devid);
    7.97  int stmfDevidFromWwn(uchar_t wwn[8], stmfDevid *devid);
    7.98 +int stmfFreeLuResource(luResource hdl);
    7.99  void stmfFreeMemory(void *);
   7.100  int stmfGetHostGroupList(stmfGroupList **initiatorGroupList);
   7.101  int stmfGetHostGroupMembers(stmfGroupName *hostGroupName,
   7.102 @@ -265,6 +316,10 @@
   7.103  int stmfGetLogicalUnitProviderList(stmfProviderList **logicalUnitProviderList);
   7.104  int stmfGetLogicalUnitProviderProperties(stmfProviderName *providerName,
   7.105      stmfLogicalUnitProviderProperties *providerProperties);
   7.106 +int stmfGetLuProp(luResource hdl, uint32_t propType, char *prop,
   7.107 +    size_t *propLen);
   7.108 +int stmfGetLuResource(stmfGuid *luGuid, luResource *hdl);
   7.109 +int stmfGetPersistMethod(uint8_t *persistType, boolean_t serviceState);
   7.110  int stmfGetProviderData(char *providerName, nvlist_t **nvl, int providerType);
   7.111  int stmfGetProviderDataProt(char *providerName, nvlist_t **nvl,
   7.112      int providerType, uint64_t *setToken);
   7.113 @@ -277,7 +332,11 @@
   7.114  int stmfGetTargetProperties(stmfDevid *target,
   7.115      stmfTargetProperties *targetProps);
   7.116  int stmfGetViewEntryList(stmfGuid *lu, stmfViewEntryList **viewEntryList);
   7.117 +int stmfImportLu(uint16_t dType, char *fname, stmfGuid *luGuid);
   7.118  int stmfLoadConfig(void);
   7.119 +int stmfModifyLu(stmfGuid *luGuid, uint32_t prop, const char *propVal);
   7.120 +int stmfModifyLuByFname(uint16_t dType, const char *fname, uint32_t prop,
   7.121 +    const char *propVal);
   7.122  int stmfOffline(void);
   7.123  int stmfOfflineTarget(stmfDevid *devid);
   7.124  int stmfOfflineLogicalUnit(stmfGuid *logicalUnit);
   7.125 @@ -289,6 +348,8 @@
   7.126  int stmfRemoveFromTargetGroup(stmfGroupName *targetGroupName,
   7.127      stmfDevid *targetName);
   7.128  int stmfRemoveViewEntry(stmfGuid *lu, uint32_t viewEntryIndex);
   7.129 +int stmfSetLuProp(luResource hdl, uint32_t propType, const char *propVal);
   7.130 +int stmfSetPersistMethod(uint8_t persistType, boolean_t serviceSet);
   7.131  int stmfSetProviderData(char *providerName, nvlist_t *nvl, int providerType);
   7.132  int stmfSetProviderDataProt(char *providerName, nvlist_t *nvl,
   7.133      int providerType, uint64_t *setToken);
     8.1 --- a/usr/src/lib/libstmf/common/mapfile-vers	Fri May 08 13:31:23 2009 -0700
     8.2 +++ b/usr/src/lib/libstmf/common/mapfile-vers	Fri May 08 16:22:42 2009 -0600
     8.3 @@ -42,26 +42,36 @@
     8.4  	    stmfAddViewEntry;
     8.5  	    stmfClearProviderData;
     8.6  	    stmfCreateHostGroup;
     8.7 +	    stmfCreateLu;
     8.8 +	    stmfCreateLuResource;
     8.9  	    stmfCreateTargetGroup;
    8.10  	    stmfDeleteHostGroup;
    8.11 +	    stmfDeleteLu;
    8.12  	    stmfDeleteTargetGroup;
    8.13  	    stmfDevidFromIscsiName;
    8.14  	    stmfDevidFromWwn;
    8.15 +	    stmfFreeLuResource;
    8.16  	    stmfFreeMemory;
    8.17  	    stmfGetHostGroupList;
    8.18  	    stmfGetHostGroupMembers;
    8.19 +	    stmfGetLuProp;
    8.20 +	    stmfGetLuResource;
    8.21  	    stmfGetTargetGroupList;
    8.22  	    stmfGetTargetGroupMembers;
    8.23  	    stmfGetTargetList;
    8.24  	    stmfGetTargetProperties;
    8.25  	    stmfGetLogicalUnitList;
    8.26  	    stmfGetLogicalUnitProperties;
    8.27 +	    stmfGetPersistMethod;
    8.28  	    stmfGetProviderData;
    8.29  	    stmfGetProviderDataList;
    8.30  	    stmfGetProviderDataProt;
    8.31  	    stmfGetSessionList;
    8.32  	    stmfGetState;
    8.33  	    stmfGetViewEntryList;
    8.34 +	    stmfImportLu;
    8.35 +	    stmfModifyLu;
    8.36 +	    stmfModifyLuByFname;
    8.37  	    stmfOfflineTarget;
    8.38  	    stmfOfflineLogicalUnit;
    8.39  	    stmfOnlineTarget;
    8.40 @@ -69,8 +79,10 @@
    8.41  	    stmfRemoveFromHostGroup;
    8.42  	    stmfRemoveFromTargetGroup;
    8.43  	    stmfRemoveViewEntry;
    8.44 +	    stmfSetPersistMethod;
    8.45  	    stmfSetProviderData;
    8.46  	    stmfSetProviderDataProt;
    8.47 +	    stmfSetLuProp;
    8.48  	local:
    8.49  		*;
    8.50  };
     9.1 --- a/usr/src/lib/libstmf/common/stmf.c	Fri May 08 13:31:23 2009 -0700
     9.2 +++ b/usr/src/lib/libstmf/common/stmf.c	Fri May 08 16:22:42 2009 -0600
     9.3 @@ -19,7 +19,7 @@
     9.4   * CDDL HEADER END
     9.5   */
     9.6  /*
     9.7 - * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     9.8 + * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     9.9   * Use is subject to license terms.
    9.10   */
    9.11  
    9.12 @@ -43,31 +43,58 @@
    9.13  #include <inttypes.h>
    9.14  #include <store.h>
    9.15  #include <locale.h>
    9.16 +#include <math.h>
    9.17 +#include <libstmf_impl.h>
    9.18  #include <sys/stmf_ioctl.h>
    9.19 +#include <sys/stmf_sbd_ioctl.h>
    9.20  
    9.21  #define	STMF_PATH    "/devices/pseudo/stmf@0:admin"
    9.22 +#define	SBD_PATH    "/devices/pseudo/stmf_sbd@0:admin"
    9.23  
    9.24  #define	EUI "eui."
    9.25  #define	WWN "wwn."
    9.26  #define	IQN "iqn."
    9.27 -#define	WWN_ASCII_SIZE 16
    9.28 +#define	LU_ASCII_GUID_SIZE 32
    9.29 +#define	LU_GUID_SIZE 16
    9.30 +#define	OUI_ASCII_SIZE 6
    9.31 +#define	OUI_SIZE 3
    9.32  #define	IDENT_LENGTH_BYTE 3
    9.33  
    9.34 -#define	MAX_LU		2<<16 - 1
    9.35 -#define	MAX_TARGET_PORT	1024
    9.36 -#define	MAX_PROVIDER	1024
    9.37 -#define	MAX_GROUP	1024
    9.38 -#define	MAX_SESSION	1024
    9.39 +/* various initial allocation values */
    9.40 +#define	ALLOC_LU		8192
    9.41 +#define	ALLOC_TARGET_PORT	2048
    9.42 +#define	ALLOC_PROVIDER		64
    9.43 +#define	ALLOC_GROUP		2048
    9.44 +#define	ALLOC_SESSION		2048
    9.45 +#define	ALLOC_VE		256
    9.46 +#define	ALLOC_PP_DATA_SIZE	128*1024
    9.47 +#define	ALLOC_GRP_MEMBER	256
    9.48 +
    9.49  #define	MAX_ISCSI_NAME	223
    9.50 +#define	MAX_SERIAL_SIZE 252 + 1
    9.51 +#define	MAX_LU_ALIAS_SIZE 256
    9.52 +#define	MAX_SBD_PROPS	MAXPATHLEN + MAX_SERIAL_SIZE + MAX_LU_ALIAS_SIZE
    9.53  
    9.54  #define	OPEN_STMF 0
    9.55  #define	OPEN_EXCL_STMF O_EXCL
    9.56 +
    9.57 +#define	OPEN_SBD 0
    9.58 +#define	OPEN_EXCL_SBD O_EXCL
    9.59  
    9.60  #define	LOGICAL_UNIT_TYPE 0
    9.61  #define	TARGET_TYPE 1
    9.62  #define	STMF_SERVICE_TYPE 2
    9.63  
    9.64 +#define	HOST_GROUP   1
    9.65 +#define	TARGET_GROUP 2
    9.66 +
    9.67 +/* set default persistence here */
    9.68 +#define	STMF_DEFAULT_PERSIST	STMF_PERSIST_SMF
    9.69 +
    9.70 +#define	MAX_PROVIDER_RETRY 30
    9.71 +
    9.72  static int openStmf(int, int *fd);
    9.73 +static int openSbd(int, int *fd);
    9.74  static int groupIoctl(int fd, int cmd, stmfGroupName *);
    9.75  static int loadStore(int fd);
    9.76  static int initializeConfig();
    9.77 @@ -78,7 +105,36 @@
    9.78  static int loadTargetGroups(int fd, stmfGroupList *);
    9.79  static int getStmfState(stmf_state_desc_t *);
    9.80  static int setStmfState(int fd, stmf_state_desc_t *, int);
    9.81 -static int setProviderData(int fd, char *, nvlist_t *, int);
    9.82 +static int setProviderData(int fd, char *, nvlist_t *, int, uint64_t *);
    9.83 +static int createDiskResource(luResourceImpl *);
    9.84 +static int createDiskLu(diskResource *, stmfGuid *);
    9.85 +static int deleteDiskLu(stmfGuid *luGuid);
    9.86 +static int getDiskProp(luResourceImpl *, uint32_t, char *, size_t *);
    9.87 +static int getDiskAllProps(stmfGuid *luGuid, luResource *hdl);
    9.88 +static int loadDiskPropsFromDriver(luResourceImpl *, sbd_lu_props_t *);
    9.89 +static int removeGuidFromDiskStore(stmfGuid *);
    9.90 +static int addGuidToDiskStore(stmfGuid *, char *);
    9.91 +static int persistDiskGuid(stmfGuid *, char *, boolean_t);
    9.92 +static int setDiskProp(luResourceImpl *, uint32_t, const char *);
    9.93 +static int checkHexUpper(char *);
    9.94 +static int strToShift(const char *);
    9.95 +static int niceStrToNum(const char *, uint64_t *);
    9.96 +static void diskError(uint32_t, int *);
    9.97 +static int importDiskLu(char *fname, stmfGuid *);
    9.98 +static int modifyDiskLu(diskResource *, stmfGuid *, const char *);
    9.99 +static int modifyDiskLuProp(stmfGuid *, const char *, uint32_t, const char *);
   9.100 +static int validateModifyDiskProp(uint32_t);
   9.101 +static uint8_t iGetPersistMethod();
   9.102 +static int groupListIoctl(stmfGroupList **, int);
   9.103 +static int iLoadGroupFromPs(stmfGroupList **, int);
   9.104 +static int groupMemberListIoctl(stmfGroupName *, stmfGroupProperties **, int);
   9.105 +static int getProviderData(char *, nvlist_t **, int, uint64_t *);
   9.106 +static int viewEntryCompare(const void *, const void *);
   9.107 +
   9.108 +static pthread_mutex_t persistenceTypeLock = PTHREAD_MUTEX_INITIALIZER;
   9.109 +static int iPersistType = 0;
   9.110 +/* when B_TRUE, no need to access SMF anymore. Just use iPersistType */
   9.111 +static boolean_t iLibSetPersist = B_FALSE;
   9.112  
   9.113  /*
   9.114   * Open for stmf module
   9.115 @@ -96,11 +152,41 @@
   9.116  	} else {
   9.117  		if (errno == EBUSY) {
   9.118  			ret = STMF_ERROR_BUSY;
   9.119 +		} else if (errno == EACCES) {
   9.120 +			ret = STMF_ERROR_PERM;
   9.121  		} else {
   9.122  			ret = STMF_STATUS_ERROR;
   9.123  		}
   9.124  		syslog(LOG_DEBUG, "openStmf:open failure:%s:errno(%d)",
   9.125  		    STMF_PATH, errno);
   9.126 +	}
   9.127 +
   9.128 +	return (ret);
   9.129 +}
   9.130 +
   9.131 +/*
   9.132 + * Open for sbd module
   9.133 + *
   9.134 + * flag - open flag (OPEN_STMF, OPEN_EXCL_STMF)
   9.135 + * fd - pointer to integer. On success, contains the stmf file descriptor
   9.136 + */
   9.137 +static int
   9.138 +openSbd(int flag, int *fd)
   9.139 +{
   9.140 +	int ret = STMF_STATUS_ERROR;
   9.141 +
   9.142 +	if ((*fd = open(SBD_PATH, O_NDELAY | O_RDONLY | flag)) != -1) {
   9.143 +		ret = STMF_STATUS_SUCCESS;
   9.144 +	} else {
   9.145 +		if (errno == EBUSY) {
   9.146 +			ret = STMF_ERROR_BUSY;
   9.147 +		} else if (errno == EACCES) {
   9.148 +			ret = STMF_ERROR_PERM;
   9.149 +		} else {
   9.150 +			ret = STMF_STATUS_ERROR;
   9.151 +		}
   9.152 +		syslog(LOG_DEBUG, "openSbd:open failure:%s:errno(%d)",
   9.153 +		    SBD_PATH, errno);
   9.154  	}
   9.155  
   9.156  	return (ret);
   9.157 @@ -187,6 +273,7 @@
   9.158  	ioctlRet = ioctl(fd, cmd, &stmfIoctl);
   9.159  	if (ioctlRet != 0) {
   9.160  		switch (errno) {
   9.161 +			case EPERM:
   9.162  			case EACCES:
   9.163  				ret = STMF_ERROR_PERM;
   9.164  				break;
   9.165 @@ -219,7 +306,7 @@
   9.166  }
   9.167  
   9.168  /*
   9.169 - * groupIoctl
   9.170 + * groupMemberIoctl
   9.171   *
   9.172   * Purpose: issue ioctl for add/remove member on group
   9.173   *
   9.174 @@ -257,6 +344,7 @@
   9.175  			case EBUSY:
   9.176  				ret = STMF_ERROR_BUSY;
   9.177  				break;
   9.178 +			case EPERM:
   9.179  			case EACCES:
   9.180  				ret = STMF_ERROR_PERM;
   9.181  				break;
   9.182 @@ -292,6 +380,22 @@
   9.183  }
   9.184  
   9.185  /*
   9.186 + * qsort function
   9.187 + * sort on veIndex
   9.188 + */
   9.189 +static int
   9.190 +viewEntryCompare(const void *p1, const void *p2)
   9.191 +{
   9.192 +
   9.193 +	stmfViewEntry *v1 = (stmfViewEntry *)p1, *v2 = (stmfViewEntry *)p2;
   9.194 +	if (v1->veIndex > v2->veIndex)
   9.195 +		return (1);
   9.196 +	if (v1->veIndex < v2->veIndex)
   9.197 +		return (-1);
   9.198 +	return (0);
   9.199 +}
   9.200 +
   9.201 +/*
   9.202   * guidCompare
   9.203   *
   9.204   * qsort function
   9.205 @@ -351,6 +455,10 @@
   9.206  		goto done;
   9.207  	}
   9.208  
   9.209 +	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
   9.210 +		goto done;
   9.211 +	}
   9.212 +
   9.213  	ret = psAddHostGroupMember((char *)hostGroupName,
   9.214  	    (char *)hostName->ident);
   9.215  	switch (ret) {
   9.216 @@ -429,6 +537,10 @@
   9.217  
   9.218  	if ((ret = groupMemberIoctl(fd, STMF_IOCTL_ADD_TG_ENTRY,
   9.219  	    targetGroupName, targetName)) != STMF_STATUS_SUCCESS) {
   9.220 +		goto done;
   9.221 +	}
   9.222 +
   9.223 +	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
   9.224  		goto done;
   9.225  	}
   9.226  
   9.227 @@ -526,6 +638,9 @@
   9.228  			case EBUSY:
   9.229  				ret = STMF_ERROR_BUSY;
   9.230  				break;
   9.231 +			case EPERM:
   9.232 +				ret = STMF_ERROR_PERM;
   9.233 +				break;
   9.234  			case EACCES:
   9.235  				switch (stmfIoctl.stmf_error) {
   9.236  					case STMF_IOCERR_UPDATE_NEED_CFG_INIT:
   9.237 @@ -651,6 +766,10 @@
   9.238  		goto done;
   9.239  	}
   9.240  
   9.241 +	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
   9.242 +		goto done;
   9.243 +	}
   9.244 +
   9.245  	/*
   9.246  	 * If the add to driver was successful, add it to the persistent
   9.247  	 * store.
   9.248 @@ -760,6 +879,7 @@
   9.249  			case EBUSY:
   9.250  				ret = STMF_ERROR_BUSY;
   9.251  				break;
   9.252 +			case EPERM:
   9.253  			case EACCES:
   9.254  				ret = STMF_ERROR_PERM;
   9.255  				break;
   9.256 @@ -773,6 +893,10 @@
   9.257  		if (savedErrno != ENOENT) {
   9.258  			goto done;
   9.259  		}
   9.260 +	}
   9.261 +
   9.262 +	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
   9.263 +		goto done;
   9.264  	}
   9.265  
   9.266  	ret = psClearProviderData(providerName, providerType);
   9.267 @@ -846,6 +970,10 @@
   9.268  		goto done;
   9.269  	}
   9.270  
   9.271 +	if (iGetPersistMethod() == STMF_PERSIST_NONE) {
   9.272 +		goto done;
   9.273 +	}
   9.274 +
   9.275  	ret = psCreateHostGroup((char *)hostGroupName);
   9.276  	switch (ret) {
   9.277  		case STMF_PS_SUCCESS:
   9.278 @@ -874,6 +1002,1641 @@
   9.279  done:
   9.280  	(void) close(fd);
   9.281  	return (ret);
   9.282 +}
   9.283 +
   9.284 +/*
   9.285 + * stmfCreateLu
   9.286 + *
   9.287 + * Purpose: Create a logical unit
   9.288 + *
   9.289 + * hdl - handle to logical unit resource created via stmfCreateLuResource
   9.290 + *
   9.291 + * luGuid - If non-NULL, on success, contains the guid of the created logical
   9.292 + *	    unit
   9.293 + */
   9.294 +int
   9.295 +stmfCreateLu(luResource hdl, stmfGuid *luGuid)
   9.296 +{
   9.297 +	int ret = STMF_STATUS_SUCCESS;
   9.298 +	luResourceImpl *luPropsHdl = hdl;
   9.299 +
   9.300 +	if (hdl == NULL) {
   9.301 +		return (STMF_ERROR_INVALID_ARG);
   9.302 +	}
   9.303 +
   9.304 +	if (luPropsHdl->type == STMF_DISK) {
   9.305 +		ret = createDiskLu((diskResource *)luPropsHdl->resource,
   9.306 +		    luGuid);
   9.307 +	} else {
   9.308 +		return (STMF_ERROR_INVALID_ARG);
   9.309 +	}
   9.310 +
   9.311 +	return (ret);
   9.312 +}
   9.313 +
   9.314 +/*
   9.315 + * stmfCreateLuResource
   9.316 + *
   9.317 + * Purpose: Create resource handle for a logical unit
   9.318 + *
   9.319 + * dType - Type of logical unit resource to create
   9.320 + *	   Can be: STMF_DISK
   9.321 + *
   9.322 + * hdl - pointer to luResource
   9.323 + */
   9.324 +int
   9.325 +stmfCreateLuResource(uint16_t dType, luResource *hdl)
   9.326 +{
   9.327 +	int ret = STMF_STATUS_SUCCESS;
   9.328 +
   9.329 +	if (dType != STMF_DISK || hdl == NULL) {
   9.330 +		return (STMF_ERROR_INVALID_ARG);
   9.331 +	}
   9.332 +
   9.333 +	*hdl = calloc(1, sizeof (luResourceImpl));
   9.334 +	if (*hdl == NULL) {
   9.335 +		return (STMF_ERROR_NOMEM);
   9.336 +	}
   9.337 +
   9.338 +	ret = createDiskResource((luResourceImpl *)*hdl);
   9.339 +	if (ret != STMF_STATUS_SUCCESS) {
   9.340 +		free(*hdl);
   9.341 +		return (ret);
   9.342 +	}
   9.343 +
   9.344 +	return (STMF_STATUS_SUCCESS);
   9.345 +}
   9.346 +
   9.347 +/*
   9.348 + * Creates a disk logical unit
   9.349 + *
   9.350 + * disk - pointer to diskResource structure that represents the properties
   9.351 + *        for the disk logical unit to be created.
   9.352 + */
   9.353 +static int
   9.354 +createDiskLu(diskResource *disk, stmfGuid *createdGuid)
   9.355 +{
   9.356 +	int ret = STMF_STATUS_SUCCESS;
   9.357 +	int dataFileNameLen = 0;
   9.358 +	int metaFileNameLen = 0;
   9.359 +	int serialNumLen = 0;
   9.360 +	int luAliasLen = 0;
   9.361 +	int sluBufSize = 0;
   9.362 +	int bufOffset = 0;
   9.363 +	int fd = 0;
   9.364 +	int ioctlRet;
   9.365 +	int savedErrno;
   9.366 +	stmfGuid guid;
   9.367 +	stmf_iocdata_t sbdIoctl = {0};
   9.368 +
   9.369 +	sbd_create_and_reg_lu_t *sbdLu = NULL;
   9.370 +
   9.371 +	/*
   9.372 +	 * Open control node for sbd
   9.373 +	 */
   9.374 +	if ((ret = openSbd(OPEN_SBD, &fd)) != STMF_STATUS_SUCCESS)
   9.375 +		return (ret);
   9.376 +
   9.377 +	/* data file name must be specified */
   9.378 +	if (disk->luDataFileNameValid) {
   9.379 +		dataFileNameLen = strlen(disk->luDataFileName);
   9.380 +	} else {
   9.381 +		(void) close(fd);
   9.382 +		return (STMF_ERROR_MISSING_PROP_VAL);
   9.383 +	}
   9.384 +
   9.385 +	sluBufSize += dataFileNameLen + 1;
   9.386 +
   9.387 +	if (disk->luMetaFileNameValid) {
   9.388 +		metaFileNameLen = strlen(disk->luMetaFileName);
   9.389 +		sluBufSize += metaFileNameLen + 1;
   9.390 +	}
   9.391 +
   9.392 +	serialNumLen = strlen(disk->serialNum);
   9.393 +	sluBufSize += serialNumLen;
   9.394 +
   9.395 +	if (disk->luAliasValid) {
   9.396 +		luAliasLen = strlen(disk->luAlias);
   9.397 +		sluBufSize += luAliasLen + 1;
   9.398 +	}
   9.399 +
   9.400 +	/*
   9.401 +	 * 8 is the size of the buffer set aside for
   9.402 +	 * concatenation of variable length fields
   9.403 +	 */
   9.404 +	sbdLu = (sbd_create_and_reg_lu_t *)calloc(1,
   9.405 +	    sizeof (sbd_create_and_reg_lu_t) + sluBufSize - 8);
   9.406 +	if (sbdLu == NULL) {
   9.407 +		return (STMF_ERROR_NOMEM);
   9.408 +	}
   9.409 +
   9.410 +	sbdLu->slu_struct_size = sizeof (sbd_create_and_reg_lu_t) +
   9.411 +	    sluBufSize - 8;
   9.412 +
   9.413 +	if (metaFileNameLen) {
   9.414 +		sbdLu->slu_meta_fname_valid = 1;
   9.415 +		sbdLu->slu_meta_fname_off = bufOffset;
   9.416 +		bcopy(disk->luMetaFileName, &(sbdLu->slu_buf[bufOffset]),
   9.417 +		    metaFileNameLen + 1);
   9.418 +		bufOffset += metaFileNameLen + 1;
   9.419 +	}
   9.420 +
   9.421 +	bcopy(disk->luDataFileName, &(sbdLu->slu_buf[bufOffset]),
   9.422 +	    dataFileNameLen + 1);
   9.423 +	sbdLu->slu_data_fname_off = bufOffset;
   9.424 +	bufOffset += dataFileNameLen + 1;
   9.425 +
   9.426 +	/* currently, serial # is not passed null terminated to the driver */
   9.427 +	if (disk->serialNumValid) {
   9.428 +		sbdLu->slu_serial_valid = 1;
   9.429 +		sbdLu->slu_serial_off = bufOffset;
   9.430 +		sbdLu->slu_serial_size = serialNumLen;
   9.431 +		bcopy(disk->serialNum, &(sbdLu->slu_buf[bufOffset]),
   9.432 +		    serialNumLen);
   9.433 +		bufOffset += serialNumLen;
   9.434 +	}
   9.435 +
   9.436 +	if (disk->luAliasValid) {
   9.437 +		sbdLu->slu_alias_valid = 1;
   9.438 +		sbdLu->slu_alias_off = bufOffset;
   9.439 +		bcopy(disk->luAlias, &(sbdLu->slu_buf[bufOffset]),
   9.440 +		    luAliasLen + 1);
   9.441 +		bufOffset += luAliasLen + 1;
   9.442 +	}
   9.443 +
   9.444 +	if (disk->luSizeValid) {
   9.445 +		sbdLu->slu_lu_size_valid = 1;
   9.446 +		sbdLu->slu_lu_size = disk->luSize;
   9.447 +	}
   9.448 +
   9.449 +	if (disk->luGuidValid) {
   9.450 +		sbdLu->slu_guid_valid = 1;
   9.451 +		bcopy(disk->luGuid, sbdLu->slu_guid, sizeof (disk->luGuid));
   9.452 +	}
   9.453 +
   9.454 +	if (disk->vidValid) {
   9.455 +		sbdLu->slu_vid_valid = 1;
   9.456 +		bcopy(disk->vid, sbdLu->slu_vid, sizeof (disk->vid));
   9.457 +	}
   9.458 +
   9.459 +	if (disk->pidValid) {
   9.460 +		sbdLu->slu_pid_valid = 1;
   9.461 +		bcopy(disk->pid, sbdLu->slu_pid, sizeof (disk->pid));
   9.462 +	}
   9.463 +
   9.464 +	if (disk->revValid) {
   9.465 +		sbdLu->slu_rev_valid = 1;
   9.466 +		bcopy(disk->rev, sbdLu->slu_rev, sizeof (disk->rev));
   9.467 +	}
   9.468 +
   9.469 +	if (disk->companyIdValid) {
   9.470 +		sbdLu->slu_company_id_valid = 1;
   9.471 +		sbdLu->slu_company_id = disk->companyId;
   9.472 +	}
   9.473 +
   9.474 +	if (disk->blkSizeValid) {
   9.475 +		sbdLu->slu_blksize_valid = 1;
   9.476 +		sbdLu->slu_blksize = disk->blkSize;
   9.477 +	}
   9.478 +
   9.479 +	if (disk->writeProtectEnableValid) {
   9.480 +		if (disk->writeProtectEnable) {
   9.481 +			sbdLu->slu_write_protected = 1;
   9.482 +		}
   9.483 +	}
   9.484 +
   9.485 +	if (disk->writebackCacheDisableValid) {
   9.486 +		sbdLu->slu_writeback_cache_disable_valid = 1;
   9.487 +		if (disk->writebackCacheDisable) {
   9.488 +			sbdLu->slu_writeback_cache_disable = 1;
   9.489 +		}
   9.490 +	}
   9.491 +
   9.492 +	sbdIoctl.stmf_version = STMF_VERSION_1;
   9.493 +	sbdIoctl.stmf_ibuf_size = sbdLu->slu_struct_size;
   9.494 +	sbdIoctl.stmf_ibuf = (uint64_t)(unsigned long)sbdLu;
   9.495 +	sbdIoctl.stmf_obuf_size = sbdLu->slu_struct_size;
   9.496 +	sbdIoctl.stmf_obuf = (uint64_t)(unsigned long)sbdLu;
   9.497 +
   9.498 +	ioctlRet = ioctl(fd, SBD_IOCTL_CREATE_AND_REGISTER_LU, &sbdIoctl);
   9.499 +	if (ioctlRet != 0) {
   9.500 +		savedErrno = errno;
   9.501 +		switch (savedErrno) {
   9.502 +			case EBUSY:
   9.503 +				ret = STMF_ERROR_BUSY;
   9.504 +				break;
   9.505 +			case EPERM:
   9.506 +			case EACCES:
   9.507 +				ret = STMF_ERROR_PERM;
   9.508 +				break;
   9.509 +			default: