xref: /onnv-gate/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c (revision 12591:cdf3cc28b713)
17836SJohn.Forte@Sun.COM /*
27836SJohn.Forte@Sun.COM  * CDDL HEADER START
37836SJohn.Forte@Sun.COM  *
47836SJohn.Forte@Sun.COM  * The contents of this file are subject to the terms of the
57836SJohn.Forte@Sun.COM  * Common Development and Distribution License (the "License").
67836SJohn.Forte@Sun.COM  * You may not use this file except in compliance with the License.
77836SJohn.Forte@Sun.COM  *
87836SJohn.Forte@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97836SJohn.Forte@Sun.COM  * or http://www.opensolaris.org/os/licensing.
107836SJohn.Forte@Sun.COM  * See the License for the specific language governing permissions
117836SJohn.Forte@Sun.COM  * and limitations under the License.
127836SJohn.Forte@Sun.COM  *
137836SJohn.Forte@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
147836SJohn.Forte@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157836SJohn.Forte@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
167836SJohn.Forte@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
177836SJohn.Forte@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
187836SJohn.Forte@Sun.COM  *
197836SJohn.Forte@Sun.COM  * CDDL HEADER END
207836SJohn.Forte@Sun.COM  */
217836SJohn.Forte@Sun.COM /*
2212202SNattuvetty.Bhavyan@Sun.COM  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
237836SJohn.Forte@Sun.COM  */
247836SJohn.Forte@Sun.COM 
257836SJohn.Forte@Sun.COM #include <sys/conf.h>
267836SJohn.Forte@Sun.COM #include <sys/file.h>
277836SJohn.Forte@Sun.COM #include <sys/ddi.h>
287836SJohn.Forte@Sun.COM #include <sys/sunddi.h>
297836SJohn.Forte@Sun.COM #include <sys/modctl.h>
307836SJohn.Forte@Sun.COM #include <sys/scsi/scsi.h>
317836SJohn.Forte@Sun.COM #include <sys/scsi/impl/scsi_reset_notify.h>
327836SJohn.Forte@Sun.COM #include <sys/disp.h>
337836SJohn.Forte@Sun.COM #include <sys/byteorder.h>
349585STim.Szeto@Sun.COM #include <sys/pathname.h>
357836SJohn.Forte@Sun.COM #include <sys/atomic.h>
367836SJohn.Forte@Sun.COM #include <sys/nvpair.h>
379585STim.Szeto@Sun.COM #include <sys/fs/zfs.h>
389585STim.Szeto@Sun.COM #include <sys/sdt.h>
399585STim.Szeto@Sun.COM #include <sys/dkio.h>
409679STim.Szeto@Sun.COM #include <sys/zfs_ioctl.h>
417836SJohn.Forte@Sun.COM 
4212571SViswanathan.Kannappan@Sun.COM #include <sys/stmf.h>
4312571SViswanathan.Kannappan@Sun.COM #include <sys/lpif.h>
4412571SViswanathan.Kannappan@Sun.COM #include <sys/stmf_ioctl.h>
4512571SViswanathan.Kannappan@Sun.COM #include <sys/stmf_sbd_ioctl.h>
4612571SViswanathan.Kannappan@Sun.COM 
4712571SViswanathan.Kannappan@Sun.COM #include "stmf_sbd.h"
4812571SViswanathan.Kannappan@Sun.COM #include "sbd_impl.h"
497836SJohn.Forte@Sun.COM 
509679STim.Szeto@Sun.COM #define	SBD_IS_ZVOL(zvol)	(strncmp("/dev/zvol", zvol, 9))
519585STim.Szeto@Sun.COM 
529933SNattuvetty.Bhavyan@Sun.COM extern sbd_status_t sbd_pgr_meta_init(sbd_lu_t *sl);
539585STim.Szeto@Sun.COM extern sbd_status_t sbd_pgr_meta_load(sbd_lu_t *sl);
5410725SJohn.Forte@Sun.COM extern void sbd_pgr_reset(sbd_lu_t *sl);
559585STim.Szeto@Sun.COM 
569585STim.Szeto@Sun.COM static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
579585STim.Szeto@Sun.COM     void **result);
587836SJohn.Forte@Sun.COM static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
597836SJohn.Forte@Sun.COM static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
607836SJohn.Forte@Sun.COM static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp);
617836SJohn.Forte@Sun.COM static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp);
627836SJohn.Forte@Sun.COM static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
639585STim.Szeto@Sun.COM     cred_t *credp, int *rval);
647836SJohn.Forte@Sun.COM void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags);
6510725SJohn.Forte@Sun.COM stmf_status_t sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg,
6610725SJohn.Forte@Sun.COM     uint32_t proxy_reg_arg_len);
6710725SJohn.Forte@Sun.COM stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
6810725SJohn.Forte@Sun.COM     uint32_t proxy_reg_arg_len);
6910725SJohn.Forte@Sun.COM stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
7010725SJohn.Forte@Sun.COM     uint32_t proxy_arg_len, uint32_t type);
719585STim.Szeto@Sun.COM int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
729585STim.Szeto@Sun.COM     uint32_t *err_ret);
7310725SJohn.Forte@Sun.COM int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
7410725SJohn.Forte@Sun.COM int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
759585STim.Szeto@Sun.COM int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
769585STim.Szeto@Sun.COM     int no_register, sbd_lu_t **slr);
7710725SJohn.Forte@Sun.COM int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
789585STim.Szeto@Sun.COM int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
799585STim.Szeto@Sun.COM int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
8011103SJohn.Forte@Sun.COM int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
8111103SJohn.Forte@Sun.COM     uint32_t *err_ret);
8211103SJohn.Forte@Sun.COM int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
8311103SJohn.Forte@Sun.COM     uint32_t *err_ret);
849585STim.Szeto@Sun.COM int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
859585STim.Szeto@Sun.COM     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
869585STim.Szeto@Sun.COM char *sbd_get_zvol_name(sbd_lu_t *sl);
879585STim.Szeto@Sun.COM sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
889585STim.Szeto@Sun.COM sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
899585STim.Szeto@Sun.COM sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
909585STim.Szeto@Sun.COM     uint64_t off);
919585STim.Szeto@Sun.COM sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
929585STim.Szeto@Sun.COM     uint64_t off);
9312499SJohn.Forte@Sun.COM sbd_status_t sbd_update_zfs_prop(sbd_lu_t *sl);
949679STim.Szeto@Sun.COM int sbd_is_zvol(char *path);
959679STim.Szeto@Sun.COM int sbd_zvolget(char *zvol_name, char **comstarprop);
969679STim.Szeto@Sun.COM int sbd_zvolset(char *zvol_name, char *comstarprop);
979857SPeter.Cudhea@Sun.COM char sbd_ctoi(char c);
9810725SJohn.Forte@Sun.COM void sbd_close_lu(sbd_lu_t *sl);
997836SJohn.Forte@Sun.COM 
1009679STim.Szeto@Sun.COM static ldi_ident_t	sbd_zfs_ident;
1017836SJohn.Forte@Sun.COM static stmf_lu_provider_t *sbd_lp;
1029585STim.Szeto@Sun.COM static sbd_lu_t		*sbd_lu_list = NULL;
1039585STim.Szeto@Sun.COM static kmutex_t		sbd_lock;
1049585STim.Szeto@Sun.COM static dev_info_t	*sbd_dip;
1059585STim.Szeto@Sun.COM static uint32_t		sbd_lu_count = 0;
10611103SJohn.Forte@Sun.COM 
10711103SJohn.Forte@Sun.COM /* Global property settings for the logical unit */
1089585STim.Szeto@Sun.COM char sbd_vendor_id[]	= "SUN     ";
1099585STim.Szeto@Sun.COM char sbd_product_id[]	= "COMSTAR         ";
1109585STim.Szeto@Sun.COM char sbd_revision[]	= "1.0 ";
11111103SJohn.Forte@Sun.COM char *sbd_mgmt_url = NULL;
11211103SJohn.Forte@Sun.COM uint16_t sbd_mgmt_url_alloc_size = 0;
11311103SJohn.Forte@Sun.COM krwlock_t sbd_global_prop_lock;
11411103SJohn.Forte@Sun.COM 
1157836SJohn.Forte@Sun.COM static char sbd_name[] = "sbd";
1167836SJohn.Forte@Sun.COM 
1177836SJohn.Forte@Sun.COM static struct cb_ops sbd_cb_ops = {
1187836SJohn.Forte@Sun.COM 	sbd_open,			/* open */
1197836SJohn.Forte@Sun.COM 	sbd_close,			/* close */
1207836SJohn.Forte@Sun.COM 	nodev,				/* strategy */
1217836SJohn.Forte@Sun.COM 	nodev,				/* print */
1227836SJohn.Forte@Sun.COM 	nodev,				/* dump */
1237836SJohn.Forte@Sun.COM 	nodev,				/* read */
1247836SJohn.Forte@Sun.COM 	nodev,				/* write */
1257836SJohn.Forte@Sun.COM 	stmf_sbd_ioctl,			/* ioctl */
1267836SJohn.Forte@Sun.COM 	nodev,				/* devmap */
1277836SJohn.Forte@Sun.COM 	nodev,				/* mmap */
1287836SJohn.Forte@Sun.COM 	nodev,				/* segmap */
1297836SJohn.Forte@Sun.COM 	nochpoll,			/* chpoll */
1307836SJohn.Forte@Sun.COM 	ddi_prop_op,			/* cb_prop_op */
1317836SJohn.Forte@Sun.COM 	0,				/* streamtab */
1327836SJohn.Forte@Sun.COM 	D_NEW | D_MP,			/* cb_flag */
1337836SJohn.Forte@Sun.COM 	CB_REV,				/* rev */
1347836SJohn.Forte@Sun.COM 	nodev,				/* aread */
1357836SJohn.Forte@Sun.COM 	nodev				/* awrite */
1367836SJohn.Forte@Sun.COM };
1377836SJohn.Forte@Sun.COM 
1387836SJohn.Forte@Sun.COM static struct dev_ops sbd_ops = {
1397836SJohn.Forte@Sun.COM 	DEVO_REV,
1407836SJohn.Forte@Sun.COM 	0,
1417836SJohn.Forte@Sun.COM 	sbd_getinfo,
1427836SJohn.Forte@Sun.COM 	nulldev,		/* identify */
1437836SJohn.Forte@Sun.COM 	nulldev,		/* probe */
1447836SJohn.Forte@Sun.COM 	sbd_attach,
1457836SJohn.Forte@Sun.COM 	sbd_detach,
1467836SJohn.Forte@Sun.COM 	nodev,			/* reset */
1477836SJohn.Forte@Sun.COM 	&sbd_cb_ops,
1487836SJohn.Forte@Sun.COM 	NULL,			/* bus_ops */
1497836SJohn.Forte@Sun.COM 	NULL			/* power */
1507836SJohn.Forte@Sun.COM };
1517836SJohn.Forte@Sun.COM 
1527836SJohn.Forte@Sun.COM #define	SBD_NAME	"COMSTAR SBD"
1537836SJohn.Forte@Sun.COM 
1547836SJohn.Forte@Sun.COM static struct modldrv modldrv = {
1557836SJohn.Forte@Sun.COM 	&mod_driverops,
1567836SJohn.Forte@Sun.COM 	SBD_NAME,
1577836SJohn.Forte@Sun.COM 	&sbd_ops
1587836SJohn.Forte@Sun.COM };
1597836SJohn.Forte@Sun.COM 
1607836SJohn.Forte@Sun.COM static struct modlinkage modlinkage = {
1617836SJohn.Forte@Sun.COM 	MODREV_1,
1627836SJohn.Forte@Sun.COM 	&modldrv,
1637836SJohn.Forte@Sun.COM 	NULL
1647836SJohn.Forte@Sun.COM };
1657836SJohn.Forte@Sun.COM 
1667836SJohn.Forte@Sun.COM int
_init(void)1677836SJohn.Forte@Sun.COM _init(void)
1687836SJohn.Forte@Sun.COM {
1697836SJohn.Forte@Sun.COM 	int ret;
1707836SJohn.Forte@Sun.COM 
1717836SJohn.Forte@Sun.COM 	ret = mod_install(&modlinkage);
1727836SJohn.Forte@Sun.COM 	if (ret)
1737836SJohn.Forte@Sun.COM 		return (ret);
1747836SJohn.Forte@Sun.COM 	sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER,
1758818STim.Szeto@Sun.COM 	    0, 0);
17610725SJohn.Forte@Sun.COM 	sbd_lp->lp_lpif_rev = LPIF_REV_2;
1777836SJohn.Forte@Sun.COM 	sbd_lp->lp_instance = 0;
1787836SJohn.Forte@Sun.COM 	sbd_lp->lp_name = sbd_name;
1797836SJohn.Forte@Sun.COM 	sbd_lp->lp_cb = sbd_lp_cb;
18010725SJohn.Forte@Sun.COM 	sbd_lp->lp_alua_support = 1;
18110725SJohn.Forte@Sun.COM 	sbd_lp->lp_proxy_msg = sbd_proxy_msg;
1829679STim.Szeto@Sun.COM 	sbd_zfs_ident = ldi_ident_from_anon();
1837836SJohn.Forte@Sun.COM 
1847836SJohn.Forte@Sun.COM 	if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) {
1857836SJohn.Forte@Sun.COM 		(void) mod_remove(&modlinkage);
1867836SJohn.Forte@Sun.COM 		stmf_free(sbd_lp);
1878818STim.Szeto@Sun.COM 		return (EINVAL);
1887836SJohn.Forte@Sun.COM 	}
1897836SJohn.Forte@Sun.COM 	mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL);
19011103SJohn.Forte@Sun.COM 	rw_init(&sbd_global_prop_lock, NULL, RW_DRIVER, NULL);
1917836SJohn.Forte@Sun.COM 	return (0);
1927836SJohn.Forte@Sun.COM }
1937836SJohn.Forte@Sun.COM 
1947836SJohn.Forte@Sun.COM int
_fini(void)1957836SJohn.Forte@Sun.COM _fini(void)
1967836SJohn.Forte@Sun.COM {
1977836SJohn.Forte@Sun.COM 	int ret;
1987836SJohn.Forte@Sun.COM 
1997836SJohn.Forte@Sun.COM 	/*
2007836SJohn.Forte@Sun.COM 	 * If we have registered lus, then make sure they are all offline
2017836SJohn.Forte@Sun.COM 	 * if so then deregister them. This should drop the sbd_lu_count
2027836SJohn.Forte@Sun.COM 	 * to zero.
2037836SJohn.Forte@Sun.COM 	 */
2047836SJohn.Forte@Sun.COM 	if (sbd_lu_count) {
2057836SJohn.Forte@Sun.COM 		sbd_lu_t *slu;
2067836SJohn.Forte@Sun.COM 
2077836SJohn.Forte@Sun.COM 		/* See if all of them are offline */
2087836SJohn.Forte@Sun.COM 		mutex_enter(&sbd_lock);
2097836SJohn.Forte@Sun.COM 		for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) {
2107836SJohn.Forte@Sun.COM 			if ((slu->sl_state != STMF_STATE_OFFLINE) ||
2117836SJohn.Forte@Sun.COM 			    slu->sl_state_not_acked) {
2127836SJohn.Forte@Sun.COM 				mutex_exit(&sbd_lock);
2137836SJohn.Forte@Sun.COM 				return (EBUSY);
2147836SJohn.Forte@Sun.COM 			}
2157836SJohn.Forte@Sun.COM 		}
2167836SJohn.Forte@Sun.COM 		mutex_exit(&sbd_lock);
2177836SJohn.Forte@Sun.COM 
2189585STim.Szeto@Sun.COM #if 0
2197836SJohn.Forte@Sun.COM 		/* ok start deregistering them */
2207836SJohn.Forte@Sun.COM 		while (sbd_lu_list) {
2217836SJohn.Forte@Sun.COM 			sbd_store_t *sst = sbd_lu_list->sl_sst;
2227836SJohn.Forte@Sun.COM 			if (sst->sst_deregister_lu(sst) != STMF_SUCCESS)
2237836SJohn.Forte@Sun.COM 				return (EBUSY);
2247836SJohn.Forte@Sun.COM 		}
2259585STim.Szeto@Sun.COM #endif
2269585STim.Szeto@Sun.COM 		return (EBUSY);
2277836SJohn.Forte@Sun.COM 	}
2287836SJohn.Forte@Sun.COM 	if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS)
2297836SJohn.Forte@Sun.COM 		return (EBUSY);
2307836SJohn.Forte@Sun.COM 	ret = mod_remove(&modlinkage);
2317836SJohn.Forte@Sun.COM 	if (ret != 0) {
2327836SJohn.Forte@Sun.COM 		(void) stmf_register_lu_provider(sbd_lp);
2337836SJohn.Forte@Sun.COM 		return (ret);
2347836SJohn.Forte@Sun.COM 	}
2357836SJohn.Forte@Sun.COM 	stmf_free(sbd_lp);
2367836SJohn.Forte@Sun.COM 	mutex_destroy(&sbd_lock);
23711103SJohn.Forte@Sun.COM 	rw_destroy(&sbd_global_prop_lock);
2389679STim.Szeto@Sun.COM 	ldi_ident_release(sbd_zfs_ident);
2397836SJohn.Forte@Sun.COM 	return (0);
2407836SJohn.Forte@Sun.COM }
2417836SJohn.Forte@Sun.COM 
2427836SJohn.Forte@Sun.COM int
_info(struct modinfo * modinfop)2437836SJohn.Forte@Sun.COM _info(struct modinfo *modinfop)
2447836SJohn.Forte@Sun.COM {
2457836SJohn.Forte@Sun.COM 	return (mod_info(&modlinkage, modinfop));
2467836SJohn.Forte@Sun.COM }
2477836SJohn.Forte@Sun.COM 
2487836SJohn.Forte@Sun.COM /* ARGSUSED */
2497836SJohn.Forte@Sun.COM static int
sbd_getinfo(dev_info_t * dip,ddi_info_cmd_t cmd,void * arg,void ** result)2507836SJohn.Forte@Sun.COM sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
2517836SJohn.Forte@Sun.COM {
2527836SJohn.Forte@Sun.COM 	switch (cmd) {
2537836SJohn.Forte@Sun.COM 	case DDI_INFO_DEVT2DEVINFO:
2547836SJohn.Forte@Sun.COM 		*result = sbd_dip;
2557836SJohn.Forte@Sun.COM 		break;
2567836SJohn.Forte@Sun.COM 	case DDI_INFO_DEVT2INSTANCE:
2579585STim.Szeto@Sun.COM 		*result = (void *)(uintptr_t)ddi_get_instance(sbd_dip);
2587836SJohn.Forte@Sun.COM 		break;
2597836SJohn.Forte@Sun.COM 	default:
2607836SJohn.Forte@Sun.COM 		return (DDI_FAILURE);
2617836SJohn.Forte@Sun.COM 	}
2627836SJohn.Forte@Sun.COM 
2637836SJohn.Forte@Sun.COM 	return (DDI_SUCCESS);
2647836SJohn.Forte@Sun.COM }
2657836SJohn.Forte@Sun.COM 
2667836SJohn.Forte@Sun.COM static int
sbd_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)2677836SJohn.Forte@Sun.COM sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
2687836SJohn.Forte@Sun.COM {
2697836SJohn.Forte@Sun.COM 	switch (cmd) {
2707836SJohn.Forte@Sun.COM 	case DDI_ATTACH:
2717836SJohn.Forte@Sun.COM 		sbd_dip = dip;
2727836SJohn.Forte@Sun.COM 
2737836SJohn.Forte@Sun.COM 		if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
2747836SJohn.Forte@Sun.COM 		    DDI_NT_STMF_LP, 0) != DDI_SUCCESS) {
2757836SJohn.Forte@Sun.COM 			break;
2767836SJohn.Forte@Sun.COM 		}
2777836SJohn.Forte@Sun.COM 		ddi_report_dev(dip);
2787836SJohn.Forte@Sun.COM 		return (DDI_SUCCESS);
2797836SJohn.Forte@Sun.COM 	}
2807836SJohn.Forte@Sun.COM 
2817836SJohn.Forte@Sun.COM 	return (DDI_FAILURE);
2827836SJohn.Forte@Sun.COM }
2837836SJohn.Forte@Sun.COM 
2847836SJohn.Forte@Sun.COM static int
sbd_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2857836SJohn.Forte@Sun.COM sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2867836SJohn.Forte@Sun.COM {
2877836SJohn.Forte@Sun.COM 	switch (cmd) {
2887836SJohn.Forte@Sun.COM 	case DDI_DETACH:
2897836SJohn.Forte@Sun.COM 		ddi_remove_minor_node(dip, 0);
2907836SJohn.Forte@Sun.COM 		return (DDI_SUCCESS);
2917836SJohn.Forte@Sun.COM 	}
2927836SJohn.Forte@Sun.COM 
2937836SJohn.Forte@Sun.COM 	return (DDI_FAILURE);
2947836SJohn.Forte@Sun.COM }
2957836SJohn.Forte@Sun.COM 
2967836SJohn.Forte@Sun.COM /* ARGSUSED */
2977836SJohn.Forte@Sun.COM static int
sbd_open(dev_t * devp,int flag,int otype,cred_t * credp)2987836SJohn.Forte@Sun.COM sbd_open(dev_t *devp, int flag, int otype, cred_t *credp)
2997836SJohn.Forte@Sun.COM {
3007836SJohn.Forte@Sun.COM 	if (otype != OTYP_CHR)
3017836SJohn.Forte@Sun.COM 		return (EINVAL);
3027836SJohn.Forte@Sun.COM 	return (0);
3037836SJohn.Forte@Sun.COM }
3047836SJohn.Forte@Sun.COM 
3057836SJohn.Forte@Sun.COM /* ARGSUSED */
3067836SJohn.Forte@Sun.COM static int
sbd_close(dev_t dev,int flag,int otype,cred_t * credp)3077836SJohn.Forte@Sun.COM sbd_close(dev_t dev, int flag, int otype, cred_t *credp)
3087836SJohn.Forte@Sun.COM {
3097836SJohn.Forte@Sun.COM 	return (0);
3107836SJohn.Forte@Sun.COM }
3117836SJohn.Forte@Sun.COM 
3127836SJohn.Forte@Sun.COM /* ARGSUSED */
3137836SJohn.Forte@Sun.COM static int
stmf_sbd_ioctl(dev_t dev,int cmd,intptr_t data,int mode,cred_t * credp,int * rval)3147836SJohn.Forte@Sun.COM stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
3157836SJohn.Forte@Sun.COM 	cred_t *credp, int *rval)
3167836SJohn.Forte@Sun.COM {
3179585STim.Szeto@Sun.COM 	stmf_iocdata_t		*iocd;
3189585STim.Szeto@Sun.COM 	void			*ibuf	= NULL;
3199585STim.Szeto@Sun.COM 	void			*obuf	= NULL;
3209585STim.Szeto@Sun.COM 	sbd_lu_t		*nsl;
3219585STim.Szeto@Sun.COM 	int			i;
3229585STim.Szeto@Sun.COM 	int			ret;
3237836SJohn.Forte@Sun.COM 
3247836SJohn.Forte@Sun.COM 	if (drv_priv(credp) != 0) {
3257836SJohn.Forte@Sun.COM 		return (EPERM);
3267836SJohn.Forte@Sun.COM 	}
3277836SJohn.Forte@Sun.COM 
3289585STim.Szeto@Sun.COM 	ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
3299585STim.Szeto@Sun.COM 	if (ret)
3309585STim.Szeto@Sun.COM 		return (ret);
3319585STim.Szeto@Sun.COM 	iocd->stmf_error = 0;
3327836SJohn.Forte@Sun.COM 
3337836SJohn.Forte@Sun.COM 	switch (cmd) {
3349585STim.Szeto@Sun.COM 	case SBD_IOCTL_CREATE_AND_REGISTER_LU:
3359585STim.Szeto@Sun.COM 		if (iocd->stmf_ibuf_size <
3369585STim.Szeto@Sun.COM 		    (sizeof (sbd_create_and_reg_lu_t) - 8)) {
3379585STim.Szeto@Sun.COM 			ret = EFAULT;
3389585STim.Szeto@Sun.COM 			break;
3399585STim.Szeto@Sun.COM 		}
3409585STim.Szeto@Sun.COM 		if ((iocd->stmf_obuf_size == 0) ||
3419585STim.Szeto@Sun.COM 		    (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
3427836SJohn.Forte@Sun.COM 			ret = EINVAL;
3437836SJohn.Forte@Sun.COM 			break;
3447836SJohn.Forte@Sun.COM 		}
3459585STim.Szeto@Sun.COM 		ret = sbd_create_register_lu((sbd_create_and_reg_lu_t *)
3469585STim.Szeto@Sun.COM 		    ibuf, iocd->stmf_ibuf_size, &iocd->stmf_error);
3479585STim.Szeto@Sun.COM 		bcopy(ibuf, obuf, iocd->stmf_obuf_size);
3487836SJohn.Forte@Sun.COM 		break;
34910725SJohn.Forte@Sun.COM 	case SBD_IOCTL_SET_LU_STANDBY:
35010725SJohn.Forte@Sun.COM 		if (iocd->stmf_ibuf_size < sizeof (sbd_set_lu_standby_t)) {
35110725SJohn.Forte@Sun.COM 			ret = EFAULT;
35210725SJohn.Forte@Sun.COM 			break;
35310725SJohn.Forte@Sun.COM 		}
35410725SJohn.Forte@Sun.COM 		if (iocd->stmf_obuf_size) {
35510725SJohn.Forte@Sun.COM 			ret = EINVAL;
35610725SJohn.Forte@Sun.COM 			break;
35710725SJohn.Forte@Sun.COM 		}
35810725SJohn.Forte@Sun.COM 		ret = sbd_set_lu_standby((sbd_set_lu_standby_t *)ibuf,
35910725SJohn.Forte@Sun.COM 		    &iocd->stmf_error);
36010725SJohn.Forte@Sun.COM 		break;
3619585STim.Szeto@Sun.COM 	case SBD_IOCTL_IMPORT_LU:
3629585STim.Szeto@Sun.COM 		if (iocd->stmf_ibuf_size <
3639585STim.Szeto@Sun.COM 		    (sizeof (sbd_import_lu_t) - 8)) {
3649585STim.Szeto@Sun.COM 			ret = EFAULT;
3659585STim.Szeto@Sun.COM 			break;
3669585STim.Szeto@Sun.COM 		}
3679585STim.Szeto@Sun.COM 		if ((iocd->stmf_obuf_size == 0) ||
3689585STim.Szeto@Sun.COM 		    (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
3699585STim.Szeto@Sun.COM 			ret = EINVAL;
3709585STim.Szeto@Sun.COM 			break;
3719585STim.Szeto@Sun.COM 		}
3729585STim.Szeto@Sun.COM 		ret = sbd_import_lu((sbd_import_lu_t *)ibuf,
3739585STim.Szeto@Sun.COM 		    iocd->stmf_ibuf_size, &iocd->stmf_error, 0, NULL);
3749585STim.Szeto@Sun.COM 		bcopy(ibuf, obuf, iocd->stmf_obuf_size);
3759585STim.Szeto@Sun.COM 		break;
3769585STim.Szeto@Sun.COM 	case SBD_IOCTL_DELETE_LU:
3779585STim.Szeto@Sun.COM 		if (iocd->stmf_ibuf_size < (sizeof (sbd_delete_lu_t) - 8)) {
3789585STim.Szeto@Sun.COM 			ret = EFAULT;
3799585STim.Szeto@Sun.COM 			break;
3809585STim.Szeto@Sun.COM 		}
3819585STim.Szeto@Sun.COM 		if (iocd->stmf_obuf_size) {
3827836SJohn.Forte@Sun.COM 			ret = EINVAL;
3837836SJohn.Forte@Sun.COM 			break;
3847836SJohn.Forte@Sun.COM 		}
3859585STim.Szeto@Sun.COM 		ret = sbd_delete_lu((sbd_delete_lu_t *)ibuf,
3869585STim.Szeto@Sun.COM 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
3877836SJohn.Forte@Sun.COM 		break;
3889585STim.Szeto@Sun.COM 	case SBD_IOCTL_MODIFY_LU:
3899585STim.Szeto@Sun.COM 		if (iocd->stmf_ibuf_size < (sizeof (sbd_modify_lu_t) - 8)) {
3909585STim.Szeto@Sun.COM 			ret = EFAULT;
3917836SJohn.Forte@Sun.COM 			break;
3927836SJohn.Forte@Sun.COM 		}
3939585STim.Szeto@Sun.COM 		if (iocd->stmf_obuf_size) {
3949585STim.Szeto@Sun.COM 			ret = EINVAL;
3957836SJohn.Forte@Sun.COM 			break;
3967836SJohn.Forte@Sun.COM 		}
3979585STim.Szeto@Sun.COM 		ret = sbd_modify_lu((sbd_modify_lu_t *)ibuf,
3989585STim.Szeto@Sun.COM 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
3999585STim.Szeto@Sun.COM 		break;
40011103SJohn.Forte@Sun.COM 	case SBD_IOCTL_SET_GLOBAL_LU:
40111103SJohn.Forte@Sun.COM 		if (iocd->stmf_ibuf_size < (sizeof (sbd_global_props_t) - 8)) {
40211103SJohn.Forte@Sun.COM 			ret = EFAULT;
40311103SJohn.Forte@Sun.COM 			break;
40411103SJohn.Forte@Sun.COM 		}
40511103SJohn.Forte@Sun.COM 		if (iocd->stmf_obuf_size) {
40611103SJohn.Forte@Sun.COM 			ret = EINVAL;
40711103SJohn.Forte@Sun.COM 			break;
40811103SJohn.Forte@Sun.COM 		}
40911103SJohn.Forte@Sun.COM 		ret = sbd_set_global_props((sbd_global_props_t *)ibuf,
41011103SJohn.Forte@Sun.COM 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
41111103SJohn.Forte@Sun.COM 		break;
41211103SJohn.Forte@Sun.COM 	case SBD_IOCTL_GET_GLOBAL_LU:
41311103SJohn.Forte@Sun.COM 		if (iocd->stmf_ibuf_size) {
41411103SJohn.Forte@Sun.COM 			ret = EINVAL;
41511103SJohn.Forte@Sun.COM 			break;
41611103SJohn.Forte@Sun.COM 		}
41711103SJohn.Forte@Sun.COM 		if (iocd->stmf_obuf_size < sizeof (sbd_global_props_t)) {
41811103SJohn.Forte@Sun.COM 			ret = EINVAL;
41911103SJohn.Forte@Sun.COM 			break;
42011103SJohn.Forte@Sun.COM 		}
42111103SJohn.Forte@Sun.COM 		ret = sbd_get_global_props((sbd_global_props_t *)obuf,
42211103SJohn.Forte@Sun.COM 		    iocd->stmf_obuf_size, &iocd->stmf_error);
42311103SJohn.Forte@Sun.COM 		break;
4249585STim.Szeto@Sun.COM 	case SBD_IOCTL_GET_LU_PROPS:
4259585STim.Szeto@Sun.COM 		if (iocd->stmf_ibuf_size < (sizeof (sbd_lu_props_t) - 8)) {
4269585STim.Szeto@Sun.COM 			ret = EFAULT;
4279585STim.Szeto@Sun.COM 			break;
4287836SJohn.Forte@Sun.COM 		}
4299585STim.Szeto@Sun.COM 		if (iocd->stmf_obuf_size < sizeof (sbd_lu_props_t)) {
4307836SJohn.Forte@Sun.COM 			ret = EINVAL;
4317836SJohn.Forte@Sun.COM 			break;
4327836SJohn.Forte@Sun.COM 		}
4339585STim.Szeto@Sun.COM 		ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
4349585STim.Szeto@Sun.COM 		    iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
4359585STim.Szeto@Sun.COM 		    iocd->stmf_obuf_size, &iocd->stmf_error);
4369585STim.Szeto@Sun.COM 		break;
4379585STim.Szeto@Sun.COM 	case SBD_IOCTL_GET_LU_LIST:
4387836SJohn.Forte@Sun.COM 		mutex_enter(&sbd_lock);
4399585STim.Szeto@Sun.COM 		iocd->stmf_obuf_max_nentries = sbd_lu_count;
4409585STim.Szeto@Sun.COM 		iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
4419585STim.Szeto@Sun.COM 		    sbd_lu_count);
4429585STim.Szeto@Sun.COM 		for (nsl = sbd_lu_list, i = 0; nsl &&
4439585STim.Szeto@Sun.COM 		    (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
4449585STim.Szeto@Sun.COM 			bcopy(nsl->sl_device_id + 4,
4459585STim.Szeto@Sun.COM 			    &(((uint8_t *)obuf)[i << 4]), 16);
4467836SJohn.Forte@Sun.COM 		}
4477836SJohn.Forte@Sun.COM 		mutex_exit(&sbd_lock);
4489585STim.Szeto@Sun.COM 		ret = 0;
4499585STim.Szeto@Sun.COM 		iocd->stmf_error = 0;
4507836SJohn.Forte@Sun.COM 		break;
4517836SJohn.Forte@Sun.COM 	default:
4529585STim.Szeto@Sun.COM 		ret = ENOTTY;
4537836SJohn.Forte@Sun.COM 	}
4547836SJohn.Forte@Sun.COM 
4559585STim.Szeto@Sun.COM 	if (ret == 0) {
4569585STim.Szeto@Sun.COM 		ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
4579585STim.Szeto@Sun.COM 	} else if (iocd->stmf_error) {
4589585STim.Szeto@Sun.COM 		(void) stmf_copyout_iocdata(data, mode, iocd, obuf);
4599585STim.Szeto@Sun.COM 	}
4609585STim.Szeto@Sun.COM 	if (obuf) {
4619585STim.Szeto@Sun.COM 		kmem_free(obuf, iocd->stmf_obuf_size);
4629585STim.Szeto@Sun.COM 		obuf = NULL;
4639585STim.Szeto@Sun.COM 	}
4649585STim.Szeto@Sun.COM 	if (ibuf) {
4659585STim.Szeto@Sun.COM 		kmem_free(ibuf, iocd->stmf_ibuf_size);
4669585STim.Szeto@Sun.COM 		ibuf = NULL;
4679585STim.Szeto@Sun.COM 	}
4689585STim.Szeto@Sun.COM 	kmem_free(iocd, sizeof (stmf_iocdata_t));
4697836SJohn.Forte@Sun.COM 	return (ret);
4707836SJohn.Forte@Sun.COM }
4717836SJohn.Forte@Sun.COM 
4727836SJohn.Forte@Sun.COM /* ARGSUSED */
4737836SJohn.Forte@Sun.COM void
sbd_lp_cb(stmf_lu_provider_t * lp,int cmd,void * arg,uint32_t flags)4747836SJohn.Forte@Sun.COM sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags)
4757836SJohn.Forte@Sun.COM {
4769585STim.Szeto@Sun.COM 	nvpair_t	*np;
4779585STim.Szeto@Sun.COM 	char		*s;
4789585STim.Szeto@Sun.COM 	sbd_import_lu_t *ilu;
4799585STim.Szeto@Sun.COM 	uint32_t	ilu_sz;
4809585STim.Szeto@Sun.COM 	uint32_t	struct_sz;
4819585STim.Szeto@Sun.COM 	uint32_t	err_ret;
4829585STim.Szeto@Sun.COM 	int		iret;
4837836SJohn.Forte@Sun.COM 
4847836SJohn.Forte@Sun.COM 	if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
4857836SJohn.Forte@Sun.COM 		return;
4867836SJohn.Forte@Sun.COM 	}
4877836SJohn.Forte@Sun.COM 
4887836SJohn.Forte@Sun.COM 	if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) {
4897836SJohn.Forte@Sun.COM 		return;
4907836SJohn.Forte@Sun.COM 	}
4917836SJohn.Forte@Sun.COM 
4927836SJohn.Forte@Sun.COM 	np = NULL;
4939585STim.Szeto@Sun.COM 	ilu_sz = 1024;
4949585STim.Szeto@Sun.COM 	ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
4957836SJohn.Forte@Sun.COM 	while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) {
4967836SJohn.Forte@Sun.COM 		if (nvpair_type(np) != DATA_TYPE_STRING) {
4977836SJohn.Forte@Sun.COM 			continue;
4987836SJohn.Forte@Sun.COM 		}
4997836SJohn.Forte@Sun.COM 		if (nvpair_value_string(np, &s) != 0) {
5007836SJohn.Forte@Sun.COM 			continue;
5017836SJohn.Forte@Sun.COM 		}
5029585STim.Szeto@Sun.COM 		struct_sz = max(8, strlen(s) + 1);
5039585STim.Szeto@Sun.COM 		struct_sz += sizeof (sbd_import_lu_t) - 8;
5049585STim.Szeto@Sun.COM 		if (struct_sz > ilu_sz) {
5059585STim.Szeto@Sun.COM 			kmem_free(ilu, ilu_sz);
5069585STim.Szeto@Sun.COM 			ilu_sz = struct_sz + 32;
5079585STim.Szeto@Sun.COM 			ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
5087836SJohn.Forte@Sun.COM 		}
5099585STim.Szeto@Sun.COM 		ilu->ilu_struct_size = struct_sz;
5109585STim.Szeto@Sun.COM 		(void) strcpy(ilu->ilu_meta_fname, s);
5119585STim.Szeto@Sun.COM 		iret = sbd_import_lu(ilu, struct_sz, &err_ret, 0, NULL);
5129585STim.Szeto@Sun.COM 		if (iret) {
5139585STim.Szeto@Sun.COM 			stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, "
5149585STim.Szeto@Sun.COM 			    "err_ret = %d", iret, err_ret);
5159585STim.Szeto@Sun.COM 		} else {
5169585STim.Szeto@Sun.COM 			stmf_trace(0, "Imported the LU %s", nvpair_name(np));
5179585STim.Szeto@Sun.COM 		}
5187836SJohn.Forte@Sun.COM 	}
5197836SJohn.Forte@Sun.COM 
5209585STim.Szeto@Sun.COM 	if (ilu) {
5219585STim.Szeto@Sun.COM 		kmem_free(ilu, ilu_sz);
5229585STim.Szeto@Sun.COM 		ilu = NULL;
5237836SJohn.Forte@Sun.COM 	}
5247836SJohn.Forte@Sun.COM }
5257836SJohn.Forte@Sun.COM 
5269585STim.Szeto@Sun.COM sbd_status_t
sbd_link_lu(sbd_lu_t * sl)5279585STim.Szeto@Sun.COM sbd_link_lu(sbd_lu_t *sl)
5287836SJohn.Forte@Sun.COM {
5299585STim.Szeto@Sun.COM 	sbd_lu_t *nsl;
5307836SJohn.Forte@Sun.COM 
5319585STim.Szeto@Sun.COM 	mutex_enter(&sbd_lock);
5329585STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_lock);
5339585STim.Szeto@Sun.COM 	ASSERT(sl->sl_trans_op != SL_OP_NONE);
5347836SJohn.Forte@Sun.COM 
5359585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_LINKED) {
5369585STim.Szeto@Sun.COM 		mutex_exit(&sbd_lock);
5379585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
5389585STim.Szeto@Sun.COM 		return (SBD_ALREADY);
5399585STim.Szeto@Sun.COM 	}
5409585STim.Szeto@Sun.COM 	for (nsl = sbd_lu_list; nsl; nsl = nsl->sl_next) {
5419585STim.Szeto@Sun.COM 		if (strcmp(nsl->sl_name, sl->sl_name) == 0)
5429585STim.Szeto@Sun.COM 			break;
5439585STim.Szeto@Sun.COM 	}
5449585STim.Szeto@Sun.COM 	if (nsl) {
5459585STim.Szeto@Sun.COM 		mutex_exit(&sbd_lock);
5469585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
5479585STim.Szeto@Sun.COM 		return (SBD_ALREADY);
5489585STim.Szeto@Sun.COM 	}
5499585STim.Szeto@Sun.COM 	sl->sl_next = sbd_lu_list;
5509585STim.Szeto@Sun.COM 	sbd_lu_list = sl;
5519585STim.Szeto@Sun.COM 	sl->sl_flags |= SL_LINKED;
5529585STim.Szeto@Sun.COM 	mutex_exit(&sbd_lock);
5539585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
5549585STim.Szeto@Sun.COM 	return (SBD_SUCCESS);
5557836SJohn.Forte@Sun.COM }
5567836SJohn.Forte@Sun.COM 
5577836SJohn.Forte@Sun.COM void
sbd_unlink_lu(sbd_lu_t * sl)5589585STim.Szeto@Sun.COM sbd_unlink_lu(sbd_lu_t *sl)
5599585STim.Szeto@Sun.COM {
5609585STim.Szeto@Sun.COM 	sbd_lu_t **ppnsl;
5619585STim.Szeto@Sun.COM 
5629585STim.Szeto@Sun.COM 	mutex_enter(&sbd_lock);
5639585STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_lock);
5649585STim.Szeto@Sun.COM 	ASSERT(sl->sl_trans_op != SL_OP_NONE);
5659585STim.Szeto@Sun.COM 
5669585STim.Szeto@Sun.COM 	ASSERT(sl->sl_flags & SL_LINKED);
5679585STim.Szeto@Sun.COM 	for (ppnsl = &sbd_lu_list; *ppnsl; ppnsl = &((*ppnsl)->sl_next)) {
5689585STim.Szeto@Sun.COM 		if (*ppnsl == sl)
5699585STim.Szeto@Sun.COM 			break;
5709585STim.Szeto@Sun.COM 	}
5719585STim.Szeto@Sun.COM 	ASSERT(*ppnsl);
5729585STim.Szeto@Sun.COM 	*ppnsl = (*ppnsl)->sl_next;
5739585STim.Szeto@Sun.COM 	sl->sl_flags &= ~SL_LINKED;
5749585STim.Szeto@Sun.COM 	mutex_exit(&sbd_lock);
5759585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
5769585STim.Szeto@Sun.COM }
5779585STim.Szeto@Sun.COM 
5789585STim.Szeto@Sun.COM sbd_status_t
sbd_find_and_lock_lu(uint8_t * guid,uint8_t * meta_name,uint8_t op,sbd_lu_t ** ppsl)5799585STim.Szeto@Sun.COM sbd_find_and_lock_lu(uint8_t *guid, uint8_t *meta_name, uint8_t op,
5809585STim.Szeto@Sun.COM     sbd_lu_t **ppsl)
5817836SJohn.Forte@Sun.COM {
5829585STim.Szeto@Sun.COM 	sbd_lu_t *sl;
5839585STim.Szeto@Sun.COM 	int found = 0;
5849585STim.Szeto@Sun.COM 	sbd_status_t sret;
5857836SJohn.Forte@Sun.COM 
5869585STim.Szeto@Sun.COM 	mutex_enter(&sbd_lock);
5879585STim.Szeto@Sun.COM 	for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
5889585STim.Szeto@Sun.COM 		if (guid) {
5899585STim.Szeto@Sun.COM 			found = bcmp(sl->sl_device_id + 4, guid, 16) == 0;
5909585STim.Szeto@Sun.COM 		} else {
5919585STim.Szeto@Sun.COM 			found = strcmp(sl->sl_name, (char *)meta_name) == 0;
5929585STim.Szeto@Sun.COM 		}
5939585STim.Szeto@Sun.COM 		if (found)
5949585STim.Szeto@Sun.COM 			break;
5959585STim.Szeto@Sun.COM 	}
5969585STim.Szeto@Sun.COM 	if (!found) {
5979585STim.Szeto@Sun.COM 		mutex_exit(&sbd_lock);
5989585STim.Szeto@Sun.COM 		return (SBD_NOT_FOUND);
5999585STim.Szeto@Sun.COM 	}
6009585STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_lock);
6019585STim.Szeto@Sun.COM 	if (sl->sl_trans_op == SL_OP_NONE) {
6029585STim.Szeto@Sun.COM 		sl->sl_trans_op = op;
6039585STim.Szeto@Sun.COM 		*ppsl = sl;
6049585STim.Szeto@Sun.COM 		sret = SBD_SUCCESS;
6059585STim.Szeto@Sun.COM 	} else {
6069585STim.Szeto@Sun.COM 		sret = SBD_BUSY;
6079585STim.Szeto@Sun.COM 	}
6089585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
6099585STim.Szeto@Sun.COM 	mutex_exit(&sbd_lock);
6109585STim.Szeto@Sun.COM 	return (sret);
6117836SJohn.Forte@Sun.COM }
6127836SJohn.Forte@Sun.COM 
6139585STim.Szeto@Sun.COM sbd_status_t
sbd_read_meta(sbd_lu_t * sl,uint64_t offset,uint64_t size,uint8_t * buf)6149585STim.Szeto@Sun.COM sbd_read_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
6157836SJohn.Forte@Sun.COM {
6169585STim.Szeto@Sun.COM 	uint64_t	meta_align;
6179585STim.Szeto@Sun.COM 	uint64_t	starting_off;
6189585STim.Szeto@Sun.COM 	uint64_t	data_off;
6199585STim.Szeto@Sun.COM 	uint64_t	ending_off;
6209585STim.Szeto@Sun.COM 	uint64_t	io_size;
6219585STim.Szeto@Sun.COM 	uint8_t		*io_buf;
6229585STim.Szeto@Sun.COM 	vnode_t		*vp;
6239585STim.Szeto@Sun.COM 	sbd_status_t	ret;
6249585STim.Szeto@Sun.COM 	ssize_t		resid;
6259585STim.Szeto@Sun.COM 	int		vret;
6267836SJohn.Forte@Sun.COM 
6279585STim.Szeto@Sun.COM 	ASSERT(sl->sl_flags & SL_META_OPENED);
6289585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_SHARED_META) {
6299585STim.Szeto@Sun.COM 		meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
6309585STim.Szeto@Sun.COM 		vp = sl->sl_data_vp;
6319585STim.Szeto@Sun.COM 		ASSERT(vp);
6327836SJohn.Forte@Sun.COM 	} else {
6339585STim.Szeto@Sun.COM 		meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
6349585STim.Szeto@Sun.COM 		if ((sl->sl_flags & SL_ZFS_META) == 0) {
6359585STim.Szeto@Sun.COM 			vp = sl->sl_meta_vp;
6369585STim.Szeto@Sun.COM 			ASSERT(vp);
6379585STim.Szeto@Sun.COM 		}
6387836SJohn.Forte@Sun.COM 	}
6399585STim.Szeto@Sun.COM 	starting_off = offset & ~(meta_align);
6409585STim.Szeto@Sun.COM 	data_off = offset & meta_align;
6419585STim.Szeto@Sun.COM 	ending_off = (offset + size + meta_align) & (~meta_align);
6429585STim.Szeto@Sun.COM 	if (ending_off > sl->sl_meta_size_used) {
6439585STim.Szeto@Sun.COM 		bzero(buf, size);
6449585STim.Szeto@Sun.COM 		if (starting_off >= sl->sl_meta_size_used) {
6459585STim.Szeto@Sun.COM 			return (SBD_SUCCESS);
6469585STim.Szeto@Sun.COM 		}
6479585STim.Szeto@Sun.COM 		ending_off = (sl->sl_meta_size_used + meta_align) &
6489585STim.Szeto@Sun.COM 		    (~meta_align);
6499585STim.Szeto@Sun.COM 		if (size > (ending_off - (starting_off + data_off))) {
6509585STim.Szeto@Sun.COM 			size = ending_off - (starting_off + data_off);
6519585STim.Szeto@Sun.COM 		}
6529585STim.Szeto@Sun.COM 	}
6539585STim.Szeto@Sun.COM 	io_size = ending_off - starting_off;
6549585STim.Szeto@Sun.COM 	io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
6559585STim.Szeto@Sun.COM 	ASSERT((starting_off + io_size) <= sl->sl_total_meta_size);
6567836SJohn.Forte@Sun.COM 
65710725SJohn.Forte@Sun.COM 	/*
65810725SJohn.Forte@Sun.COM 	 * Don't proceed if the device has been closed
65910725SJohn.Forte@Sun.COM 	 * This can occur on an access state change to standby or
66010725SJohn.Forte@Sun.COM 	 * a delete. The writer lock is acquired before closing the
66110725SJohn.Forte@Sun.COM 	 * lu. If importing, reading the metadata is valid, hence
66210725SJohn.Forte@Sun.COM 	 * the check on SL_OP_IMPORT_LU.
66310725SJohn.Forte@Sun.COM 	 */
66410725SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_access_state_lock, RW_READER);
66510725SJohn.Forte@Sun.COM 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
66610725SJohn.Forte@Sun.COM 	    sl->sl_trans_op != SL_OP_IMPORT_LU) {
66710725SJohn.Forte@Sun.COM 		rw_exit(&sl->sl_access_state_lock);
66810725SJohn.Forte@Sun.COM 		ret = SBD_FILEIO_FAILURE;
66910725SJohn.Forte@Sun.COM 		goto sbd_read_meta_failure;
67010725SJohn.Forte@Sun.COM 	}
6719585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
6729585STim.Szeto@Sun.COM 		if ((ret = sbd_read_zfs_meta(sl, io_buf, io_size,
6739585STim.Szeto@Sun.COM 		    starting_off)) != SBD_SUCCESS) {
67410725SJohn.Forte@Sun.COM 			rw_exit(&sl->sl_access_state_lock);
6759585STim.Szeto@Sun.COM 			goto sbd_read_meta_failure;
6769585STim.Szeto@Sun.COM 		}
6777836SJohn.Forte@Sun.COM 	} else {
6789585STim.Szeto@Sun.COM 		vret = vn_rdwr(UIO_READ, vp, (caddr_t)io_buf, (ssize_t)io_size,
6799585STim.Szeto@Sun.COM 		    (offset_t)starting_off, UIO_SYSSPACE, FRSYNC,
6809585STim.Szeto@Sun.COM 		    RLIM64_INFINITY, CRED(), &resid);
6819585STim.Szeto@Sun.COM 
6829585STim.Szeto@Sun.COM 		if (vret || resid) {
6839585STim.Szeto@Sun.COM 			ret = SBD_FILEIO_FAILURE | vret;
68410725SJohn.Forte@Sun.COM 			rw_exit(&sl->sl_access_state_lock);
6859585STim.Szeto@Sun.COM 			goto sbd_read_meta_failure;
6869585STim.Szeto@Sun.COM 		}
6877836SJohn.Forte@Sun.COM 	}
68810725SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_access_state_lock);
6897836SJohn.Forte@Sun.COM 
6909585STim.Szeto@Sun.COM 	bcopy(io_buf + data_off, buf, size);
6919585STim.Szeto@Sun.COM 	ret = SBD_SUCCESS;
6929585STim.Szeto@Sun.COM 
6939585STim.Szeto@Sun.COM sbd_read_meta_failure:
6949585STim.Szeto@Sun.COM 	kmem_free(io_buf, io_size);
6957836SJohn.Forte@Sun.COM 	return (ret);
6967836SJohn.Forte@Sun.COM }
6977836SJohn.Forte@Sun.COM 
6989585STim.Szeto@Sun.COM sbd_status_t
sbd_write_meta(sbd_lu_t * sl,uint64_t offset,uint64_t size,uint8_t * buf)6999585STim.Szeto@Sun.COM sbd_write_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
7007836SJohn.Forte@Sun.COM {
7019585STim.Szeto@Sun.COM 	uint64_t	meta_align;
7029585STim.Szeto@Sun.COM 	uint64_t	starting_off;
7039585STim.Szeto@Sun.COM 	uint64_t	data_off;
7049585STim.Szeto@Sun.COM 	uint64_t	ending_off;
7059585STim.Szeto@Sun.COM 	uint64_t	io_size;
7069585STim.Szeto@Sun.COM 	uint8_t		*io_buf;
7079585STim.Szeto@Sun.COM 	vnode_t		*vp;
7089585STim.Szeto@Sun.COM 	sbd_status_t	ret;
7099585STim.Szeto@Sun.COM 	ssize_t		resid;
7109585STim.Szeto@Sun.COM 	int		vret;
7117836SJohn.Forte@Sun.COM 
7129585STim.Szeto@Sun.COM 	ASSERT(sl->sl_flags & SL_META_OPENED);
7139585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_SHARED_META) {
7149585STim.Szeto@Sun.COM 		meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
7159585STim.Szeto@Sun.COM 		vp = sl->sl_data_vp;
7169585STim.Szeto@Sun.COM 		ASSERT(vp);
7177836SJohn.Forte@Sun.COM 	} else {
7189585STim.Szeto@Sun.COM 		meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
7199585STim.Szeto@Sun.COM 		if ((sl->sl_flags & SL_ZFS_META) == 0) {
7209585STim.Szeto@Sun.COM 			vp = sl->sl_meta_vp;
7219585STim.Szeto@Sun.COM 			ASSERT(vp);
7229585STim.Szeto@Sun.COM 		}
7239585STim.Szeto@Sun.COM 	}
7249585STim.Szeto@Sun.COM 	starting_off = offset & ~(meta_align);
7259585STim.Szeto@Sun.COM 	data_off = offset & meta_align;
7269585STim.Szeto@Sun.COM 	ending_off = (offset + size + meta_align) & (~meta_align);
7279585STim.Szeto@Sun.COM 	io_size = ending_off - starting_off;
7289585STim.Szeto@Sun.COM 	io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
7299585STim.Szeto@Sun.COM 	ret = sbd_read_meta(sl, starting_off, io_size, io_buf);
7309585STim.Szeto@Sun.COM 	if (ret != SBD_SUCCESS) {
7319585STim.Szeto@Sun.COM 		goto sbd_write_meta_failure;
7327836SJohn.Forte@Sun.COM 	}
7339585STim.Szeto@Sun.COM 	bcopy(buf, io_buf + data_off, size);
73410725SJohn.Forte@Sun.COM 	/*
73510725SJohn.Forte@Sun.COM 	 * Don't proceed if the device has been closed
73610725SJohn.Forte@Sun.COM 	 * This can occur on an access state change to standby or
73710725SJohn.Forte@Sun.COM 	 * a delete. The writer lock is acquired before closing the
73810725SJohn.Forte@Sun.COM 	 * lu. If importing, reading the metadata is valid, hence
73910725SJohn.Forte@Sun.COM 	 * the check on SL_OP_IMPORT_LU.
74010725SJohn.Forte@Sun.COM 	 */
74110725SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_access_state_lock, RW_READER);
74210725SJohn.Forte@Sun.COM 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
74310725SJohn.Forte@Sun.COM 	    sl->sl_trans_op != SL_OP_IMPORT_LU) {
74410725SJohn.Forte@Sun.COM 		rw_exit(&sl->sl_access_state_lock);
74510725SJohn.Forte@Sun.COM 		ret = SBD_FILEIO_FAILURE;
74610725SJohn.Forte@Sun.COM 		goto sbd_write_meta_failure;
74710725SJohn.Forte@Sun.COM 	}
7489585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
7499585STim.Szeto@Sun.COM 		if ((ret = sbd_write_zfs_meta(sl, io_buf, io_size,
7509585STim.Szeto@Sun.COM 		    starting_off)) != SBD_SUCCESS) {
75110725SJohn.Forte@Sun.COM 			rw_exit(&sl->sl_access_state_lock);
7529585STim.Szeto@Sun.COM 			goto sbd_write_meta_failure;
7539585STim.Szeto@Sun.COM 		}
7549585STim.Szeto@Sun.COM 	} else {
7559585STim.Szeto@Sun.COM 		vret = vn_rdwr(UIO_WRITE, vp, (caddr_t)io_buf, (ssize_t)io_size,
7569585STim.Szeto@Sun.COM 		    (offset_t)starting_off, UIO_SYSSPACE, FDSYNC,
7579585STim.Szeto@Sun.COM 		    RLIM64_INFINITY, CRED(), &resid);
7587836SJohn.Forte@Sun.COM 
7599585STim.Szeto@Sun.COM 		if (vret || resid) {
7609585STim.Szeto@Sun.COM 			ret = SBD_FILEIO_FAILURE | vret;
76110725SJohn.Forte@Sun.COM 			rw_exit(&sl->sl_access_state_lock);
7629585STim.Szeto@Sun.COM 			goto sbd_write_meta_failure;
7639585STim.Szeto@Sun.COM 		}
7649585STim.Szeto@Sun.COM 	}
76510725SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_access_state_lock);
7669585STim.Szeto@Sun.COM 
7679585STim.Szeto@Sun.COM 	ret = SBD_SUCCESS;
7689585STim.Szeto@Sun.COM 
7699585STim.Szeto@Sun.COM sbd_write_meta_failure:
7709585STim.Szeto@Sun.COM 	kmem_free(io_buf, io_size);
7717836SJohn.Forte@Sun.COM 	return (ret);
7727836SJohn.Forte@Sun.COM }
7737836SJohn.Forte@Sun.COM 
7747836SJohn.Forte@Sun.COM uint8_t
sbd_calc_sum(uint8_t * buf,int size)7757836SJohn.Forte@Sun.COM sbd_calc_sum(uint8_t *buf, int size)
7767836SJohn.Forte@Sun.COM {
7777836SJohn.Forte@Sun.COM 	uint8_t s = 0;
7787836SJohn.Forte@Sun.COM 
7797836SJohn.Forte@Sun.COM 	while (size > 0)
7807836SJohn.Forte@Sun.COM 		s += buf[--size];
7817836SJohn.Forte@Sun.COM 
7827836SJohn.Forte@Sun.COM 	return (s);
7837836SJohn.Forte@Sun.COM }
7847836SJohn.Forte@Sun.COM 
7859585STim.Szeto@Sun.COM uint8_t
sbd_calc_section_sum(sm_section_hdr_t * sm,uint32_t sz)7869585STim.Szeto@Sun.COM sbd_calc_section_sum(sm_section_hdr_t *sm, uint32_t sz)
7879585STim.Szeto@Sun.COM {
7889585STim.Szeto@Sun.COM 	uint8_t s, o;
7899585STim.Szeto@Sun.COM 
7909585STim.Szeto@Sun.COM 	o = sm->sms_chksum;
7919585STim.Szeto@Sun.COM 	sm->sms_chksum = 0;
7929585STim.Szeto@Sun.COM 	s = sbd_calc_sum((uint8_t *)sm, sz);
7939585STim.Szeto@Sun.COM 	sm->sms_chksum = o;
7949585STim.Szeto@Sun.COM 
7959585STim.Szeto@Sun.COM 	return (s);
7969585STim.Szeto@Sun.COM }
7979585STim.Szeto@Sun.COM 
7989585STim.Szeto@Sun.COM uint32_t
sbd_strlen(char * str,uint32_t maxlen)7999585STim.Szeto@Sun.COM sbd_strlen(char *str, uint32_t maxlen)
8009585STim.Szeto@Sun.COM {
8019585STim.Szeto@Sun.COM 	uint32_t i;
8029585STim.Szeto@Sun.COM 
8039585STim.Szeto@Sun.COM 	for (i = 0; i < maxlen; i++) {
8049585STim.Szeto@Sun.COM 		if (str[i] == 0)
8059585STim.Szeto@Sun.COM 			return (i);
8069585STim.Szeto@Sun.COM 	}
8079585STim.Szeto@Sun.COM 	return (i);
8089585STim.Szeto@Sun.COM }
8099585STim.Szeto@Sun.COM 
8107836SJohn.Forte@Sun.COM void
sbd_swap_meta_start(sbd_meta_start_t * sm)8117836SJohn.Forte@Sun.COM sbd_swap_meta_start(sbd_meta_start_t *sm)
8127836SJohn.Forte@Sun.COM {
8139585STim.Szeto@Sun.COM 	if (sm->sm_magic == SBD_MAGIC)
8149585STim.Szeto@Sun.COM 		return;
8157836SJohn.Forte@Sun.COM 	sm->sm_magic		= BSWAP_64(sm->sm_magic);
8167836SJohn.Forte@Sun.COM 	sm->sm_meta_size	= BSWAP_64(sm->sm_meta_size);
8177836SJohn.Forte@Sun.COM 	sm->sm_meta_size_used	= BSWAP_64(sm->sm_meta_size_used);
8187836SJohn.Forte@Sun.COM 	sm->sm_ver_major	= BSWAP_16(sm->sm_ver_major);
8197836SJohn.Forte@Sun.COM 	sm->sm_ver_minor	= BSWAP_16(sm->sm_ver_minor);
8207836SJohn.Forte@Sun.COM 	sm->sm_ver_subminor	= BSWAP_16(sm->sm_ver_subminor);
8217836SJohn.Forte@Sun.COM }
8227836SJohn.Forte@Sun.COM 
8237836SJohn.Forte@Sun.COM void
sbd_swap_section_hdr(sm_section_hdr_t * sm)8249585STim.Szeto@Sun.COM sbd_swap_section_hdr(sm_section_hdr_t *sm)
8257836SJohn.Forte@Sun.COM {
8269585STim.Szeto@Sun.COM 	if (sm->sms_data_order == SMS_DATA_ORDER)
8279585STim.Szeto@Sun.COM 		return;
8289585STim.Szeto@Sun.COM 	sm->sms_offset		= BSWAP_64(sm->sms_offset);
8299585STim.Szeto@Sun.COM 	sm->sms_size		= BSWAP_32(sm->sms_size);
8309585STim.Szeto@Sun.COM 	sm->sms_id		= BSWAP_16(sm->sms_id);
8319585STim.Szeto@Sun.COM 	sm->sms_chksum		+= SMS_DATA_ORDER - sm->sms_data_order;
8329585STim.Szeto@Sun.COM 	sm->sms_data_order	= SMS_DATA_ORDER;
8339585STim.Szeto@Sun.COM }
8349585STim.Szeto@Sun.COM 
8359585STim.Szeto@Sun.COM void
sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t * sli)8369585STim.Szeto@Sun.COM sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t *sli)
8379585STim.Szeto@Sun.COM {
8389585STim.Szeto@Sun.COM 	sbd_swap_section_hdr(&sli->sli_sms_header);
8399585STim.Szeto@Sun.COM 	if (sli->sli_data_order == SMS_DATA_ORDER)
8409585STim.Szeto@Sun.COM 		return;
8419585STim.Szeto@Sun.COM 	sli->sli_sms_header.sms_chksum	+= SMS_DATA_ORDER - sli->sli_data_order;
8429585STim.Szeto@Sun.COM 	sli->sli_data_order		= SMS_DATA_ORDER;
8439585STim.Szeto@Sun.COM 	sli->sli_total_store_size	= BSWAP_64(sli->sli_total_store_size);
8449585STim.Szeto@Sun.COM 	sli->sli_total_meta_size	= BSWAP_64(sli->sli_total_meta_size);
8459585STim.Szeto@Sun.COM 	sli->sli_lu_data_offset		= BSWAP_64(sli->sli_lu_data_offset);
8469585STim.Szeto@Sun.COM 	sli->sli_lu_data_size		= BSWAP_64(sli->sli_lu_data_size);
8479585STim.Szeto@Sun.COM 	sli->sli_flags			= BSWAP_32(sli->sli_flags);
8489585STim.Szeto@Sun.COM 	sli->sli_blocksize		= BSWAP_16(sli->sli_blocksize);
8497836SJohn.Forte@Sun.COM }
8507836SJohn.Forte@Sun.COM 
8517836SJohn.Forte@Sun.COM void
sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t * sli)8529585STim.Szeto@Sun.COM sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t *sli)
8537836SJohn.Forte@Sun.COM {
8549585STim.Szeto@Sun.COM 	sbd_swap_section_hdr(&sli->sli_sms_header);
8559585STim.Szeto@Sun.COM 	if (sli->sli_data_order == SMS_DATA_ORDER)
8569585STim.Szeto@Sun.COM 		return;
8579585STim.Szeto@Sun.COM 	sli->sli_sms_header.sms_chksum	+= SMS_DATA_ORDER - sli->sli_data_order;
8589585STim.Szeto@Sun.COM 	sli->sli_data_order		= SMS_DATA_ORDER;
8599585STim.Szeto@Sun.COM 	sli->sli_flags			= BSWAP_32(sli->sli_flags);
8609585STim.Szeto@Sun.COM 	sli->sli_lu_size		= BSWAP_64(sli->sli_lu_size);
86110114STim.Szeto@Sun.COM 	sli->sli_meta_fname_offset	= BSWAP_64(sli->sli_meta_fname_offset);
86210365SSrivijitha.Dugganapalli@Sun.COM 	sli->sli_data_fname_offset	= BSWAP_64(sli->sli_data_fname_offset);
86310365SSrivijitha.Dugganapalli@Sun.COM 	sli->sli_serial_offset		= BSWAP_64(sli->sli_serial_offset);
86410365SSrivijitha.Dugganapalli@Sun.COM 	sli->sli_alias_offset		= BSWAP_64(sli->sli_alias_offset);
86510962STim.Szeto@Sun.COM 	sli->sli_mgmt_url_offset	= BSWAP_64(sli->sli_mgmt_url_offset);
8667836SJohn.Forte@Sun.COM }
8677836SJohn.Forte@Sun.COM 
8689585STim.Szeto@Sun.COM sbd_status_t
sbd_load_section_hdr(sbd_lu_t * sl,sm_section_hdr_t * sms)8699585STim.Szeto@Sun.COM sbd_load_section_hdr(sbd_lu_t *sl, sm_section_hdr_t *sms)
8707836SJohn.Forte@Sun.COM {
8719679STim.Szeto@Sun.COM 	sm_section_hdr_t	h;
8729679STim.Szeto@Sun.COM 	uint64_t		st;
8739679STim.Szeto@Sun.COM 	sbd_status_t 		ret;
8747836SJohn.Forte@Sun.COM 
8759679STim.Szeto@Sun.COM 	for (st = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
8769585STim.Szeto@Sun.COM 	    st < sl->sl_meta_size_used; st += h.sms_size) {
8779585STim.Szeto@Sun.COM 		if ((ret = sbd_read_meta(sl, st, sizeof (sm_section_hdr_t),
8789585STim.Szeto@Sun.COM 		    (uint8_t *)&h)) != SBD_SUCCESS) {
8799585STim.Szeto@Sun.COM 			return (ret);
8809585STim.Szeto@Sun.COM 		}
8819585STim.Szeto@Sun.COM 		if (h.sms_data_order != SMS_DATA_ORDER) {
8829585STim.Szeto@Sun.COM 			sbd_swap_section_hdr(&h);
8839585STim.Szeto@Sun.COM 		}
8849585STim.Szeto@Sun.COM 		if ((h.sms_data_order != SMS_DATA_ORDER) ||
8859585STim.Szeto@Sun.COM 		    (h.sms_offset != st) || (h.sms_size < sizeof (h)) ||
8869585STim.Szeto@Sun.COM 		    ((st + h.sms_size) > sl->sl_meta_size_used)) {
8879585STim.Szeto@Sun.COM 			return (SBD_META_CORRUPTED);
8889585STim.Szeto@Sun.COM 		}
8899585STim.Szeto@Sun.COM 		if (h.sms_id == sms->sms_id) {
8909585STim.Szeto@Sun.COM 			bcopy(&h, sms, sizeof (h));
8919585STim.Szeto@Sun.COM 			return (SBD_SUCCESS);
8927836SJohn.Forte@Sun.COM 		}
8937836SJohn.Forte@Sun.COM 	}
8947836SJohn.Forte@Sun.COM 
8959585STim.Szeto@Sun.COM 	return (SBD_NOT_FOUND);
8969585STim.Szeto@Sun.COM }
8979585STim.Szeto@Sun.COM 
8989585STim.Szeto@Sun.COM sbd_status_t
sbd_load_meta_start(sbd_lu_t * sl)8999585STim.Szeto@Sun.COM sbd_load_meta_start(sbd_lu_t *sl)
9009585STim.Szeto@Sun.COM {
9019585STim.Szeto@Sun.COM 	sbd_meta_start_t *sm;
9029585STim.Szeto@Sun.COM 	sbd_status_t ret;
9039585STim.Szeto@Sun.COM 
9049585STim.Szeto@Sun.COM 	/* Fake meta params initially */
9059585STim.Szeto@Sun.COM 	sl->sl_total_meta_size = (uint64_t)-1;
9069679STim.Szeto@Sun.COM 	sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
9079585STim.Szeto@Sun.COM 
9089585STim.Szeto@Sun.COM 	sm = kmem_zalloc(sizeof (*sm), KM_SLEEP);
9099679STim.Szeto@Sun.COM 	ret = sbd_read_meta(sl, sl->sl_meta_offset, sizeof (*sm),
9109679STim.Szeto@Sun.COM 	    (uint8_t *)sm);
9119585STim.Szeto@Sun.COM 	if (ret != SBD_SUCCESS) {
9129585STim.Szeto@Sun.COM 		goto load_meta_start_failed;
9139585STim.Szeto@Sun.COM 	}
9149585STim.Szeto@Sun.COM 
9159585STim.Szeto@Sun.COM 	if (sm->sm_magic != SBD_MAGIC) {
9169585STim.Szeto@Sun.COM 		sbd_swap_meta_start(sm);
9179585STim.Szeto@Sun.COM 	}
9189585STim.Szeto@Sun.COM 
9199585STim.Szeto@Sun.COM 	if ((sm->sm_magic != SBD_MAGIC) || (sbd_calc_sum((uint8_t *)sm,
9209585STim.Szeto@Sun.COM 	    sizeof (*sm) - 1) != sm->sm_chksum)) {
9219585STim.Szeto@Sun.COM 		ret = SBD_META_CORRUPTED;
9229585STim.Szeto@Sun.COM 		goto load_meta_start_failed;
9239585STim.Szeto@Sun.COM 	}
9249585STim.Szeto@Sun.COM 
9259585STim.Szeto@Sun.COM 	if (sm->sm_ver_major != SBD_VER_MAJOR) {
9269585STim.Szeto@Sun.COM 		ret = SBD_NOT_SUPPORTED;
9279585STim.Szeto@Sun.COM 		goto load_meta_start_failed;
9289585STim.Szeto@Sun.COM 	}
9299585STim.Szeto@Sun.COM 
9309585STim.Szeto@Sun.COM 	sl->sl_total_meta_size = sm->sm_meta_size;
9319585STim.Szeto@Sun.COM 	sl->sl_meta_size_used = sm->sm_meta_size_used;
9329585STim.Szeto@Sun.COM 	ret = SBD_SUCCESS;
9339585STim.Szeto@Sun.COM 
9349585STim.Szeto@Sun.COM load_meta_start_failed:
9359585STim.Szeto@Sun.COM 	kmem_free(sm, sizeof (*sm));
9369585STim.Szeto@Sun.COM 	return (ret);
9379585STim.Szeto@Sun.COM }
9389585STim.Szeto@Sun.COM 
9399585STim.Szeto@Sun.COM sbd_status_t
sbd_write_meta_start(sbd_lu_t * sl,uint64_t meta_size,uint64_t meta_size_used)9409585STim.Szeto@Sun.COM sbd_write_meta_start(sbd_lu_t *sl, uint64_t meta_size, uint64_t meta_size_used)
9419585STim.Szeto@Sun.COM {
9429585STim.Szeto@Sun.COM 	sbd_meta_start_t *sm;
9439585STim.Szeto@Sun.COM 	sbd_status_t ret;
9449585STim.Szeto@Sun.COM 
9459585STim.Szeto@Sun.COM 	sm = (sbd_meta_start_t *)kmem_zalloc(sizeof (sbd_meta_start_t),
9469585STim.Szeto@Sun.COM 	    KM_SLEEP);
9479585STim.Szeto@Sun.COM 
9489585STim.Szeto@Sun.COM 	sm->sm_magic = SBD_MAGIC;
9499585STim.Szeto@Sun.COM 	sm->sm_meta_size = meta_size;
9509585STim.Szeto@Sun.COM 	sm->sm_meta_size_used = meta_size_used;
9519585STim.Szeto@Sun.COM 	sm->sm_ver_major = SBD_VER_MAJOR;
9529585STim.Szeto@Sun.COM 	sm->sm_ver_minor = SBD_VER_MINOR;
9539585STim.Szeto@Sun.COM 	sm->sm_ver_subminor = SBD_VER_SUBMINOR;
9549585STim.Szeto@Sun.COM 	sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (*sm) - 1);
9559585STim.Szeto@Sun.COM 
9569679STim.Szeto@Sun.COM 	ret = sbd_write_meta(sl, sl->sl_meta_offset, sizeof (*sm),
9579679STim.Szeto@Sun.COM 	    (uint8_t *)sm);
9589585STim.Szeto@Sun.COM 	kmem_free(sm, sizeof (*sm));
9597836SJohn.Forte@Sun.COM 
9607836SJohn.Forte@Sun.COM 	return (ret);
9617836SJohn.Forte@Sun.COM }
9627836SJohn.Forte@Sun.COM 
9639585STim.Szeto@Sun.COM sbd_status_t
sbd_read_meta_section(sbd_lu_t * sl,sm_section_hdr_t ** ppsms,uint16_t sms_id)9649585STim.Szeto@Sun.COM sbd_read_meta_section(sbd_lu_t *sl, sm_section_hdr_t **ppsms, uint16_t sms_id)
9657836SJohn.Forte@Sun.COM {
9669585STim.Szeto@Sun.COM 	sbd_status_t ret;
9679585STim.Szeto@Sun.COM 	sm_section_hdr_t sms;
9689585STim.Szeto@Sun.COM 	int alloced = 0;
9697836SJohn.Forte@Sun.COM 
97010526STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_metadata_lock);
9719585STim.Szeto@Sun.COM 	if (((*ppsms) == NULL) || ((*ppsms)->sms_offset == 0)) {
9729585STim.Szeto@Sun.COM 		bzero(&sms, sizeof (sm_section_hdr_t));
9739585STim.Szeto@Sun.COM 		sms.sms_id = sms_id;
9749585STim.Szeto@Sun.COM 		if ((ret = sbd_load_section_hdr(sl, &sms)) != SBD_SUCCESS) {
97510526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
9769585STim.Szeto@Sun.COM 			return (ret);
9779585STim.Szeto@Sun.COM 		} else {
9789585STim.Szeto@Sun.COM 			if ((*ppsms) == NULL) {
9799585STim.Szeto@Sun.COM 				*ppsms = (sm_section_hdr_t *)kmem_zalloc(
9809585STim.Szeto@Sun.COM 				    sms.sms_size, KM_SLEEP);
9819585STim.Szeto@Sun.COM 				alloced = 1;
9829585STim.Szeto@Sun.COM 			}
9839585STim.Szeto@Sun.COM 			bcopy(&sms, *ppsms, sizeof (sm_section_hdr_t));
9849585STim.Szeto@Sun.COM 		}
9857836SJohn.Forte@Sun.COM 	}
9867836SJohn.Forte@Sun.COM 
9879585STim.Szeto@Sun.COM 	ret = sbd_read_meta(sl, (*ppsms)->sms_offset, (*ppsms)->sms_size,
9889585STim.Szeto@Sun.COM 	    (uint8_t *)(*ppsms));
9899585STim.Szeto@Sun.COM 	if (ret == SBD_SUCCESS) {
9909585STim.Szeto@Sun.COM 		uint8_t s;
9919585STim.Szeto@Sun.COM 		if ((*ppsms)->sms_data_order != SMS_DATA_ORDER)
9929585STim.Szeto@Sun.COM 			sbd_swap_section_hdr(*ppsms);
9939585STim.Szeto@Sun.COM 		if ((*ppsms)->sms_id != SMS_ID_UNUSED) {
9949585STim.Szeto@Sun.COM 			s = sbd_calc_section_sum(*ppsms, (*ppsms)->sms_size);
9959585STim.Szeto@Sun.COM 			if (s != (*ppsms)->sms_chksum)
9969585STim.Szeto@Sun.COM 				ret = SBD_META_CORRUPTED;
9979585STim.Szeto@Sun.COM 		}
9987836SJohn.Forte@Sun.COM 	}
99910526STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_metadata_lock);
10007836SJohn.Forte@Sun.COM 
10019585STim.Szeto@Sun.COM 	if ((ret != SBD_SUCCESS) && alloced)
10029585STim.Szeto@Sun.COM 		kmem_free(*ppsms, sms.sms_size);
10037836SJohn.Forte@Sun.COM 	return (ret);
10047836SJohn.Forte@Sun.COM }
10057836SJohn.Forte@Sun.COM 
10069585STim.Szeto@Sun.COM sbd_status_t
sbd_load_section_hdr_unbuffered(sbd_lu_t * sl,sm_section_hdr_t * sms)100710526STim.Szeto@Sun.COM sbd_load_section_hdr_unbuffered(sbd_lu_t *sl, sm_section_hdr_t *sms)
100810526STim.Szeto@Sun.COM {
100910526STim.Szeto@Sun.COM 	sbd_status_t	ret;
101010526STim.Szeto@Sun.COM 
101110526STim.Szeto@Sun.COM 	/*
101210526STim.Szeto@Sun.COM 	 * Bypass buffering and re-read the meta data from permanent storage.
101310526STim.Szeto@Sun.COM 	 */
101410526STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
101510526STim.Szeto@Sun.COM 		if ((ret = sbd_open_zfs_meta(sl)) != SBD_SUCCESS) {
101610526STim.Szeto@Sun.COM 			return (ret);
101710526STim.Szeto@Sun.COM 		}
101810526STim.Szeto@Sun.COM 	}
101910526STim.Szeto@Sun.COM 	/* Re-get the meta sizes into sl */
102010526STim.Szeto@Sun.COM 	if ((ret = sbd_load_meta_start(sl)) != SBD_SUCCESS) {
102110526STim.Szeto@Sun.COM 		return (ret);
102210526STim.Szeto@Sun.COM 	}
102310526STim.Szeto@Sun.COM 	return (sbd_load_section_hdr(sl, sms));
102410526STim.Szeto@Sun.COM }
102510526STim.Szeto@Sun.COM 
102610526STim.Szeto@Sun.COM sbd_status_t
sbd_write_meta_section(sbd_lu_t * sl,sm_section_hdr_t * sms)10279585STim.Szeto@Sun.COM sbd_write_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms)
10287836SJohn.Forte@Sun.COM {
10299585STim.Szeto@Sun.COM 	sm_section_hdr_t t;
10309585STim.Szeto@Sun.COM 	uint64_t off, s;
10319585STim.Szeto@Sun.COM 	uint64_t unused_start;
10329585STim.Szeto@Sun.COM 	sbd_status_t ret;
103310526STim.Szeto@Sun.COM 	sbd_status_t write_meta_ret = SBD_SUCCESS;
10349585STim.Szeto@Sun.COM 	uint8_t *cb;
103510526STim.Szeto@Sun.COM 	int meta_size_changed = 0;
103610526STim.Szeto@Sun.COM 	sm_section_hdr_t sms_before_unused = {0};
10377836SJohn.Forte@Sun.COM 
103810526STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_metadata_lock);
10399585STim.Szeto@Sun.COM write_meta_section_again:
10409585STim.Szeto@Sun.COM 	if (sms->sms_offset) {
104110526STim.Szeto@Sun.COM 		/*
104210526STim.Szeto@Sun.COM 		 * If the section already exists and the size is the
104310526STim.Szeto@Sun.COM 		 * same as this new data then overwrite in place. If
104410526STim.Szeto@Sun.COM 		 * the sizes are different then mark the existing as
104510526STim.Szeto@Sun.COM 		 * unused and look for free space.
104610526STim.Szeto@Sun.COM 		 */
10479585STim.Szeto@Sun.COM 		ret = sbd_read_meta(sl, sms->sms_offset, sizeof (t),
10489585STim.Szeto@Sun.COM 		    (uint8_t *)&t);
104910526STim.Szeto@Sun.COM 		if (ret != SBD_SUCCESS) {
105010526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
10519585STim.Szeto@Sun.COM 			return (ret);
105210526STim.Szeto@Sun.COM 		}
10539585STim.Szeto@Sun.COM 		if (t.sms_data_order != SMS_DATA_ORDER) {
10549585STim.Szeto@Sun.COM 			sbd_swap_section_hdr(&t);
10559585STim.Szeto@Sun.COM 		}
10569585STim.Szeto@Sun.COM 		if (t.sms_id != sms->sms_id) {
105710526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
10589585STim.Szeto@Sun.COM 			return (SBD_INVALID_ARG);
10599585STim.Szeto@Sun.COM 		}
10609585STim.Szeto@Sun.COM 		if (t.sms_size == sms->sms_size) {
106110526STim.Szeto@Sun.COM 			ret = sbd_write_meta(sl, sms->sms_offset,
106210526STim.Szeto@Sun.COM 			    sms->sms_size, (uint8_t *)sms);
106310526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
106410526STim.Szeto@Sun.COM 			return (ret);
10659585STim.Szeto@Sun.COM 		}
106610526STim.Szeto@Sun.COM 		sms_before_unused = t;
106710526STim.Szeto@Sun.COM 
10689585STim.Szeto@Sun.COM 		t.sms_id = SMS_ID_UNUSED;
10699585STim.Szeto@Sun.COM 		/*
10709585STim.Szeto@Sun.COM 		 * For unused sections we only use chksum of the header. for
10719585STim.Szeto@Sun.COM 		 * all other sections, the chksum is for the entire section.
10729585STim.Szeto@Sun.COM 		 */
10739585STim.Szeto@Sun.COM 		t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
10749585STim.Szeto@Sun.COM 		ret = sbd_write_meta(sl, t.sms_offset, sizeof (t),
10759585STim.Szeto@Sun.COM 		    (uint8_t *)&t);
107610526STim.Szeto@Sun.COM 		if (ret != SBD_SUCCESS) {
107710526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
10789585STim.Szeto@Sun.COM 			return (ret);
107910526STim.Szeto@Sun.COM 		}
10809585STim.Szeto@Sun.COM 		sms->sms_offset = 0;
10819585STim.Szeto@Sun.COM 	} else {
108210526STim.Szeto@Sun.COM 		/* Section location is unknown, search for it. */
10839585STim.Szeto@Sun.COM 		t.sms_id = sms->sms_id;
10849585STim.Szeto@Sun.COM 		t.sms_data_order = SMS_DATA_ORDER;
10859585STim.Szeto@Sun.COM 		ret = sbd_load_section_hdr(sl, &t);
10869585STim.Szeto@Sun.COM 		if (ret == SBD_SUCCESS) {
10879585STim.Szeto@Sun.COM 			sms->sms_offset = t.sms_offset;
10889585STim.Szeto@Sun.COM 			sms->sms_chksum =
10899585STim.Szeto@Sun.COM 			    sbd_calc_section_sum(sms, sms->sms_size);
10909585STim.Szeto@Sun.COM 			goto write_meta_section_again;
10919585STim.Szeto@Sun.COM 		} else if (ret != SBD_NOT_FOUND) {
109210526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
10939585STim.Szeto@Sun.COM 			return (ret);
10949585STim.Szeto@Sun.COM 		}
10957836SJohn.Forte@Sun.COM 	}
10967836SJohn.Forte@Sun.COM 
10977836SJohn.Forte@Sun.COM 	/*
10989585STim.Szeto@Sun.COM 	 * At this point we know that section does not already exist.
109910526STim.Szeto@Sun.COM 	 * Find space large enough to hold the section or grow meta if
11009585STim.Szeto@Sun.COM 	 * possible.
11017836SJohn.Forte@Sun.COM 	 */
11029585STim.Szeto@Sun.COM 	unused_start = 0;
110310526STim.Szeto@Sun.COM 	s = 0;	/* size of space found */
110410526STim.Szeto@Sun.COM 
110510526STim.Szeto@Sun.COM 	/*
110610526STim.Szeto@Sun.COM 	 * Search all sections for unused space of sufficient size.
110710526STim.Szeto@Sun.COM 	 * The first one found is taken. Contiguous unused sections
110810526STim.Szeto@Sun.COM 	 * will be combined.
110910526STim.Szeto@Sun.COM 	 */
11109679STim.Szeto@Sun.COM 	for (off = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
11119585STim.Szeto@Sun.COM 	    off < sl->sl_meta_size_used; off += t.sms_size) {
11129585STim.Szeto@Sun.COM 		ret = sbd_read_meta(sl, off, sizeof (t), (uint8_t *)&t);
111310526STim.Szeto@Sun.COM 		if (ret != SBD_SUCCESS) {
111410526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
11159585STim.Szeto@Sun.COM 			return (ret);
111610526STim.Szeto@Sun.COM 		}
11179585STim.Szeto@Sun.COM 		if (t.sms_data_order != SMS_DATA_ORDER)
11189585STim.Szeto@Sun.COM 			sbd_swap_section_hdr(&t);
111910526STim.Szeto@Sun.COM 		if (t.sms_size == 0) {
112010526STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_metadata_lock);
11219585STim.Szeto@Sun.COM 			return (SBD_META_CORRUPTED);
112210526STim.Szeto@Sun.COM 		}
11239585STim.Szeto@Sun.COM 		if (t.sms_id == SMS_ID_UNUSED) {
11249585STim.Szeto@Sun.COM 			if (unused_start == 0)
11259585STim.Szeto@Sun.COM 				unused_start = off;
112610526STim.Szeto@Sun.COM 			/*
112710526STim.Szeto@Sun.COM 			 * Calculate size of the unused space, break out
112810526STim.Szeto@Sun.COM 			 * if it satisfies the requirement.
112910526STim.Szeto@Sun.COM 			 */
11309585STim.Szeto@Sun.COM 			s = t.sms_size - unused_start + off;
11319585STim.Szeto@Sun.COM 			if ((s == sms->sms_size) || (s >= (sms->sms_size +
11329585STim.Szeto@Sun.COM 			    sizeof (t)))) {
11339585STim.Szeto@Sun.COM 				break;
11349585STim.Szeto@Sun.COM 			} else {
11359585STim.Szeto@Sun.COM 				s = 0;
11369585STim.Szeto@Sun.COM 			}
11379585STim.Szeto@Sun.COM 		} else {
11389585STim.Szeto@Sun.COM 			unused_start = 0;
11397836SJohn.Forte@Sun.COM 		}
11409585STim.Szeto@Sun.COM 	}
11417836SJohn.Forte@Sun.COM 
11429585STim.Szeto@Sun.COM 	off = (unused_start == 0) ? sl->sl_meta_size_used : unused_start;
114310526STim.Szeto@Sun.COM 	/*
114410526STim.Szeto@Sun.COM 	 * If none found, how much room is at the end?
114510526STim.Szeto@Sun.COM 	 * See if the data can be expanded.
114610526STim.Szeto@Sun.COM 	 */
11479585STim.Szeto@Sun.COM 	if (s == 0) {
11489585STim.Szeto@Sun.COM 		s = sl->sl_total_meta_size - off;
11499585STim.Szeto@Sun.COM 		if (s >= sms->sms_size || !(sl->sl_flags & SL_SHARED_META)) {
11509585STim.Szeto@Sun.COM 			s = sms->sms_size;
115110526STim.Szeto@Sun.COM 			meta_size_changed = 1;
11529585STim.Szeto@Sun.COM 		} else {
11539585STim.Szeto@Sun.COM 			s = 0;
11547836SJohn.Forte@Sun.COM 		}
11557836SJohn.Forte@Sun.COM 	}
11567836SJohn.Forte@Sun.COM 
115710526STim.Szeto@Sun.COM 	if (s == 0) {
115810526STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_metadata_lock);
11599585STim.Szeto@Sun.COM 		return (SBD_ALLOC_FAILURE);
116010526STim.Szeto@Sun.COM 	}
11617836SJohn.Forte@Sun.COM 
11629585STim.Szeto@Sun.COM 	sms->sms_offset = off;
11639585STim.Szeto@Sun.COM 	sms->sms_chksum = sbd_calc_section_sum(sms, sms->sms_size);
11649585STim.Szeto@Sun.COM 	/*
11659585STim.Szeto@Sun.COM 	 * Since we may have to write more than one section (current +
11669585STim.Szeto@Sun.COM 	 * any unused), use a combined buffer.
11679585STim.Szeto@Sun.COM 	 */
11689585STim.Szeto@Sun.COM 	cb = kmem_zalloc(s, KM_SLEEP);
11699585STim.Szeto@Sun.COM 	bcopy(sms, cb, sms->sms_size);
11709585STim.Szeto@Sun.COM 	if (s > sms->sms_size) {
11719585STim.Szeto@Sun.COM 		t.sms_offset = off + sms->sms_size;
11729585STim.Szeto@Sun.COM 		t.sms_size = s - sms->sms_size;
11739585STim.Szeto@Sun.COM 		t.sms_id = SMS_ID_UNUSED;
11749585STim.Szeto@Sun.COM 		t.sms_data_order = SMS_DATA_ORDER;
11759585STim.Szeto@Sun.COM 		t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
11769585STim.Szeto@Sun.COM 		bcopy(&t, cb + sms->sms_size, sizeof (t));
11779585STim.Szeto@Sun.COM 	}
117810526STim.Szeto@Sun.COM 	/*
117910526STim.Szeto@Sun.COM 	 * Two write events & statuses take place. Failure writing the
118010526STim.Szeto@Sun.COM 	 * meta section takes precedence, can possibly be rolled back,
118110526STim.Szeto@Sun.COM 	 * & gets reported. Else return status from writing the meta start.
118210526STim.Szeto@Sun.COM 	 */
118310526STim.Szeto@Sun.COM 	ret = SBD_SUCCESS; /* Set a default, it's not always loaded below. */
118410526STim.Szeto@Sun.COM 	if (meta_size_changed) {
118510526STim.Szeto@Sun.COM 		uint64_t old_meta_size;
11869585STim.Szeto@Sun.COM 		uint64_t old_sz_used = sl->sl_meta_size_used; /* save a copy */
118710526STim.Szeto@Sun.COM 		old_meta_size = sl->sl_total_meta_size; /* save a copy */
118810526STim.Szeto@Sun.COM 
118910526STim.Szeto@Sun.COM 		write_meta_ret = sbd_write_meta(sl, off, s, cb);
119010526STim.Szeto@Sun.COM 		if (write_meta_ret == SBD_SUCCESS) {
119110526STim.Szeto@Sun.COM 			sl->sl_meta_size_used = off + s;
119210526STim.Szeto@Sun.COM 			if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
119310526STim.Szeto@Sun.COM 				uint64_t meta_align =
119410526STim.Szeto@Sun.COM 				    (((uint64_t)1) <<
119510526STim.Szeto@Sun.COM 				    sl->sl_meta_blocksize_shift) - 1;
119610526STim.Szeto@Sun.COM 				sl->sl_total_meta_size =
119710526STim.Szeto@Sun.COM 				    (sl->sl_meta_size_used + meta_align) &
119810526STim.Szeto@Sun.COM 				    (~meta_align);
119910526STim.Szeto@Sun.COM 			}
120010526STim.Szeto@Sun.COM 			ret = sbd_write_meta_start(sl, sl->sl_total_meta_size,
120110526STim.Szeto@Sun.COM 			    sl->sl_meta_size_used);
120210526STim.Szeto@Sun.COM 			if (ret != SBD_SUCCESS) {
120310526STim.Szeto@Sun.COM 				sl->sl_meta_size_used = old_sz_used;
120410526STim.Szeto@Sun.COM 				sl->sl_total_meta_size = old_meta_size;
120510526STim.Szeto@Sun.COM 			}
120610526STim.Szeto@Sun.COM 		} else {
120710526STim.Szeto@Sun.COM 			sl->sl_meta_size_used = old_sz_used;
120810526STim.Szeto@Sun.COM 			sl->sl_total_meta_size = old_meta_size;
12097836SJohn.Forte@Sun.COM 		}
121010526STim.Szeto@Sun.COM 	} else {
121110526STim.Szeto@Sun.COM 		write_meta_ret = sbd_write_meta(sl, off, s, cb);
121210526STim.Szeto@Sun.COM 	}
121310526STim.Szeto@Sun.COM 	if ((write_meta_ret != SBD_SUCCESS) &&
121410526STim.Szeto@Sun.COM 	    (sms_before_unused.sms_offset != 0)) {
121510526STim.Szeto@Sun.COM 		sm_section_hdr_t new_sms;
121610526STim.Szeto@Sun.COM 		sm_section_hdr_t *unused_sms;
121710526STim.Szeto@Sun.COM 		/*
121810526STim.Szeto@Sun.COM 		 * On failure writing the meta section attempt to undo
121910526STim.Szeto@Sun.COM 		 * the change to unused.
122010526STim.Szeto@Sun.COM 		 * Re-read the meta data from permanent storage.
122110526STim.Szeto@Sun.COM 		 * The section id can't exist for undo to be possible.
122210526STim.Szeto@Sun.COM 		 * Read what should be the entire old section data and
122310526STim.Szeto@Sun.COM 		 * insure the old data's still present by validating
122410526STim.Szeto@Sun.COM 		 * against it's old checksum.
122510526STim.Szeto@Sun.COM 		 */
122610526STim.Szeto@Sun.COM 		new_sms.sms_id = sms->sms_id;
122710526STim.Szeto@Sun.COM 		new_sms.sms_data_order = SMS_DATA_ORDER;
122810526STim.Szeto@Sun.COM 		if (sbd_load_section_hdr_unbuffered(sl, &new_sms) !=
122910526STim.Szeto@Sun.COM 		    SBD_NOT_FOUND) {
123010526STim.Szeto@Sun.COM 			goto done;
123110526STim.Szeto@Sun.COM 		}
123210526STim.Szeto@Sun.COM 		unused_sms = kmem_zalloc(sms_before_unused.sms_size, KM_SLEEP);
123310526STim.Szeto@Sun.COM 		if (sbd_read_meta(sl, sms_before_unused.sms_offset,
123410526STim.Szeto@Sun.COM 		    sms_before_unused.sms_size,
123510526STim.Szeto@Sun.COM 		    (uint8_t *)unused_sms) != SBD_SUCCESS) {
123610526STim.Szeto@Sun.COM 			goto done;
12379585STim.Szeto@Sun.COM 		}
123810526STim.Szeto@Sun.COM 		if (unused_sms->sms_data_order != SMS_DATA_ORDER) {
123910526STim.Szeto@Sun.COM 			sbd_swap_section_hdr(unused_sms);
124010526STim.Szeto@Sun.COM 		}
124110526STim.Szeto@Sun.COM 		if (unused_sms->sms_id != SMS_ID_UNUSED) {
124210526STim.Szeto@Sun.COM 			goto done;
124310526STim.Szeto@Sun.COM 		}
124410526STim.Szeto@Sun.COM 		if (unused_sms->sms_offset != sms_before_unused.sms_offset) {
124510526STim.Szeto@Sun.COM 			goto done;
124610526STim.Szeto@Sun.COM 		}
124710526STim.Szeto@Sun.COM 		if (unused_sms->sms_size != sms_before_unused.sms_size) {
124810526STim.Szeto@Sun.COM 			goto done;
124910526STim.Szeto@Sun.COM 		}
125010526STim.Szeto@Sun.COM 		unused_sms->sms_id = sms_before_unused.sms_id;
125110526STim.Szeto@Sun.COM 		if (sbd_calc_section_sum(unused_sms,
125210526STim.Szeto@Sun.COM 		    sizeof (sm_section_hdr_t)) !=
125310526STim.Szeto@Sun.COM 		    sbd_calc_section_sum(&sms_before_unused,
125410526STim.Szeto@Sun.COM 		    sizeof (sm_section_hdr_t))) {
125510526STim.Szeto@Sun.COM 			goto done;
125610526STim.Szeto@Sun.COM 		}
125710526STim.Szeto@Sun.COM 		unused_sms->sms_chksum =
125810526STim.Szeto@Sun.COM 		    sbd_calc_section_sum(unused_sms, unused_sms->sms_size);
125910526STim.Szeto@Sun.COM 		if (unused_sms->sms_chksum != sms_before_unused.sms_chksum) {
126010526STim.Szeto@Sun.COM 			goto done;
126110526STim.Szeto@Sun.COM 		}
126210526STim.Szeto@Sun.COM 		(void) sbd_write_meta(sl, unused_sms->sms_offset,
126310526STim.Szeto@Sun.COM 		    sizeof (sm_section_hdr_t), (uint8_t *)unused_sms);
126410526STim.Szeto@Sun.COM 	}
126510526STim.Szeto@Sun.COM done:
126610526STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_metadata_lock);
126710526STim.Szeto@Sun.COM 	kmem_free(cb, s);
126810526STim.Szeto@Sun.COM 	if (write_meta_ret != SBD_SUCCESS) {
126910526STim.Szeto@Sun.COM 		return (write_meta_ret);
12707836SJohn.Forte@Sun.COM 	}
12717836SJohn.Forte@Sun.COM 	return (ret);
12727836SJohn.Forte@Sun.COM }
12737836SJohn.Forte@Sun.COM 
12749585STim.Szeto@Sun.COM sbd_status_t
sbd_write_lu_info(sbd_lu_t * sl)12759585STim.Szeto@Sun.COM sbd_write_lu_info(sbd_lu_t *sl)
12769585STim.Szeto@Sun.COM {
12779585STim.Szeto@Sun.COM 	sbd_lu_info_1_1_t *sli;
12789585STim.Szeto@Sun.COM 	int s;
12799585STim.Szeto@Sun.COM 	uint8_t *p;
12809585STim.Szeto@Sun.COM 	char *zvol_name = NULL;
12819585STim.Szeto@Sun.COM 	sbd_status_t ret;
12829585STim.Szeto@Sun.COM 
12839585STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_lock);
12849585STim.Szeto@Sun.COM 
12859585STim.Szeto@Sun.COM 	s = sl->sl_serial_no_size;
12869585STim.Szeto@Sun.COM 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
12879585STim.Szeto@Sun.COM 		if (sl->sl_data_filename) {
12889585STim.Szeto@Sun.COM 			s += strlen(sl->sl_data_filename) + 1;
12899585STim.Szeto@Sun.COM 		}
12909585STim.Szeto@Sun.COM 	}
12919585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
12929585STim.Szeto@Sun.COM 		zvol_name = sbd_get_zvol_name(sl);
12939585STim.Szeto@Sun.COM 		s += strlen(zvol_name) + 1;
12949585STim.Szeto@Sun.COM 	}
12959585STim.Szeto@Sun.COM 	if (sl->sl_alias) {
12969585STim.Szeto@Sun.COM 		s += strlen(sl->sl_alias) + 1;
12977836SJohn.Forte@Sun.COM 	}
129810113SNattuvetty.Bhavyan@Sun.COM 	if (sl->sl_mgmt_url) {
129910113SNattuvetty.Bhavyan@Sun.COM 		s += strlen(sl->sl_mgmt_url) + 1;
130010113SNattuvetty.Bhavyan@Sun.COM 	}
13019585STim.Szeto@Sun.COM 	sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP);
13029585STim.Szeto@Sun.COM 	p = sli->sli_buf;
13039585STim.Szeto@Sun.COM 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
13049585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_SEPARATE_META;
13059585STim.Szeto@Sun.COM 		(void) strcpy((char *)p, sl->sl_data_filename);
13069585STim.Szeto@Sun.COM 		sli->sli_data_fname_offset =
13079585STim.Szeto@Sun.COM 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
13089585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_DATA_FNAME_VALID;
13099585STim.Szeto@Sun.COM 		p += strlen(sl->sl_data_filename) + 1;
13109585STim.Szeto@Sun.COM 	}
13119585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
13129585STim.Szeto@Sun.COM 		(void) strcpy((char *)p, zvol_name);
13139585STim.Szeto@Sun.COM 		sli->sli_meta_fname_offset =
13149585STim.Szeto@Sun.COM 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
13159585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_META_FNAME_VALID | SLI_ZFS_META;
13169585STim.Szeto@Sun.COM 		p += strlen(zvol_name) + 1;
13179585STim.Szeto@Sun.COM 		kmem_free(zvol_name, strlen(zvol_name) + 1);
13189585STim.Szeto@Sun.COM 		zvol_name = NULL;
13199585STim.Szeto@Sun.COM 	}
13209585STim.Szeto@Sun.COM 	if (sl->sl_alias) {
13219585STim.Szeto@Sun.COM 		(void) strcpy((char *)p, sl->sl_alias);
13229585STim.Szeto@Sun.COM 		sli->sli_alias_offset =
13239585STim.Szeto@Sun.COM 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
13249585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_ALIAS_VALID;
13259585STim.Szeto@Sun.COM 		p += strlen(sl->sl_alias) + 1;
13269585STim.Szeto@Sun.COM 	}
132710113SNattuvetty.Bhavyan@Sun.COM 	if (sl->sl_mgmt_url) {
132810113SNattuvetty.Bhavyan@Sun.COM 		(void) strcpy((char *)p, sl->sl_mgmt_url);
132910113SNattuvetty.Bhavyan@Sun.COM 		sli->sli_mgmt_url_offset =
133010113SNattuvetty.Bhavyan@Sun.COM 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
133110113SNattuvetty.Bhavyan@Sun.COM 		sli->sli_flags |= SLI_MGMT_URL_VALID;
133210113SNattuvetty.Bhavyan@Sun.COM 		p += strlen(sl->sl_mgmt_url) + 1;
133310113SNattuvetty.Bhavyan@Sun.COM 	}
13349585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
13359585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_WRITE_PROTECTED;
13367836SJohn.Forte@Sun.COM 	}
13379585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
13389585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE;
13399585STim.Szeto@Sun.COM 	}
13409585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_VID_VALID) {
13419585STim.Szeto@Sun.COM 		bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
13429585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_VID_VALID;
13439585STim.Szeto@Sun.COM 	}
13449585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_PID_VALID) {
13459585STim.Szeto@Sun.COM 		bcopy(sl->sl_product_id, sli->sli_pid, 16);
13469585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_PID_VALID;
13479585STim.Szeto@Sun.COM 	}
13489585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_REV_VALID) {
13499585STim.Szeto@Sun.COM 		bcopy(sl->sl_revision, sli->sli_rev, 4);
13509585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_REV_VALID;
13517836SJohn.Forte@Sun.COM 	}
13529585STim.Szeto@Sun.COM 	if (sl->sl_serial_no_size) {
13539585STim.Szeto@Sun.COM 		bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size);
13549585STim.Szeto@Sun.COM 		sli->sli_serial_size = sl->sl_serial_no_size;
13559585STim.Szeto@Sun.COM 		sli->sli_serial_offset =
13569585STim.Szeto@Sun.COM 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
13579585STim.Szeto@Sun.COM 		sli->sli_flags |= SLI_SERIAL_VALID;
13589585STim.Szeto@Sun.COM 		p += sli->sli_serial_size;
13599585STim.Szeto@Sun.COM 	}
13609585STim.Szeto@Sun.COM 	sli->sli_lu_size = sl->sl_lu_size;
13619585STim.Szeto@Sun.COM 	sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
13629585STim.Szeto@Sun.COM 	sli->sli_data_order = SMS_DATA_ORDER;
13639585STim.Szeto@Sun.COM 	bcopy(sl->sl_device_id, sli->sli_device_id, 20);
13647836SJohn.Forte@Sun.COM 
13659585STim.Szeto@Sun.COM 	sli->sli_sms_header.sms_size = sizeof (*sli) + s;
13669585STim.Szeto@Sun.COM 	sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
13677836SJohn.Forte@Sun.COM 	sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
13687836SJohn.Forte@Sun.COM 
13699585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
13709585STim.Szeto@Sun.COM 	ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
13719585STim.Szeto@Sun.COM 	kmem_free(sli, sizeof (*sli) + s);
13729585STim.Szeto@Sun.COM 	return (ret);
13739585STim.Szeto@Sun.COM }
13747836SJohn.Forte@Sun.COM 
13759585STim.Szeto@Sun.COM int
sbd_populate_and_register_lu(sbd_lu_t * sl,uint32_t * err_ret)13769585STim.Szeto@Sun.COM sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
13779585STim.Szeto@Sun.COM {
13789585STim.Szeto@Sun.COM 	stmf_lu_t *lu = sl->sl_lu;
13799585STim.Szeto@Sun.COM 	stmf_status_t ret;
13807836SJohn.Forte@Sun.COM 
13819585STim.Szeto@Sun.COM 	lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
13829585STim.Szeto@Sun.COM 	if (sl->sl_alias) {
13839585STim.Szeto@Sun.COM 		lu->lu_alias = sl->sl_alias;
13849585STim.Szeto@Sun.COM 	} else {
13859585STim.Szeto@Sun.COM 		lu->lu_alias = sl->sl_name;
13867836SJohn.Forte@Sun.COM 	}
138710725SJohn.Forte@Sun.COM 	if (sl->sl_access_state == SBD_LU_STANDBY) {
138810725SJohn.Forte@Sun.COM 		/* call set access state */
138910725SJohn.Forte@Sun.COM 		ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
139010725SJohn.Forte@Sun.COM 		if (ret != STMF_SUCCESS) {
139110725SJohn.Forte@Sun.COM 			*err_ret = SBD_RET_ACCESS_STATE_FAILED;
139210725SJohn.Forte@Sun.COM 			return (EIO);
139310725SJohn.Forte@Sun.COM 		}
139410725SJohn.Forte@Sun.COM 	}
139510725SJohn.Forte@Sun.COM 	/* set proxy_reg_cb_arg to meta filename */
139610725SJohn.Forte@Sun.COM 	if (sl->sl_meta_filename) {
139710725SJohn.Forte@Sun.COM 		lu->lu_proxy_reg_arg = sl->sl_meta_filename;
139810725SJohn.Forte@Sun.COM 		lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
139910725SJohn.Forte@Sun.COM 	} else {
140010725SJohn.Forte@Sun.COM 		lu->lu_proxy_reg_arg = sl->sl_data_filename;
140110725SJohn.Forte@Sun.COM 		lu->lu_proxy_reg_arg_len = strlen(sl->sl_data_filename) + 1;
140210725SJohn.Forte@Sun.COM 	}
14037836SJohn.Forte@Sun.COM 	lu->lu_lp = sbd_lp;
14047836SJohn.Forte@Sun.COM 	lu->lu_task_alloc = sbd_task_alloc;
14057836SJohn.Forte@Sun.COM 	lu->lu_new_task = sbd_new_task;
14067836SJohn.Forte@Sun.COM 	lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
14077836SJohn.Forte@Sun.COM 	lu->lu_send_status_done = sbd_send_status_done;
14087836SJohn.Forte@Sun.COM 	lu->lu_task_free = sbd_task_free;
14097836SJohn.Forte@Sun.COM 	lu->lu_abort = sbd_abort;
141012314SJames.Moore@Sun.COM 	lu->lu_dbuf_free = sbd_dbuf_free;
14117836SJohn.Forte@Sun.COM 	lu->lu_ctl = sbd_ctl;
14127836SJohn.Forte@Sun.COM 	lu->lu_info = sbd_info;
14139585STim.Szeto@Sun.COM 	sl->sl_state = STMF_STATE_OFFLINE;
14147836SJohn.Forte@Sun.COM 
14157836SJohn.Forte@Sun.COM 	if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
14167836SJohn.Forte@Sun.COM 		stmf_trace(0, "Failed to register with framework, ret=%llx",
14178818STim.Szeto@Sun.COM 		    ret);
14189585STim.Szeto@Sun.COM 		if (ret == STMF_ALREADY) {
14199585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_GUID_ALREADY_REGISTERED;
14209585STim.Szeto@Sun.COM 		}
14219585STim.Szeto@Sun.COM 		return (EIO);
14227836SJohn.Forte@Sun.COM 	}
14237836SJohn.Forte@Sun.COM 
14249585STim.Szeto@Sun.COM 	*err_ret = 0;
14259585STim.Szeto@Sun.COM 	return (0);
14269585STim.Szeto@Sun.COM }
14279585STim.Szeto@Sun.COM 
14289585STim.Szeto@Sun.COM int
sbd_open_data_file(sbd_lu_t * sl,uint32_t * err_ret,int lu_size_valid,int vp_valid,int keep_open)14299585STim.Szeto@Sun.COM sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid,
14309585STim.Szeto@Sun.COM     int vp_valid, int keep_open)
14319585STim.Szeto@Sun.COM {
14329585STim.Szeto@Sun.COM 	int ret;
14339585STim.Szeto@Sun.COM 	int flag;
14349585STim.Szeto@Sun.COM 	ulong_t	nbits;
14359585STim.Szeto@Sun.COM 	uint64_t supported_size;
14369585STim.Szeto@Sun.COM 	vattr_t vattr;
14379585STim.Szeto@Sun.COM 	enum vtype vt;
143812314SJames.Moore@Sun.COM 	struct dk_cinfo dki;
143912314SJames.Moore@Sun.COM 	int unused;
14407836SJohn.Forte@Sun.COM 
14419585STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_lock);
14429585STim.Szeto@Sun.COM 	if (vp_valid) {
14439585STim.Szeto@Sun.COM 		goto odf_over_open;
14449585STim.Szeto@Sun.COM 	}
14459585STim.Szeto@Sun.COM 	if (sl->sl_data_filename[0] != '/') {
14469585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE;
14479585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
14489585STim.Szeto@Sun.COM 		return (EINVAL);
14499585STim.Szeto@Sun.COM 	}
14509585STim.Szeto@Sun.COM 	if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW,
14519585STim.Szeto@Sun.COM 	    NULLVPP, &sl->sl_data_vp)) != 0) {
14529585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED;
14539585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
14549585STim.Szeto@Sun.COM 		return (ret);
14559585STim.Szeto@Sun.COM 	}
14569585STim.Szeto@Sun.COM 	sl->sl_data_vtype = vt = sl->sl_data_vp->v_type;
14579585STim.Szeto@Sun.COM 	VN_RELE(sl->sl_data_vp);
14589585STim.Szeto@Sun.COM 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
14599585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
14609585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
14619585STim.Szeto@Sun.COM 		return (EINVAL);
14629585STim.Szeto@Sun.COM 	}
14639585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
14649585STim.Szeto@Sun.COM 		flag = FREAD | FOFFMAX;
14659585STim.Szeto@Sun.COM 	} else {
14669585STim.Szeto@Sun.COM 		flag = FREAD | FWRITE | FOFFMAX | FEXCL;
14679585STim.Szeto@Sun.COM 	}
14689585STim.Szeto@Sun.COM 	if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0,
14699585STim.Szeto@Sun.COM 	    &sl->sl_data_vp, 0, 0)) != 0) {
14709585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_DATA_FILE_OPEN_FAILED;
14719585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
14729585STim.Szeto@Sun.COM 		return (ret);
14739585STim.Szeto@Sun.COM 	}
14749585STim.Szeto@Sun.COM odf_over_open:
14759585STim.Szeto@Sun.COM 	vattr.va_mask = AT_SIZE;
14769585STim.Szeto@Sun.COM 	if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) {
14779585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED;
14789585STim.Szeto@Sun.COM 		goto odf_close_data_and_exit;
14799585STim.Szeto@Sun.COM 	}
14809585STim.Szeto@Sun.COM 	if ((vt != VREG) && (vattr.va_size == 0)) {
14819585STim.Szeto@Sun.COM 		/*
14829585STim.Szeto@Sun.COM 		 * Its a zero byte block or char device. This cannot be
14839585STim.Szeto@Sun.COM 		 * a raw disk.
14849585STim.Szeto@Sun.COM 		 */
14859585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
14869585STim.Szeto@Sun.COM 		ret = EINVAL;
14879585STim.Szeto@Sun.COM 		goto odf_close_data_and_exit;
14887836SJohn.Forte@Sun.COM 	}
14899585STim.Szeto@Sun.COM 	/* sl_data_readable size includes any metadata. */
14909585STim.Szeto@Sun.COM 	sl->sl_data_readable_size = vattr.va_size;
149112314SJames.Moore@Sun.COM 
14929585STim.Szeto@Sun.COM 	if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits,
14939585STim.Szeto@Sun.COM 	    CRED(), NULL) != 0) {
14949585STim.Szeto@Sun.COM 		nbits = 0;
14959585STim.Szeto@Sun.COM 	}
14969585STim.Szeto@Sun.COM 	/* nbits cannot be greater than 64 */
14979585STim.Szeto@Sun.COM 	sl->sl_data_fs_nbits = (uint8_t)nbits;
14989585STim.Szeto@Sun.COM 	if (lu_size_valid) {
14999585STim.Szeto@Sun.COM 		sl->sl_total_data_size = sl->sl_lu_size;
15009585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_SHARED_META) {
15019585STim.Szeto@Sun.COM 			sl->sl_total_data_size += SHARED_META_DATA_SIZE;
15029585STim.Szeto@Sun.COM 		}
15039585STim.Szeto@Sun.COM 		if ((nbits > 0) && (nbits < 64)) {
15049585STim.Szeto@Sun.COM 			/*
15059585STim.Szeto@Sun.COM 			 * The expression below is correct only if nbits is
15069585STim.Szeto@Sun.COM 			 * positive and less than 64.
15079585STim.Szeto@Sun.COM 			 */
15089585STim.Szeto@Sun.COM 			supported_size = (((uint64_t)1) << nbits) - 1;
15099585STim.Szeto@Sun.COM 			if (sl->sl_total_data_size > supported_size) {
15109585STim.Szeto@Sun.COM 				*err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS;
15119585STim.Szeto@Sun.COM 				ret = EINVAL;
15129585STim.Szeto@Sun.COM 				goto odf_close_data_and_exit;
15139585STim.Szeto@Sun.COM 			}
15149585STim.Szeto@Sun.COM 		}
15159585STim.Szeto@Sun.COM 	} else {
15169585STim.Szeto@Sun.COM 		sl->sl_total_data_size = vattr.va_size;
15179585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_SHARED_META) {
15189585STim.Szeto@Sun.COM 			if (vattr.va_size > SHARED_META_DATA_SIZE) {
15199585STim.Szeto@Sun.COM 				sl->sl_lu_size = vattr.va_size -
15209585STim.Szeto@Sun.COM 				    SHARED_META_DATA_SIZE;
15219585STim.Szeto@Sun.COM 			} else {
15229585STim.Szeto@Sun.COM 				*err_ret = SBD_RET_FILE_SIZE_ERROR;
15239585STim.Szeto@Sun.COM 				ret = EINVAL;
15249585STim.Szeto@Sun.COM 				goto odf_close_data_and_exit;
15259585STim.Szeto@Sun.COM 			}
15269585STim.Szeto@Sun.COM 		} else {
15279585STim.Szeto@Sun.COM 			sl->sl_lu_size = vattr.va_size;
15289585STim.Szeto@Sun.COM 		}
15299585STim.Szeto@Sun.COM 	}
15309585STim.Szeto@Sun.COM 	if (sl->sl_lu_size < SBD_MIN_LU_SIZE) {
15319585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_FILE_SIZE_ERROR;
15329585STim.Szeto@Sun.COM 		ret = EINVAL;
15339585STim.Szeto@Sun.COM 		goto odf_close_data_and_exit;
15349585STim.Szeto@Sun.COM 	}
15359585STim.Szeto@Sun.COM 	if (sl->sl_lu_size &
15369585STim.Szeto@Sun.COM 	    ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) {
15379585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_FILE_ALIGN_ERROR;
15389585STim.Szeto@Sun.COM 		ret = EINVAL;
15399585STim.Szeto@Sun.COM 		goto odf_close_data_and_exit;
15409585STim.Szeto@Sun.COM 	}
154112314SJames.Moore@Sun.COM 	/*
154212314SJames.Moore@Sun.COM 	 * Get the minor device for direct zvol access
154312314SJames.Moore@Sun.COM 	 */
154412314SJames.Moore@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
154512314SJames.Moore@Sun.COM 		if ((ret = VOP_IOCTL(sl->sl_data_vp, DKIOCINFO, (intptr_t)&dki,
154612314SJames.Moore@Sun.COM 		    FKIOCTL, kcred, &unused, NULL)) != 0) {
154712314SJames.Moore@Sun.COM 			cmn_err(CE_WARN, "ioctl(DKIOCINFO) failed %d", ret);
154812314SJames.Moore@Sun.COM 			/* zvol reserves 0, so this would fail later */
154912314SJames.Moore@Sun.COM 			sl->sl_zvol_minor = 0;
155012314SJames.Moore@Sun.COM 		} else {
155112314SJames.Moore@Sun.COM 			sl->sl_zvol_minor = dki.dki_unit;
155212314SJames.Moore@Sun.COM 			if (sbd_zvol_get_volume_params(sl) == 0)
155312314SJames.Moore@Sun.COM 				sl->sl_flags |= SL_CALL_ZVOL;
155412314SJames.Moore@Sun.COM 		}
155512314SJames.Moore@Sun.COM 	}
15569585STim.Szeto@Sun.COM 	sl->sl_flags |= SL_MEDIA_LOADED;
15579585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
15589585STim.Szeto@Sun.COM 	return (0);
15597836SJohn.Forte@Sun.COM 
15609585STim.Szeto@Sun.COM odf_close_data_and_exit:
15619585STim.Szeto@Sun.COM 	if (!keep_open) {
15629585STim.Szeto@Sun.COM 		(void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
15639585STim.Szeto@Sun.COM 		VN_RELE(sl->sl_data_vp);
15649585STim.Szeto@Sun.COM 	}
15659585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
15669585STim.Szeto@Sun.COM 	return (ret);
15679585STim.Szeto@Sun.COM }
15689585STim.Szeto@Sun.COM 
156910725SJohn.Forte@Sun.COM void
sbd_close_lu(sbd_lu_t * sl)157010725SJohn.Forte@Sun.COM sbd_close_lu(sbd_lu_t *sl)
15719585STim.Szeto@Sun.COM {
15729585STim.Szeto@Sun.COM 	int flag;
15739585STim.Szeto@Sun.COM 
15749585STim.Szeto@Sun.COM 	if (((sl->sl_flags & SL_SHARED_META) == 0) &&
15759585STim.Szeto@Sun.COM 	    (sl->sl_flags & SL_META_OPENED)) {
15769585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_ZFS_META) {
15779679STim.Szeto@Sun.COM 			rw_destroy(&sl->sl_zfs_meta_lock);
15789679STim.Szeto@Sun.COM 			if (sl->sl_zfs_meta) {
15799679STim.Szeto@Sun.COM 				kmem_free(sl->sl_zfs_meta, ZAP_MAXVALUELEN / 2);
158010725SJohn.Forte@Sun.COM 				sl->sl_zfs_meta = NULL;
15819679STim.Szeto@Sun.COM 			}
15829585STim.Szeto@Sun.COM 		} else {
15839585STim.Szeto@Sun.COM 			flag = FREAD | FWRITE | FOFFMAX | FEXCL;
15849585STim.Szeto@Sun.COM 			(void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0,
15859585STim.Szeto@Sun.COM 			    CRED(), NULL);
15869585STim.Szeto@Sun.COM 			VN_RELE(sl->sl_meta_vp);
15879585STim.Szeto@Sun.COM 		}
15889585STim.Szeto@Sun.COM 		sl->sl_flags &= ~SL_META_OPENED;
15899585STim.Szeto@Sun.COM 	}
15909585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_MEDIA_LOADED) {
15919585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_WRITE_PROTECTED) {
15929585STim.Szeto@Sun.COM 			flag = FREAD | FOFFMAX;
15939585STim.Szeto@Sun.COM 		} else {
15949585STim.Szeto@Sun.COM 			flag = FREAD | FWRITE | FOFFMAX | FEXCL;
15959585STim.Szeto@Sun.COM 		}
15969585STim.Szeto@Sun.COM 		(void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
15979585STim.Szeto@Sun.COM 		VN_RELE(sl->sl_data_vp);
15989585STim.Szeto@Sun.COM 		sl->sl_flags &= ~SL_MEDIA_LOADED;
15999585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_SHARED_META) {
16009585STim.Szeto@Sun.COM 			sl->sl_flags &= ~SL_META_OPENED;
16019585STim.Szeto@Sun.COM 		}
16029585STim.Szeto@Sun.COM 	}
160310725SJohn.Forte@Sun.COM }
160410725SJohn.Forte@Sun.COM 
160510725SJohn.Forte@Sun.COM int
sbd_set_lu_standby(sbd_set_lu_standby_t * stlu,uint32_t * err_ret)160610725SJohn.Forte@Sun.COM sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret)
160710725SJohn.Forte@Sun.COM {
160810725SJohn.Forte@Sun.COM 	sbd_lu_t *sl;
160910725SJohn.Forte@Sun.COM 	sbd_status_t sret;
161010725SJohn.Forte@Sun.COM 	stmf_status_t stret;
161112202SNattuvetty.Bhavyan@Sun.COM 	uint8_t old_access_state;
161210725SJohn.Forte@Sun.COM 
161310725SJohn.Forte@Sun.COM 	sret = sbd_find_and_lock_lu(stlu->stlu_guid, NULL,
161410725SJohn.Forte@Sun.COM 	    SL_OP_MODIFY_LU, &sl);
161510725SJohn.Forte@Sun.COM 	if (sret != SBD_SUCCESS) {
161610725SJohn.Forte@Sun.COM 		if (sret == SBD_BUSY) {
161710725SJohn.Forte@Sun.COM 			*err_ret = SBD_RET_LU_BUSY;
161810725SJohn.Forte@Sun.COM 			return (EBUSY);
161910725SJohn.Forte@Sun.COM 		} else if (sret == SBD_NOT_FOUND) {
162010725SJohn.Forte@Sun.COM 			*err_ret = SBD_RET_NOT_FOUND;
162110725SJohn.Forte@Sun.COM 			return (ENOENT);
162210725SJohn.Forte@Sun.COM 		}
162310725SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
162410725SJohn.Forte@Sun.COM 		return (EIO);
162510725SJohn.Forte@Sun.COM 	}
162610725SJohn.Forte@Sun.COM 
162712202SNattuvetty.Bhavyan@Sun.COM 	old_access_state = sl->sl_access_state;
162810725SJohn.Forte@Sun.COM 	sl->sl_access_state = SBD_LU_TRANSITION_TO_STANDBY;
162910725SJohn.Forte@Sun.COM 	stret = stmf_set_lu_access((stmf_lu_t *)sl->sl_lu, STMF_LU_STANDBY);
163010725SJohn.Forte@Sun.COM 	if (stret != STMF_SUCCESS) {
163110725SJohn.Forte@Sun.COM 		sl->sl_trans_op = SL_OP_NONE;
163210725SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
163312202SNattuvetty.Bhavyan@Sun.COM 		sl->sl_access_state = old_access_state;
163410725SJohn.Forte@Sun.COM 		return (EIO);
163510725SJohn.Forte@Sun.COM 	}
163610725SJohn.Forte@Sun.COM 
163710725SJohn.Forte@Sun.COM 	/*
163810725SJohn.Forte@Sun.COM 	 * acquire the writer lock here to ensure we're not pulling
163910725SJohn.Forte@Sun.COM 	 * the rug from the vn_rdwr to the backing store
164010725SJohn.Forte@Sun.COM 	 */
164110725SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_access_state_lock, RW_WRITER);
164210725SJohn.Forte@Sun.COM 	sbd_close_lu(sl);
164310725SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_access_state_lock);
164410725SJohn.Forte@Sun.COM 
164510725SJohn.Forte@Sun.COM 	sl->sl_trans_op = SL_OP_NONE;
164610725SJohn.Forte@Sun.COM 	return (0);
164710725SJohn.Forte@Sun.COM }
164810725SJohn.Forte@Sun.COM 
164910725SJohn.Forte@Sun.COM int
sbd_close_delete_lu(sbd_lu_t * sl,int ret)165010725SJohn.Forte@Sun.COM sbd_close_delete_lu(sbd_lu_t *sl, int ret)
165110725SJohn.Forte@Sun.COM {
165210725SJohn.Forte@Sun.COM 
165310725SJohn.Forte@Sun.COM 	/*
165410725SJohn.Forte@Sun.COM 	 * acquire the writer lock here to ensure we're not pulling
165510725SJohn.Forte@Sun.COM 	 * the rug from the vn_rdwr to the backing store
165610725SJohn.Forte@Sun.COM 	 */
165710725SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_access_state_lock, RW_WRITER);
165810725SJohn.Forte@Sun.COM 	sbd_close_lu(sl);
165910725SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_access_state_lock);
166010725SJohn.Forte@Sun.COM 
16619585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_LINKED)
16629585STim.Szeto@Sun.COM 		sbd_unlink_lu(sl);
166310526STim.Szeto@Sun.COM 	mutex_destroy(&sl->sl_metadata_lock);
16649585STim.Szeto@Sun.COM 	mutex_destroy(&sl->sl_lock);
16659585STim.Szeto@Sun.COM 	rw_destroy(&sl->sl_pgr->pgr_lock);
166610725SJohn.Forte@Sun.COM 	rw_destroy(&sl->sl_access_state_lock);
16679585STim.Szeto@Sun.COM 	if (sl->sl_serial_no_alloc_size) {
16689585STim.Szeto@Sun.COM 		kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size);
16699585STim.Szeto@Sun.COM 	}
16709585STim.Szeto@Sun.COM 	if (sl->sl_data_fname_alloc_size) {
16719585STim.Szeto@Sun.COM 		kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size);
16729585STim.Szeto@Sun.COM 	}
16739585STim.Szeto@Sun.COM 	if (sl->sl_alias_alloc_size) {
16749585STim.Szeto@Sun.COM 		kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
16759585STim.Szeto@Sun.COM 	}
167610113SNattuvetty.Bhavyan@Sun.COM 	if (sl->sl_mgmt_url_alloc_size) {
167710113SNattuvetty.Bhavyan@Sun.COM 		kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
167810113SNattuvetty.Bhavyan@Sun.COM 	}
16799585STim.Szeto@Sun.COM 	stmf_free(sl->sl_lu);
16807836SJohn.Forte@Sun.COM 	return (ret);
16817836SJohn.Forte@Sun.COM }
16827836SJohn.Forte@Sun.COM 
16839585STim.Szeto@Sun.COM int
sbd_create_register_lu(sbd_create_and_reg_lu_t * slu,int struct_sz,uint32_t * err_ret)16849585STim.Szeto@Sun.COM sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
16859585STim.Szeto@Sun.COM     uint32_t *err_ret)
16867836SJohn.Forte@Sun.COM {
16879585STim.Szeto@Sun.COM 	char *namebuf;
16889585STim.Szeto@Sun.COM 	sbd_lu_t *sl;
16899585STim.Szeto@Sun.COM 	stmf_lu_t *lu;
16909585STim.Szeto@Sun.COM 	sbd_status_t sret;
16919585STim.Szeto@Sun.COM 	char *p;
16929585STim.Szeto@Sun.COM 	int sz;
16939585STim.Szeto@Sun.COM 	int alloc_sz;
16949585STim.Szeto@Sun.COM 	int ret = EIO;
16959585STim.Szeto@Sun.COM 	int flag;
16969585STim.Szeto@Sun.COM 	int wcd = 0;
169710765SJohn.Forte@Sun.COM 	uint32_t hid = 0;
16989585STim.Szeto@Sun.COM 	enum vtype vt;
16999585STim.Szeto@Sun.COM 
17009585STim.Szeto@Sun.COM 	sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1;
17019585STim.Szeto@Sun.COM 
17029585STim.Szeto@Sun.COM 	*err_ret = 0;
17039585STim.Szeto@Sun.COM 
17049585STim.Szeto@Sun.COM 	/* Lets validate various offsets */
17059585STim.Szeto@Sun.COM 	if (((slu->slu_meta_fname_valid) &&
17069585STim.Szeto@Sun.COM 	    (slu->slu_meta_fname_off >= sz)) ||
17079585STim.Szeto@Sun.COM 	    (slu->slu_data_fname_off >= sz) ||
17089585STim.Szeto@Sun.COM 	    ((slu->slu_alias_valid) &&
17099585STim.Szeto@Sun.COM 	    (slu->slu_alias_off >= sz)) ||
171010113SNattuvetty.Bhavyan@Sun.COM 	    ((slu->slu_mgmt_url_valid) &&
171110113SNattuvetty.Bhavyan@Sun.COM 	    (slu->slu_mgmt_url_off >= sz)) ||
17129585STim.Szeto@Sun.COM 	    ((slu->slu_serial_valid) &&
17139585STim.Szeto@Sun.COM 	    ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
17149585STim.Szeto@Sun.COM 		return (EINVAL);
17159585STim.Szeto@Sun.COM 	}
17169585STim.Szeto@Sun.COM 
17179585STim.Szeto@Sun.COM 	namebuf = kmem_zalloc(sz, KM_SLEEP);
17189585STim.Szeto@Sun.COM 	bcopy(slu->slu_buf, namebuf, sz - 1);
17199585STim.Szeto@Sun.COM 	namebuf[sz - 1] = 0;
17209585STim.Szeto@Sun.COM 
17219585STim.Szeto@Sun.COM 	alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
17229585STim.Szeto@Sun.COM 	if (slu->slu_meta_fname_valid) {
17239585STim.Szeto@Sun.COM 		alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1;
17249585STim.Szeto@Sun.COM 	}
17259585STim.Szeto@Sun.COM 	alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1;
17269585STim.Szeto@Sun.COM 	if (slu->slu_alias_valid) {
17279585STim.Szeto@Sun.COM 		alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
17289585STim.Szeto@Sun.COM 	}
172910113SNattuvetty.Bhavyan@Sun.COM 	if (slu->slu_mgmt_url_valid) {
173010113SNattuvetty.Bhavyan@Sun.COM 		alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1;
173110113SNattuvetty.Bhavyan@Sun.COM 	}
17329585STim.Szeto@Sun.COM 	if (slu->slu_serial_valid) {
17339585STim.Szeto@Sun.COM 		alloc_sz += slu->slu_serial_size;
17349585STim.Szeto@Sun.COM 	}
17359585STim.Szeto@Sun.COM 
17369585STim.Szeto@Sun.COM 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
17379585STim.Szeto@Sun.COM 	if (lu == NULL) {
17389585STim.Szeto@Sun.COM 		kmem_free(namebuf, sz);
17399585STim.Szeto@Sun.COM 		return (ENOMEM);
17409585STim.Szeto@Sun.COM 	}
17419585STim.Szeto@Sun.COM 	sl = (sbd_lu_t *)lu->lu_provider_private;
17429585STim.Szeto@Sun.COM 	bzero(sl, alloc_sz);
17439585STim.Szeto@Sun.COM 	sl->sl_lu = lu;
17449585STim.Szeto@Sun.COM 	sl->sl_alloc_size = alloc_sz;
17459585STim.Szeto@Sun.COM 	sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
17469585STim.Szeto@Sun.COM 	rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
17479585STim.Szeto@Sun.COM 	mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
174810526STim.Szeto@Sun.COM 	mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
174910725SJohn.Forte@Sun.COM 	rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
17509585STim.Szeto@Sun.COM 	p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
17519585STim.Szeto@Sun.COM 	sl->sl_data_filename = p;
17529585STim.Szeto@Sun.COM 	(void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off);
17539585STim.Szeto@Sun.COM 	p += strlen(sl->sl_data_filename) + 1;
17549679STim.Szeto@Sun.COM 	sl->sl_meta_offset = SBD_META_OFFSET;
175510725SJohn.Forte@Sun.COM 	sl->sl_access_state = SBD_LU_ACTIVE;
17569585STim.Szeto@Sun.COM 	if (slu->slu_meta_fname_valid) {
17579585STim.Szeto@Sun.COM 		sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p;
17589585STim.Szeto@Sun.COM 		(void) strcpy(sl->sl_meta_filename, namebuf +
17599585STim.Szeto@Sun.COM 		    slu->slu_meta_fname_off);
17609585STim.Szeto@Sun.COM 		p += strlen(sl->sl_meta_filename) + 1;
17619585STim.Szeto@Sun.COM 	} else {
17629585STim.Szeto@Sun.COM 		sl->sl_alias = sl->sl_name = sl->sl_data_filename;
17639679STim.Szeto@Sun.COM 		if (sbd_is_zvol(sl->sl_data_filename)) {
17649585STim.Szeto@Sun.COM 			sl->sl_flags |= SL_ZFS_META;
17659679STim.Szeto@Sun.COM 			sl->sl_meta_offset = 0;
17669585STim.Szeto@Sun.COM 		} else {
17679585STim.Szeto@Sun.COM 			sl->sl_flags |= SL_SHARED_META;
17689585STim.Szeto@Sun.COM 			sl->sl_data_offset = SHARED_META_DATA_SIZE;
17699585STim.Szeto@Sun.COM 			sl->sl_total_meta_size = SHARED_META_DATA_SIZE;
17709585STim.Szeto@Sun.COM 			sl->sl_meta_size_used = 0;
17719585STim.Szeto@Sun.COM 		}
17729585STim.Szeto@Sun.COM 	}
17739585STim.Szeto@Sun.COM 	if (slu->slu_alias_valid) {
17749585STim.Szeto@Sun.COM 		sl->sl_alias = p;
17759585STim.Szeto@Sun.COM 		(void) strcpy(p, namebuf + slu->slu_alias_off);
17769585STim.Szeto@Sun.COM 		p += strlen(sl->sl_alias) + 1;
17779585STim.Szeto@Sun.COM 	}
177810113SNattuvetty.Bhavyan@Sun.COM 	if (slu->slu_mgmt_url_valid) {
177910113SNattuvetty.Bhavyan@Sun.COM 		sl->sl_mgmt_url = p;
178010113SNattuvetty.Bhavyan@Sun.COM 		(void) strcpy(p, namebuf + slu->slu_mgmt_url_off);
178110113SNattuvetty.Bhavyan@Sun.COM 		p += strlen(sl->sl_mgmt_url) + 1;
178210113SNattuvetty.Bhavyan@Sun.COM 	}
17839585STim.Szeto@Sun.COM 	if (slu->slu_serial_valid) {
17849585STim.Szeto@Sun.COM 		sl->sl_serial_no = (uint8_t *)p;
17859585STim.Szeto@Sun.COM 		bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
17869585STim.Szeto@Sun.COM 		    slu->slu_serial_size);
17879585STim.Szeto@Sun.COM 		sl->sl_serial_no_size = slu->slu_serial_size;
17889585STim.Szeto@Sun.COM 		p += slu->slu_serial_size;
17899585STim.Szeto@Sun.COM 	}
17909585STim.Szeto@Sun.COM 	kmem_free(namebuf, sz);
17919585STim.Szeto@Sun.COM 	if (slu->slu_vid_valid) {
17929585STim.Szeto@Sun.COM 		bcopy(slu->slu_vid, sl->sl_vendor_id, 8);
17939585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_VID_VALID;
17949585STim.Szeto@Sun.COM 	}
17959585STim.Szeto@Sun.COM 	if (slu->slu_pid_valid) {
17969585STim.Szeto@Sun.COM 		bcopy(slu->slu_pid, sl->sl_product_id, 16);
17979585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_PID_VALID;
17989585STim.Szeto@Sun.COM 	}
17999585STim.Szeto@Sun.COM 	if (slu->slu_rev_valid) {
18009585STim.Szeto@Sun.COM 		bcopy(slu->slu_rev, sl->sl_revision, 4);
18019585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_REV_VALID;
18029585STim.Szeto@Sun.COM 	}
18039585STim.Szeto@Sun.COM 	if (slu->slu_write_protected) {
18049585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITE_PROTECTED;
18059585STim.Szeto@Sun.COM 	}
18069585STim.Szeto@Sun.COM 	if (slu->slu_writeback_cache_disable) {
18079585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
18089585STim.Szeto@Sun.COM 		    SL_SAVED_WRITE_CACHE_DISABLE;
18099585STim.Szeto@Sun.COM 	}
18109585STim.Szeto@Sun.COM 
18119585STim.Szeto@Sun.COM 	if (slu->slu_blksize_valid) {
18129585STim.Szeto@Sun.COM 		if ((slu->slu_blksize & (slu->slu_blksize - 1)) ||
18139585STim.Szeto@Sun.COM 		    (slu->slu_blksize > (32 * 1024)) ||
18149585STim.Szeto@Sun.COM 		    (slu->slu_blksize == 0)) {
18159585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_INVALID_BLKSIZE;
18169585STim.Szeto@Sun.COM 			ret = EINVAL;
18179585STim.Szeto@Sun.COM 			goto scm_err_out;
18189585STim.Szeto@Sun.COM 		}
18199585STim.Szeto@Sun.COM 		while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) {
18209585STim.Szeto@Sun.COM 			sl->sl_data_blocksize_shift++;
18219585STim.Szeto@Sun.COM 		}
18229585STim.Szeto@Sun.COM 	} else {
18239585STim.Szeto@Sun.COM 		sl->sl_data_blocksize_shift = 9;	/* 512 by default */
18249585STim.Szeto@Sun.COM 		slu->slu_blksize = 512;
18259585STim.Szeto@Sun.COM 	}
18269585STim.Szeto@Sun.COM 
18279585STim.Szeto@Sun.COM 	/* Now lets start creating meta */
18289585STim.Szeto@Sun.COM 	sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
18299585STim.Szeto@Sun.COM 	if (sbd_link_lu(sl) != SBD_SUCCESS) {
18309585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
18319585STim.Szeto@Sun.COM 		ret = EALREADY;
18329585STim.Szeto@Sun.COM 		goto scm_err_out;
18339585STim.Szeto@Sun.COM 	}
18347836SJohn.Forte@Sun.COM 
18359585STim.Szeto@Sun.COM 	/* 1st focus on the data store */
18369585STim.Szeto@Sun.COM 	if (slu->slu_lu_size_valid) {
18379585STim.Szeto@Sun.COM 		sl->sl_lu_size = slu->slu_lu_size;
18389585STim.Szeto@Sun.COM 	}
18399585STim.Szeto@Sun.COM 	ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0);
18409585STim.Szeto@Sun.COM 	slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits;
18419585STim.Szeto@Sun.COM 	slu->slu_lu_size = sl->sl_lu_size;
18429585STim.Szeto@Sun.COM 	if (ret) {
18439585STim.Szeto@Sun.COM 		goto scm_err_out;
18449585STim.Szeto@Sun.COM 	}
18459585STim.Szeto@Sun.COM 
18469585STim.Szeto@Sun.COM 	/*
18479585STim.Szeto@Sun.COM 	 * set write cache disable on the device
18489585STim.Szeto@Sun.COM 	 * if it fails, we'll support it using sync/flush
18499585STim.Szeto@Sun.COM 	 */
18509585STim.Szeto@Sun.COM 	if (slu->slu_writeback_cache_disable) {
18519585STim.Szeto@Sun.COM 		(void) sbd_wcd_set(1, sl);
18529585STim.Szeto@Sun.COM 		wcd = 1;
18539585STim.Szeto@Sun.COM 	/*
18549585STim.Szeto@Sun.COM 	 * Attempt to set it to enable, if that fails and it was explicitly set
18559585STim.Szeto@Sun.COM 	 * return an error, otherwise get the current setting and use that
18569585STim.Szeto@Sun.COM 	 */
18579585STim.Szeto@Sun.COM 	} else {
18589585STim.Szeto@Sun.COM 		sret = sbd_wcd_set(0, sl);
18599585STim.Szeto@Sun.COM 		if (slu->slu_writeback_cache_disable_valid &&
18609585STim.Szeto@Sun.COM 		    sret != SBD_SUCCESS) {
18619585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
18629585STim.Szeto@Sun.COM 			ret = EFAULT;
18639585STim.Szeto@Sun.COM 			goto scm_err_out;
18649585STim.Szeto@Sun.COM 		}
18659585STim.Szeto@Sun.COM 		if (sret != SBD_SUCCESS) {
18669585STim.Szeto@Sun.COM 			sbd_wcd_get(&wcd, sl);
18679585STim.Szeto@Sun.COM 		}
18689585STim.Szeto@Sun.COM 	}
18699585STim.Szeto@Sun.COM 
18709585STim.Szeto@Sun.COM 	if (wcd) {
18719585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
18729585STim.Szeto@Sun.COM 		    SL_SAVED_WRITE_CACHE_DISABLE;
18739585STim.Szeto@Sun.COM 	}
18749585STim.Szeto@Sun.COM 
18759585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_SHARED_META) {
18769585STim.Szeto@Sun.COM 		goto over_meta_open;
18779585STim.Szeto@Sun.COM 	}
18789585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
18799585STim.Szeto@Sun.COM 		if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) {
18809585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_ZFS_META_CREATE_FAILED;
18819679STim.Szeto@Sun.COM 			ret = ENOMEM;
18829585STim.Szeto@Sun.COM 			goto scm_err_out;
18839585STim.Szeto@Sun.COM 		}
18849585STim.Szeto@Sun.COM 		sl->sl_meta_blocksize_shift = 0;
18859585STim.Szeto@Sun.COM 		goto over_meta_create;
18869585STim.Szeto@Sun.COM 	}
18879585STim.Szeto@Sun.COM 	if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
18889585STim.Szeto@Sun.COM 	    NULLVPP, &sl->sl_meta_vp)) != 0) {
18899585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
18909585STim.Szeto@Sun.COM 		goto scm_err_out;
18919585STim.Szeto@Sun.COM 	}
18929585STim.Szeto@Sun.COM 	sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
18939585STim.Szeto@Sun.COM 	VN_RELE(sl->sl_meta_vp);
18949585STim.Szeto@Sun.COM 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
18959585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_WRONG_META_FILE_TYPE;
18969585STim.Szeto@Sun.COM 		ret = EINVAL;
18979585STim.Szeto@Sun.COM 		goto scm_err_out;
18989585STim.Szeto@Sun.COM 	}
18999585STim.Szeto@Sun.COM 	if (vt == VREG) {
19009585STim.Szeto@Sun.COM 		sl->sl_meta_blocksize_shift = 0;
19019585STim.Szeto@Sun.COM 	} else {
19029585STim.Szeto@Sun.COM 		sl->sl_meta_blocksize_shift = 9;
19039585STim.Szeto@Sun.COM 	}
19049585STim.Szeto@Sun.COM 	flag = FREAD | FWRITE | FOFFMAX | FEXCL;
19059585STim.Szeto@Sun.COM 	if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
19069585STim.Szeto@Sun.COM 	    &sl->sl_meta_vp, 0, 0)) != 0) {
19079585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
19089585STim.Szeto@Sun.COM 		goto scm_err_out;
19099585STim.Szeto@Sun.COM 	}
19109585STim.Szeto@Sun.COM over_meta_create:
19119679STim.Szeto@Sun.COM 	sl->sl_total_meta_size = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
19129585STim.Szeto@Sun.COM 	sl->sl_total_meta_size +=
19139585STim.Szeto@Sun.COM 	    (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
19149585STim.Szeto@Sun.COM 	sl->sl_total_meta_size &=
19159585STim.Szeto@Sun.COM 	    ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1);
19169585STim.Szeto@Sun.COM 	sl->sl_meta_size_used = 0;
19179585STim.Szeto@Sun.COM over_meta_open:
19189585STim.Szeto@Sun.COM 	sl->sl_flags |= SL_META_OPENED;
19199585STim.Szeto@Sun.COM 
19209585STim.Szeto@Sun.COM 	sl->sl_device_id[3] = 16;
19219585STim.Szeto@Sun.COM 	if (slu->slu_guid_valid) {
19229585STim.Szeto@Sun.COM 		sl->sl_device_id[0] = 0xf1;
19239585STim.Szeto@Sun.COM 		sl->sl_device_id[1] = 3;
19249585STim.Szeto@Sun.COM 		sl->sl_device_id[2] = 0;
19259585STim.Szeto@Sun.COM 		bcopy(slu->slu_guid, sl->sl_device_id + 4, 16);
19269585STim.Szeto@Sun.COM 	} else {
192710765SJohn.Forte@Sun.COM 		if (slu->slu_host_id_valid)
192810765SJohn.Forte@Sun.COM 			hid = slu->slu_host_id;
19299585STim.Szeto@Sun.COM 		if (!slu->slu_company_id_valid)
19309585STim.Szeto@Sun.COM 			slu->slu_company_id = COMPANY_ID_SUN;
193110765SJohn.Forte@Sun.COM 		if (stmf_scsilib_uniq_lu_id2(slu->slu_company_id, hid,
19329585STim.Szeto@Sun.COM 		    (scsi_devid_desc_t *)&sl->sl_device_id[0]) !=
19339585STim.Szeto@Sun.COM 		    STMF_SUCCESS) {
19349585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_META_CREATION_FAILED;
19359585STim.Szeto@Sun.COM 			ret = EIO;
19369585STim.Szeto@Sun.COM 			goto scm_err_out;
19379585STim.Szeto@Sun.COM 		}
19389585STim.Szeto@Sun.COM 		bcopy(sl->sl_device_id + 4, slu->slu_guid, 16);
19399585STim.Szeto@Sun.COM 	}
19409585STim.Szeto@Sun.COM 
19419585STim.Szeto@Sun.COM 	/* Lets create the meta now */
194210526STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_metadata_lock);
19439585STim.Szeto@Sun.COM 	if (sbd_write_meta_start(sl, sl->sl_total_meta_size,
19449585STim.Szeto@Sun.COM 	    sizeof (sbd_meta_start_t)) != SBD_SUCCESS) {
194510526STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_metadata_lock);
19469585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_CREATION_FAILED;
19479585STim.Szeto@Sun.COM 		ret = EIO;
19489585STim.Szeto@Sun.COM 		goto scm_err_out;
19499585STim.Szeto@Sun.COM 	}
195010526STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_metadata_lock);
19519679STim.Szeto@Sun.COM 	sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
19529585STim.Szeto@Sun.COM 
19539585STim.Szeto@Sun.COM 	if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
19549585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_CREATION_FAILED;
19559585STim.Szeto@Sun.COM 		ret = EIO;
19569585STim.Szeto@Sun.COM 		goto scm_err_out;
19579585STim.Szeto@Sun.COM 	}
19589585STim.Szeto@Sun.COM 
19599933SNattuvetty.Bhavyan@Sun.COM 	if (sbd_pgr_meta_init(sl) != SBD_SUCCESS) {
19609585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_CREATION_FAILED;
19619585STim.Szeto@Sun.COM 		ret = EIO;
19629585STim.Szeto@Sun.COM 		goto scm_err_out;
19639585STim.Szeto@Sun.COM 	}
19649585STim.Szeto@Sun.COM 
196512499SJohn.Forte@Sun.COM 	/*
196612499SJohn.Forte@Sun.COM 	 * Update the zvol separately as this need only be called upon
196712499SJohn.Forte@Sun.COM 	 * completion of the metadata initialization.
196812499SJohn.Forte@Sun.COM 	 */
196912499SJohn.Forte@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
197012499SJohn.Forte@Sun.COM 		if (sbd_update_zfs_prop(sl) != SBD_SUCCESS) {
197112499SJohn.Forte@Sun.COM 			*err_ret = SBD_RET_META_CREATION_FAILED;
197212499SJohn.Forte@Sun.COM 			ret = EIO;
197312499SJohn.Forte@Sun.COM 			goto scm_err_out;
197412499SJohn.Forte@Sun.COM 		}
197512499SJohn.Forte@Sun.COM 	}
197612499SJohn.Forte@Sun.COM 
19779585STim.Szeto@Sun.COM 	ret = sbd_populate_and_register_lu(sl, err_ret);
19789585STim.Szeto@Sun.COM 	if (ret) {
19799585STim.Szeto@Sun.COM 		goto scm_err_out;
19809585STim.Szeto@Sun.COM 	}
19819585STim.Szeto@Sun.COM 
19829585STim.Szeto@Sun.COM 	sl->sl_trans_op = SL_OP_NONE;
19839585STim.Szeto@Sun.COM 	atomic_add_32(&sbd_lu_count, 1);
19849585STim.Szeto@Sun.COM 	return (0);
19859585STim.Szeto@Sun.COM 
19869585STim.Szeto@Sun.COM scm_err_out:
19879585STim.Szeto@Sun.COM 	return (sbd_close_delete_lu(sl, ret));
19889585STim.Szeto@Sun.COM }
19899585STim.Szeto@Sun.COM 
199010725SJohn.Forte@Sun.COM stmf_status_t
sbd_proxy_msg(uint8_t * luid,void * proxy_arg,uint32_t proxy_arg_len,uint32_t type)199110725SJohn.Forte@Sun.COM sbd_proxy_msg(uint8_t *luid, void *proxy_arg, uint32_t proxy_arg_len,
199210725SJohn.Forte@Sun.COM     uint32_t type)
199310725SJohn.Forte@Sun.COM {
199410725SJohn.Forte@Sun.COM 	switch (type) {
199510725SJohn.Forte@Sun.COM 		case STMF_MSG_LU_ACTIVE:
199610725SJohn.Forte@Sun.COM 			return (sbd_proxy_reg_lu(luid, proxy_arg,
199710725SJohn.Forte@Sun.COM 			    proxy_arg_len));
199810725SJohn.Forte@Sun.COM 		case STMF_MSG_LU_REGISTER:
199910725SJohn.Forte@Sun.COM 			return (sbd_proxy_reg_lu(luid, proxy_arg,
200010725SJohn.Forte@Sun.COM 			    proxy_arg_len));
200110725SJohn.Forte@Sun.COM 		case STMF_MSG_LU_DEREGISTER:
200210725SJohn.Forte@Sun.COM 			return (sbd_proxy_dereg_lu(luid, proxy_arg,
200310725SJohn.Forte@Sun.COM 			    proxy_arg_len));
200410725SJohn.Forte@Sun.COM 		default:
200510725SJohn.Forte@Sun.COM 			return (STMF_INVALID_ARG);
200610725SJohn.Forte@Sun.COM 	}
200710725SJohn.Forte@Sun.COM }
200810725SJohn.Forte@Sun.COM 
200910725SJohn.Forte@Sun.COM 
201010725SJohn.Forte@Sun.COM /*
201110725SJohn.Forte@Sun.COM  * register a standby logical unit
201210725SJohn.Forte@Sun.COM  * proxy_reg_arg contains the meta filename
201310725SJohn.Forte@Sun.COM  */
201410725SJohn.Forte@Sun.COM stmf_status_t
sbd_proxy_reg_lu(uint8_t * luid,void * proxy_reg_arg,uint32_t proxy_reg_arg_len)201510725SJohn.Forte@Sun.COM sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg, uint32_t proxy_reg_arg_len)
201610725SJohn.Forte@Sun.COM {
201710725SJohn.Forte@Sun.COM 	sbd_lu_t *sl;
201810725SJohn.Forte@Sun.COM 	sbd_status_t sret;
201910725SJohn.Forte@Sun.COM 	sbd_create_standby_lu_t *stlu;
202010725SJohn.Forte@Sun.COM 	int alloc_sz;
202110725SJohn.Forte@Sun.COM 	uint32_t err_ret = 0;
202210725SJohn.Forte@Sun.COM 	stmf_status_t stret = STMF_SUCCESS;
202310725SJohn.Forte@Sun.COM 
202410725SJohn.Forte@Sun.COM 	if (luid == NULL) {
202510725SJohn.Forte@Sun.COM 		return (STMF_INVALID_ARG);
202610725SJohn.Forte@Sun.COM 	}
202710725SJohn.Forte@Sun.COM 
202810725SJohn.Forte@Sun.COM 	do {
202910725SJohn.Forte@Sun.COM 		sret = sbd_find_and_lock_lu(luid, NULL, SL_OP_MODIFY_LU, &sl);
203010725SJohn.Forte@Sun.COM 	} while (sret == SBD_BUSY);
203110725SJohn.Forte@Sun.COM 
203210725SJohn.Forte@Sun.COM 	if (sret == SBD_NOT_FOUND) {
203310725SJohn.Forte@Sun.COM 		alloc_sz = sizeof (*stlu) + proxy_reg_arg_len - 8;
203410725SJohn.Forte@Sun.COM 		stlu = (sbd_create_standby_lu_t *)kmem_zalloc(alloc_sz,
203510725SJohn.Forte@Sun.COM 		    KM_SLEEP);
203610725SJohn.Forte@Sun.COM 		bcopy(luid, stlu->stlu_guid, 16);
203710725SJohn.Forte@Sun.COM 		if (proxy_reg_arg_len) {
203810725SJohn.Forte@Sun.COM 			bcopy(proxy_reg_arg, stlu->stlu_meta_fname,
203910725SJohn.Forte@Sun.COM 			    proxy_reg_arg_len);
204010725SJohn.Forte@Sun.COM 			stlu->stlu_meta_fname_size = proxy_reg_arg_len;
204110725SJohn.Forte@Sun.COM 		}
204210725SJohn.Forte@Sun.COM 		if (sbd_create_standby_lu(stlu, &err_ret) != 0) {
204310725SJohn.Forte@Sun.COM 			cmn_err(CE_WARN,
204410725SJohn.Forte@Sun.COM 			    "Unable to create standby logical unit for %s",
204510725SJohn.Forte@Sun.COM 			    stlu->stlu_meta_fname);
204610725SJohn.Forte@Sun.COM 			stret = STMF_FAILURE;
204710725SJohn.Forte@Sun.COM 		}
204810725SJohn.Forte@Sun.COM 		kmem_free(stlu, alloc_sz);
204910725SJohn.Forte@Sun.COM 		return (stret);
205010725SJohn.Forte@Sun.COM 	} else if (sret == SBD_SUCCESS) {
205110725SJohn.Forte@Sun.COM 		/*
205210725SJohn.Forte@Sun.COM 		 * if the lu is already registered, then the lu should now
205310725SJohn.Forte@Sun.COM 		 * be in standby mode
205410725SJohn.Forte@Sun.COM 		 */
205510725SJohn.Forte@Sun.COM 		sbd_it_data_t *it;
205610725SJohn.Forte@Sun.COM 		if (sl->sl_access_state != SBD_LU_STANDBY) {
205710725SJohn.Forte@Sun.COM 			mutex_enter(&sl->sl_lock);
205810725SJohn.Forte@Sun.COM 			sl->sl_access_state = SBD_LU_STANDBY;
205910725SJohn.Forte@Sun.COM 			for (it = sl->sl_it_list; it != NULL;
206010725SJohn.Forte@Sun.COM 			    it = it->sbd_it_next) {
206110725SJohn.Forte@Sun.COM 				it->sbd_it_ua_conditions |=
206210725SJohn.Forte@Sun.COM 				    SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
206310725SJohn.Forte@Sun.COM 				it->sbd_it_flags &=
206410725SJohn.Forte@Sun.COM 				    ~SBD_IT_HAS_SCSI2_RESERVATION;
206510725SJohn.Forte@Sun.COM 				sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
206610725SJohn.Forte@Sun.COM 			}
206710725SJohn.Forte@Sun.COM 			mutex_exit(&sl->sl_lock);
206810725SJohn.Forte@Sun.COM 			sbd_pgr_reset(sl);
206910725SJohn.Forte@Sun.COM 		}
207010725SJohn.Forte@Sun.COM 		sl->sl_trans_op = SL_OP_NONE;
207110725SJohn.Forte@Sun.COM 	} else {
207210725SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "could not find and lock logical unit");
207310725SJohn.Forte@Sun.COM 		stret = STMF_FAILURE;
207410725SJohn.Forte@Sun.COM 	}
207510725SJohn.Forte@Sun.COM out:
207610725SJohn.Forte@Sun.COM 	return (stret);
207710725SJohn.Forte@Sun.COM }
207810725SJohn.Forte@Sun.COM 
207910725SJohn.Forte@Sun.COM /* ARGSUSED */
208010725SJohn.Forte@Sun.COM stmf_status_t
sbd_proxy_dereg_lu(uint8_t * luid,void * proxy_reg_arg,uint32_t proxy_reg_arg_len)208110725SJohn.Forte@Sun.COM sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
208210725SJohn.Forte@Sun.COM     uint32_t proxy_reg_arg_len)
208310725SJohn.Forte@Sun.COM {
208410725SJohn.Forte@Sun.COM 	sbd_delete_lu_t dlu = {0};
208510725SJohn.Forte@Sun.COM 	uint32_t err_ret;
208610725SJohn.Forte@Sun.COM 
208710725SJohn.Forte@Sun.COM 	if (luid == NULL) {
208810725SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "de-register lu request had null luid");
208910725SJohn.Forte@Sun.COM 		return (STMF_INVALID_ARG);
209010725SJohn.Forte@Sun.COM 	}
209110725SJohn.Forte@Sun.COM 
209210725SJohn.Forte@Sun.COM 	bcopy(luid, &dlu.dlu_guid, 16);
209310725SJohn.Forte@Sun.COM 
209410725SJohn.Forte@Sun.COM 	if (sbd_delete_lu(&dlu, (int)sizeof (dlu), &err_ret) != 0) {
209510725SJohn.Forte@Sun.COM 		cmn_err(CE_WARN, "failed to delete de-register lu request");
209610725SJohn.Forte@Sun.COM 		return (STMF_FAILURE);
209710725SJohn.Forte@Sun.COM 	}
209810725SJohn.Forte@Sun.COM 
209910725SJohn.Forte@Sun.COM 	return (STMF_SUCCESS);
210010725SJohn.Forte@Sun.COM }
210110725SJohn.Forte@Sun.COM 
210210725SJohn.Forte@Sun.COM int
sbd_create_standby_lu(sbd_create_standby_lu_t * slu,uint32_t * err_ret)210310725SJohn.Forte@Sun.COM sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret)
210410725SJohn.Forte@Sun.COM {
210510725SJohn.Forte@Sun.COM 	sbd_lu_t *sl;
210610725SJohn.Forte@Sun.COM 	stmf_lu_t *lu;
210710725SJohn.Forte@Sun.COM 	int ret = EIO;
210810725SJohn.Forte@Sun.COM 	int alloc_sz;
210910725SJohn.Forte@Sun.COM 
211010725SJohn.Forte@Sun.COM 	alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) +
211110725SJohn.Forte@Sun.COM 	    slu->stlu_meta_fname_size;
211210725SJohn.Forte@Sun.COM 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
211310725SJohn.Forte@Sun.COM 	if (lu == NULL) {
211410725SJohn.Forte@Sun.COM 		return (ENOMEM);
211510725SJohn.Forte@Sun.COM 	}
211610725SJohn.Forte@Sun.COM 	sl = (sbd_lu_t *)lu->lu_provider_private;
211710725SJohn.Forte@Sun.COM 	bzero(sl, alloc_sz);
211810725SJohn.Forte@Sun.COM 	sl->sl_lu = lu;
211910725SJohn.Forte@Sun.COM 	sl->sl_alloc_size = alloc_sz;
212010725SJohn.Forte@Sun.COM 
212110725SJohn.Forte@Sun.COM 	sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
212210725SJohn.Forte@Sun.COM 	sl->sl_meta_filename = ((char *)sl) + sizeof (sbd_lu_t) +
212310725SJohn.Forte@Sun.COM 	    sizeof (sbd_pgr_t);
212410725SJohn.Forte@Sun.COM 
212510725SJohn.Forte@Sun.COM 	if (slu->stlu_meta_fname_size > 0) {
212610725SJohn.Forte@Sun.COM 		(void) strcpy(sl->sl_meta_filename, slu->stlu_meta_fname);
212710725SJohn.Forte@Sun.COM 	}
212810725SJohn.Forte@Sun.COM 	sl->sl_name = sl->sl_meta_filename;
212910725SJohn.Forte@Sun.COM 
213010725SJohn.Forte@Sun.COM 	sl->sl_device_id[3] = 16;
213110725SJohn.Forte@Sun.COM 	sl->sl_device_id[0] = 0xf1;
213210725SJohn.Forte@Sun.COM 	sl->sl_device_id[1] = 3;
213310725SJohn.Forte@Sun.COM 	sl->sl_device_id[2] = 0;
213410725SJohn.Forte@Sun.COM 	bcopy(slu->stlu_guid, sl->sl_device_id + 4, 16);
213510725SJohn.Forte@Sun.COM 	lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
213610725SJohn.Forte@Sun.COM 	sl->sl_access_state = SBD_LU_STANDBY;
213710725SJohn.Forte@Sun.COM 
213810725SJohn.Forte@Sun.COM 	rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
213910725SJohn.Forte@Sun.COM 	mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
214010725SJohn.Forte@Sun.COM 	mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
214110725SJohn.Forte@Sun.COM 	rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
214210725SJohn.Forte@Sun.COM 
214310725SJohn.Forte@Sun.COM 	sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
214410725SJohn.Forte@Sun.COM 
214510725SJohn.Forte@Sun.COM 	if (sbd_link_lu(sl) != SBD_SUCCESS) {
214610725SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
214710725SJohn.Forte@Sun.COM 		ret = EALREADY;
214810725SJohn.Forte@Sun.COM 		goto scs_err_out;
214910725SJohn.Forte@Sun.COM 	}
215010725SJohn.Forte@Sun.COM 
215110725SJohn.Forte@Sun.COM 	ret = sbd_populate_and_register_lu(sl, err_ret);
215210725SJohn.Forte@Sun.COM 	if (ret) {
215310725SJohn.Forte@Sun.COM 		goto scs_err_out;
215410725SJohn.Forte@Sun.COM 	}
215510725SJohn.Forte@Sun.COM 
215610725SJohn.Forte@Sun.COM 	sl->sl_trans_op = SL_OP_NONE;
215710725SJohn.Forte@Sun.COM 	atomic_add_32(&sbd_lu_count, 1);
215810725SJohn.Forte@Sun.COM 	return (0);
215910725SJohn.Forte@Sun.COM 
216010725SJohn.Forte@Sun.COM scs_err_out:
216110725SJohn.Forte@Sun.COM 	return (sbd_close_delete_lu(sl, ret));
216210725SJohn.Forte@Sun.COM }
216310725SJohn.Forte@Sun.COM 
21649585STim.Szeto@Sun.COM int
sbd_load_sli_1_0(sbd_lu_t * sl,uint32_t * err_ret)21659585STim.Szeto@Sun.COM sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret)
21669585STim.Szeto@Sun.COM {
21679585STim.Szeto@Sun.COM 	sbd_lu_info_1_0_t *sli = NULL;
21689585STim.Szeto@Sun.COM 	sbd_status_t sret;
21699585STim.Szeto@Sun.COM 
21709585STim.Szeto@Sun.COM 	sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
21719585STim.Szeto@Sun.COM 	    SMS_ID_LU_INFO_1_0);
21727836SJohn.Forte@Sun.COM 
21739585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
21749585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_NO_META;
21759585STim.Szeto@Sun.COM 		return (EIO);
21769585STim.Szeto@Sun.COM 	}
21779585STim.Szeto@Sun.COM 	if (sli->sli_data_order != SMS_DATA_ORDER) {
21789585STim.Szeto@Sun.COM 		sbd_swap_lu_info_1_0(sli);
21799585STim.Szeto@Sun.COM 		if (sli->sli_data_order != SMS_DATA_ORDER) {
21809585STim.Szeto@Sun.COM 			kmem_free(sli, sli->sli_sms_header.sms_size);
21819585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_NO_META;
21829585STim.Szeto@Sun.COM 			return (EIO);
21839585STim.Szeto@Sun.COM 		}
21849585STim.Szeto@Sun.COM 	}
21859585STim.Szeto@Sun.COM 
21869585STim.Szeto@Sun.COM 	sl->sl_flags |= SL_SHARED_META;
21879585STim.Szeto@Sun.COM 	sl->sl_data_blocksize_shift = 9;
21889585STim.Szeto@Sun.COM 	sl->sl_data_offset = SHARED_META_DATA_SIZE;
21899585STim.Szeto@Sun.COM 	sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE;
21909585STim.Szeto@Sun.COM 	sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size;
21919585STim.Szeto@Sun.COM 	bcopy(sli->sli_lu_devid, sl->sl_device_id, 20);
21929585STim.Szeto@Sun.COM 
21939585STim.Szeto@Sun.COM 	kmem_free(sli, sli->sli_sms_header.sms_size);
21949585STim.Szeto@Sun.COM 	return (0);
21959585STim.Szeto@Sun.COM }
21969585STim.Szeto@Sun.COM 
21979585STim.Szeto@Sun.COM int
sbd_import_lu(sbd_import_lu_t * ilu,int struct_sz,uint32_t * err_ret,int no_register,sbd_lu_t ** slr)21989585STim.Szeto@Sun.COM sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
21999585STim.Szeto@Sun.COM     int no_register, sbd_lu_t **slr)
22009585STim.Szeto@Sun.COM {
22019585STim.Szeto@Sun.COM 	stmf_lu_t *lu;
22029585STim.Szeto@Sun.COM 	sbd_lu_t *sl;
22039585STim.Szeto@Sun.COM 	sbd_lu_info_1_1_t *sli = NULL;
22049585STim.Szeto@Sun.COM 	int asz;
22059585STim.Szeto@Sun.COM 	int ret = 0;
220610725SJohn.Forte@Sun.COM 	stmf_status_t stret;
22079585STim.Szeto@Sun.COM 	int flag;
22089585STim.Szeto@Sun.COM 	int wcd = 0;
22099585STim.Szeto@Sun.COM 	int data_opened;
22109585STim.Szeto@Sun.COM 	uint16_t sli_buf_sz;
22119585STim.Szeto@Sun.COM 	uint8_t *sli_buf_copy = NULL;
22129585STim.Szeto@Sun.COM 	enum vtype vt;
221310725SJohn.Forte@Sun.COM 	int standby = 0;
22149585STim.Szeto@Sun.COM 	sbd_status_t sret;
22159585STim.Szeto@Sun.COM 
22169585STim.Szeto@Sun.COM 	if (no_register && slr == NULL) {
22179585STim.Szeto@Sun.COM 		return (EINVAL);
22189585STim.Szeto@Sun.COM 	}
22199585STim.Szeto@Sun.COM 	ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0;
222010725SJohn.Forte@Sun.COM 	/*
222110725SJohn.Forte@Sun.COM 	 * check whether logical unit is already registered ALUA
222210725SJohn.Forte@Sun.COM 	 * For a standby logical unit, the meta filename is set. Use
222310725SJohn.Forte@Sun.COM 	 * that to search for an existing logical unit.
222410725SJohn.Forte@Sun.COM 	 */
222510725SJohn.Forte@Sun.COM 	sret = sbd_find_and_lock_lu(NULL, (uint8_t *)&(ilu->ilu_meta_fname),
222610725SJohn.Forte@Sun.COM 	    SL_OP_IMPORT_LU, &sl);
22279585STim.Szeto@Sun.COM 
222810725SJohn.Forte@Sun.COM 	if (sret == SBD_SUCCESS) {
222910725SJohn.Forte@Sun.COM 		if (sl->sl_access_state != SBD_LU_ACTIVE) {
223010725SJohn.Forte@Sun.COM 			no_register = 1;
223110725SJohn.Forte@Sun.COM 			standby = 1;
223210725SJohn.Forte@Sun.COM 			lu = sl->sl_lu;
223310725SJohn.Forte@Sun.COM 			if (sl->sl_alias_alloc_size) {
223410725SJohn.Forte@Sun.COM 				kmem_free(sl->sl_alias,
223510725SJohn.Forte@Sun.COM 				    sl->sl_alias_alloc_size);
223610725SJohn.Forte@Sun.COM 				sl->sl_alias_alloc_size = 0;
223710725SJohn.Forte@Sun.COM 				sl->sl_alias = NULL;
223810725SJohn.Forte@Sun.COM 				lu->lu_alias = NULL;
223910725SJohn.Forte@Sun.COM 			}
224010725SJohn.Forte@Sun.COM 			if (sl->sl_meta_filename == NULL) {
224110725SJohn.Forte@Sun.COM 				sl->sl_meta_filename = sl->sl_data_filename;
224210725SJohn.Forte@Sun.COM 			} else if (sl->sl_data_fname_alloc_size) {
224310725SJohn.Forte@Sun.COM 				kmem_free(sl->sl_data_filename,
224410725SJohn.Forte@Sun.COM 				    sl->sl_data_fname_alloc_size);
224510725SJohn.Forte@Sun.COM 				sl->sl_data_fname_alloc_size = 0;
224610725SJohn.Forte@Sun.COM 			}
224710725SJohn.Forte@Sun.COM 			if (sl->sl_serial_no_alloc_size) {
224810725SJohn.Forte@Sun.COM 				kmem_free(sl->sl_serial_no,
224910725SJohn.Forte@Sun.COM 				    sl->sl_serial_no_alloc_size);
225010725SJohn.Forte@Sun.COM 				sl->sl_serial_no_alloc_size = 0;
225110725SJohn.Forte@Sun.COM 			}
225210725SJohn.Forte@Sun.COM 			if (sl->sl_mgmt_url_alloc_size) {
225310725SJohn.Forte@Sun.COM 				kmem_free(sl->sl_mgmt_url,
225410725SJohn.Forte@Sun.COM 				    sl->sl_mgmt_url_alloc_size);
225510725SJohn.Forte@Sun.COM 				sl->sl_mgmt_url_alloc_size = 0;
225610725SJohn.Forte@Sun.COM 			}
225710725SJohn.Forte@Sun.COM 		} else {
225810725SJohn.Forte@Sun.COM 			*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2259*12591SSrivijitha.Dugganapalli@Sun.COM 			bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
226010725SJohn.Forte@Sun.COM 			sl->sl_trans_op = SL_OP_NONE;
226110725SJohn.Forte@Sun.COM 			return (EALREADY);
226210725SJohn.Forte@Sun.COM 		}
226310725SJohn.Forte@Sun.COM 	} else if (sret == SBD_NOT_FOUND) {
226410725SJohn.Forte@Sun.COM 		asz = strlen(ilu->ilu_meta_fname) + 1;
226510725SJohn.Forte@Sun.COM 
226610725SJohn.Forte@Sun.COM 		lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU,
226710725SJohn.Forte@Sun.COM 		    sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0);
226810725SJohn.Forte@Sun.COM 		if (lu == NULL) {
226910725SJohn.Forte@Sun.COM 			return (ENOMEM);
227010725SJohn.Forte@Sun.COM 		}
227110725SJohn.Forte@Sun.COM 		sl = (sbd_lu_t *)lu->lu_provider_private;
227210725SJohn.Forte@Sun.COM 		bzero(sl, sizeof (*sl));
227310725SJohn.Forte@Sun.COM 		sl->sl_lu = lu;
227410725SJohn.Forte@Sun.COM 		sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
227510725SJohn.Forte@Sun.COM 		sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) +
227610725SJohn.Forte@Sun.COM 		    sizeof (sbd_pgr_t);
227710725SJohn.Forte@Sun.COM 		(void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname);
227810725SJohn.Forte@Sun.COM 		sl->sl_name = sl->sl_meta_filename;
227910725SJohn.Forte@Sun.COM 		rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
228010725SJohn.Forte@Sun.COM 		rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
228110725SJohn.Forte@Sun.COM 		mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
228210725SJohn.Forte@Sun.COM 		mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
228310725SJohn.Forte@Sun.COM 		sl->sl_trans_op = SL_OP_IMPORT_LU;
228410725SJohn.Forte@Sun.COM 	} else {
228510725SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
228610725SJohn.Forte@Sun.COM 		return (EIO);
22879585STim.Szeto@Sun.COM 	}
228810725SJohn.Forte@Sun.COM 
22899585STim.Szeto@Sun.COM 	/* we're only loading the metadata */
22909585STim.Szeto@Sun.COM 	if (!no_register) {
22919585STim.Szeto@Sun.COM 		if (sbd_link_lu(sl) != SBD_SUCCESS) {
22929585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2293*12591SSrivijitha.Dugganapalli@Sun.COM 			bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
22949585STim.Szeto@Sun.COM 			ret = EALREADY;
22959585STim.Szeto@Sun.COM 			goto sim_err_out;
22969585STim.Szeto@Sun.COM 		}
22979585STim.Szeto@Sun.COM 	}
22989585STim.Szeto@Sun.COM 	if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
22999585STim.Szeto@Sun.COM 	    NULLVPP, &sl->sl_meta_vp)) != 0) {
23009585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
23019585STim.Szeto@Sun.COM 		goto sim_err_out;
23029585STim.Szeto@Sun.COM 	}
23039679STim.Szeto@Sun.COM 	if (sbd_is_zvol(sl->sl_meta_filename)) {
23049585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_ZFS_META;
23059585STim.Szeto@Sun.COM 		sl->sl_data_filename = sl->sl_meta_filename;
23069585STim.Szeto@Sun.COM 	}
23079585STim.Szeto@Sun.COM 	sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
23089585STim.Szeto@Sun.COM 	VN_RELE(sl->sl_meta_vp);
23099585STim.Szeto@Sun.COM 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
23109585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_WRONG_META_FILE_TYPE;
23119585STim.Szeto@Sun.COM 		ret = EINVAL;
23129585STim.Szeto@Sun.COM 		goto sim_err_out;
23139585STim.Szeto@Sun.COM 	}
23149585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_ZFS_META) {
23159585STim.Szeto@Sun.COM 		if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) {
23169679STim.Szeto@Sun.COM 			/* let see if metadata is in the 64k block */
23179679STim.Szeto@Sun.COM 			sl->sl_flags &= ~SL_ZFS_META;
23189585STim.Szeto@Sun.COM 		}
23199679STim.Szeto@Sun.COM 	}
23209679STim.Szeto@Sun.COM 	if (!(sl->sl_flags & SL_ZFS_META)) {
23219585STim.Szeto@Sun.COM 		/* metadata is always writable */
23229585STim.Szeto@Sun.COM 		flag = FREAD | FWRITE | FOFFMAX | FEXCL;
23239585STim.Szeto@Sun.COM 		if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
23249585STim.Szeto@Sun.COM 		    &sl->sl_meta_vp, 0, 0)) != 0) {
23259585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
23269585STim.Szeto@Sun.COM 			goto sim_err_out;
23279585STim.Szeto@Sun.COM 		}
23289585STim.Szeto@Sun.COM 	}
23299585STim.Szeto@Sun.COM 	if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) {
23309585STim.Szeto@Sun.COM 		sl->sl_meta_blocksize_shift = 0;
23319585STim.Szeto@Sun.COM 	} else {
23329585STim.Szeto@Sun.COM 		sl->sl_meta_blocksize_shift = 9;
23339585STim.Szeto@Sun.COM 	}
23349679STim.Szeto@Sun.COM 	sl->sl_meta_offset = (sl->sl_flags & SL_ZFS_META) ? 0 : SBD_META_OFFSET;
23359585STim.Szeto@Sun.COM 	sl->sl_flags |= SL_META_OPENED;
23369585STim.Szeto@Sun.COM 
233710526STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_metadata_lock);
23389585STim.Szeto@Sun.COM 	sret = sbd_load_meta_start(sl);
233910526STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_metadata_lock);
23409585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
23419585STim.Szeto@Sun.COM 		if (sret == SBD_META_CORRUPTED) {
23429585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_NO_META;
23439585STim.Szeto@Sun.COM 		} else if (sret == SBD_NOT_SUPPORTED) {
23449585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_VERSION_NOT_SUPPORTED;
23459585STim.Szeto@Sun.COM 		} else {
23469585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_NO_META;
23479585STim.Szeto@Sun.COM 		}
23489585STim.Szeto@Sun.COM 		ret = EINVAL;
23499585STim.Szeto@Sun.COM 		goto sim_err_out;
23509585STim.Szeto@Sun.COM 	}
23517836SJohn.Forte@Sun.COM 
23529585STim.Szeto@Sun.COM 	/* Now lets see if we can read the most recent LU info */
23539585STim.Szeto@Sun.COM 	sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
23549585STim.Szeto@Sun.COM 	    SMS_ID_LU_INFO_1_1);
23559585STim.Szeto@Sun.COM 	if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) {
23569585STim.Szeto@Sun.COM 		ret = sbd_load_sli_1_0(sl, err_ret);
235710725SJohn.Forte@Sun.COM 		if (ret) {
23589585STim.Szeto@Sun.COM 			goto sim_err_out;
235910725SJohn.Forte@Sun.COM 		}
23609585STim.Szeto@Sun.COM 		goto sim_sli_loaded;
23619585STim.Szeto@Sun.COM 	}
23629585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
23639585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_NO_META;
23649585STim.Szeto@Sun.COM 		ret = EIO;
23659585STim.Szeto@Sun.COM 		goto sim_err_out;
23669585STim.Szeto@Sun.COM 	}
23679585STim.Szeto@Sun.COM 	/* load sli 1.1 */
23689585STim.Szeto@Sun.COM 	if (sli->sli_data_order != SMS_DATA_ORDER) {
23699585STim.Szeto@Sun.COM 		sbd_swap_lu_info_1_1(sli);
23709585STim.Szeto@Sun.COM 		if (sli->sli_data_order != SMS_DATA_ORDER) {
23719585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_NO_META;
23729585STim.Szeto@Sun.COM 			ret = EIO;
23739585STim.Szeto@Sun.COM 			goto sim_err_out;
23749585STim.Szeto@Sun.COM 		}
23759585STim.Szeto@Sun.COM 	}
23769585STim.Szeto@Sun.COM 
23779585STim.Szeto@Sun.COM 	sli_buf_sz = sli->sli_sms_header.sms_size -
23789585STim.Szeto@Sun.COM 	    sizeof (sbd_lu_info_1_1_t) + 8;
23799585STim.Szeto@Sun.COM 	sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP);
23809585STim.Szeto@Sun.COM 	bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz);
23819585STim.Szeto@Sun.COM 	sli_buf_copy[sli_buf_sz] = 0;
23829585STim.Szeto@Sun.COM 
23839585STim.Szeto@Sun.COM 	/* Make sure all the offsets are within limits */
23849585STim.Szeto@Sun.COM 	if (((sli->sli_flags & SLI_META_FNAME_VALID) &&
23859585STim.Szeto@Sun.COM 	    (sli->sli_meta_fname_offset > sli_buf_sz)) ||
23869585STim.Szeto@Sun.COM 	    ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
23879585STim.Szeto@Sun.COM 	    (sli->sli_data_fname_offset > sli_buf_sz)) ||
238810113SNattuvetty.Bhavyan@Sun.COM 	    ((sli->sli_flags & SLI_MGMT_URL_VALID) &&
238910113SNattuvetty.Bhavyan@Sun.COM 	    (sli->sli_mgmt_url_offset > sli_buf_sz)) ||
23909585STim.Szeto@Sun.COM 	    ((sli->sli_flags & SLI_SERIAL_VALID) &&
23919585STim.Szeto@Sun.COM 	    ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
23929585STim.Szeto@Sun.COM 	    ((sli->sli_flags & SLI_ALIAS_VALID) &&
23939585STim.Szeto@Sun.COM 	    (sli->sli_alias_offset > sli_buf_sz))) {
23949585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_NO_META;
23959585STim.Szeto@Sun.COM 		ret = EIO;
23969585STim.Szeto@Sun.COM 		goto sim_err_out;
23979585STim.Szeto@Sun.COM 	}
23989585STim.Szeto@Sun.COM 
23999585STim.Szeto@Sun.COM 	sl->sl_lu_size = sli->sli_lu_size;
24009585STim.Szeto@Sun.COM 	sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift;
24019585STim.Szeto@Sun.COM 	bcopy(sli->sli_device_id, sl->sl_device_id, 20);
24029585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_SERIAL_VALID) {
24039585STim.Szeto@Sun.COM 		sl->sl_serial_no_size = sl->sl_serial_no_alloc_size =
24049585STim.Szeto@Sun.COM 		    sli->sli_serial_size;
24059585STim.Szeto@Sun.COM 		sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP);
24069585STim.Szeto@Sun.COM 		bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no,
24079585STim.Szeto@Sun.COM 		    sl->sl_serial_no_size);
24089585STim.Szeto@Sun.COM 	}
24099585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_SEPARATE_META) {
24109585STim.Szeto@Sun.COM 		sl->sl_total_data_size = sl->sl_lu_size;
24119585STim.Szeto@Sun.COM 		if (sli->sli_flags & SLI_DATA_FNAME_VALID) {
24129585STim.Szeto@Sun.COM 			sl->sl_data_fname_alloc_size = strlen((char *)
24139585STim.Szeto@Sun.COM 			    sli_buf_copy + sli->sli_data_fname_offset) + 1;
24149585STim.Szeto@Sun.COM 			sl->sl_data_filename = kmem_zalloc(
24159585STim.Szeto@Sun.COM 			    sl->sl_data_fname_alloc_size, KM_SLEEP);
24169585STim.Szeto@Sun.COM 			(void) strcpy(sl->sl_data_filename,
24179585STim.Szeto@Sun.COM 			    (char *)sli_buf_copy + sli->sli_data_fname_offset);
24189585STim.Szeto@Sun.COM 		}
24199585STim.Szeto@Sun.COM 	} else {
24209585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_ZFS_META) {
24219585STim.Szeto@Sun.COM 			sl->sl_total_data_size = sl->sl_lu_size;
24229585STim.Szeto@Sun.COM 			sl->sl_data_offset = 0;
24239585STim.Szeto@Sun.COM 		} else {
24249585STim.Szeto@Sun.COM 			sl->sl_total_data_size =
24259585STim.Szeto@Sun.COM 			    sl->sl_lu_size + SHARED_META_DATA_SIZE;
24269585STim.Szeto@Sun.COM 			sl->sl_data_offset = SHARED_META_DATA_SIZE;
24279585STim.Szeto@Sun.COM 			sl->sl_flags |= SL_SHARED_META;
24289585STim.Szeto@Sun.COM 		}
24299585STim.Szeto@Sun.COM 	}
24309585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_ALIAS_VALID) {
24319585STim.Szeto@Sun.COM 		sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy +
24329585STim.Szeto@Sun.COM 		    sli->sli_alias_offset) + 1;
24339585STim.Szeto@Sun.COM 		sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP);
24349585STim.Szeto@Sun.COM 		(void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
24359585STim.Szeto@Sun.COM 		    sli->sli_alias_offset);
24369585STim.Szeto@Sun.COM 	}
243710113SNattuvetty.Bhavyan@Sun.COM 	if (sli->sli_flags & SLI_MGMT_URL_VALID) {
243810113SNattuvetty.Bhavyan@Sun.COM 		sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy +
243910113SNattuvetty.Bhavyan@Sun.COM 		    sli->sli_mgmt_url_offset) + 1;
244010113SNattuvetty.Bhavyan@Sun.COM 		sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size,
244110113SNattuvetty.Bhavyan@Sun.COM 		    KM_SLEEP);
244210113SNattuvetty.Bhavyan@Sun.COM 		(void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy +
244310113SNattuvetty.Bhavyan@Sun.COM 		    sli->sli_mgmt_url_offset);
244410113SNattuvetty.Bhavyan@Sun.COM 	}
24459585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_WRITE_PROTECTED) {
24469585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITE_PROTECTED;
24479585STim.Szeto@Sun.COM 	}
24489585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_VID_VALID) {
24499585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_VID_VALID;
24509585STim.Szeto@Sun.COM 		bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
24519585STim.Szeto@Sun.COM 	}
24529585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_PID_VALID) {
24539585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_PID_VALID;
24549585STim.Szeto@Sun.COM 		bcopy(sli->sli_pid, sl->sl_product_id, 16);
24559585STim.Szeto@Sun.COM 	}
24569585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_REV_VALID) {
24579585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_REV_VALID;
24589585STim.Szeto@Sun.COM 		bcopy(sli->sli_rev, sl->sl_revision, 4);
24599585STim.Szeto@Sun.COM 	}
24609585STim.Szeto@Sun.COM 	if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) {
24619585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
24629585STim.Szeto@Sun.COM 	}
24639585STim.Szeto@Sun.COM sim_sli_loaded:
24649585STim.Szeto@Sun.COM 	if ((sl->sl_flags & SL_SHARED_META) == 0) {
24659585STim.Szeto@Sun.COM 		data_opened = 0;
24669585STim.Szeto@Sun.COM 	} else {
24679585STim.Szeto@Sun.COM 		data_opened = 1;
24689585STim.Szeto@Sun.COM 		sl->sl_data_filename = sl->sl_meta_filename;
24699585STim.Szeto@Sun.COM 		sl->sl_data_vp = sl->sl_meta_vp;
24709585STim.Szeto@Sun.COM 		sl->sl_data_vtype = sl->sl_meta_vtype;
24719585STim.Szeto@Sun.COM 	}
24729585STim.Szeto@Sun.COM 
24739585STim.Szeto@Sun.COM 	sret = sbd_pgr_meta_load(sl);
24749585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
24759585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_NO_META;
24769585STim.Szeto@Sun.COM 		ret = EIO;
24779585STim.Szeto@Sun.COM 		goto sim_err_out;
24789585STim.Szeto@Sun.COM 	}
24799585STim.Szeto@Sun.COM 
24809585STim.Szeto@Sun.COM 	ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0);
248110725SJohn.Forte@Sun.COM 	if (ret) {
24829585STim.Szeto@Sun.COM 		goto sim_err_out;
248310725SJohn.Forte@Sun.COM 	}
24849585STim.Szeto@Sun.COM 
24859585STim.Szeto@Sun.COM 	/*
24869585STim.Szeto@Sun.COM 	 * set write cache disable on the device
24879585STim.Szeto@Sun.COM 	 * Note: this shouldn't fail on import unless the cache capabilities
24889585STim.Szeto@Sun.COM 	 * of the device changed. If that happened, modify will need to
24899585STim.Szeto@Sun.COM 	 * be used to set the cache flag appropriately after import is done.
24909585STim.Szeto@Sun.COM 	 */
24919585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
24929585STim.Szeto@Sun.COM 		(void) sbd_wcd_set(1, sl);
24939585STim.Szeto@Sun.COM 		wcd = 1;
24949585STim.Szeto@Sun.COM 	/*
24959585STim.Szeto@Sun.COM 	 * if not explicitly set, attempt to set it to enable, if that fails
24969585STim.Szeto@Sun.COM 	 * get the current setting and use that
24979585STim.Szeto@Sun.COM 	 */
24989585STim.Szeto@Sun.COM 	} else {
24999585STim.Szeto@Sun.COM 		sret = sbd_wcd_set(0, sl);
25009585STim.Szeto@Sun.COM 		if (sret != SBD_SUCCESS) {
25019585STim.Szeto@Sun.COM 			sbd_wcd_get(&wcd, sl);
25027836SJohn.Forte@Sun.COM 		}
25037836SJohn.Forte@Sun.COM 	}
25049585STim.Szeto@Sun.COM 
25059585STim.Szeto@Sun.COM 	if (wcd) {
25069585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
25079585STim.Szeto@Sun.COM 		    SL_SAVED_WRITE_CACHE_DISABLE;
25089585STim.Szeto@Sun.COM 	}
25099585STim.Szeto@Sun.COM 
25109585STim.Szeto@Sun.COM 	/* we're only loading the metadata */
25119585STim.Szeto@Sun.COM 	if (!no_register) {
25129585STim.Szeto@Sun.COM 		ret = sbd_populate_and_register_lu(sl, err_ret);
251310725SJohn.Forte@Sun.COM 		if (ret) {
25149585STim.Szeto@Sun.COM 			goto sim_err_out;
251510725SJohn.Forte@Sun.COM 		}
25169585STim.Szeto@Sun.COM 		atomic_add_32(&sbd_lu_count, 1);
25179585STim.Szeto@Sun.COM 	}
25189585STim.Szeto@Sun.COM 
25199585STim.Szeto@Sun.COM 	bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
25209585STim.Szeto@Sun.COM 	sl->sl_trans_op = SL_OP_NONE;
252110725SJohn.Forte@Sun.COM 
25229585STim.Szeto@Sun.COM 	if (sli) {
25239585STim.Szeto@Sun.COM 		kmem_free(sli, sli->sli_sms_header.sms_size);
25249585STim.Szeto@Sun.COM 		sli = NULL;
25259585STim.Szeto@Sun.COM 	}
25269585STim.Szeto@Sun.COM 	if (sli_buf_copy) {
25279585STim.Szeto@Sun.COM 		kmem_free(sli_buf_copy, sli_buf_sz + 1);
25289585STim.Szeto@Sun.COM 		sli_buf_copy = NULL;
25299585STim.Szeto@Sun.COM 	}
253010725SJohn.Forte@Sun.COM 	if (no_register && !standby) {
25319585STim.Szeto@Sun.COM 		*slr = sl;
25329585STim.Szeto@Sun.COM 	}
253310725SJohn.Forte@Sun.COM 
253410725SJohn.Forte@Sun.COM 	/*
253510725SJohn.Forte@Sun.COM 	 * if this was imported from standby, set the access state
253610725SJohn.Forte@Sun.COM 	 * to active.
253710725SJohn.Forte@Sun.COM 	 */
253810725SJohn.Forte@Sun.COM 	if (standby) {
253910725SJohn.Forte@Sun.COM 		sbd_it_data_t *it;
254010725SJohn.Forte@Sun.COM 		mutex_enter(&sl->sl_lock);
254110725SJohn.Forte@Sun.COM 		sl->sl_access_state = SBD_LU_ACTIVE;
254210725SJohn.Forte@Sun.COM 		for (it = sl->sl_it_list; it != NULL;
254310725SJohn.Forte@Sun.COM 		    it = it->sbd_it_next) {
254410725SJohn.Forte@Sun.COM 			it->sbd_it_ua_conditions |=
254510725SJohn.Forte@Sun.COM 			    SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
254610725SJohn.Forte@Sun.COM 			it->sbd_it_ua_conditions |= SBD_UA_POR;
254712202SNattuvetty.Bhavyan@Sun.COM 			it->sbd_it_flags |=  SBD_IT_PGR_CHECK_FLAG;
254810725SJohn.Forte@Sun.COM 		}
254910725SJohn.Forte@Sun.COM 		mutex_exit(&sl->sl_lock);
255010725SJohn.Forte@Sun.COM 		/* call set access state */
255110725SJohn.Forte@Sun.COM 		stret = stmf_set_lu_access(lu, STMF_LU_ACTIVE);
255210725SJohn.Forte@Sun.COM 		if (stret != STMF_SUCCESS) {
255310725SJohn.Forte@Sun.COM 			*err_ret = SBD_RET_ACCESS_STATE_FAILED;
255410725SJohn.Forte@Sun.COM 			sl->sl_access_state = SBD_LU_STANDBY;
255510725SJohn.Forte@Sun.COM 			goto sim_err_out;
255610725SJohn.Forte@Sun.COM 		}
255710725SJohn.Forte@Sun.COM 		if (sl->sl_alias) {
255810725SJohn.Forte@Sun.COM 			lu->lu_alias = sl->sl_alias;
255910725SJohn.Forte@Sun.COM 		} else {
256010725SJohn.Forte@Sun.COM 			lu->lu_alias = sl->sl_name;
256110725SJohn.Forte@Sun.COM 		}
256210725SJohn.Forte@Sun.COM 	}
256310725SJohn.Forte@Sun.COM 	sl->sl_access_state = SBD_LU_ACTIVE;
25649585STim.Szeto@Sun.COM 	return (0);
25659585STim.Szeto@Sun.COM 
25669585STim.Szeto@Sun.COM sim_err_out:
25679585STim.Szeto@Sun.COM 	if (sli) {
25689585STim.Szeto@Sun.COM 		kmem_free(sli, sli->sli_sms_header.sms_size);
25699585STim.Szeto@Sun.COM 		sli = NULL;
25709585STim.Szeto@Sun.COM 	}
25719585STim.Szeto@Sun.COM 	if (sli_buf_copy) {
25729585STim.Szeto@Sun.COM 		kmem_free(sli_buf_copy, sli_buf_sz + 1);
25739585STim.Szeto@Sun.COM 		sli_buf_copy = NULL;
25749585STim.Szeto@Sun.COM 	}
257510725SJohn.Forte@Sun.COM 
257610725SJohn.Forte@Sun.COM 	if (standby) {
257710725SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
257810725SJohn.Forte@Sun.COM 		sl->sl_trans_op = SL_OP_NONE;
257910725SJohn.Forte@Sun.COM 		return (EIO);
258010725SJohn.Forte@Sun.COM 	} else {
258110725SJohn.Forte@Sun.COM 		return (sbd_close_delete_lu(sl, ret));
258210725SJohn.Forte@Sun.COM 	}
25839585STim.Szeto@Sun.COM }
25849585STim.Szeto@Sun.COM 
25859585STim.Szeto@Sun.COM int
sbd_modify_lu(sbd_modify_lu_t * mlu,int struct_sz,uint32_t * err_ret)25869585STim.Szeto@Sun.COM sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
25879585STim.Szeto@Sun.COM {
25889585STim.Szeto@Sun.COM 	sbd_lu_t *sl = NULL;
258910113SNattuvetty.Bhavyan@Sun.COM 	uint16_t alias_sz;
25909585STim.Szeto@Sun.COM 	int ret = 0;
25919585STim.Szeto@Sun.COM 	sbd_it_data_t *it;
25929585STim.Szeto@Sun.COM 	sbd_status_t sret;
25939585STim.Szeto@Sun.COM 	uint64_t old_size;
25949585STim.Szeto@Sun.COM 	int modify_unregistered = 0;
25959585STim.Szeto@Sun.COM 	int ua = 0;
25969585STim.Szeto@Sun.COM 	sbd_import_lu_t *ilu;
25979585STim.Szeto@Sun.COM 	stmf_lu_t *lu;
25989585STim.Szeto@Sun.COM 	uint32_t ilu_sz;
25999585STim.Szeto@Sun.COM 	uint32_t sz;
26009585STim.Szeto@Sun.COM 
26019585STim.Szeto@Sun.COM 	sz = struct_sz - sizeof (*mlu) + 8 + 1;
26029585STim.Szeto@Sun.COM 
26039585STim.Szeto@Sun.COM 	/* if there is data in the buf, null terminate it */
26049585STim.Szeto@Sun.COM 	if (struct_sz > sizeof (*mlu)) {
26059585STim.Szeto@Sun.COM 		mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
26069585STim.Szeto@Sun.COM 	}
26079585STim.Szeto@Sun.COM 
26089585STim.Szeto@Sun.COM 	*err_ret = 0;
26099585STim.Szeto@Sun.COM 
26109585STim.Szeto@Sun.COM 	/* Lets validate offsets */
26119585STim.Szeto@Sun.COM 	if (((mlu->mlu_alias_valid) &&
26129585STim.Szeto@Sun.COM 	    (mlu->mlu_alias_off >= sz)) ||
261310113SNattuvetty.Bhavyan@Sun.COM 	    ((mlu->mlu_mgmt_url_valid) &&
261410113SNattuvetty.Bhavyan@Sun.COM 	    (mlu->mlu_mgmt_url_off >= sz)) ||
26159585STim.Szeto@Sun.COM 	    (mlu->mlu_by_fname) &&
26169585STim.Szeto@Sun.COM 	    (mlu->mlu_fname_off >= sz)) {
26179585STim.Szeto@Sun.COM 		return (EINVAL);
26189585STim.Szeto@Sun.COM 	}
26199585STim.Szeto@Sun.COM 
26209585STim.Szeto@Sun.COM 	/*
26219585STim.Szeto@Sun.COM 	 * We'll look for the device but if we don't find it registered,
26229585STim.Szeto@Sun.COM 	 * we'll still try to modify the unregistered device.
26239585STim.Szeto@Sun.COM 	 */
26249585STim.Szeto@Sun.COM 	if (mlu->mlu_by_guid) {
26259585STim.Szeto@Sun.COM 		sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL,
26269585STim.Szeto@Sun.COM 		    SL_OP_MODIFY_LU, &sl);
26279585STim.Szeto@Sun.COM 	} else if (mlu->mlu_by_fname) {
26289585STim.Szeto@Sun.COM 		sret = sbd_find_and_lock_lu(NULL,
26299585STim.Szeto@Sun.COM 		    (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]),
26309585STim.Szeto@Sun.COM 		    SL_OP_MODIFY_LU, &sl);
26319585STim.Szeto@Sun.COM 	} else {
26329585STim.Szeto@Sun.COM 		return (EINVAL);
26339585STim.Szeto@Sun.COM 	}
26349585STim.Szeto@Sun.COM 
26359585STim.Szeto@Sun.COM 
26369585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
26379585STim.Szeto@Sun.COM 		if (sret == SBD_BUSY) {
26389585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_LU_BUSY;
26399585STim.Szeto@Sun.COM 			return (EBUSY);
26409585STim.Szeto@Sun.COM 		} else if (sret != SBD_NOT_FOUND) {
26419585STim.Szeto@Sun.COM 			return (EIO);
26429585STim.Szeto@Sun.COM 		} else if (!mlu->mlu_by_fname) {
26439585STim.Szeto@Sun.COM 			return (EINVAL);
26449585STim.Szeto@Sun.COM 		}
26459585STim.Szeto@Sun.COM 		/* Okay, try to import the device */
26469585STim.Szeto@Sun.COM 		struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off]))
26479585STim.Szeto@Sun.COM 		    + 1);
26489585STim.Szeto@Sun.COM 		struct_sz += sizeof (sbd_import_lu_t) - 8;
26499585STim.Szeto@Sun.COM 		ilu_sz = struct_sz;
26509585STim.Szeto@Sun.COM 		ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
26519585STim.Szeto@Sun.COM 		ilu->ilu_struct_size = struct_sz;
26529585STim.Szeto@Sun.COM 		(void) strcpy(ilu->ilu_meta_fname,
26539585STim.Szeto@Sun.COM 		    &(mlu->mlu_buf[mlu->mlu_fname_off]));
26549585STim.Szeto@Sun.COM 		ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl);
26559585STim.Szeto@Sun.COM 		kmem_free(ilu, ilu_sz);
26569585STim.Szeto@Sun.COM 		if (ret != SBD_SUCCESS) {
26579585STim.Szeto@Sun.COM 			return (ENOENT);
26589585STim.Szeto@Sun.COM 		}
26599585STim.Szeto@Sun.COM 		modify_unregistered = 1;
26609585STim.Szeto@Sun.COM 	}
26619585STim.Szeto@Sun.COM 
266210725SJohn.Forte@Sun.COM 	if (sl->sl_access_state != SBD_LU_ACTIVE) {
266310725SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
266410725SJohn.Forte@Sun.COM 		ret = EINVAL;
266510725SJohn.Forte@Sun.COM 		goto smm_err_out;
266610725SJohn.Forte@Sun.COM 	}
266710725SJohn.Forte@Sun.COM 
26689585STim.Szeto@Sun.COM 	/* check for write cache change */
26699585STim.Szeto@Sun.COM 	if (mlu->mlu_writeback_cache_disable_valid) {
26709585STim.Szeto@Sun.COM 		/* set wce on device */
26719585STim.Szeto@Sun.COM 		sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl);
26729585STim.Szeto@Sun.COM 		if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) {
26739585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
26749585STim.Szeto@Sun.COM 			ret = EFAULT;
26759585STim.Szeto@Sun.COM 			goto smm_err_out;
26769585STim.Szeto@Sun.COM 		}
26779585STim.Szeto@Sun.COM 		mutex_enter(&sl->sl_lock);
26789585STim.Szeto@Sun.COM 		if (!mlu->mlu_writeback_cache_disable) {
26799585STim.Szeto@Sun.COM 			if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
26809585STim.Szeto@Sun.COM 				ua = 1;
26819585STim.Szeto@Sun.COM 				sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
26829585STim.Szeto@Sun.COM 				sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
26839585STim.Szeto@Sun.COM 			}
26849585STim.Szeto@Sun.COM 		} else {
26859585STim.Szeto@Sun.COM 			if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
26869585STim.Szeto@Sun.COM 				ua = 1;
26879585STim.Szeto@Sun.COM 				sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
26889585STim.Szeto@Sun.COM 				sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
26899585STim.Szeto@Sun.COM 			}
26909585STim.Szeto@Sun.COM 		}
26919585STim.Szeto@Sun.COM 		for (it = sl->sl_it_list; ua && it != NULL;
26929585STim.Szeto@Sun.COM 		    it = it->sbd_it_next) {
26939585STim.Szeto@Sun.COM 			it->sbd_it_ua_conditions |=
26949585STim.Szeto@Sun.COM 			    SBD_UA_MODE_PARAMETERS_CHANGED;
26959585STim.Szeto@Sun.COM 		}
26969585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
26979585STim.Szeto@Sun.COM 	}
26989585STim.Szeto@Sun.COM 	ua = 0;
26999585STim.Szeto@Sun.COM 
27009585STim.Szeto@Sun.COM 	if (mlu->mlu_alias_valid) {
27019585STim.Szeto@Sun.COM 		alias_sz = strlen((char *)mlu->mlu_buf +
27029585STim.Szeto@Sun.COM 		    mlu->mlu_alias_off) + 1;
27039585STim.Szeto@Sun.COM 		/*
27049585STim.Szeto@Sun.COM 		 * Use the allocated buffer or alloc a new one.
27059585STim.Szeto@Sun.COM 		 * Don't copy into sl_alias if sl_alias_alloc_size is 0
27069585STim.Szeto@Sun.COM 		 * otherwise or you'll be writing over the data/metadata
27079585STim.Szeto@Sun.COM 		 * filename.
27089585STim.Szeto@Sun.COM 		 */
27099585STim.Szeto@Sun.COM 		mutex_enter(&sl->sl_lock);
27109585STim.Szeto@Sun.COM 		if (sl->sl_alias_alloc_size > 0 &&
27119585STim.Szeto@Sun.COM 		    sl->sl_alias_alloc_size < alias_sz) {
27129585STim.Szeto@Sun.COM 			kmem_free(sl->sl_alias,
27139585STim.Szeto@Sun.COM 			    sl->sl_alias_alloc_size);
27149585STim.Szeto@Sun.COM 			sl->sl_alias_alloc_size = 0;
27159585STim.Szeto@Sun.COM 		}
27169585STim.Szeto@Sun.COM 		if (sl->sl_alias_alloc_size == 0) {
27179585STim.Szeto@Sun.COM 			sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP);
27189585STim.Szeto@Sun.COM 			sl->sl_alias_alloc_size = alias_sz;
27199585STim.Szeto@Sun.COM 		}
27209585STim.Szeto@Sun.COM 		(void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf +
27219585STim.Szeto@Sun.COM 		    mlu->mlu_alias_off);
27229585STim.Szeto@Sun.COM 		lu = sl->sl_lu;
27239585STim.Szeto@Sun.COM 		lu->lu_alias = sl->sl_alias;
27249585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
27259585STim.Szeto@Sun.COM 	}
27269585STim.Szeto@Sun.COM 
272710113SNattuvetty.Bhavyan@Sun.COM 	if (mlu->mlu_mgmt_url_valid) {
272810113SNattuvetty.Bhavyan@Sun.COM 		uint16_t url_sz;
272910113SNattuvetty.Bhavyan@Sun.COM 
273010113SNattuvetty.Bhavyan@Sun.COM 		url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
273110113SNattuvetty.Bhavyan@Sun.COM 		if (url_sz > 0)
273210113SNattuvetty.Bhavyan@Sun.COM 			url_sz++;
273310113SNattuvetty.Bhavyan@Sun.COM 
273410113SNattuvetty.Bhavyan@Sun.COM 		mutex_enter(&sl->sl_lock);
273510113SNattuvetty.Bhavyan@Sun.COM 		if (sl->sl_mgmt_url_alloc_size > 0 &&
273610113SNattuvetty.Bhavyan@Sun.COM 		    (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) {
273710113SNattuvetty.Bhavyan@Sun.COM 			kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
273810113SNattuvetty.Bhavyan@Sun.COM 			sl->sl_mgmt_url = NULL;
273910113SNattuvetty.Bhavyan@Sun.COM 			sl->sl_mgmt_url_alloc_size = 0;
274010113SNattuvetty.Bhavyan@Sun.COM 		}
274110113SNattuvetty.Bhavyan@Sun.COM 		if (url_sz > 0) {
274210113SNattuvetty.Bhavyan@Sun.COM 			if (sl->sl_mgmt_url_alloc_size == 0) {
274310113SNattuvetty.Bhavyan@Sun.COM 				sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
274410113SNattuvetty.Bhavyan@Sun.COM 				sl->sl_mgmt_url_alloc_size = url_sz;
274510113SNattuvetty.Bhavyan@Sun.COM 			}
274610113SNattuvetty.Bhavyan@Sun.COM 			(void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf +
274710113SNattuvetty.Bhavyan@Sun.COM 			    mlu->mlu_mgmt_url_off);
274810113SNattuvetty.Bhavyan@Sun.COM 		}
274910113SNattuvetty.Bhavyan@Sun.COM 		for (it = sl->sl_it_list; it != NULL;
275010113SNattuvetty.Bhavyan@Sun.COM 		    it = it->sbd_it_next) {
275110113SNattuvetty.Bhavyan@Sun.COM 			it->sbd_it_ua_conditions |=
275210113SNattuvetty.Bhavyan@Sun.COM 			    SBD_UA_MODE_PARAMETERS_CHANGED;
275310113SNattuvetty.Bhavyan@Sun.COM 		}
275410113SNattuvetty.Bhavyan@Sun.COM 		mutex_exit(&sl->sl_lock);
275510113SNattuvetty.Bhavyan@Sun.COM 	}
27569585STim.Szeto@Sun.COM 
27579585STim.Szeto@Sun.COM 	if (mlu->mlu_write_protected_valid) {
27589585STim.Szeto@Sun.COM 		mutex_enter(&sl->sl_lock);
27599585STim.Szeto@Sun.COM 		if (mlu->mlu_write_protected) {
27609585STim.Szeto@Sun.COM 			if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) {
27619585STim.Szeto@Sun.COM 				ua = 1;
27629585STim.Szeto@Sun.COM 				sl->sl_flags |= SL_WRITE_PROTECTED;
27639585STim.Szeto@Sun.COM 			}
27649585STim.Szeto@Sun.COM 		} else {
27659585STim.Szeto@Sun.COM 			if (sl->sl_flags & SL_WRITE_PROTECTED) {
27669585STim.Szeto@Sun.COM 				ua = 1;
27679585STim.Szeto@Sun.COM 				sl->sl_flags &= ~SL_WRITE_PROTECTED;
27689585STim.Szeto@Sun.COM 			}
27699585STim.Szeto@Sun.COM 		}
27709585STim.Szeto@Sun.COM 		for (it = sl->sl_it_list; ua && it != NULL;
27719585STim.Szeto@Sun.COM 		    it = it->sbd_it_next) {
27729585STim.Szeto@Sun.COM 			it->sbd_it_ua_conditions |=
27739585STim.Szeto@Sun.COM 			    SBD_UA_MODE_PARAMETERS_CHANGED;
27749585STim.Szeto@Sun.COM 		}
27759585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
27769585STim.Szeto@Sun.COM 	}
27779585STim.Szeto@Sun.COM 
27789585STim.Szeto@Sun.COM 	if (mlu->mlu_lu_size_valid) {
27799585STim.Szeto@Sun.COM 		/*
27809585STim.Szeto@Sun.COM 		 * validate lu size and set
27819585STim.Szeto@Sun.COM 		 * For open file only (registered lu)
27829585STim.Szeto@Sun.COM 		 */
27839585STim.Szeto@Sun.COM 		mutex_enter(&sl->sl_lock);
27849585STim.Szeto@Sun.COM 		old_size = sl->sl_lu_size;
27859585STim.Szeto@Sun.COM 		sl->sl_lu_size = mlu->mlu_lu_size;
27869585STim.Szeto@Sun.COM 		mutex_exit(&sl->sl_lock);
27879585STim.Szeto@Sun.COM 		ret = sbd_open_data_file(sl, err_ret, 1, 1, 1);
27889585STim.Szeto@Sun.COM 		if (ret) {
27899585STim.Szeto@Sun.COM 			mutex_enter(&sl->sl_lock);
27909585STim.Szeto@Sun.COM 			sl->sl_lu_size = old_size;
27919585STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_lock);
27929585STim.Szeto@Sun.COM 			goto smm_err_out;
27939585STim.Szeto@Sun.COM 		}
27949585STim.Szeto@Sun.COM 		if (old_size != mlu->mlu_lu_size) {
27959585STim.Szeto@Sun.COM 			mutex_enter(&sl->sl_lock);
27969585STim.Szeto@Sun.COM 			for (it = sl->sl_it_list; it != NULL;
27979585STim.Szeto@Sun.COM 			    it = it->sbd_it_next) {
27989585STim.Szeto@Sun.COM 				it->sbd_it_ua_conditions |=
27999585STim.Szeto@Sun.COM 				    SBD_UA_CAPACITY_CHANGED;
28009585STim.Szeto@Sun.COM 			}
28019585STim.Szeto@Sun.COM 			mutex_exit(&sl->sl_lock);
28029585STim.Szeto@Sun.COM 		}
28039585STim.Szeto@Sun.COM 	}
28049585STim.Szeto@Sun.COM 
28059585STim.Szeto@Sun.COM 	if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
28069585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_META_CREATION_FAILED;
28079585STim.Szeto@Sun.COM 		ret = EIO;
28089585STim.Szeto@Sun.COM 	}
28099585STim.Szeto@Sun.COM 
28109585STim.Szeto@Sun.COM smm_err_out:
28119585STim.Szeto@Sun.COM 	if (modify_unregistered) {
28129585STim.Szeto@Sun.COM 		(void) sbd_close_delete_lu(sl, 0);
28139585STim.Szeto@Sun.COM 	} else {
28149585STim.Szeto@Sun.COM 		sl->sl_trans_op = SL_OP_NONE;
28159585STim.Szeto@Sun.COM 	}
28169585STim.Szeto@Sun.COM 	return (ret);
28179585STim.Szeto@Sun.COM }
28189585STim.Szeto@Sun.COM 
281911103SJohn.Forte@Sun.COM int
sbd_set_global_props(sbd_global_props_t * mlu,int struct_sz,uint32_t * err_ret)282011103SJohn.Forte@Sun.COM sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
282111103SJohn.Forte@Sun.COM     uint32_t *err_ret)
282211103SJohn.Forte@Sun.COM {
282311103SJohn.Forte@Sun.COM 	sbd_lu_t *sl = NULL;
282411103SJohn.Forte@Sun.COM 	int ret = 0;
282511103SJohn.Forte@Sun.COM 	sbd_it_data_t *it;
282611103SJohn.Forte@Sun.COM 	uint32_t sz;
282711103SJohn.Forte@Sun.COM 
282811103SJohn.Forte@Sun.COM 	sz = struct_sz - sizeof (*mlu) + 8 + 1;
282911103SJohn.Forte@Sun.COM 
283011103SJohn.Forte@Sun.COM 	/* if there is data in the buf, null terminate it */
283111103SJohn.Forte@Sun.COM 	if (struct_sz > sizeof (*mlu)) {
283211103SJohn.Forte@Sun.COM 		mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
283311103SJohn.Forte@Sun.COM 	}
283411103SJohn.Forte@Sun.COM 
283511103SJohn.Forte@Sun.COM 	*err_ret = 0;
283611103SJohn.Forte@Sun.COM 
283711103SJohn.Forte@Sun.COM 	/* Lets validate offsets */
283811103SJohn.Forte@Sun.COM 	if (((mlu->mlu_mgmt_url_valid) &&
283911103SJohn.Forte@Sun.COM 	    (mlu->mlu_mgmt_url_off >= sz))) {
284011103SJohn.Forte@Sun.COM 		return (EINVAL);
284111103SJohn.Forte@Sun.COM 	}
284211103SJohn.Forte@Sun.COM 
284311103SJohn.Forte@Sun.COM 	if (mlu->mlu_mgmt_url_valid) {
284411103SJohn.Forte@Sun.COM 		uint16_t url_sz;
284511103SJohn.Forte@Sun.COM 
284611103SJohn.Forte@Sun.COM 		url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
284711103SJohn.Forte@Sun.COM 		if (url_sz > 0)
284811103SJohn.Forte@Sun.COM 			url_sz++;
284911103SJohn.Forte@Sun.COM 
285011103SJohn.Forte@Sun.COM 		rw_enter(&sbd_global_prop_lock, RW_WRITER);
285111103SJohn.Forte@Sun.COM 		if (sbd_mgmt_url_alloc_size > 0 &&
285211103SJohn.Forte@Sun.COM 		    (url_sz == 0 || sbd_mgmt_url_alloc_size < url_sz)) {
285311103SJohn.Forte@Sun.COM 			kmem_free(sbd_mgmt_url, sbd_mgmt_url_alloc_size);
285411103SJohn.Forte@Sun.COM 			sbd_mgmt_url = NULL;
285511103SJohn.Forte@Sun.COM 			sbd_mgmt_url_alloc_size = 0;
285611103SJohn.Forte@Sun.COM 		}
285711103SJohn.Forte@Sun.COM 		if (url_sz > 0) {
285811103SJohn.Forte@Sun.COM 			if (sbd_mgmt_url_alloc_size == 0) {
285911103SJohn.Forte@Sun.COM 				sbd_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
286011103SJohn.Forte@Sun.COM 				sbd_mgmt_url_alloc_size = url_sz;
286111103SJohn.Forte@Sun.COM 			}
286211103SJohn.Forte@Sun.COM 			(void) strcpy(sbd_mgmt_url, (char *)mlu->mlu_buf +
286311103SJohn.Forte@Sun.COM 			    mlu->mlu_mgmt_url_off);
286411103SJohn.Forte@Sun.COM 		}
286511103SJohn.Forte@Sun.COM 		/*
286611103SJohn.Forte@Sun.COM 		 * check each lu to determine whether a UA is needed.
286711103SJohn.Forte@Sun.COM 		 */
286811103SJohn.Forte@Sun.COM 		mutex_enter(&sbd_lock);
286911103SJohn.Forte@Sun.COM 		for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
287011103SJohn.Forte@Sun.COM 			if (sl->sl_mgmt_url) {
287111103SJohn.Forte@Sun.COM 				continue;
287211103SJohn.Forte@Sun.COM 			}
287311103SJohn.Forte@Sun.COM 			mutex_enter(&sl->sl_lock);
287411103SJohn.Forte@Sun.COM 			for (it = sl->sl_it_list; it != NULL;
287511103SJohn.Forte@Sun.COM 			    it = it->sbd_it_next) {
287611103SJohn.Forte@Sun.COM 				it->sbd_it_ua_conditions |=
287711103SJohn.Forte@Sun.COM 				    SBD_UA_MODE_PARAMETERS_CHANGED;
287811103SJohn.Forte@Sun.COM 			}
287911103SJohn.Forte@Sun.COM 			mutex_exit(&sl->sl_lock);
288011103SJohn.Forte@Sun.COM 		}
288111103SJohn.Forte@Sun.COM 		mutex_exit(&sbd_lock);
288211103SJohn.Forte@Sun.COM 		rw_exit(&sbd_global_prop_lock);
288311103SJohn.Forte@Sun.COM 	}
288411103SJohn.Forte@Sun.COM 	return (ret);
288511103SJohn.Forte@Sun.COM }
288611103SJohn.Forte@Sun.COM 
28879585STim.Szeto@Sun.COM /* ARGSUSED */
28889585STim.Szeto@Sun.COM int
sbd_delete_locked_lu(sbd_lu_t * sl,uint32_t * err_ret,stmf_state_change_info_t * ssi)28899585STim.Szeto@Sun.COM sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret,
28909585STim.Szeto@Sun.COM     stmf_state_change_info_t *ssi)
28919585STim.Szeto@Sun.COM {
28929585STim.Szeto@Sun.COM 	int i;
289311107SWayne.Ihde@Sun.COM 	stmf_status_t ret;
28949585STim.Szeto@Sun.COM 
28959585STim.Szeto@Sun.COM 	if ((sl->sl_state == STMF_STATE_OFFLINE) &&
28969585STim.Szeto@Sun.COM 	    !sl->sl_state_not_acked) {
28979585STim.Szeto@Sun.COM 		goto sdl_do_dereg;
28989585STim.Szeto@Sun.COM 	}
28999585STim.Szeto@Sun.COM 
29009585STim.Szeto@Sun.COM 	if ((sl->sl_state != STMF_STATE_ONLINE) ||
29019585STim.Szeto@Sun.COM 	    sl->sl_state_not_acked) {
29029585STim.Szeto@Sun.COM 		return (EBUSY);
29039585STim.Szeto@Sun.COM 	}
290411107SWayne.Ihde@Sun.COM 
290511107SWayne.Ihde@Sun.COM 	ret = stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi);
290611107SWayne.Ihde@Sun.COM 	if ((ret != STMF_SUCCESS) && (ret != STMF_ALREADY)) {
29079585STim.Szeto@Sun.COM 		return (EBUSY);
29089585STim.Szeto@Sun.COM 	}
29099585STim.Szeto@Sun.COM 
29109585STim.Szeto@Sun.COM 	for (i = 0; i < 500; i++) {
291111107SWayne.Ihde@Sun.COM 		if ((sl->sl_state == STMF_STATE_OFFLINE) &&
291211107SWayne.Ihde@Sun.COM 		    !sl->sl_state_not_acked) {
291311107SWayne.Ihde@Sun.COM 			goto sdl_do_dereg;
291411107SWayne.Ihde@Sun.COM 		}
29159585STim.Szeto@Sun.COM 		delay(drv_usectohz(10000));
29169585STim.Szeto@Sun.COM 	}
29179585STim.Szeto@Sun.COM 	return (EBUSY);
291811107SWayne.Ihde@Sun.COM 
29199585STim.Szeto@Sun.COM sdl_do_dereg:;
29209585STim.Szeto@Sun.COM 	if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS)
29219585STim.Szeto@Sun.COM 		return (EBUSY);
29229585STim.Szeto@Sun.COM 	atomic_add_32(&sbd_lu_count, -1);
29239585STim.Szeto@Sun.COM 
29249585STim.Szeto@Sun.COM 	return (sbd_close_delete_lu(sl, 0));
29259585STim.Szeto@Sun.COM }
29269585STim.Szeto@Sun.COM 
29279585STim.Szeto@Sun.COM int
sbd_delete_lu(sbd_delete_lu_t * dlu,int struct_sz,uint32_t * err_ret)29289585STim.Szeto@Sun.COM sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret)
29299585STim.Szeto@Sun.COM {
29309585STim.Szeto@Sun.COM 	sbd_lu_t *sl;
29319585STim.Szeto@Sun.COM 	sbd_status_t sret;
29329585STim.Szeto@Sun.COM 	stmf_state_change_info_t ssi;
29339585STim.Szeto@Sun.COM 	int ret;
29349585STim.Szeto@Sun.COM 
29359585STim.Szeto@Sun.COM 	if (dlu->dlu_by_meta_name) {
29369585STim.Szeto@Sun.COM 		((char *)dlu)[struct_sz - 1] = 0;
29379585STim.Szeto@Sun.COM 		sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name,
29389585STim.Szeto@Sun.COM 		    SL_OP_DELETE_LU, &sl);
29399585STim.Szeto@Sun.COM 	} else {
29409585STim.Szeto@Sun.COM 		sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL,
29419585STim.Szeto@Sun.COM 		    SL_OP_DELETE_LU, &sl);
29429585STim.Szeto@Sun.COM 	}
29439585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
29449585STim.Szeto@Sun.COM 		if (sret == SBD_BUSY) {
29459585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_LU_BUSY;
29469585STim.Szeto@Sun.COM 			return (EBUSY);
29479585STim.Szeto@Sun.COM 		} else if (sret == SBD_NOT_FOUND) {
29489585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_NOT_FOUND;
29499585STim.Szeto@Sun.COM 			return (ENOENT);
29509585STim.Szeto@Sun.COM 		}
29519585STim.Szeto@Sun.COM 		return (EIO);
29529585STim.Szeto@Sun.COM 	}
29539585STim.Szeto@Sun.COM 
29549585STim.Szeto@Sun.COM 	ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
29559585STim.Szeto@Sun.COM 	ssi.st_additional_info = "sbd_delete_lu call (ioctl)";
29569585STim.Szeto@Sun.COM 	ret = sbd_delete_locked_lu(sl, err_ret, &ssi);
29579585STim.Szeto@Sun.COM 
29589585STim.Szeto@Sun.COM 	if (ret) {
29599585STim.Szeto@Sun.COM 		/* Once its locked, no need to grab mutex again */
29609585STim.Szeto@Sun.COM 		sl->sl_trans_op = SL_OP_NONE;
29619585STim.Szeto@Sun.COM 	}
29629585STim.Szeto@Sun.COM 	return (ret);
29639585STim.Szeto@Sun.COM }
29649585STim.Szeto@Sun.COM 
29659585STim.Szeto@Sun.COM sbd_status_t
sbd_data_read(sbd_lu_t * sl,struct scsi_task * task,uint64_t offset,uint64_t size,uint8_t * buf)296611773STim.Szeto@Sun.COM sbd_data_read(sbd_lu_t *sl, struct scsi_task *task,
296711773STim.Szeto@Sun.COM     uint64_t offset, uint64_t size, uint8_t *buf)
29689585STim.Szeto@Sun.COM {
29699585STim.Szeto@Sun.COM 	int ret;
29709585STim.Szeto@Sun.COM 	long resid;
297111773STim.Szeto@Sun.COM 	hrtime_t xfer_start, xfer_done;
29729585STim.Szeto@Sun.COM 
29739585STim.Szeto@Sun.COM 	if ((offset + size) > sl->sl_lu_size) {
29749585STim.Szeto@Sun.COM 		return (SBD_IO_PAST_EOF);
29759585STim.Szeto@Sun.COM 	}
29769585STim.Szeto@Sun.COM 
29779585STim.Szeto@Sun.COM 	offset += sl->sl_data_offset;
29789585STim.Szeto@Sun.COM 
29799585STim.Szeto@Sun.COM 	if ((offset + size) > sl->sl_data_readable_size) {
29809585STim.Szeto@Sun.COM 		uint64_t store_end;
29819585STim.Szeto@Sun.COM 		if (offset > sl->sl_data_readable_size) {
29829585STim.Szeto@Sun.COM 			bzero(buf, size);
29839585STim.Szeto@Sun.COM 			return (SBD_SUCCESS);
29849585STim.Szeto@Sun.COM 		}
29859585STim.Szeto@Sun.COM 		store_end = sl->sl_data_readable_size - offset;
29869585STim.Szeto@Sun.COM 		bzero(buf + store_end, size - store_end);
29879585STim.Szeto@Sun.COM 		size = store_end;
29889585STim.Szeto@Sun.COM 	}
29899585STim.Szeto@Sun.COM 
299011773STim.Szeto@Sun.COM 	xfer_start = gethrtime();
299111773STim.Szeto@Sun.COM 	stmf_lu_xfer_start(task);
299211773STim.Szeto@Sun.COM 	DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
299311773STim.Szeto@Sun.COM 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
299411773STim.Szeto@Sun.COM 	    scsi_task_t *, task);
29959585STim.Szeto@Sun.COM 
299610725SJohn.Forte@Sun.COM 	/*
299710725SJohn.Forte@Sun.COM 	 * Don't proceed if the device has been closed
299810725SJohn.Forte@Sun.COM 	 * This can occur on an access state change to standby or
299910725SJohn.Forte@Sun.COM 	 * a delete. The writer lock is acquired before closing the
300010725SJohn.Forte@Sun.COM 	 * lu.
300110725SJohn.Forte@Sun.COM 	 */
300210725SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_access_state_lock, RW_READER);
300310725SJohn.Forte@Sun.COM 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
300410725SJohn.Forte@Sun.COM 		rw_exit(&sl->sl_access_state_lock);
300510725SJohn.Forte@Sun.COM 		return (SBD_FAILURE);
300610725SJohn.Forte@Sun.COM 	}
30079585STim.Szeto@Sun.COM 	ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
30089585STim.Szeto@Sun.COM 	    (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(),
30099585STim.Szeto@Sun.COM 	    &resid);
301010725SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_access_state_lock);
30119585STim.Szeto@Sun.COM 
301211773STim.Szeto@Sun.COM 	xfer_done = gethrtime() - xfer_start;
301311773STim.Szeto@Sun.COM 	stmf_lu_xfer_done(task, B_TRUE /* read */, size, xfer_done);
301411773STim.Szeto@Sun.COM 	DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
30159585STim.Szeto@Sun.COM 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
301611773STim.Szeto@Sun.COM 	    int, ret, scsi_task_t *, task);
30179585STim.Szeto@Sun.COM 
30189585STim.Szeto@Sun.COM over_sl_data_read:
30199585STim.Szeto@Sun.COM 	if (ret || resid) {
30209585STim.Szeto@Sun.COM 		stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret,
30219585STim.Szeto@Sun.COM 		    resid);
30229585STim.Szeto@Sun.COM 		return (SBD_FAILURE);
30239585STim.Szeto@Sun.COM 	}
30249585STim.Szeto@Sun.COM 
30259585STim.Szeto@Sun.COM 	return (SBD_SUCCESS);
30269585STim.Szeto@Sun.COM }
30279585STim.Szeto@Sun.COM 
30289585STim.Szeto@Sun.COM sbd_status_t
sbd_data_write(sbd_lu_t * sl,struct scsi_task * task,uint64_t offset,uint64_t size,uint8_t * buf)302911773STim.Szeto@Sun.COM sbd_data_write(sbd_lu_t *sl, struct scsi_task *task,
303011773STim.Szeto@Sun.COM     uint64_t offset, uint64_t size, uint8_t *buf)
30319585STim.Szeto@Sun.COM {
30329585STim.Szeto@Sun.COM 	int ret;
30339585STim.Szeto@Sun.COM 	long resid;
30349585STim.Szeto@Sun.COM 	sbd_status_t sret = SBD_SUCCESS;
30359585STim.Szeto@Sun.COM 	int ioflag;
303611773STim.Szeto@Sun.COM 	hrtime_t xfer_start, xfer_done;
30379585STim.Szeto@Sun.COM 
30389585STim.Szeto@Sun.COM 	if ((offset + size) > sl->sl_lu_size) {
30399585STim.Szeto@Sun.COM 		return (SBD_IO_PAST_EOF);
30407836SJohn.Forte@Sun.COM 	}
30419585STim.Szeto@Sun.COM 
30429585STim.Szeto@Sun.COM 	offset += sl->sl_data_offset;
30439585STim.Szeto@Sun.COM 
30449585STim.Szeto@Sun.COM 	if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
30459585STim.Szeto@Sun.COM 	    (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
30469585STim.Szeto@Sun.COM 		ioflag = FSYNC;
30479585STim.Szeto@Sun.COM 	} else {
30489585STim.Szeto@Sun.COM 		ioflag = 0;
30499585STim.Szeto@Sun.COM 	}
30509585STim.Szeto@Sun.COM 
305111773STim.Szeto@Sun.COM 	xfer_start = gethrtime();
305211773STim.Szeto@Sun.COM 	stmf_lu_xfer_start(task);
305311773STim.Szeto@Sun.COM 	DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
305411773STim.Szeto@Sun.COM 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
305511773STim.Szeto@Sun.COM 	    scsi_task_t *, task);
30569585STim.Szeto@Sun.COM 
305710725SJohn.Forte@Sun.COM 	/*
305810725SJohn.Forte@Sun.COM 	 * Don't proceed if the device has been closed
305910725SJohn.Forte@Sun.COM 	 * This can occur on an access state change to standby or
306010725SJohn.Forte@Sun.COM 	 * a delete. The writer lock is acquired before closing the
306110725SJohn.Forte@Sun.COM 	 * lu.
306210725SJohn.Forte@Sun.COM 	 */
306310725SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_access_state_lock, RW_READER);
306410725SJohn.Forte@Sun.COM 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
306510725SJohn.Forte@Sun.COM 		rw_exit(&sl->sl_access_state_lock);
306610725SJohn.Forte@Sun.COM 		return (SBD_FAILURE);
306710725SJohn.Forte@Sun.COM 	}
30689585STim.Szeto@Sun.COM 	ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
30699585STim.Szeto@Sun.COM 	    (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(),
30709585STim.Szeto@Sun.COM 	    &resid);
307110725SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_access_state_lock);
30729585STim.Szeto@Sun.COM 
307311773STim.Szeto@Sun.COM 	xfer_done = gethrtime() - xfer_start;
307411773STim.Szeto@Sun.COM 	stmf_lu_xfer_done(task, B_FALSE /* write */, size, xfer_done);
307511773STim.Szeto@Sun.COM 	DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
30769585STim.Szeto@Sun.COM 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
307711773STim.Szeto@Sun.COM 	    int, ret, scsi_task_t *, task);
30789585STim.Szeto@Sun.COM 
30799585STim.Szeto@Sun.COM 	if ((ret == 0) && (resid == 0) &&
30809585STim.Szeto@Sun.COM 	    (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
30819585STim.Szeto@Sun.COM 	    (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
30829585STim.Szeto@Sun.COM 		sret = sbd_flush_data_cache(sl, 1);
30839585STim.Szeto@Sun.COM 	}
30849585STim.Szeto@Sun.COM over_sl_data_write:
30859585STim.Szeto@Sun.COM 
30869585STim.Szeto@Sun.COM 	if ((ret || resid) || (sret != SBD_SUCCESS)) {
30879585STim.Szeto@Sun.COM 		return (SBD_FAILURE);
30889585STim.Szeto@Sun.COM 	} else if ((offset + size) > sl->sl_data_readable_size) {
30899585STim.Szeto@Sun.COM 		uint64_t old_size, new_size;
30909585STim.Szeto@Sun.COM 
30919585STim.Szeto@Sun.COM 		do {
30929585STim.Szeto@Sun.COM 			old_size = sl->sl_data_readable_size;
30939585STim.Szeto@Sun.COM 			if ((offset + size) <= old_size)
30949585STim.Szeto@Sun.COM 				break;
30959585STim.Szeto@Sun.COM 			new_size = offset + size;
30969585STim.Szeto@Sun.COM 		} while (atomic_cas_64(&sl->sl_data_readable_size, old_size,
30979585STim.Szeto@Sun.COM 		    new_size) != old_size);
30989585STim.Szeto@Sun.COM 	}
30999585STim.Szeto@Sun.COM 
31009585STim.Szeto@Sun.COM 	return (SBD_SUCCESS);
31019585STim.Szeto@Sun.COM }
31029585STim.Szeto@Sun.COM 
31039585STim.Szeto@Sun.COM int
sbd_get_global_props(sbd_global_props_t * oslp,uint32_t oslp_sz,uint32_t * err_ret)310411103SJohn.Forte@Sun.COM sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
310511103SJohn.Forte@Sun.COM     uint32_t *err_ret)
310611103SJohn.Forte@Sun.COM {
310711103SJohn.Forte@Sun.COM 	uint32_t sz = 0;
310811103SJohn.Forte@Sun.COM 	uint16_t off;
310911103SJohn.Forte@Sun.COM 
311011103SJohn.Forte@Sun.COM 	rw_enter(&sbd_global_prop_lock, RW_READER);
311111103SJohn.Forte@Sun.COM 	if (sbd_mgmt_url) {
311211103SJohn.Forte@Sun.COM 		sz += strlen(sbd_mgmt_url) + 1;
311311103SJohn.Forte@Sun.COM 	}
311411103SJohn.Forte@Sun.COM 	bzero(oslp, sizeof (*oslp) - 8);
311511103SJohn.Forte@Sun.COM 	oslp->mlu_buf_size_needed = sz;
311611103SJohn.Forte@Sun.COM 
311711103SJohn.Forte@Sun.COM 	if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
311811103SJohn.Forte@Sun.COM 		*err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
311911103SJohn.Forte@Sun.COM 		rw_exit(&sbd_global_prop_lock);
312011103SJohn.Forte@Sun.COM 		return (ENOMEM);
312111103SJohn.Forte@Sun.COM 	}
312211103SJohn.Forte@Sun.COM 
312311103SJohn.Forte@Sun.COM 	off = 0;
312411103SJohn.Forte@Sun.COM 	if (sbd_mgmt_url) {
312511103SJohn.Forte@Sun.COM 		oslp->mlu_mgmt_url_valid = 1;
312611103SJohn.Forte@Sun.COM 		oslp->mlu_mgmt_url_off = off;
312711103SJohn.Forte@Sun.COM 		(void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
312811103SJohn.Forte@Sun.COM 		off += strlen(sbd_mgmt_url) + 1;
312911103SJohn.Forte@Sun.COM 	}
313011103SJohn.Forte@Sun.COM 
313111103SJohn.Forte@Sun.COM 	rw_exit(&sbd_global_prop_lock);
313211103SJohn.Forte@Sun.COM 	return (0);
313311103SJohn.Forte@Sun.COM }
313411103SJohn.Forte@Sun.COM 
313511103SJohn.Forte@Sun.COM int
sbd_get_lu_props(sbd_lu_props_t * islp,uint32_t islp_sz,sbd_lu_props_t * oslp,uint32_t oslp_sz,uint32_t * err_ret)31369585STim.Szeto@Sun.COM sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
31379585STim.Szeto@Sun.COM     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
31389585STim.Szeto@Sun.COM {
31399585STim.Szeto@Sun.COM 	sbd_status_t sret;
31409585STim.Szeto@Sun.COM 	sbd_lu_t *sl = NULL;
31419585STim.Szeto@Sun.COM 	uint32_t sz;
31429585STim.Szeto@Sun.COM 	uint16_t off;
31439585STim.Szeto@Sun.COM 
31449585STim.Szeto@Sun.COM 	if (islp->slp_input_guid) {
31459585STim.Szeto@Sun.COM 		sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
31469585STim.Szeto@Sun.COM 		    SL_OP_LU_PROPS, &sl);
31479585STim.Szeto@Sun.COM 	} else {
31489585STim.Szeto@Sun.COM 		((char *)islp)[islp_sz - 1] = 0;
31499585STim.Szeto@Sun.COM 		sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
31509585STim.Szeto@Sun.COM 		    SL_OP_LU_PROPS, &sl);
31519585STim.Szeto@Sun.COM 	}
31529585STim.Szeto@Sun.COM 	if (sret != SBD_SUCCESS) {
31539585STim.Szeto@Sun.COM 		if (sret == SBD_BUSY) {
31549585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_LU_BUSY;
31559585STim.Szeto@Sun.COM 			return (EBUSY);
31569585STim.Szeto@Sun.COM 		} else if (sret == SBD_NOT_FOUND) {
31579585STim.Szeto@Sun.COM 			*err_ret = SBD_RET_NOT_FOUND;
31589585STim.Szeto@Sun.COM 			return (ENOENT);
31599585STim.Szeto@Sun.COM 		}
31609585STim.Szeto@Sun.COM 		return (EIO);
31619585STim.Szeto@Sun.COM 	}
31629585STim.Szeto@Sun.COM 
31639585STim.Szeto@Sun.COM 	sz = strlen(sl->sl_name) + 1;
31649585STim.Szeto@Sun.COM 	if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
31659585STim.Szeto@Sun.COM 		if (sl->sl_data_filename) {
31669585STim.Szeto@Sun.COM 			sz += strlen(sl->sl_data_filename) + 1;
31679585STim.Szeto@Sun.COM 		}
31689585STim.Szeto@Sun.COM 	}
31699585STim.Szeto@Sun.COM 	sz += sl->sl_serial_no_size;
31709585STim.Szeto@Sun.COM 	if (sl->sl_alias) {
31719585STim.Szeto@Sun.COM 		sz += strlen(sl->sl_alias) + 1;
31729585STim.Szeto@Sun.COM 	}
31739585STim.Szeto@Sun.COM 
317411103SJohn.Forte@Sun.COM 	rw_enter(&sbd_global_prop_lock, RW_READER);
317510113SNattuvetty.Bhavyan@Sun.COM 	if (sl->sl_mgmt_url) {
317610113SNattuvetty.Bhavyan@Sun.COM 		sz += strlen(sl->sl_mgmt_url) + 1;
317711103SJohn.Forte@Sun.COM 	} else if (sbd_mgmt_url) {
317811103SJohn.Forte@Sun.COM 		sz += strlen(sbd_mgmt_url) + 1;
317910113SNattuvetty.Bhavyan@Sun.COM 	}
31809585STim.Szeto@Sun.COM 	bzero(oslp, sizeof (*oslp) - 8);
31819585STim.Szeto@Sun.COM 	oslp->slp_buf_size_needed = sz;
31829585STim.Szeto@Sun.COM 
31839585STim.Szeto@Sun.COM 	if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
31849585STim.Szeto@Sun.COM 		sl->sl_trans_op = SL_OP_NONE;
31859585STim.Szeto@Sun.COM 		*err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
318611103SJohn.Forte@Sun.COM 		rw_exit(&sbd_global_prop_lock);
31879585STim.Szeto@Sun.COM 		return (ENOMEM);
31889585STim.Szeto@Sun.COM 	}
31899585STim.Szeto@Sun.COM 
31909585STim.Szeto@Sun.COM 	off = 0;
31919585STim.Szeto@Sun.COM 	(void) strcpy((char *)oslp->slp_buf, sl->sl_name);
31929585STim.Szeto@Sun.COM 	oslp->slp_meta_fname_off = off;
31939585STim.Szeto@Sun.COM 	off += strlen(sl->sl_name) + 1;
31949585STim.Szeto@Sun.COM 	if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
31959585STim.Szeto@Sun.COM 		oslp->slp_meta_fname_valid = 1;
31969585STim.Szeto@Sun.COM 		oslp->slp_separate_meta = 1;
31979585STim.Szeto@Sun.COM 		if (sl->sl_data_filename) {
31989585STim.Szeto@Sun.COM 			oslp->slp_data_fname_valid = 1;
31999585STim.Szeto@Sun.COM 			oslp->slp_data_fname_off = off;
32009585STim.Szeto@Sun.COM 			(void) strcpy((char *)&oslp->slp_buf[off],
32019585STim.Szeto@Sun.COM 			    sl->sl_data_filename);
32029585STim.Szeto@Sun.COM 			off += strlen(sl->sl_data_filename) + 1;
32039585STim.Szeto@Sun.COM 		}
32049585STim.Szeto@Sun.COM 	} else {
32059585STim.Szeto@Sun.COM 		oslp->slp_data_fname_valid = 1;
32069585STim.Szeto@Sun.COM 		oslp->slp_data_fname_off = oslp->slp_meta_fname_off;
32079585STim.Szeto@Sun.COM 		if (sl->sl_flags & SL_ZFS_META) {
32089585STim.Szeto@Sun.COM 			oslp->slp_zfs_meta = 1;
32099585STim.Szeto@Sun.COM 		}
32109585STim.Szeto@Sun.COM 	}
32119585STim.Szeto@Sun.COM 	if (sl->sl_alias) {
32129585STim.Szeto@Sun.COM 		oslp->slp_alias_valid = 1;
32139585STim.Szeto@Sun.COM 		oslp->slp_alias_off = off;
32149585STim.Szeto@Sun.COM 		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
32159585STim.Szeto@Sun.COM 		off += strlen(sl->sl_alias) + 1;
32169585STim.Szeto@Sun.COM 	}
321710113SNattuvetty.Bhavyan@Sun.COM 	if (sl->sl_mgmt_url) {
321810113SNattuvetty.Bhavyan@Sun.COM 		oslp->slp_mgmt_url_valid = 1;
321910113SNattuvetty.Bhavyan@Sun.COM 		oslp->slp_mgmt_url_off = off;
322010113SNattuvetty.Bhavyan@Sun.COM 		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url);
322110113SNattuvetty.Bhavyan@Sun.COM 		off += strlen(sl->sl_mgmt_url) + 1;
322211103SJohn.Forte@Sun.COM 	} else if (sbd_mgmt_url) {
322311103SJohn.Forte@Sun.COM 		oslp->slp_mgmt_url_valid = 1;
322411103SJohn.Forte@Sun.COM 		oslp->slp_mgmt_url_off = off;
322511103SJohn.Forte@Sun.COM 		(void) strcpy((char *)&oslp->slp_buf[off], sbd_mgmt_url);
322611103SJohn.Forte@Sun.COM 		off += strlen(sbd_mgmt_url) + 1;
322710113SNattuvetty.Bhavyan@Sun.COM 	}
32289585STim.Szeto@Sun.COM 	if (sl->sl_serial_no_size) {
32299585STim.Szeto@Sun.COM 		oslp->slp_serial_off = off;
32309585STim.Szeto@Sun.COM 		bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
32319585STim.Szeto@Sun.COM 		    sl->sl_serial_no_size);
32329585STim.Szeto@Sun.COM 		oslp->slp_serial_size = sl->sl_serial_no_size;
32339585STim.Szeto@Sun.COM 		oslp->slp_serial_valid = 1;
32349585STim.Szeto@Sun.COM 		off += sl->sl_serial_no_size;
32359585STim.Szeto@Sun.COM 	}
32369585STim.Szeto@Sun.COM 
32379585STim.Szeto@Sun.COM 	oslp->slp_lu_size = sl->sl_lu_size;
32389585STim.Szeto@Sun.COM 	oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
32399585STim.Szeto@Sun.COM 
324010725SJohn.Forte@Sun.COM 	oslp->slp_access_state = sl->sl_access_state;
324110725SJohn.Forte@Sun.COM 
32429585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_VID_VALID) {
32439585STim.Szeto@Sun.COM 		oslp->slp_lu_vid = 1;
32449585STim.Szeto@Sun.COM 		bcopy(sl->sl_vendor_id, oslp->slp_vid, 8);
32459585STim.Szeto@Sun.COM 	} else {
32469585STim.Szeto@Sun.COM 		bcopy(sbd_vendor_id, oslp->slp_vid, 8);
32479585STim.Szeto@Sun.COM 	}
32489585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_PID_VALID) {
32499585STim.Szeto@Sun.COM 		oslp->slp_lu_pid = 1;
32509585STim.Szeto@Sun.COM 		bcopy(sl->sl_product_id, oslp->slp_pid, 16);
32519585STim.Szeto@Sun.COM 	} else {
32529585STim.Szeto@Sun.COM 		bcopy(sbd_product_id, oslp->slp_pid, 16);
32539585STim.Szeto@Sun.COM 	}
32549585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_REV_VALID) {
32559585STim.Szeto@Sun.COM 		oslp->slp_lu_rev = 1;
32569585STim.Szeto@Sun.COM 		bcopy(sl->sl_revision, oslp->slp_rev, 4);
32579585STim.Szeto@Sun.COM 	} else {
32589585STim.Szeto@Sun.COM 		bcopy(sbd_revision, oslp->slp_rev, 4);
32599585STim.Szeto@Sun.COM 	}
32609585STim.Szeto@Sun.COM 	bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
32619585STim.Szeto@Sun.COM 
32629585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
32639585STim.Szeto@Sun.COM 		oslp->slp_writeback_cache_disable_cur = 1;
32649585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
32659585STim.Szeto@Sun.COM 		oslp->slp_writeback_cache_disable_saved = 1;
32669585STim.Szeto@Sun.COM 	if (sl->sl_flags & SL_WRITE_PROTECTED)
32679585STim.Szeto@Sun.COM 		oslp->slp_write_protected = 1;
32689585STim.Szeto@Sun.COM 
32699585STim.Szeto@Sun.COM 	sl->sl_trans_op = SL_OP_NONE;
32709585STim.Szeto@Sun.COM 
327111103SJohn.Forte@Sun.COM 	rw_exit(&sbd_global_prop_lock);
32729585STim.Szeto@Sun.COM 	return (0);
32739585STim.Szeto@Sun.COM }
32749585STim.Szeto@Sun.COM 
32759585STim.Szeto@Sun.COM char *
sbd_get_zvol_name(sbd_lu_t * sl)32769585STim.Szeto@Sun.COM sbd_get_zvol_name(sbd_lu_t *sl)
32779585STim.Szeto@Sun.COM {
32789585STim.Szeto@Sun.COM 	char *src;
32799585STim.Szeto@Sun.COM 	char *p;
32809585STim.Szeto@Sun.COM 
32819585STim.Szeto@Sun.COM 	if (sl->sl_data_filename)
32829585STim.Szeto@Sun.COM 		src = sl->sl_data_filename;
32839585STim.Szeto@Sun.COM 	else
32849585STim.Szeto@Sun.COM 		src = sl->sl_meta_filename;
32859585STim.Szeto@Sun.COM 	/* There has to be a better way */
32869679STim.Szeto@Sun.COM 	if (SBD_IS_ZVOL(src) != 0) {
32879585STim.Szeto@Sun.COM 		ASSERT(0);
32889585STim.Szeto@Sun.COM 	}
32899585STim.Szeto@Sun.COM 	src += 14;
32909585STim.Szeto@Sun.COM 	if (*src == '/')
32919585STim.Szeto@Sun.COM 		src++;
32929585STim.Szeto@Sun.COM 	p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
32939585STim.Szeto@Sun.COM 	(void) strcpy(p, src);
32949585STim.Szeto@Sun.COM 	return (p);
32959585STim.Szeto@Sun.COM }
32969585STim.Szeto@Sun.COM 
32979679STim.Szeto@Sun.COM /*
32989679STim.Szeto@Sun.COM  * this function creates a local metadata zvol property
32999679STim.Szeto@Sun.COM  */
33009585STim.Szeto@Sun.COM sbd_status_t
sbd_create_zfs_meta_object(sbd_lu_t * sl)33019585STim.Szeto@Sun.COM sbd_create_zfs_meta_object(sbd_lu_t *sl)
33029585STim.Szeto@Sun.COM {
33039679STim.Szeto@Sun.COM 	/*
33049679STim.Szeto@Sun.COM 	 * -allocate 1/2 the property size, the zfs property
33059679STim.Szeto@Sun.COM 	 *  is 8k in size and stored as ascii hex string, all
33069679STim.Szeto@Sun.COM 	 *  we needed is 4k buffer to store the binary data.
33079679STim.Szeto@Sun.COM 	 * -initialize reader/write lock
33089679STim.Szeto@Sun.COM 	 */
33099679STim.Szeto@Sun.COM 	if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
33109679STim.Szeto@Sun.COM 	    == NULL)
33119585STim.Szeto@Sun.COM 		return (SBD_FAILURE);
33129679STim.Szeto@Sun.COM 	rw_init(&sl->sl_zfs_meta_lock, NULL, RW_DRIVER, NULL);
33139585STim.Szeto@Sun.COM 	return (SBD_SUCCESS);
33149585STim.Szeto@Sun.COM }
33159585STim.Szeto@Sun.COM 
33169857SPeter.Cudhea@Sun.COM char
sbd_ctoi(char c)33179857SPeter.Cudhea@Sun.COM sbd_ctoi(char c)
33189679STim.Szeto@Sun.COM {
33199679STim.Szeto@Sun.COM 	if ((c >= '0') && (c <= '9'))
33209679STim.Szeto@Sun.COM 		c -= '0';
33219679STim.Szeto@Sun.COM 	else if ((c >= 'A') && (c <= 'F'))
33229679STim.Szeto@Sun.COM 		c = c - 'A' + 10;
33239679STim.Szeto@Sun.COM 	else if ((c >= 'a') && (c <= 'f'))
33249679STim.Szeto@Sun.COM 		c = c - 'a' + 10;
33259679STim.Szeto@Sun.COM 	else
33269679STim.Szeto@Sun.COM 		c = -1;
33279679STim.Szeto@Sun.COM 	return (c);
33289679STim.Szeto@Sun.COM }
33299679STim.Szeto@Sun.COM 
33309679STim.Szeto@Sun.COM /*
33319679STim.Szeto@Sun.COM  * read zvol property and convert to binary
33329679STim.Szeto@Sun.COM  */
33339585STim.Szeto@Sun.COM sbd_status_t
sbd_open_zfs_meta(sbd_lu_t * sl)33349585STim.Szeto@Sun.COM sbd_open_zfs_meta(sbd_lu_t *sl)
33359585STim.Szeto@Sun.COM {
33369679STim.Szeto@Sun.COM 	char		*meta = NULL, cl, ch;
33379679STim.Szeto@Sun.COM 	int		i;
33389679STim.Szeto@Sun.COM 	char		*tmp, *ptr;
33399679STim.Szeto@Sun.COM 	uint64_t	rc = SBD_SUCCESS;
33409679STim.Szeto@Sun.COM 	int		len;
33419679STim.Szeto@Sun.COM 	char		*file;
33429585STim.Szeto@Sun.COM 
334310526STim.Szeto@Sun.COM 	if (sl->sl_zfs_meta == NULL) {
334410526STim.Szeto@Sun.COM 		if (sbd_create_zfs_meta_object(sl) == SBD_FAILURE)
334510526STim.Szeto@Sun.COM 			return (SBD_FAILURE);
334610526STim.Szeto@Sun.COM 	} else {
334710526STim.Szeto@Sun.COM 		bzero(sl->sl_zfs_meta, (ZAP_MAXVALUELEN / 2));
334810526STim.Szeto@Sun.COM 	}
33499679STim.Szeto@Sun.COM 
33509679STim.Szeto@Sun.COM 	rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
33519679STim.Szeto@Sun.COM 	file = sbd_get_zvol_name(sl);
33529679STim.Szeto@Sun.COM 	if (sbd_zvolget(file, &meta)) {
33539679STim.Szeto@Sun.COM 		rc = SBD_FAILURE;
33549679STim.Szeto@Sun.COM 		goto done;
33559585STim.Szeto@Sun.COM 	}
33569679STim.Szeto@Sun.COM 	tmp = meta;
33579679STim.Szeto@Sun.COM 	/* convert ascii hex to binary meta */
33589679STim.Szeto@Sun.COM 	len = strlen(meta);
33599679STim.Szeto@Sun.COM 	ptr = sl->sl_zfs_meta;
33609679STim.Szeto@Sun.COM 	for (i = 0; i < len; i += 2) {
33619857SPeter.Cudhea@Sun.COM 		ch = sbd_ctoi(*tmp++);
33629857SPeter.Cudhea@Sun.COM 		cl = sbd_ctoi(*tmp++);
33639679STim.Szeto@Sun.COM 		if (ch == -1 || cl == -1) {
33649679STim.Szeto@Sun.COM 			rc = SBD_FAILURE;
33659679STim.Szeto@Sun.COM 			break;
33669679STim.Szeto@Sun.COM 		}
33679679STim.Szeto@Sun.COM 		*ptr++ = (ch << 4) + cl;
33689679STim.Szeto@Sun.COM 	}
33699679STim.Szeto@Sun.COM done:
33709679STim.Szeto@Sun.COM 	rw_exit(&sl->sl_zfs_meta_lock);
33719679STim.Szeto@Sun.COM 	if (meta)
33729679STim.Szeto@Sun.COM 		kmem_free(meta, len + 1);
33739679STim.Szeto@Sun.COM 	kmem_free(file, strlen(file) + 1);
33749679STim.Szeto@Sun.COM 	return (rc);
33759585STim.Szeto@Sun.COM }
33769585STim.Szeto@Sun.COM 
33779585STim.Szeto@Sun.COM sbd_status_t
sbd_read_zfs_meta(sbd_lu_t * sl,uint8_t * buf,uint64_t sz,uint64_t off)33789585STim.Szeto@Sun.COM sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
33799585STim.Szeto@Sun.COM {
33809679STim.Szeto@Sun.COM 	ASSERT(sl->sl_zfs_meta);
33819679STim.Szeto@Sun.COM 	rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
33829679STim.Szeto@Sun.COM 	bcopy(&sl->sl_zfs_meta[off], buf, sz);
33839679STim.Szeto@Sun.COM 	rw_exit(&sl->sl_zfs_meta_lock);
33849585STim.Szeto@Sun.COM 	return (SBD_SUCCESS);
33859585STim.Szeto@Sun.COM }
33869585STim.Szeto@Sun.COM 
33879585STim.Szeto@Sun.COM sbd_status_t
sbd_write_zfs_meta(sbd_lu_t * sl,uint8_t * buf,uint64_t sz,uint64_t off)33889585STim.Szeto@Sun.COM sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
33899585STim.Szeto@Sun.COM {
33909679STim.Szeto@Sun.COM 	ASSERT(sl->sl_zfs_meta);
33919679STim.Szeto@Sun.COM 	if ((off + sz) > (ZAP_MAXVALUELEN / 2 - 1)) {
33929679STim.Szeto@Sun.COM 		return (SBD_META_CORRUPTED);
33939585STim.Szeto@Sun.COM 	}
339410526STim.Szeto@Sun.COM 	if ((off + sz) > sl->sl_meta_size_used) {
339510526STim.Szeto@Sun.COM 		sl->sl_meta_size_used = off + sz;
339610526STim.Szeto@Sun.COM 		if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
339710526STim.Szeto@Sun.COM 			uint64_t meta_align =
339810526STim.Szeto@Sun.COM 			    (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
339910526STim.Szeto@Sun.COM 			sl->sl_total_meta_size = (sl->sl_meta_size_used +
340010526STim.Szeto@Sun.COM 			    meta_align) & (~meta_align);
340110526STim.Szeto@Sun.COM 		}
340210526STim.Szeto@Sun.COM 	}
34039679STim.Szeto@Sun.COM 	rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
34049679STim.Szeto@Sun.COM 	bcopy(buf, &sl->sl_zfs_meta[off], sz);
340512499SJohn.Forte@Sun.COM 	rw_exit(&sl->sl_zfs_meta_lock);
340612499SJohn.Forte@Sun.COM 	/*
340712499SJohn.Forte@Sun.COM 	 * During creation of a logical unit, sbd_update_zfs_prop will be
340812499SJohn.Forte@Sun.COM 	 * called separately to avoid multiple calls as each meta section
340912499SJohn.Forte@Sun.COM 	 * create/update will result in a call to sbd_write_zfs_meta().
341012499SJohn.Forte@Sun.COM 	 * We only need to update the zvol once during create.
341112499SJohn.Forte@Sun.COM 	 */
341212499SJohn.Forte@Sun.COM 	mutex_enter(&sl->sl_lock);
341312499SJohn.Forte@Sun.COM 	if (sl->sl_trans_op != SL_OP_CREATE_REGISTER_LU) {
341412499SJohn.Forte@Sun.COM 		mutex_exit(&sl->sl_lock);
341512499SJohn.Forte@Sun.COM 		return (sbd_update_zfs_prop(sl));
341612499SJohn.Forte@Sun.COM 	}
341712499SJohn.Forte@Sun.COM 	mutex_exit(&sl->sl_lock);
341812499SJohn.Forte@Sun.COM 	return (SBD_SUCCESS);
341912499SJohn.Forte@Sun.COM }
342012499SJohn.Forte@Sun.COM 
342112499SJohn.Forte@Sun.COM sbd_status_t
sbd_update_zfs_prop(sbd_lu_t * sl)342212499SJohn.Forte@Sun.COM sbd_update_zfs_prop(sbd_lu_t *sl)
342312499SJohn.Forte@Sun.COM {
342412499SJohn.Forte@Sun.COM 	char	*ptr, *ah_meta;
342512499SJohn.Forte@Sun.COM 	char	*dp = NULL;
342612499SJohn.Forte@Sun.COM 	int	i, num;
342712499SJohn.Forte@Sun.COM 	char	*file;
342812499SJohn.Forte@Sun.COM 	sbd_status_t ret = SBD_SUCCESS;
342912499SJohn.Forte@Sun.COM 
343012499SJohn.Forte@Sun.COM 	ASSERT(sl->sl_zfs_meta);
343112499SJohn.Forte@Sun.COM 	ptr = ah_meta = kmem_zalloc(ZAP_MAXVALUELEN, KM_SLEEP);
343212499SJohn.Forte@Sun.COM 	rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
34339679STim.Szeto@Sun.COM 	/* convert local copy to ascii hex */
34349679STim.Szeto@Sun.COM 	dp = sl->sl_zfs_meta;
34359679STim.Szeto@Sun.COM 	for (i = 0; i < sl->sl_total_meta_size; i++, dp++) {
34369679STim.Szeto@Sun.COM 		num = ((*dp) >> 4) & 0xF;
34379679STim.Szeto@Sun.COM 		*ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
34389679STim.Szeto@Sun.COM 		num = (*dp) & 0xF;
34399679STim.Szeto@Sun.COM 		*ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
34409679STim.Szeto@Sun.COM 	}
34419679STim.Szeto@Sun.COM 	*ah_meta = NULL;
34429679STim.Szeto@Sun.COM 	file = sbd_get_zvol_name(sl);
34439679STim.Szeto@Sun.COM 	if (sbd_zvolset(file, (char *)ptr)) {
344412499SJohn.Forte@Sun.COM 		ret = SBD_META_CORRUPTED;
34459679STim.Szeto@Sun.COM 	}
34469679STim.Szeto@Sun.COM 	rw_exit(&sl->sl_zfs_meta_lock);
34479679STim.Szeto@Sun.COM 	kmem_free(ptr, ZAP_MAXVALUELEN);
34489679STim.Szeto@Sun.COM 	kmem_free(file, strlen(file) + 1);
344912499SJohn.Forte@Sun.COM 	return (ret);
34509585STim.Szeto@Sun.COM }
34519585STim.Szeto@Sun.COM 
34529585STim.Szeto@Sun.COM int
sbd_is_zvol(char * path)34539679STim.Szeto@Sun.COM sbd_is_zvol(char *path)
34549585STim.Szeto@Sun.COM {
34559585STim.Szeto@Sun.COM 	int is_zfs = 0;
34569585STim.Szeto@Sun.COM 
34579679STim.Szeto@Sun.COM 	if (SBD_IS_ZVOL(path) == 0)
34589679STim.Szeto@Sun.COM 		is_zfs = 1;
34599585STim.Szeto@Sun.COM 
34609585STim.Szeto@Sun.COM 	return (is_zfs);
34619585STim.Szeto@Sun.COM }
34629585STim.Szeto@Sun.COM 
34639585STim.Szeto@Sun.COM /*
34649585STim.Szeto@Sun.COM  * set write cache disable
34659585STim.Szeto@Sun.COM  * wcd - 1 = disable, 0 = enable
34669585STim.Szeto@Sun.COM  */
34679585STim.Szeto@Sun.COM sbd_status_t
sbd_wcd_set(int wcd,sbd_lu_t * sl)34689585STim.Szeto@Sun.COM sbd_wcd_set(int wcd, sbd_lu_t *sl)
34699585STim.Szeto@Sun.COM {
34709585STim.Szeto@Sun.COM 	/* translate to wce bit */
34719585STim.Szeto@Sun.COM 	int wce = wcd ? 0 : 1;
34729585STim.Szeto@Sun.COM 	int ret;
34739585STim.Szeto@Sun.COM 	sbd_status_t sret = SBD_SUCCESS;
34749585STim.Szeto@Sun.COM 
34759585STim.Szeto@Sun.COM 	mutex_enter(&sl->sl_lock);
34769585STim.Szeto@Sun.COM 	sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
34779585STim.Szeto@Sun.COM 
34789585STim.Szeto@Sun.COM 	if (sl->sl_data_vp->v_type == VREG) {
34799585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
34809585STim.Szeto@Sun.COM 		goto done;
34819585STim.Szeto@Sun.COM 	}
34829585STim.Szeto@Sun.COM 
34839585STim.Szeto@Sun.COM 	ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL,
34849585STim.Szeto@Sun.COM 	    kcred, NULL, NULL);
34859585STim.Szeto@Sun.COM 	if (ret == 0) {
34869585STim.Szeto@Sun.COM 		sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
34879585STim.Szeto@Sun.COM 		sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE;
34889585STim.Szeto@Sun.COM 	} else {
34899585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
34909585STim.Szeto@Sun.COM 		sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
34919585STim.Szeto@Sun.COM 		sret = SBD_FAILURE;
34929585STim.Szeto@Sun.COM 		goto done;
34939585STim.Szeto@Sun.COM 	}
34949585STim.Szeto@Sun.COM 
34959585STim.Szeto@Sun.COM done:
34969585STim.Szeto@Sun.COM 	mutex_exit(&sl->sl_lock);
34979585STim.Szeto@Sun.COM 	return (sret);
34989585STim.Szeto@Sun.COM }
34999585STim.Szeto@Sun.COM 
35009585STim.Szeto@Sun.COM /*
35019585STim.Szeto@Sun.COM  * get write cache disable
35029585STim.Szeto@Sun.COM  * wcd - 1 = disable, 0 = enable
35039585STim.Szeto@Sun.COM  */
35049585STim.Szeto@Sun.COM void
sbd_wcd_get(int * wcd,sbd_lu_t * sl)35059585STim.Szeto@Sun.COM sbd_wcd_get(int *wcd, sbd_lu_t *sl)
35069585STim.Szeto@Sun.COM {
35079585STim.Szeto@Sun.COM 	int wce;
35089585STim.Szeto@Sun.COM 	int ret;
35099585STim.Szeto@Sun.COM 
35109585STim.Szeto@Sun.COM 	if (sl->sl_data_vp->v_type == VREG) {
35119585STim.Szeto@Sun.COM 		*wcd = 0;
35129585STim.Szeto@Sun.COM 		return;
35139585STim.Szeto@Sun.COM 	}
35149585STim.Szeto@Sun.COM 
35159585STim.Szeto@Sun.COM 	ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL,
35169585STim.Szeto@Sun.COM 	    kcred, NULL, NULL);
35179585STim.Szeto@Sun.COM 	/* if write cache get failed, assume disabled */
35189585STim.Szeto@Sun.COM 	if (ret) {
35199585STim.Szeto@Sun.COM 		*wcd = 1;
35209585STim.Szeto@Sun.COM 	} else {
35219585STim.Szeto@Sun.COM 		/* translate to wcd bit */
35229585STim.Szeto@Sun.COM 		*wcd = wce ? 0 : 1;
35239585STim.Szeto@Sun.COM 	}
35247836SJohn.Forte@Sun.COM }
35257836SJohn.Forte@Sun.COM 
35267836SJohn.Forte@Sun.COM int
sbd_zvolget(char * zvol_name,char ** comstarprop)35279679STim.Szeto@Sun.COM sbd_zvolget(char *zvol_name, char **comstarprop)
35287836SJohn.Forte@Sun.COM {
35299679STim.Szeto@Sun.COM 	ldi_handle_t	zfs_lh;
35309679STim.Szeto@Sun.COM 	nvlist_t	*nv = NULL, *nv2;
35319679STim.Szeto@Sun.COM 	zfs_cmd_t	*zc;
35329679STim.Szeto@Sun.COM 	char		*ptr;
35339679STim.Szeto@Sun.COM 	int size = 1024;
35349679STim.Szeto@Sun.COM 	int unused;
35359679STim.Szeto@Sun.COM 	int rc;
35367836SJohn.Forte@Sun.COM 
35379679STim.Szeto@Sun.COM 	if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
35389679STim.Szeto@Sun.COM 	    &zfs_lh, sbd_zfs_ident)) != 0) {
35399679STim.Szeto@Sun.COM 		cmn_err(CE_WARN, "ldi_open %d", rc);
35409679STim.Szeto@Sun.COM 		return (ENXIO);
35417836SJohn.Forte@Sun.COM 	}
35427836SJohn.Forte@Sun.COM 
35439679STim.Szeto@Sun.COM 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
35449679STim.Szeto@Sun.COM 	(void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
35459679STim.Szeto@Sun.COM again:
35469679STim.Szeto@Sun.COM 	zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
35479679STim.Szeto@Sun.COM 	    KM_SLEEP);
35489679STim.Szeto@Sun.COM 	zc->zc_nvlist_dst_size = size;
35499679STim.Szeto@Sun.COM 	rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
35509679STim.Szeto@Sun.COM 	    FKIOCTL, kcred, &unused);
35519679STim.Szeto@Sun.COM 	/*
35529679STim.Szeto@Sun.COM 	 * ENOMEM means the list is larger than what we've allocated
35539679STim.Szeto@Sun.COM 	 * ldi_ioctl will fail with ENOMEM only once
35549679STim.Szeto@Sun.COM 	 */
35559679STim.Szeto@Sun.COM 	if (rc == ENOMEM) {
35569679STim.Szeto@Sun.COM 		int newsize;
35579679STim.Szeto@Sun.COM 		newsize = zc->zc_nvlist_dst_size;
35589679STim.Szeto@Sun.COM 		kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
35599679STim.Szeto@Sun.COM 		size = newsize;
35609679STim.Szeto@Sun.COM 		goto again;
35619679STim.Szeto@Sun.COM 	} else if (rc != 0) {
35629679STim.Szeto@Sun.COM 		goto out;
35639679STim.Szeto@Sun.COM 	}
35649679STim.Szeto@Sun.COM 	rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
35659679STim.Szeto@Sun.COM 	    zc->zc_nvlist_dst_size, &nv, 0);
35669679STim.Szeto@Sun.COM 	ASSERT(rc == 0);	/* nvlist_unpack should not fail */
35679679STim.Szeto@Sun.COM 	if ((rc = nvlist_lookup_nvlist(nv, "stmf_sbd_lu", &nv2)) == 0) {
35689679STim.Szeto@Sun.COM 		rc = nvlist_lookup_string(nv2, ZPROP_VALUE, &ptr);
35699679STim.Szeto@Sun.COM 		if (rc != 0) {
35709679STim.Szeto@Sun.COM 			cmn_err(CE_WARN, "couldn't get value");
35719679STim.Szeto@Sun.COM 		} else {
35729679STim.Szeto@Sun.COM 			*comstarprop = kmem_alloc(strlen(ptr) + 1,
35739679STim.Szeto@Sun.COM 			    KM_SLEEP);
35749679STim.Szeto@Sun.COM 			(void) strcpy(*comstarprop, ptr);
35759679STim.Szeto@Sun.COM 		}
35767836SJohn.Forte@Sun.COM 	}
35779679STim.Szeto@Sun.COM out:
35789679STim.Szeto@Sun.COM 	if (nv != NULL)
35799679STim.Szeto@Sun.COM 		nvlist_free(nv);
35809679STim.Szeto@Sun.COM 	kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
35819679STim.Szeto@Sun.COM 	kmem_free(zc, sizeof (zfs_cmd_t));
35829679STim.Szeto@Sun.COM 	(void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
35839679STim.Szeto@Sun.COM 
35849679STim.Szeto@Sun.COM 	return (rc);
35857836SJohn.Forte@Sun.COM }
35869679STim.Szeto@Sun.COM 
35879679STim.Szeto@Sun.COM int
sbd_zvolset(char * zvol_name,char * comstarprop)35889679STim.Szeto@Sun.COM sbd_zvolset(char *zvol_name, char *comstarprop)
35899679STim.Szeto@Sun.COM {
35909679STim.Szeto@Sun.COM 	ldi_handle_t	zfs_lh;
35919679STim.Szeto@Sun.COM 	nvlist_t	*nv;
35929679STim.Szeto@Sun.COM 	char		*packed = NULL;
35939679STim.Szeto@Sun.COM 	size_t		len;
35949679STim.Szeto@Sun.COM 	zfs_cmd_t	*zc;
35959679STim.Szeto@Sun.COM 	int unused;
35969679STim.Szeto@Sun.COM 	int rc;
35979679STim.Szeto@Sun.COM 
35989679STim.Szeto@Sun.COM 	if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
35999679STim.Szeto@Sun.COM 	    &zfs_lh, sbd_zfs_ident)) != 0) {
36009679STim.Szeto@Sun.COM 		cmn_err(CE_WARN, "ldi_open %d", rc);
36019679STim.Szeto@Sun.COM 		return (ENXIO);
36029679STim.Szeto@Sun.COM 	}
36039679STim.Szeto@Sun.COM 	(void) nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP);
36049679STim.Szeto@Sun.COM 	(void) nvlist_add_string(nv, "stmf_sbd_lu", comstarprop);
36059679STim.Szeto@Sun.COM 	if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
36069679STim.Szeto@Sun.COM 		goto out;
36079679STim.Szeto@Sun.COM 	}
36089679STim.Szeto@Sun.COM 
36099679STim.Szeto@Sun.COM 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
36109679STim.Szeto@Sun.COM 	(void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
36119679STim.Szeto@Sun.COM 	zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
36129679STim.Szeto@Sun.COM 	zc->zc_nvlist_src_size = len;
36139679STim.Szeto@Sun.COM 	rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
36149679STim.Szeto@Sun.COM 	    FKIOCTL, kcred, &unused);
36159679STim.Szeto@Sun.COM 	if (rc != 0) {
36169679STim.Szeto@Sun.COM 		cmn_err(CE_NOTE, "ioctl failed %d", rc);
36179679STim.Szeto@Sun.COM 	}
36189679STim.Szeto@Sun.COM 	kmem_free(zc, sizeof (zfs_cmd_t));
361910572STim.Szeto@Sun.COM 	if (packed)
362010572STim.Szeto@Sun.COM 		kmem_free(packed, len);
36219679STim.Szeto@Sun.COM out:
36229679STim.Szeto@Sun.COM 	nvlist_free(nv);
36239679STim.Szeto@Sun.COM 	(void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
36249679STim.Szeto@Sun.COM 	return (rc);
36259679STim.Szeto@Sun.COM }
3626