xref: /illumos-gate/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c (revision 134379c07d59b848341b71d3c4819af39ad347cc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <sys/conf.h>
26 #include <sys/file.h>
27 #include <sys/ddi.h>
28 #include <sys/sunddi.h>
29 #include <sys/modctl.h>
30 #include <sys/scsi/scsi.h>
31 #include <sys/scsi/impl/scsi_reset_notify.h>
32 #include <sys/disp.h>
33 #include <sys/byteorder.h>
34 #include <sys/pathname.h>
35 #include <sys/atomic.h>
36 #include <sys/nvpair.h>
37 #include <sys/fs/zfs.h>
38 #include <sys/sdt.h>
39 #include <sys/dkio.h>
40 #include <sys/zfs_ioctl.h>
41 
42 #include <stmf.h>
43 #include <lpif.h>
44 #include <stmf_ioctl.h>
45 #include <stmf_sbd.h>
46 #include <sbd_impl.h>
47 #include <stmf_sbd_ioctl.h>
48 
49 #define	SBD_IS_ZVOL(zvol)	(strncmp("/dev/zvol", zvol, 9))
50 
51 extern sbd_status_t sbd_pgr_meta_init(sbd_lu_t *sl);
52 extern sbd_status_t sbd_pgr_meta_load(sbd_lu_t *sl);
53 extern void sbd_pgr_reset(sbd_lu_t *sl);
54 
55 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
56     void **result);
57 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
58 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
59 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp);
60 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp);
61 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
62     cred_t *credp, int *rval);
63 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags);
64 stmf_status_t sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg,
65     uint32_t proxy_reg_arg_len);
66 stmf_status_t sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
67     uint32_t proxy_reg_arg_len);
68 stmf_status_t sbd_proxy_msg(uint8_t *luid, void *proxy_arg,
69     uint32_t proxy_arg_len, uint32_t type);
70 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
71     uint32_t *err_ret);
72 int sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret);
73 int sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret);
74 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
75     int no_register, sbd_lu_t **slr);
76 int sbd_import_active_lu(sbd_import_lu_t *ilu, sbd_lu_t *sl, uint32_t *err_ret);
77 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
78 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
79 int sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
80     uint32_t *err_ret);
81 int sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
82     uint32_t *err_ret);
83 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
84     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
85 char *sbd_get_zvol_name(sbd_lu_t *sl);
86 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
87 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
88 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
89     uint64_t off);
90 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
91     uint64_t off);
92 int sbd_is_zvol(char *path);
93 int sbd_zvolget(char *zvol_name, char **comstarprop);
94 int sbd_zvolset(char *zvol_name, char *comstarprop);
95 char sbd_ctoi(char c);
96 void sbd_close_lu(sbd_lu_t *sl);
97 
98 static ldi_ident_t	sbd_zfs_ident;
99 static stmf_lu_provider_t *sbd_lp;
100 static sbd_lu_t		*sbd_lu_list = NULL;
101 static kmutex_t		sbd_lock;
102 static dev_info_t	*sbd_dip;
103 static uint32_t		sbd_lu_count = 0;
104 
105 /* Global property settings for the logical unit */
106 char sbd_vendor_id[]	= "SUN     ";
107 char sbd_product_id[]	= "COMSTAR         ";
108 char sbd_revision[]	= "1.0 ";
109 char *sbd_mgmt_url = NULL;
110 uint16_t sbd_mgmt_url_alloc_size = 0;
111 krwlock_t sbd_global_prop_lock;
112 
113 static char sbd_name[] = "sbd";
114 
115 static struct cb_ops sbd_cb_ops = {
116 	sbd_open,			/* open */
117 	sbd_close,			/* close */
118 	nodev,				/* strategy */
119 	nodev,				/* print */
120 	nodev,				/* dump */
121 	nodev,				/* read */
122 	nodev,				/* write */
123 	stmf_sbd_ioctl,			/* ioctl */
124 	nodev,				/* devmap */
125 	nodev,				/* mmap */
126 	nodev,				/* segmap */
127 	nochpoll,			/* chpoll */
128 	ddi_prop_op,			/* cb_prop_op */
129 	0,				/* streamtab */
130 	D_NEW | D_MP,			/* cb_flag */
131 	CB_REV,				/* rev */
132 	nodev,				/* aread */
133 	nodev				/* awrite */
134 };
135 
136 static struct dev_ops sbd_ops = {
137 	DEVO_REV,
138 	0,
139 	sbd_getinfo,
140 	nulldev,		/* identify */
141 	nulldev,		/* probe */
142 	sbd_attach,
143 	sbd_detach,
144 	nodev,			/* reset */
145 	&sbd_cb_ops,
146 	NULL,			/* bus_ops */
147 	NULL			/* power */
148 };
149 
150 #define	SBD_NAME	"COMSTAR SBD"
151 
152 static struct modldrv modldrv = {
153 	&mod_driverops,
154 	SBD_NAME,
155 	&sbd_ops
156 };
157 
158 static struct modlinkage modlinkage = {
159 	MODREV_1,
160 	&modldrv,
161 	NULL
162 };
163 
164 int
165 _init(void)
166 {
167 	int ret;
168 
169 	ret = mod_install(&modlinkage);
170 	if (ret)
171 		return (ret);
172 	sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER,
173 	    0, 0);
174 	sbd_lp->lp_lpif_rev = LPIF_REV_2;
175 	sbd_lp->lp_instance = 0;
176 	sbd_lp->lp_name = sbd_name;
177 	sbd_lp->lp_cb = sbd_lp_cb;
178 	sbd_lp->lp_alua_support = 1;
179 	sbd_lp->lp_proxy_msg = sbd_proxy_msg;
180 	sbd_zfs_ident = ldi_ident_from_anon();
181 
182 	if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) {
183 		(void) mod_remove(&modlinkage);
184 		stmf_free(sbd_lp);
185 		return (EINVAL);
186 	}
187 	mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL);
188 	rw_init(&sbd_global_prop_lock, NULL, RW_DRIVER, NULL);
189 	return (0);
190 }
191 
192 int
193 _fini(void)
194 {
195 	int ret;
196 
197 	/*
198 	 * If we have registered lus, then make sure they are all offline
199 	 * if so then deregister them. This should drop the sbd_lu_count
200 	 * to zero.
201 	 */
202 	if (sbd_lu_count) {
203 		sbd_lu_t *slu;
204 
205 		/* See if all of them are offline */
206 		mutex_enter(&sbd_lock);
207 		for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) {
208 			if ((slu->sl_state != STMF_STATE_OFFLINE) ||
209 			    slu->sl_state_not_acked) {
210 				mutex_exit(&sbd_lock);
211 				return (EBUSY);
212 			}
213 		}
214 		mutex_exit(&sbd_lock);
215 
216 #if 0
217 		/* ok start deregistering them */
218 		while (sbd_lu_list) {
219 			sbd_store_t *sst = sbd_lu_list->sl_sst;
220 			if (sst->sst_deregister_lu(sst) != STMF_SUCCESS)
221 				return (EBUSY);
222 		}
223 #endif
224 		return (EBUSY);
225 	}
226 	if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS)
227 		return (EBUSY);
228 	ret = mod_remove(&modlinkage);
229 	if (ret != 0) {
230 		(void) stmf_register_lu_provider(sbd_lp);
231 		return (ret);
232 	}
233 	stmf_free(sbd_lp);
234 	mutex_destroy(&sbd_lock);
235 	rw_destroy(&sbd_global_prop_lock);
236 	ldi_ident_release(sbd_zfs_ident);
237 	return (0);
238 }
239 
240 int
241 _info(struct modinfo *modinfop)
242 {
243 	return (mod_info(&modlinkage, modinfop));
244 }
245 
246 /* ARGSUSED */
247 static int
248 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
249 {
250 	switch (cmd) {
251 	case DDI_INFO_DEVT2DEVINFO:
252 		*result = sbd_dip;
253 		break;
254 	case DDI_INFO_DEVT2INSTANCE:
255 		*result = (void *)(uintptr_t)ddi_get_instance(sbd_dip);
256 		break;
257 	default:
258 		return (DDI_FAILURE);
259 	}
260 
261 	return (DDI_SUCCESS);
262 }
263 
264 static int
265 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
266 {
267 	switch (cmd) {
268 	case DDI_ATTACH:
269 		sbd_dip = dip;
270 
271 		if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
272 		    DDI_NT_STMF_LP, 0) != DDI_SUCCESS) {
273 			break;
274 		}
275 		ddi_report_dev(dip);
276 		return (DDI_SUCCESS);
277 	}
278 
279 	return (DDI_FAILURE);
280 }
281 
282 static int
283 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
284 {
285 	switch (cmd) {
286 	case DDI_DETACH:
287 		ddi_remove_minor_node(dip, 0);
288 		return (DDI_SUCCESS);
289 	}
290 
291 	return (DDI_FAILURE);
292 }
293 
294 /* ARGSUSED */
295 static int
296 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp)
297 {
298 	if (otype != OTYP_CHR)
299 		return (EINVAL);
300 	return (0);
301 }
302 
303 /* ARGSUSED */
304 static int
305 sbd_close(dev_t dev, int flag, int otype, cred_t *credp)
306 {
307 	return (0);
308 }
309 
310 /* ARGSUSED */
311 static int
312 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
313 	cred_t *credp, int *rval)
314 {
315 	stmf_iocdata_t		*iocd;
316 	void			*ibuf	= NULL;
317 	void			*obuf	= NULL;
318 	sbd_lu_t		*nsl;
319 	int			i;
320 	int			ret;
321 
322 	if (drv_priv(credp) != 0) {
323 		return (EPERM);
324 	}
325 
326 	ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
327 	if (ret)
328 		return (ret);
329 	iocd->stmf_error = 0;
330 
331 	switch (cmd) {
332 	case SBD_IOCTL_CREATE_AND_REGISTER_LU:
333 		if (iocd->stmf_ibuf_size <
334 		    (sizeof (sbd_create_and_reg_lu_t) - 8)) {
335 			ret = EFAULT;
336 			break;
337 		}
338 		if ((iocd->stmf_obuf_size == 0) ||
339 		    (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
340 			ret = EINVAL;
341 			break;
342 		}
343 		ret = sbd_create_register_lu((sbd_create_and_reg_lu_t *)
344 		    ibuf, iocd->stmf_ibuf_size, &iocd->stmf_error);
345 		bcopy(ibuf, obuf, iocd->stmf_obuf_size);
346 		break;
347 	case SBD_IOCTL_SET_LU_STANDBY:
348 		if (iocd->stmf_ibuf_size < sizeof (sbd_set_lu_standby_t)) {
349 			ret = EFAULT;
350 			break;
351 		}
352 		if (iocd->stmf_obuf_size) {
353 			ret = EINVAL;
354 			break;
355 		}
356 		ret = sbd_set_lu_standby((sbd_set_lu_standby_t *)ibuf,
357 		    &iocd->stmf_error);
358 		break;
359 	case SBD_IOCTL_IMPORT_LU:
360 		if (iocd->stmf_ibuf_size <
361 		    (sizeof (sbd_import_lu_t) - 8)) {
362 			ret = EFAULT;
363 			break;
364 		}
365 		if ((iocd->stmf_obuf_size == 0) ||
366 		    (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
367 			ret = EINVAL;
368 			break;
369 		}
370 		ret = sbd_import_lu((sbd_import_lu_t *)ibuf,
371 		    iocd->stmf_ibuf_size, &iocd->stmf_error, 0, NULL);
372 		bcopy(ibuf, obuf, iocd->stmf_obuf_size);
373 		break;
374 	case SBD_IOCTL_DELETE_LU:
375 		if (iocd->stmf_ibuf_size < (sizeof (sbd_delete_lu_t) - 8)) {
376 			ret = EFAULT;
377 			break;
378 		}
379 		if (iocd->stmf_obuf_size) {
380 			ret = EINVAL;
381 			break;
382 		}
383 		ret = sbd_delete_lu((sbd_delete_lu_t *)ibuf,
384 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
385 		break;
386 	case SBD_IOCTL_MODIFY_LU:
387 		if (iocd->stmf_ibuf_size < (sizeof (sbd_modify_lu_t) - 8)) {
388 			ret = EFAULT;
389 			break;
390 		}
391 		if (iocd->stmf_obuf_size) {
392 			ret = EINVAL;
393 			break;
394 		}
395 		ret = sbd_modify_lu((sbd_modify_lu_t *)ibuf,
396 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
397 		break;
398 	case SBD_IOCTL_SET_GLOBAL_LU:
399 		if (iocd->stmf_ibuf_size < (sizeof (sbd_global_props_t) - 8)) {
400 			ret = EFAULT;
401 			break;
402 		}
403 		if (iocd->stmf_obuf_size) {
404 			ret = EINVAL;
405 			break;
406 		}
407 		ret = sbd_set_global_props((sbd_global_props_t *)ibuf,
408 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
409 		break;
410 	case SBD_IOCTL_GET_GLOBAL_LU:
411 		if (iocd->stmf_ibuf_size) {
412 			ret = EINVAL;
413 			break;
414 		}
415 		if (iocd->stmf_obuf_size < sizeof (sbd_global_props_t)) {
416 			ret = EINVAL;
417 			break;
418 		}
419 		ret = sbd_get_global_props((sbd_global_props_t *)obuf,
420 		    iocd->stmf_obuf_size, &iocd->stmf_error);
421 		break;
422 	case SBD_IOCTL_GET_LU_PROPS:
423 		if (iocd->stmf_ibuf_size < (sizeof (sbd_lu_props_t) - 8)) {
424 			ret = EFAULT;
425 			break;
426 		}
427 		if (iocd->stmf_obuf_size < sizeof (sbd_lu_props_t)) {
428 			ret = EINVAL;
429 			break;
430 		}
431 		ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
432 		    iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
433 		    iocd->stmf_obuf_size, &iocd->stmf_error);
434 		break;
435 	case SBD_IOCTL_GET_LU_LIST:
436 		mutex_enter(&sbd_lock);
437 		iocd->stmf_obuf_max_nentries = sbd_lu_count;
438 		iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
439 		    sbd_lu_count);
440 		for (nsl = sbd_lu_list, i = 0; nsl &&
441 		    (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
442 			bcopy(nsl->sl_device_id + 4,
443 			    &(((uint8_t *)obuf)[i << 4]), 16);
444 		}
445 		mutex_exit(&sbd_lock);
446 		ret = 0;
447 		iocd->stmf_error = 0;
448 		break;
449 	default:
450 		ret = ENOTTY;
451 	}
452 
453 	if (ret == 0) {
454 		ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
455 	} else if (iocd->stmf_error) {
456 		(void) stmf_copyout_iocdata(data, mode, iocd, obuf);
457 	}
458 	if (obuf) {
459 		kmem_free(obuf, iocd->stmf_obuf_size);
460 		obuf = NULL;
461 	}
462 	if (ibuf) {
463 		kmem_free(ibuf, iocd->stmf_ibuf_size);
464 		ibuf = NULL;
465 	}
466 	kmem_free(iocd, sizeof (stmf_iocdata_t));
467 	return (ret);
468 }
469 
470 /* ARGSUSED */
471 void
472 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags)
473 {
474 	nvpair_t	*np;
475 	char		*s;
476 	sbd_import_lu_t *ilu;
477 	uint32_t	ilu_sz;
478 	uint32_t	struct_sz;
479 	uint32_t	err_ret;
480 	int		iret;
481 
482 	if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
483 		return;
484 	}
485 
486 	if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) {
487 		return;
488 	}
489 
490 	np = NULL;
491 	ilu_sz = 1024;
492 	ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
493 	while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) {
494 		if (nvpair_type(np) != DATA_TYPE_STRING) {
495 			continue;
496 		}
497 		if (nvpair_value_string(np, &s) != 0) {
498 			continue;
499 		}
500 		struct_sz = max(8, strlen(s) + 1);
501 		struct_sz += sizeof (sbd_import_lu_t) - 8;
502 		if (struct_sz > ilu_sz) {
503 			kmem_free(ilu, ilu_sz);
504 			ilu_sz = struct_sz + 32;
505 			ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
506 		}
507 		ilu->ilu_struct_size = struct_sz;
508 		(void) strcpy(ilu->ilu_meta_fname, s);
509 		iret = sbd_import_lu(ilu, struct_sz, &err_ret, 0, NULL);
510 		if (iret) {
511 			stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, "
512 			    "err_ret = %d", iret, err_ret);
513 		} else {
514 			stmf_trace(0, "Imported the LU %s", nvpair_name(np));
515 		}
516 	}
517 
518 	if (ilu) {
519 		kmem_free(ilu, ilu_sz);
520 		ilu = NULL;
521 	}
522 }
523 
524 sbd_status_t
525 sbd_link_lu(sbd_lu_t *sl)
526 {
527 	sbd_lu_t *nsl;
528 
529 	mutex_enter(&sbd_lock);
530 	mutex_enter(&sl->sl_lock);
531 	ASSERT(sl->sl_trans_op != SL_OP_NONE);
532 
533 	if (sl->sl_flags & SL_LINKED) {
534 		mutex_exit(&sbd_lock);
535 		mutex_exit(&sl->sl_lock);
536 		return (SBD_ALREADY);
537 	}
538 	for (nsl = sbd_lu_list; nsl; nsl = nsl->sl_next) {
539 		if (strcmp(nsl->sl_name, sl->sl_name) == 0)
540 			break;
541 	}
542 	if (nsl) {
543 		mutex_exit(&sbd_lock);
544 		mutex_exit(&sl->sl_lock);
545 		return (SBD_ALREADY);
546 	}
547 	sl->sl_next = sbd_lu_list;
548 	sbd_lu_list = sl;
549 	sl->sl_flags |= SL_LINKED;
550 	mutex_exit(&sbd_lock);
551 	mutex_exit(&sl->sl_lock);
552 	return (SBD_SUCCESS);
553 }
554 
555 void
556 sbd_unlink_lu(sbd_lu_t *sl)
557 {
558 	sbd_lu_t **ppnsl;
559 
560 	mutex_enter(&sbd_lock);
561 	mutex_enter(&sl->sl_lock);
562 	ASSERT(sl->sl_trans_op != SL_OP_NONE);
563 
564 	ASSERT(sl->sl_flags & SL_LINKED);
565 	for (ppnsl = &sbd_lu_list; *ppnsl; ppnsl = &((*ppnsl)->sl_next)) {
566 		if (*ppnsl == sl)
567 			break;
568 	}
569 	ASSERT(*ppnsl);
570 	*ppnsl = (*ppnsl)->sl_next;
571 	sl->sl_flags &= ~SL_LINKED;
572 	mutex_exit(&sbd_lock);
573 	mutex_exit(&sl->sl_lock);
574 }
575 
576 sbd_status_t
577 sbd_find_and_lock_lu(uint8_t *guid, uint8_t *meta_name, uint8_t op,
578     sbd_lu_t **ppsl)
579 {
580 	sbd_lu_t *sl;
581 	int found = 0;
582 	sbd_status_t sret;
583 
584 	mutex_enter(&sbd_lock);
585 	for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
586 		if (guid) {
587 			found = bcmp(sl->sl_device_id + 4, guid, 16) == 0;
588 		} else {
589 			found = strcmp(sl->sl_name, (char *)meta_name) == 0;
590 		}
591 		if (found)
592 			break;
593 	}
594 	if (!found) {
595 		mutex_exit(&sbd_lock);
596 		return (SBD_NOT_FOUND);
597 	}
598 	mutex_enter(&sl->sl_lock);
599 	if (sl->sl_trans_op == SL_OP_NONE) {
600 		sl->sl_trans_op = op;
601 		*ppsl = sl;
602 		sret = SBD_SUCCESS;
603 	} else {
604 		sret = SBD_BUSY;
605 	}
606 	mutex_exit(&sl->sl_lock);
607 	mutex_exit(&sbd_lock);
608 	return (sret);
609 }
610 
611 sbd_status_t
612 sbd_read_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
613 {
614 	uint64_t	meta_align;
615 	uint64_t	starting_off;
616 	uint64_t	data_off;
617 	uint64_t	ending_off;
618 	uint64_t	io_size;
619 	uint8_t		*io_buf;
620 	vnode_t		*vp;
621 	sbd_status_t	ret;
622 	ssize_t		resid;
623 	int		vret;
624 
625 	ASSERT(sl->sl_flags & SL_META_OPENED);
626 	if (sl->sl_flags & SL_SHARED_META) {
627 		meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
628 		vp = sl->sl_data_vp;
629 		ASSERT(vp);
630 	} else {
631 		meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
632 		if ((sl->sl_flags & SL_ZFS_META) == 0) {
633 			vp = sl->sl_meta_vp;
634 			ASSERT(vp);
635 		}
636 	}
637 	starting_off = offset & ~(meta_align);
638 	data_off = offset & meta_align;
639 	ending_off = (offset + size + meta_align) & (~meta_align);
640 	if (ending_off > sl->sl_meta_size_used) {
641 		bzero(buf, size);
642 		if (starting_off >= sl->sl_meta_size_used) {
643 			return (SBD_SUCCESS);
644 		}
645 		ending_off = (sl->sl_meta_size_used + meta_align) &
646 		    (~meta_align);
647 		if (size > (ending_off - (starting_off + data_off))) {
648 			size = ending_off - (starting_off + data_off);
649 		}
650 	}
651 	io_size = ending_off - starting_off;
652 	io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
653 	ASSERT((starting_off + io_size) <= sl->sl_total_meta_size);
654 
655 	/*
656 	 * Don't proceed if the device has been closed
657 	 * This can occur on an access state change to standby or
658 	 * a delete. The writer lock is acquired before closing the
659 	 * lu. If importing, reading the metadata is valid, hence
660 	 * the check on SL_OP_IMPORT_LU.
661 	 */
662 	rw_enter(&sl->sl_access_state_lock, RW_READER);
663 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
664 	    sl->sl_trans_op != SL_OP_IMPORT_LU) {
665 		rw_exit(&sl->sl_access_state_lock);
666 		ret = SBD_FILEIO_FAILURE;
667 		goto sbd_read_meta_failure;
668 	}
669 	if (sl->sl_flags & SL_ZFS_META) {
670 		if ((ret = sbd_read_zfs_meta(sl, io_buf, io_size,
671 		    starting_off)) != SBD_SUCCESS) {
672 			rw_exit(&sl->sl_access_state_lock);
673 			goto sbd_read_meta_failure;
674 		}
675 	} else {
676 		vret = vn_rdwr(UIO_READ, vp, (caddr_t)io_buf, (ssize_t)io_size,
677 		    (offset_t)starting_off, UIO_SYSSPACE, FRSYNC,
678 		    RLIM64_INFINITY, CRED(), &resid);
679 
680 		if (vret || resid) {
681 			ret = SBD_FILEIO_FAILURE | vret;
682 			rw_exit(&sl->sl_access_state_lock);
683 			goto sbd_read_meta_failure;
684 		}
685 	}
686 	rw_exit(&sl->sl_access_state_lock);
687 
688 	bcopy(io_buf + data_off, buf, size);
689 	ret = SBD_SUCCESS;
690 
691 sbd_read_meta_failure:
692 	kmem_free(io_buf, io_size);
693 	return (ret);
694 }
695 
696 sbd_status_t
697 sbd_write_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
698 {
699 	uint64_t	meta_align;
700 	uint64_t	starting_off;
701 	uint64_t	data_off;
702 	uint64_t	ending_off;
703 	uint64_t	io_size;
704 	uint8_t		*io_buf;
705 	vnode_t		*vp;
706 	sbd_status_t	ret;
707 	ssize_t		resid;
708 	int		vret;
709 
710 	ASSERT(sl->sl_flags & SL_META_OPENED);
711 	if (sl->sl_flags & SL_SHARED_META) {
712 		meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
713 		vp = sl->sl_data_vp;
714 		ASSERT(vp);
715 	} else {
716 		meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
717 		if ((sl->sl_flags & SL_ZFS_META) == 0) {
718 			vp = sl->sl_meta_vp;
719 			ASSERT(vp);
720 		}
721 	}
722 	starting_off = offset & ~(meta_align);
723 	data_off = offset & meta_align;
724 	ending_off = (offset + size + meta_align) & (~meta_align);
725 	io_size = ending_off - starting_off;
726 	io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
727 	ret = sbd_read_meta(sl, starting_off, io_size, io_buf);
728 	if (ret != SBD_SUCCESS) {
729 		goto sbd_write_meta_failure;
730 	}
731 	bcopy(buf, io_buf + data_off, size);
732 	/*
733 	 * Don't proceed if the device has been closed
734 	 * This can occur on an access state change to standby or
735 	 * a delete. The writer lock is acquired before closing the
736 	 * lu. If importing, reading the metadata is valid, hence
737 	 * the check on SL_OP_IMPORT_LU.
738 	 */
739 	rw_enter(&sl->sl_access_state_lock, RW_READER);
740 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0 &&
741 	    sl->sl_trans_op != SL_OP_IMPORT_LU) {
742 		rw_exit(&sl->sl_access_state_lock);
743 		ret = SBD_FILEIO_FAILURE;
744 		goto sbd_write_meta_failure;
745 	}
746 	if (sl->sl_flags & SL_ZFS_META) {
747 		if ((ret = sbd_write_zfs_meta(sl, io_buf, io_size,
748 		    starting_off)) != SBD_SUCCESS) {
749 			rw_exit(&sl->sl_access_state_lock);
750 			goto sbd_write_meta_failure;
751 		}
752 	} else {
753 		vret = vn_rdwr(UIO_WRITE, vp, (caddr_t)io_buf, (ssize_t)io_size,
754 		    (offset_t)starting_off, UIO_SYSSPACE, FDSYNC,
755 		    RLIM64_INFINITY, CRED(), &resid);
756 
757 		if (vret || resid) {
758 			ret = SBD_FILEIO_FAILURE | vret;
759 			rw_exit(&sl->sl_access_state_lock);
760 			goto sbd_write_meta_failure;
761 		}
762 	}
763 	rw_exit(&sl->sl_access_state_lock);
764 
765 	ret = SBD_SUCCESS;
766 
767 sbd_write_meta_failure:
768 	kmem_free(io_buf, io_size);
769 	return (ret);
770 }
771 
772 uint8_t
773 sbd_calc_sum(uint8_t *buf, int size)
774 {
775 	uint8_t s = 0;
776 
777 	while (size > 0)
778 		s += buf[--size];
779 
780 	return (s);
781 }
782 
783 uint8_t
784 sbd_calc_section_sum(sm_section_hdr_t *sm, uint32_t sz)
785 {
786 	uint8_t s, o;
787 
788 	o = sm->sms_chksum;
789 	sm->sms_chksum = 0;
790 	s = sbd_calc_sum((uint8_t *)sm, sz);
791 	sm->sms_chksum = o;
792 
793 	return (s);
794 }
795 
796 uint32_t
797 sbd_strlen(char *str, uint32_t maxlen)
798 {
799 	uint32_t i;
800 
801 	for (i = 0; i < maxlen; i++) {
802 		if (str[i] == 0)
803 			return (i);
804 	}
805 	return (i);
806 }
807 
808 void
809 sbd_swap_meta_start(sbd_meta_start_t *sm)
810 {
811 	if (sm->sm_magic == SBD_MAGIC)
812 		return;
813 	sm->sm_magic		= BSWAP_64(sm->sm_magic);
814 	sm->sm_meta_size	= BSWAP_64(sm->sm_meta_size);
815 	sm->sm_meta_size_used	= BSWAP_64(sm->sm_meta_size_used);
816 	sm->sm_ver_major	= BSWAP_16(sm->sm_ver_major);
817 	sm->sm_ver_minor	= BSWAP_16(sm->sm_ver_minor);
818 	sm->sm_ver_subminor	= BSWAP_16(sm->sm_ver_subminor);
819 }
820 
821 void
822 sbd_swap_section_hdr(sm_section_hdr_t *sm)
823 {
824 	if (sm->sms_data_order == SMS_DATA_ORDER)
825 		return;
826 	sm->sms_offset		= BSWAP_64(sm->sms_offset);
827 	sm->sms_size		= BSWAP_32(sm->sms_size);
828 	sm->sms_id		= BSWAP_16(sm->sms_id);
829 	sm->sms_chksum		+= SMS_DATA_ORDER - sm->sms_data_order;
830 	sm->sms_data_order	= SMS_DATA_ORDER;
831 }
832 
833 void
834 sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t *sli)
835 {
836 	sbd_swap_section_hdr(&sli->sli_sms_header);
837 	if (sli->sli_data_order == SMS_DATA_ORDER)
838 		return;
839 	sli->sli_sms_header.sms_chksum	+= SMS_DATA_ORDER - sli->sli_data_order;
840 	sli->sli_data_order		= SMS_DATA_ORDER;
841 	sli->sli_total_store_size	= BSWAP_64(sli->sli_total_store_size);
842 	sli->sli_total_meta_size	= BSWAP_64(sli->sli_total_meta_size);
843 	sli->sli_lu_data_offset		= BSWAP_64(sli->sli_lu_data_offset);
844 	sli->sli_lu_data_size		= BSWAP_64(sli->sli_lu_data_size);
845 	sli->sli_flags			= BSWAP_32(sli->sli_flags);
846 	sli->sli_blocksize		= BSWAP_16(sli->sli_blocksize);
847 }
848 
849 void
850 sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t *sli)
851 {
852 	sbd_swap_section_hdr(&sli->sli_sms_header);
853 	if (sli->sli_data_order == SMS_DATA_ORDER)
854 		return;
855 	sli->sli_sms_header.sms_chksum	+= SMS_DATA_ORDER - sli->sli_data_order;
856 	sli->sli_data_order		= SMS_DATA_ORDER;
857 	sli->sli_flags			= BSWAP_32(sli->sli_flags);
858 	sli->sli_lu_size		= BSWAP_64(sli->sli_lu_size);
859 	sli->sli_meta_fname_offset	= BSWAP_64(sli->sli_meta_fname_offset);
860 	sli->sli_data_fname_offset	= BSWAP_64(sli->sli_data_fname_offset);
861 	sli->sli_serial_offset		= BSWAP_64(sli->sli_serial_offset);
862 	sli->sli_alias_offset		= BSWAP_64(sli->sli_alias_offset);
863 	sli->sli_mgmt_url_offset	= BSWAP_64(sli->sli_mgmt_url_offset);
864 }
865 
866 sbd_status_t
867 sbd_load_section_hdr(sbd_lu_t *sl, sm_section_hdr_t *sms)
868 {
869 	sm_section_hdr_t	h;
870 	uint64_t		st;
871 	sbd_status_t 		ret;
872 
873 	for (st = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
874 	    st < sl->sl_meta_size_used; st += h.sms_size) {
875 		if ((ret = sbd_read_meta(sl, st, sizeof (sm_section_hdr_t),
876 		    (uint8_t *)&h)) != SBD_SUCCESS) {
877 			return (ret);
878 		}
879 		if (h.sms_data_order != SMS_DATA_ORDER) {
880 			sbd_swap_section_hdr(&h);
881 		}
882 		if ((h.sms_data_order != SMS_DATA_ORDER) ||
883 		    (h.sms_offset != st) || (h.sms_size < sizeof (h)) ||
884 		    ((st + h.sms_size) > sl->sl_meta_size_used)) {
885 			return (SBD_META_CORRUPTED);
886 		}
887 		if (h.sms_id == sms->sms_id) {
888 			bcopy(&h, sms, sizeof (h));
889 			return (SBD_SUCCESS);
890 		}
891 	}
892 
893 	return (SBD_NOT_FOUND);
894 }
895 
896 sbd_status_t
897 sbd_load_meta_start(sbd_lu_t *sl)
898 {
899 	sbd_meta_start_t *sm;
900 	sbd_status_t ret;
901 
902 	/* Fake meta params initially */
903 	sl->sl_total_meta_size = (uint64_t)-1;
904 	sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
905 
906 	sm = kmem_zalloc(sizeof (*sm), KM_SLEEP);
907 	ret = sbd_read_meta(sl, sl->sl_meta_offset, sizeof (*sm),
908 	    (uint8_t *)sm);
909 	if (ret != SBD_SUCCESS) {
910 		goto load_meta_start_failed;
911 	}
912 
913 	if (sm->sm_magic != SBD_MAGIC) {
914 		sbd_swap_meta_start(sm);
915 	}
916 
917 	if ((sm->sm_magic != SBD_MAGIC) || (sbd_calc_sum((uint8_t *)sm,
918 	    sizeof (*sm) - 1) != sm->sm_chksum)) {
919 		ret = SBD_META_CORRUPTED;
920 		goto load_meta_start_failed;
921 	}
922 
923 	if (sm->sm_ver_major != SBD_VER_MAJOR) {
924 		ret = SBD_NOT_SUPPORTED;
925 		goto load_meta_start_failed;
926 	}
927 
928 	sl->sl_total_meta_size = sm->sm_meta_size;
929 	sl->sl_meta_size_used = sm->sm_meta_size_used;
930 	ret = SBD_SUCCESS;
931 
932 load_meta_start_failed:
933 	kmem_free(sm, sizeof (*sm));
934 	return (ret);
935 }
936 
937 sbd_status_t
938 sbd_write_meta_start(sbd_lu_t *sl, uint64_t meta_size, uint64_t meta_size_used)
939 {
940 	sbd_meta_start_t *sm;
941 	sbd_status_t ret;
942 
943 	sm = (sbd_meta_start_t *)kmem_zalloc(sizeof (sbd_meta_start_t),
944 	    KM_SLEEP);
945 
946 	sm->sm_magic = SBD_MAGIC;
947 	sm->sm_meta_size = meta_size;
948 	sm->sm_meta_size_used = meta_size_used;
949 	sm->sm_ver_major = SBD_VER_MAJOR;
950 	sm->sm_ver_minor = SBD_VER_MINOR;
951 	sm->sm_ver_subminor = SBD_VER_SUBMINOR;
952 	sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (*sm) - 1);
953 
954 	ret = sbd_write_meta(sl, sl->sl_meta_offset, sizeof (*sm),
955 	    (uint8_t *)sm);
956 	kmem_free(sm, sizeof (*sm));
957 
958 	return (ret);
959 }
960 
961 sbd_status_t
962 sbd_read_meta_section(sbd_lu_t *sl, sm_section_hdr_t **ppsms, uint16_t sms_id)
963 {
964 	sbd_status_t ret;
965 	sm_section_hdr_t sms;
966 	int alloced = 0;
967 
968 	mutex_enter(&sl->sl_metadata_lock);
969 	if (((*ppsms) == NULL) || ((*ppsms)->sms_offset == 0)) {
970 		bzero(&sms, sizeof (sm_section_hdr_t));
971 		sms.sms_id = sms_id;
972 		if ((ret = sbd_load_section_hdr(sl, &sms)) != SBD_SUCCESS) {
973 			mutex_exit(&sl->sl_metadata_lock);
974 			return (ret);
975 		} else {
976 			if ((*ppsms) == NULL) {
977 				*ppsms = (sm_section_hdr_t *)kmem_zalloc(
978 				    sms.sms_size, KM_SLEEP);
979 				alloced = 1;
980 			}
981 			bcopy(&sms, *ppsms, sizeof (sm_section_hdr_t));
982 		}
983 	}
984 
985 	ret = sbd_read_meta(sl, (*ppsms)->sms_offset, (*ppsms)->sms_size,
986 	    (uint8_t *)(*ppsms));
987 	if (ret == SBD_SUCCESS) {
988 		uint8_t s;
989 		if ((*ppsms)->sms_data_order != SMS_DATA_ORDER)
990 			sbd_swap_section_hdr(*ppsms);
991 		if ((*ppsms)->sms_id != SMS_ID_UNUSED) {
992 			s = sbd_calc_section_sum(*ppsms, (*ppsms)->sms_size);
993 			if (s != (*ppsms)->sms_chksum)
994 				ret = SBD_META_CORRUPTED;
995 		}
996 	}
997 	mutex_exit(&sl->sl_metadata_lock);
998 
999 	if ((ret != SBD_SUCCESS) && alloced)
1000 		kmem_free(*ppsms, sms.sms_size);
1001 	return (ret);
1002 }
1003 
1004 sbd_status_t
1005 sbd_load_section_hdr_unbuffered(sbd_lu_t *sl, sm_section_hdr_t *sms)
1006 {
1007 	sbd_status_t	ret;
1008 
1009 	/*
1010 	 * Bypass buffering and re-read the meta data from permanent storage.
1011 	 */
1012 	if (sl->sl_flags & SL_ZFS_META) {
1013 		if ((ret = sbd_open_zfs_meta(sl)) != SBD_SUCCESS) {
1014 			return (ret);
1015 		}
1016 	}
1017 	/* Re-get the meta sizes into sl */
1018 	if ((ret = sbd_load_meta_start(sl)) != SBD_SUCCESS) {
1019 		return (ret);
1020 	}
1021 	return (sbd_load_section_hdr(sl, sms));
1022 }
1023 
1024 sbd_status_t
1025 sbd_write_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms)
1026 {
1027 	sm_section_hdr_t t;
1028 	uint64_t off, s;
1029 	uint64_t unused_start;
1030 	sbd_status_t ret;
1031 	sbd_status_t write_meta_ret = SBD_SUCCESS;
1032 	uint8_t *cb;
1033 	int meta_size_changed = 0;
1034 	sm_section_hdr_t sms_before_unused = {0};
1035 
1036 	mutex_enter(&sl->sl_metadata_lock);
1037 write_meta_section_again:
1038 	if (sms->sms_offset) {
1039 		/*
1040 		 * If the section already exists and the size is the
1041 		 * same as this new data then overwrite in place. If
1042 		 * the sizes are different then mark the existing as
1043 		 * unused and look for free space.
1044 		 */
1045 		ret = sbd_read_meta(sl, sms->sms_offset, sizeof (t),
1046 		    (uint8_t *)&t);
1047 		if (ret != SBD_SUCCESS) {
1048 			mutex_exit(&sl->sl_metadata_lock);
1049 			return (ret);
1050 		}
1051 		if (t.sms_data_order != SMS_DATA_ORDER) {
1052 			sbd_swap_section_hdr(&t);
1053 		}
1054 		if (t.sms_id != sms->sms_id) {
1055 			mutex_exit(&sl->sl_metadata_lock);
1056 			return (SBD_INVALID_ARG);
1057 		}
1058 		if (t.sms_size == sms->sms_size) {
1059 			ret = sbd_write_meta(sl, sms->sms_offset,
1060 			    sms->sms_size, (uint8_t *)sms);
1061 			mutex_exit(&sl->sl_metadata_lock);
1062 			return (ret);
1063 		}
1064 		sms_before_unused = t;
1065 
1066 		t.sms_id = SMS_ID_UNUSED;
1067 		/*
1068 		 * For unused sections we only use chksum of the header. for
1069 		 * all other sections, the chksum is for the entire section.
1070 		 */
1071 		t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1072 		ret = sbd_write_meta(sl, t.sms_offset, sizeof (t),
1073 		    (uint8_t *)&t);
1074 		if (ret != SBD_SUCCESS) {
1075 			mutex_exit(&sl->sl_metadata_lock);
1076 			return (ret);
1077 		}
1078 		sms->sms_offset = 0;
1079 	} else {
1080 		/* Section location is unknown, search for it. */
1081 		t.sms_id = sms->sms_id;
1082 		t.sms_data_order = SMS_DATA_ORDER;
1083 		ret = sbd_load_section_hdr(sl, &t);
1084 		if (ret == SBD_SUCCESS) {
1085 			sms->sms_offset = t.sms_offset;
1086 			sms->sms_chksum =
1087 			    sbd_calc_section_sum(sms, sms->sms_size);
1088 			goto write_meta_section_again;
1089 		} else if (ret != SBD_NOT_FOUND) {
1090 			mutex_exit(&sl->sl_metadata_lock);
1091 			return (ret);
1092 		}
1093 	}
1094 
1095 	/*
1096 	 * At this point we know that section does not already exist.
1097 	 * Find space large enough to hold the section or grow meta if
1098 	 * possible.
1099 	 */
1100 	unused_start = 0;
1101 	s = 0;	/* size of space found */
1102 
1103 	/*
1104 	 * Search all sections for unused space of sufficient size.
1105 	 * The first one found is taken. Contiguous unused sections
1106 	 * will be combined.
1107 	 */
1108 	for (off = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1109 	    off < sl->sl_meta_size_used; off += t.sms_size) {
1110 		ret = sbd_read_meta(sl, off, sizeof (t), (uint8_t *)&t);
1111 		if (ret != SBD_SUCCESS) {
1112 			mutex_exit(&sl->sl_metadata_lock);
1113 			return (ret);
1114 		}
1115 		if (t.sms_data_order != SMS_DATA_ORDER)
1116 			sbd_swap_section_hdr(&t);
1117 		if (t.sms_size == 0) {
1118 			mutex_exit(&sl->sl_metadata_lock);
1119 			return (SBD_META_CORRUPTED);
1120 		}
1121 		if (t.sms_id == SMS_ID_UNUSED) {
1122 			if (unused_start == 0)
1123 				unused_start = off;
1124 			/*
1125 			 * Calculate size of the unused space, break out
1126 			 * if it satisfies the requirement.
1127 			 */
1128 			s = t.sms_size - unused_start + off;
1129 			if ((s == sms->sms_size) || (s >= (sms->sms_size +
1130 			    sizeof (t)))) {
1131 				break;
1132 			} else {
1133 				s = 0;
1134 			}
1135 		} else {
1136 			unused_start = 0;
1137 		}
1138 	}
1139 
1140 	off = (unused_start == 0) ? sl->sl_meta_size_used : unused_start;
1141 	/*
1142 	 * If none found, how much room is at the end?
1143 	 * See if the data can be expanded.
1144 	 */
1145 	if (s == 0) {
1146 		s = sl->sl_total_meta_size - off;
1147 		if (s >= sms->sms_size || !(sl->sl_flags & SL_SHARED_META)) {
1148 			s = sms->sms_size;
1149 			meta_size_changed = 1;
1150 		} else {
1151 			s = 0;
1152 		}
1153 	}
1154 
1155 	if (s == 0) {
1156 		mutex_exit(&sl->sl_metadata_lock);
1157 		return (SBD_ALLOC_FAILURE);
1158 	}
1159 
1160 	sms->sms_offset = off;
1161 	sms->sms_chksum = sbd_calc_section_sum(sms, sms->sms_size);
1162 	/*
1163 	 * Since we may have to write more than one section (current +
1164 	 * any unused), use a combined buffer.
1165 	 */
1166 	cb = kmem_zalloc(s, KM_SLEEP);
1167 	bcopy(sms, cb, sms->sms_size);
1168 	if (s > sms->sms_size) {
1169 		t.sms_offset = off + sms->sms_size;
1170 		t.sms_size = s - sms->sms_size;
1171 		t.sms_id = SMS_ID_UNUSED;
1172 		t.sms_data_order = SMS_DATA_ORDER;
1173 		t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1174 		bcopy(&t, cb + sms->sms_size, sizeof (t));
1175 	}
1176 	/*
1177 	 * Two write events & statuses take place. Failure writing the
1178 	 * meta section takes precedence, can possibly be rolled back,
1179 	 * & gets reported. Else return status from writing the meta start.
1180 	 */
1181 	ret = SBD_SUCCESS; /* Set a default, it's not always loaded below. */
1182 	if (meta_size_changed) {
1183 		uint64_t old_meta_size;
1184 		uint64_t old_sz_used = sl->sl_meta_size_used; /* save a copy */
1185 		old_meta_size = sl->sl_total_meta_size; /* save a copy */
1186 
1187 		write_meta_ret = sbd_write_meta(sl, off, s, cb);
1188 		if (write_meta_ret == SBD_SUCCESS) {
1189 			sl->sl_meta_size_used = off + s;
1190 			if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
1191 				uint64_t meta_align =
1192 				    (((uint64_t)1) <<
1193 				    sl->sl_meta_blocksize_shift) - 1;
1194 				sl->sl_total_meta_size =
1195 				    (sl->sl_meta_size_used + meta_align) &
1196 				    (~meta_align);
1197 			}
1198 			ret = sbd_write_meta_start(sl, sl->sl_total_meta_size,
1199 			    sl->sl_meta_size_used);
1200 			if (ret != SBD_SUCCESS) {
1201 				sl->sl_meta_size_used = old_sz_used;
1202 				sl->sl_total_meta_size = old_meta_size;
1203 			}
1204 		} else {
1205 			sl->sl_meta_size_used = old_sz_used;
1206 			sl->sl_total_meta_size = old_meta_size;
1207 		}
1208 	} else {
1209 		write_meta_ret = sbd_write_meta(sl, off, s, cb);
1210 	}
1211 	if ((write_meta_ret != SBD_SUCCESS) &&
1212 	    (sms_before_unused.sms_offset != 0)) {
1213 		sm_section_hdr_t new_sms;
1214 		sm_section_hdr_t *unused_sms;
1215 		/*
1216 		 * On failure writing the meta section attempt to undo
1217 		 * the change to unused.
1218 		 * Re-read the meta data from permanent storage.
1219 		 * The section id can't exist for undo to be possible.
1220 		 * Read what should be the entire old section data and
1221 		 * insure the old data's still present by validating
1222 		 * against it's old checksum.
1223 		 */
1224 		new_sms.sms_id = sms->sms_id;
1225 		new_sms.sms_data_order = SMS_DATA_ORDER;
1226 		if (sbd_load_section_hdr_unbuffered(sl, &new_sms) !=
1227 		    SBD_NOT_FOUND) {
1228 			goto done;
1229 		}
1230 		unused_sms = kmem_zalloc(sms_before_unused.sms_size, KM_SLEEP);
1231 		if (sbd_read_meta(sl, sms_before_unused.sms_offset,
1232 		    sms_before_unused.sms_size,
1233 		    (uint8_t *)unused_sms) != SBD_SUCCESS) {
1234 			goto done;
1235 		}
1236 		if (unused_sms->sms_data_order != SMS_DATA_ORDER) {
1237 			sbd_swap_section_hdr(unused_sms);
1238 		}
1239 		if (unused_sms->sms_id != SMS_ID_UNUSED) {
1240 			goto done;
1241 		}
1242 		if (unused_sms->sms_offset != sms_before_unused.sms_offset) {
1243 			goto done;
1244 		}
1245 		if (unused_sms->sms_size != sms_before_unused.sms_size) {
1246 			goto done;
1247 		}
1248 		unused_sms->sms_id = sms_before_unused.sms_id;
1249 		if (sbd_calc_section_sum(unused_sms,
1250 		    sizeof (sm_section_hdr_t)) !=
1251 		    sbd_calc_section_sum(&sms_before_unused,
1252 		    sizeof (sm_section_hdr_t))) {
1253 			goto done;
1254 		}
1255 		unused_sms->sms_chksum =
1256 		    sbd_calc_section_sum(unused_sms, unused_sms->sms_size);
1257 		if (unused_sms->sms_chksum != sms_before_unused.sms_chksum) {
1258 			goto done;
1259 		}
1260 		(void) sbd_write_meta(sl, unused_sms->sms_offset,
1261 		    sizeof (sm_section_hdr_t), (uint8_t *)unused_sms);
1262 	}
1263 done:
1264 	mutex_exit(&sl->sl_metadata_lock);
1265 	kmem_free(cb, s);
1266 	if (write_meta_ret != SBD_SUCCESS) {
1267 		return (write_meta_ret);
1268 	}
1269 	return (ret);
1270 }
1271 
1272 sbd_status_t
1273 sbd_write_lu_info(sbd_lu_t *sl)
1274 {
1275 	sbd_lu_info_1_1_t *sli;
1276 	int s;
1277 	uint8_t *p;
1278 	char *zvol_name = NULL;
1279 	sbd_status_t ret;
1280 
1281 	mutex_enter(&sl->sl_lock);
1282 
1283 	s = sl->sl_serial_no_size;
1284 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1285 		if (sl->sl_data_filename) {
1286 			s += strlen(sl->sl_data_filename) + 1;
1287 		}
1288 	}
1289 	if (sl->sl_flags & SL_ZFS_META) {
1290 		zvol_name = sbd_get_zvol_name(sl);
1291 		s += strlen(zvol_name) + 1;
1292 	}
1293 	if (sl->sl_alias) {
1294 		s += strlen(sl->sl_alias) + 1;
1295 	}
1296 	if (sl->sl_mgmt_url) {
1297 		s += strlen(sl->sl_mgmt_url) + 1;
1298 	}
1299 	sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP);
1300 	p = sli->sli_buf;
1301 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1302 		sli->sli_flags |= SLI_SEPARATE_META;
1303 		(void) strcpy((char *)p, sl->sl_data_filename);
1304 		sli->sli_data_fname_offset =
1305 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1306 		sli->sli_flags |= SLI_DATA_FNAME_VALID;
1307 		p += strlen(sl->sl_data_filename) + 1;
1308 	}
1309 	if (sl->sl_flags & SL_ZFS_META) {
1310 		(void) strcpy((char *)p, zvol_name);
1311 		sli->sli_meta_fname_offset =
1312 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1313 		sli->sli_flags |= SLI_META_FNAME_VALID | SLI_ZFS_META;
1314 		p += strlen(zvol_name) + 1;
1315 		kmem_free(zvol_name, strlen(zvol_name) + 1);
1316 		zvol_name = NULL;
1317 	}
1318 	if (sl->sl_alias) {
1319 		(void) strcpy((char *)p, sl->sl_alias);
1320 		sli->sli_alias_offset =
1321 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1322 		sli->sli_flags |= SLI_ALIAS_VALID;
1323 		p += strlen(sl->sl_alias) + 1;
1324 	}
1325 	if (sl->sl_mgmt_url) {
1326 		(void) strcpy((char *)p, sl->sl_mgmt_url);
1327 		sli->sli_mgmt_url_offset =
1328 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1329 		sli->sli_flags |= SLI_MGMT_URL_VALID;
1330 		p += strlen(sl->sl_mgmt_url) + 1;
1331 	}
1332 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
1333 		sli->sli_flags |= SLI_WRITE_PROTECTED;
1334 	}
1335 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
1336 		sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE;
1337 	}
1338 	if (sl->sl_flags & SL_VID_VALID) {
1339 		bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
1340 		sli->sli_flags |= SLI_VID_VALID;
1341 	}
1342 	if (sl->sl_flags & SL_PID_VALID) {
1343 		bcopy(sl->sl_product_id, sli->sli_pid, 16);
1344 		sli->sli_flags |= SLI_PID_VALID;
1345 	}
1346 	if (sl->sl_flags & SL_REV_VALID) {
1347 		bcopy(sl->sl_revision, sli->sli_rev, 4);
1348 		sli->sli_flags |= SLI_REV_VALID;
1349 	}
1350 	if (sl->sl_serial_no_size) {
1351 		bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size);
1352 		sli->sli_serial_size = sl->sl_serial_no_size;
1353 		sli->sli_serial_offset =
1354 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1355 		sli->sli_flags |= SLI_SERIAL_VALID;
1356 		p += sli->sli_serial_size;
1357 	}
1358 	sli->sli_lu_size = sl->sl_lu_size;
1359 	sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1360 	sli->sli_data_order = SMS_DATA_ORDER;
1361 	bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1362 
1363 	sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1364 	sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1365 	sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1366 
1367 	mutex_exit(&sl->sl_lock);
1368 	ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1369 	kmem_free(sli, sizeof (*sli) + s);
1370 	return (ret);
1371 }
1372 
1373 int
1374 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1375 {
1376 	stmf_lu_t *lu = sl->sl_lu;
1377 	stmf_status_t ret;
1378 
1379 	lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1380 	if (sl->sl_alias) {
1381 		lu->lu_alias = sl->sl_alias;
1382 	} else {
1383 		lu->lu_alias = sl->sl_name;
1384 	}
1385 	if (sl->sl_access_state == SBD_LU_STANDBY) {
1386 		/* call set access state */
1387 		ret = stmf_set_lu_access(lu, STMF_LU_STANDBY);
1388 		if (ret != STMF_SUCCESS) {
1389 			*err_ret = SBD_RET_ACCESS_STATE_FAILED;
1390 			return (EIO);
1391 		}
1392 	}
1393 	/* set proxy_reg_cb_arg to meta filename */
1394 	if (sl->sl_meta_filename) {
1395 		lu->lu_proxy_reg_arg = sl->sl_meta_filename;
1396 		lu->lu_proxy_reg_arg_len = strlen(sl->sl_meta_filename) + 1;
1397 	} else {
1398 		lu->lu_proxy_reg_arg = sl->sl_data_filename;
1399 		lu->lu_proxy_reg_arg_len = strlen(sl->sl_data_filename) + 1;
1400 	}
1401 	lu->lu_lp = sbd_lp;
1402 	lu->lu_task_alloc = sbd_task_alloc;
1403 	lu->lu_new_task = sbd_new_task;
1404 	lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
1405 	lu->lu_send_status_done = sbd_send_status_done;
1406 	lu->lu_task_free = sbd_task_free;
1407 	lu->lu_abort = sbd_abort;
1408 	lu->lu_dbuf_free = sbd_dbuf_free;
1409 	lu->lu_ctl = sbd_ctl;
1410 	lu->lu_info = sbd_info;
1411 	sl->sl_state = STMF_STATE_OFFLINE;
1412 
1413 	if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
1414 		stmf_trace(0, "Failed to register with framework, ret=%llx",
1415 		    ret);
1416 		if (ret == STMF_ALREADY) {
1417 			*err_ret = SBD_RET_GUID_ALREADY_REGISTERED;
1418 		}
1419 		return (EIO);
1420 	}
1421 
1422 	*err_ret = 0;
1423 	return (0);
1424 }
1425 
1426 int
1427 sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid,
1428     int vp_valid, int keep_open)
1429 {
1430 	int ret;
1431 	int flag;
1432 	ulong_t	nbits;
1433 	uint64_t supported_size;
1434 	vattr_t vattr;
1435 	enum vtype vt;
1436 	struct dk_cinfo dki;
1437 	int unused;
1438 
1439 	mutex_enter(&sl->sl_lock);
1440 	if (vp_valid) {
1441 		goto odf_over_open;
1442 	}
1443 	if (sl->sl_data_filename[0] != '/') {
1444 		*err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE;
1445 		mutex_exit(&sl->sl_lock);
1446 		return (EINVAL);
1447 	}
1448 	if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW,
1449 	    NULLVPP, &sl->sl_data_vp)) != 0) {
1450 		*err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED;
1451 		mutex_exit(&sl->sl_lock);
1452 		return (ret);
1453 	}
1454 	sl->sl_data_vtype = vt = sl->sl_data_vp->v_type;
1455 	VN_RELE(sl->sl_data_vp);
1456 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1457 		*err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1458 		mutex_exit(&sl->sl_lock);
1459 		return (EINVAL);
1460 	}
1461 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
1462 		flag = FREAD | FOFFMAX;
1463 	} else {
1464 		flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1465 	}
1466 	if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0,
1467 	    &sl->sl_data_vp, 0, 0)) != 0) {
1468 		*err_ret = SBD_RET_DATA_FILE_OPEN_FAILED;
1469 		mutex_exit(&sl->sl_lock);
1470 		return (ret);
1471 	}
1472 odf_over_open:
1473 	vattr.va_mask = AT_SIZE;
1474 	if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) {
1475 		*err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED;
1476 		goto odf_close_data_and_exit;
1477 	}
1478 	if ((vt != VREG) && (vattr.va_size == 0)) {
1479 		/*
1480 		 * Its a zero byte block or char device. This cannot be
1481 		 * a raw disk.
1482 		 */
1483 		*err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1484 		ret = EINVAL;
1485 		goto odf_close_data_and_exit;
1486 	}
1487 	/* sl_data_readable size includes any metadata. */
1488 	sl->sl_data_readable_size = vattr.va_size;
1489 
1490 	if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits,
1491 	    CRED(), NULL) != 0) {
1492 		nbits = 0;
1493 	}
1494 	/* nbits cannot be greater than 64 */
1495 	sl->sl_data_fs_nbits = (uint8_t)nbits;
1496 	if (lu_size_valid) {
1497 		sl->sl_total_data_size = sl->sl_lu_size;
1498 		if (sl->sl_flags & SL_SHARED_META) {
1499 			sl->sl_total_data_size += SHARED_META_DATA_SIZE;
1500 		}
1501 		if ((nbits > 0) && (nbits < 64)) {
1502 			/*
1503 			 * The expression below is correct only if nbits is
1504 			 * positive and less than 64.
1505 			 */
1506 			supported_size = (((uint64_t)1) << nbits) - 1;
1507 			if (sl->sl_total_data_size > supported_size) {
1508 				*err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS;
1509 				ret = EINVAL;
1510 				goto odf_close_data_and_exit;
1511 			}
1512 		}
1513 	} else {
1514 		sl->sl_total_data_size = vattr.va_size;
1515 		if (sl->sl_flags & SL_SHARED_META) {
1516 			if (vattr.va_size > SHARED_META_DATA_SIZE) {
1517 				sl->sl_lu_size = vattr.va_size -
1518 				    SHARED_META_DATA_SIZE;
1519 			} else {
1520 				*err_ret = SBD_RET_FILE_SIZE_ERROR;
1521 				ret = EINVAL;
1522 				goto odf_close_data_and_exit;
1523 			}
1524 		} else {
1525 			sl->sl_lu_size = vattr.va_size;
1526 		}
1527 	}
1528 	if (sl->sl_lu_size < SBD_MIN_LU_SIZE) {
1529 		*err_ret = SBD_RET_FILE_SIZE_ERROR;
1530 		ret = EINVAL;
1531 		goto odf_close_data_and_exit;
1532 	}
1533 	if (sl->sl_lu_size &
1534 	    ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) {
1535 		*err_ret = SBD_RET_FILE_ALIGN_ERROR;
1536 		ret = EINVAL;
1537 		goto odf_close_data_and_exit;
1538 	}
1539 	/*
1540 	 * Get the minor device for direct zvol access
1541 	 */
1542 	if (sl->sl_flags & SL_ZFS_META) {
1543 		if ((ret = VOP_IOCTL(sl->sl_data_vp, DKIOCINFO, (intptr_t)&dki,
1544 		    FKIOCTL, kcred, &unused, NULL)) != 0) {
1545 			cmn_err(CE_WARN, "ioctl(DKIOCINFO) failed %d", ret);
1546 			/* zvol reserves 0, so this would fail later */
1547 			sl->sl_zvol_minor = 0;
1548 		} else {
1549 			sl->sl_zvol_minor = dki.dki_unit;
1550 			if (sbd_zvol_get_volume_params(sl) == 0)
1551 				sl->sl_flags |= SL_CALL_ZVOL;
1552 		}
1553 	}
1554 	sl->sl_flags |= SL_MEDIA_LOADED;
1555 	mutex_exit(&sl->sl_lock);
1556 	return (0);
1557 
1558 odf_close_data_and_exit:
1559 	if (!keep_open) {
1560 		(void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1561 		VN_RELE(sl->sl_data_vp);
1562 	}
1563 	mutex_exit(&sl->sl_lock);
1564 	return (ret);
1565 }
1566 
1567 void
1568 sbd_close_lu(sbd_lu_t *sl)
1569 {
1570 	int flag;
1571 
1572 	if (((sl->sl_flags & SL_SHARED_META) == 0) &&
1573 	    (sl->sl_flags & SL_META_OPENED)) {
1574 		if (sl->sl_flags & SL_ZFS_META) {
1575 			rw_destroy(&sl->sl_zfs_meta_lock);
1576 			if (sl->sl_zfs_meta) {
1577 				kmem_free(sl->sl_zfs_meta, ZAP_MAXVALUELEN / 2);
1578 				sl->sl_zfs_meta = NULL;
1579 			}
1580 		} else {
1581 			flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1582 			(void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0,
1583 			    CRED(), NULL);
1584 			VN_RELE(sl->sl_meta_vp);
1585 		}
1586 		sl->sl_flags &= ~SL_META_OPENED;
1587 	}
1588 	if (sl->sl_flags & SL_MEDIA_LOADED) {
1589 		if (sl->sl_flags & SL_WRITE_PROTECTED) {
1590 			flag = FREAD | FOFFMAX;
1591 		} else {
1592 			flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1593 		}
1594 		(void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1595 		VN_RELE(sl->sl_data_vp);
1596 		sl->sl_flags &= ~SL_MEDIA_LOADED;
1597 		if (sl->sl_flags & SL_SHARED_META) {
1598 			sl->sl_flags &= ~SL_META_OPENED;
1599 		}
1600 	}
1601 }
1602 
1603 int
1604 sbd_set_lu_standby(sbd_set_lu_standby_t *stlu, uint32_t *err_ret)
1605 {
1606 	sbd_lu_t *sl;
1607 	sbd_status_t sret;
1608 	stmf_status_t stret;
1609 	uint8_t old_access_state;
1610 
1611 	sret = sbd_find_and_lock_lu(stlu->stlu_guid, NULL,
1612 	    SL_OP_MODIFY_LU, &sl);
1613 	if (sret != SBD_SUCCESS) {
1614 		if (sret == SBD_BUSY) {
1615 			*err_ret = SBD_RET_LU_BUSY;
1616 			return (EBUSY);
1617 		} else if (sret == SBD_NOT_FOUND) {
1618 			*err_ret = SBD_RET_NOT_FOUND;
1619 			return (ENOENT);
1620 		}
1621 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
1622 		return (EIO);
1623 	}
1624 
1625 	old_access_state = sl->sl_access_state;
1626 	sl->sl_access_state = SBD_LU_TRANSITION_TO_STANDBY;
1627 	stret = stmf_set_lu_access((stmf_lu_t *)sl->sl_lu, STMF_LU_STANDBY);
1628 	if (stret != STMF_SUCCESS) {
1629 		sl->sl_trans_op = SL_OP_NONE;
1630 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
1631 		sl->sl_access_state = old_access_state;
1632 		return (EIO);
1633 	}
1634 
1635 	/*
1636 	 * acquire the writer lock here to ensure we're not pulling
1637 	 * the rug from the vn_rdwr to the backing store
1638 	 */
1639 	rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1640 	sbd_close_lu(sl);
1641 	rw_exit(&sl->sl_access_state_lock);
1642 
1643 	sl->sl_trans_op = SL_OP_NONE;
1644 	return (0);
1645 }
1646 
1647 int
1648 sbd_close_delete_lu(sbd_lu_t *sl, int ret)
1649 {
1650 
1651 	/*
1652 	 * acquire the writer lock here to ensure we're not pulling
1653 	 * the rug from the vn_rdwr to the backing store
1654 	 */
1655 	rw_enter(&sl->sl_access_state_lock, RW_WRITER);
1656 	sbd_close_lu(sl);
1657 	rw_exit(&sl->sl_access_state_lock);
1658 
1659 	if (sl->sl_flags & SL_LINKED)
1660 		sbd_unlink_lu(sl);
1661 	mutex_destroy(&sl->sl_metadata_lock);
1662 	mutex_destroy(&sl->sl_lock);
1663 	rw_destroy(&sl->sl_pgr->pgr_lock);
1664 	rw_destroy(&sl->sl_access_state_lock);
1665 	if (sl->sl_serial_no_alloc_size) {
1666 		kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size);
1667 	}
1668 	if (sl->sl_data_fname_alloc_size) {
1669 		kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size);
1670 	}
1671 	if (sl->sl_alias_alloc_size) {
1672 		kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
1673 	}
1674 	if (sl->sl_mgmt_url_alloc_size) {
1675 		kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
1676 	}
1677 	stmf_free(sl->sl_lu);
1678 	return (ret);
1679 }
1680 
1681 int
1682 sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
1683     uint32_t *err_ret)
1684 {
1685 	char *namebuf;
1686 	sbd_lu_t *sl;
1687 	stmf_lu_t *lu;
1688 	sbd_status_t sret;
1689 	char *p;
1690 	int sz;
1691 	int alloc_sz;
1692 	int ret = EIO;
1693 	int flag;
1694 	int wcd = 0;
1695 	uint32_t hid = 0;
1696 	enum vtype vt;
1697 
1698 	sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1;
1699 
1700 	*err_ret = 0;
1701 
1702 	/* Lets validate various offsets */
1703 	if (((slu->slu_meta_fname_valid) &&
1704 	    (slu->slu_meta_fname_off >= sz)) ||
1705 	    (slu->slu_data_fname_off >= sz) ||
1706 	    ((slu->slu_alias_valid) &&
1707 	    (slu->slu_alias_off >= sz)) ||
1708 	    ((slu->slu_mgmt_url_valid) &&
1709 	    (slu->slu_mgmt_url_off >= sz)) ||
1710 	    ((slu->slu_serial_valid) &&
1711 	    ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
1712 		return (EINVAL);
1713 	}
1714 
1715 	namebuf = kmem_zalloc(sz, KM_SLEEP);
1716 	bcopy(slu->slu_buf, namebuf, sz - 1);
1717 	namebuf[sz - 1] = 0;
1718 
1719 	alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1720 	if (slu->slu_meta_fname_valid) {
1721 		alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1;
1722 	}
1723 	alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1;
1724 	if (slu->slu_alias_valid) {
1725 		alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
1726 	}
1727 	if (slu->slu_mgmt_url_valid) {
1728 		alloc_sz += strlen(namebuf + slu->slu_mgmt_url_off) + 1;
1729 	}
1730 	if (slu->slu_serial_valid) {
1731 		alloc_sz += slu->slu_serial_size;
1732 	}
1733 
1734 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
1735 	if (lu == NULL) {
1736 		kmem_free(namebuf, sz);
1737 		return (ENOMEM);
1738 	}
1739 	sl = (sbd_lu_t *)lu->lu_provider_private;
1740 	bzero(sl, alloc_sz);
1741 	sl->sl_lu = lu;
1742 	sl->sl_alloc_size = alloc_sz;
1743 	sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
1744 	rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
1745 	mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
1746 	mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
1747 	rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
1748 	p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1749 	sl->sl_data_filename = p;
1750 	(void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off);
1751 	p += strlen(sl->sl_data_filename) + 1;
1752 	sl->sl_meta_offset = SBD_META_OFFSET;
1753 	sl->sl_access_state = SBD_LU_ACTIVE;
1754 	if (slu->slu_meta_fname_valid) {
1755 		sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p;
1756 		(void) strcpy(sl->sl_meta_filename, namebuf +
1757 		    slu->slu_meta_fname_off);
1758 		p += strlen(sl->sl_meta_filename) + 1;
1759 	} else {
1760 		sl->sl_alias = sl->sl_name = sl->sl_data_filename;
1761 		if (sbd_is_zvol(sl->sl_data_filename)) {
1762 			sl->sl_flags |= SL_ZFS_META;
1763 			sl->sl_meta_offset = 0;
1764 		} else {
1765 			sl->sl_flags |= SL_SHARED_META;
1766 			sl->sl_data_offset = SHARED_META_DATA_SIZE;
1767 			sl->sl_total_meta_size = SHARED_META_DATA_SIZE;
1768 			sl->sl_meta_size_used = 0;
1769 		}
1770 	}
1771 	if (slu->slu_alias_valid) {
1772 		sl->sl_alias = p;
1773 		(void) strcpy(p, namebuf + slu->slu_alias_off);
1774 		p += strlen(sl->sl_alias) + 1;
1775 	}
1776 	if (slu->slu_mgmt_url_valid) {
1777 		sl->sl_mgmt_url = p;
1778 		(void) strcpy(p, namebuf + slu->slu_mgmt_url_off);
1779 		p += strlen(sl->sl_mgmt_url) + 1;
1780 	}
1781 	if (slu->slu_serial_valid) {
1782 		sl->sl_serial_no = (uint8_t *)p;
1783 		bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
1784 		    slu->slu_serial_size);
1785 		sl->sl_serial_no_size = slu->slu_serial_size;
1786 		p += slu->slu_serial_size;
1787 	}
1788 	kmem_free(namebuf, sz);
1789 	if (slu->slu_vid_valid) {
1790 		bcopy(slu->slu_vid, sl->sl_vendor_id, 8);
1791 		sl->sl_flags |= SL_VID_VALID;
1792 	}
1793 	if (slu->slu_pid_valid) {
1794 		bcopy(slu->slu_pid, sl->sl_product_id, 16);
1795 		sl->sl_flags |= SL_PID_VALID;
1796 	}
1797 	if (slu->slu_rev_valid) {
1798 		bcopy(slu->slu_rev, sl->sl_revision, 4);
1799 		sl->sl_flags |= SL_REV_VALID;
1800 	}
1801 	if (slu->slu_write_protected) {
1802 		sl->sl_flags |= SL_WRITE_PROTECTED;
1803 	}
1804 	if (slu->slu_writeback_cache_disable) {
1805 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1806 		    SL_SAVED_WRITE_CACHE_DISABLE;
1807 	}
1808 
1809 	if (slu->slu_blksize_valid) {
1810 		if ((slu->slu_blksize & (slu->slu_blksize - 1)) ||
1811 		    (slu->slu_blksize > (32 * 1024)) ||
1812 		    (slu->slu_blksize == 0)) {
1813 			*err_ret = SBD_RET_INVALID_BLKSIZE;
1814 			ret = EINVAL;
1815 			goto scm_err_out;
1816 		}
1817 		while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) {
1818 			sl->sl_data_blocksize_shift++;
1819 		}
1820 	} else {
1821 		sl->sl_data_blocksize_shift = 9;	/* 512 by default */
1822 		slu->slu_blksize = 512;
1823 	}
1824 
1825 	/* Now lets start creating meta */
1826 	sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
1827 	if (sbd_link_lu(sl) != SBD_SUCCESS) {
1828 		*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
1829 		ret = EALREADY;
1830 		goto scm_err_out;
1831 	}
1832 
1833 	/* 1st focus on the data store */
1834 	if (slu->slu_lu_size_valid) {
1835 		sl->sl_lu_size = slu->slu_lu_size;
1836 	}
1837 	ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0);
1838 	slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits;
1839 	slu->slu_lu_size = sl->sl_lu_size;
1840 	if (ret) {
1841 		goto scm_err_out;
1842 	}
1843 
1844 	/*
1845 	 * set write cache disable on the device
1846 	 * if it fails, we'll support it using sync/flush
1847 	 */
1848 	if (slu->slu_writeback_cache_disable) {
1849 		(void) sbd_wcd_set(1, sl);
1850 		wcd = 1;
1851 	/*
1852 	 * Attempt to set it to enable, if that fails and it was explicitly set
1853 	 * return an error, otherwise get the current setting and use that
1854 	 */
1855 	} else {
1856 		sret = sbd_wcd_set(0, sl);
1857 		if (slu->slu_writeback_cache_disable_valid &&
1858 		    sret != SBD_SUCCESS) {
1859 			*err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
1860 			ret = EFAULT;
1861 			goto scm_err_out;
1862 		}
1863 		if (sret != SBD_SUCCESS) {
1864 			sbd_wcd_get(&wcd, sl);
1865 		}
1866 	}
1867 
1868 	if (wcd) {
1869 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1870 		    SL_SAVED_WRITE_CACHE_DISABLE;
1871 	}
1872 
1873 	if (sl->sl_flags & SL_SHARED_META) {
1874 		goto over_meta_open;
1875 	}
1876 	if (sl->sl_flags & SL_ZFS_META) {
1877 		if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) {
1878 			*err_ret = SBD_RET_ZFS_META_CREATE_FAILED;
1879 			ret = ENOMEM;
1880 			goto scm_err_out;
1881 		}
1882 		sl->sl_meta_blocksize_shift = 0;
1883 		goto over_meta_create;
1884 	}
1885 	if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
1886 	    NULLVPP, &sl->sl_meta_vp)) != 0) {
1887 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
1888 		goto scm_err_out;
1889 	}
1890 	sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
1891 	VN_RELE(sl->sl_meta_vp);
1892 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1893 		*err_ret = SBD_RET_WRONG_META_FILE_TYPE;
1894 		ret = EINVAL;
1895 		goto scm_err_out;
1896 	}
1897 	if (vt == VREG) {
1898 		sl->sl_meta_blocksize_shift = 0;
1899 	} else {
1900 		sl->sl_meta_blocksize_shift = 9;
1901 	}
1902 	flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1903 	if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
1904 	    &sl->sl_meta_vp, 0, 0)) != 0) {
1905 		*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1906 		goto scm_err_out;
1907 	}
1908 over_meta_create:
1909 	sl->sl_total_meta_size = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1910 	sl->sl_total_meta_size +=
1911 	    (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
1912 	sl->sl_total_meta_size &=
1913 	    ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1);
1914 	sl->sl_meta_size_used = 0;
1915 over_meta_open:
1916 	sl->sl_flags |= SL_META_OPENED;
1917 
1918 	sl->sl_device_id[3] = 16;
1919 	if (slu->slu_guid_valid) {
1920 		sl->sl_device_id[0] = 0xf1;
1921 		sl->sl_device_id[1] = 3;
1922 		sl->sl_device_id[2] = 0;
1923 		bcopy(slu->slu_guid, sl->sl_device_id + 4, 16);
1924 	} else {
1925 		if (slu->slu_host_id_valid)
1926 			hid = slu->slu_host_id;
1927 		if (!slu->slu_company_id_valid)
1928 			slu->slu_company_id = COMPANY_ID_SUN;
1929 		if (stmf_scsilib_uniq_lu_id2(slu->slu_company_id, hid,
1930 		    (scsi_devid_desc_t *)&sl->sl_device_id[0]) !=
1931 		    STMF_SUCCESS) {
1932 			*err_ret = SBD_RET_META_CREATION_FAILED;
1933 			ret = EIO;
1934 			goto scm_err_out;
1935 		}
1936 		bcopy(sl->sl_device_id + 4, slu->slu_guid, 16);
1937 	}
1938 
1939 	/* Lets create the meta now */
1940 	mutex_enter(&sl->sl_metadata_lock);
1941 	if (sbd_write_meta_start(sl, sl->sl_total_meta_size,
1942 	    sizeof (sbd_meta_start_t)) != SBD_SUCCESS) {
1943 		mutex_exit(&sl->sl_metadata_lock);
1944 		*err_ret = SBD_RET_META_CREATION_FAILED;
1945 		ret = EIO;
1946 		goto scm_err_out;
1947 	}
1948 	mutex_exit(&sl->sl_metadata_lock);
1949 	sl->sl_meta_size_used = sl->sl_meta_offset + sizeof (sbd_meta_start_t);
1950 
1951 	if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
1952 		*err_ret = SBD_RET_META_CREATION_FAILED;
1953 		ret = EIO;
1954 		goto scm_err_out;
1955 	}
1956 
1957 	if (sbd_pgr_meta_init(sl) != SBD_SUCCESS) {
1958 		*err_ret = SBD_RET_META_CREATION_FAILED;
1959 		ret = EIO;
1960 		goto scm_err_out;
1961 	}
1962 
1963 	ret = sbd_populate_and_register_lu(sl, err_ret);
1964 	if (ret) {
1965 		goto scm_err_out;
1966 	}
1967 
1968 	sl->sl_trans_op = SL_OP_NONE;
1969 	atomic_add_32(&sbd_lu_count, 1);
1970 	return (0);
1971 
1972 scm_err_out:
1973 	return (sbd_close_delete_lu(sl, ret));
1974 }
1975 
1976 stmf_status_t
1977 sbd_proxy_msg(uint8_t *luid, void *proxy_arg, uint32_t proxy_arg_len,
1978     uint32_t type)
1979 {
1980 	switch (type) {
1981 		case STMF_MSG_LU_ACTIVE:
1982 			return (sbd_proxy_reg_lu(luid, proxy_arg,
1983 			    proxy_arg_len));
1984 		case STMF_MSG_LU_REGISTER:
1985 			return (sbd_proxy_reg_lu(luid, proxy_arg,
1986 			    proxy_arg_len));
1987 		case STMF_MSG_LU_DEREGISTER:
1988 			return (sbd_proxy_dereg_lu(luid, proxy_arg,
1989 			    proxy_arg_len));
1990 		default:
1991 			return (STMF_INVALID_ARG);
1992 	}
1993 }
1994 
1995 
1996 /*
1997  * register a standby logical unit
1998  * proxy_reg_arg contains the meta filename
1999  */
2000 stmf_status_t
2001 sbd_proxy_reg_lu(uint8_t *luid, void *proxy_reg_arg, uint32_t proxy_reg_arg_len)
2002 {
2003 	sbd_lu_t *sl;
2004 	sbd_status_t sret;
2005 	sbd_create_standby_lu_t *stlu;
2006 	int alloc_sz;
2007 	uint32_t err_ret = 0;
2008 	stmf_status_t stret = STMF_SUCCESS;
2009 
2010 	if (luid == NULL) {
2011 		return (STMF_INVALID_ARG);
2012 	}
2013 
2014 	do {
2015 		sret = sbd_find_and_lock_lu(luid, NULL, SL_OP_MODIFY_LU, &sl);
2016 	} while (sret == SBD_BUSY);
2017 
2018 	if (sret == SBD_NOT_FOUND) {
2019 		alloc_sz = sizeof (*stlu) + proxy_reg_arg_len - 8;
2020 		stlu = (sbd_create_standby_lu_t *)kmem_zalloc(alloc_sz,
2021 		    KM_SLEEP);
2022 		bcopy(luid, stlu->stlu_guid, 16);
2023 		if (proxy_reg_arg_len) {
2024 			bcopy(proxy_reg_arg, stlu->stlu_meta_fname,
2025 			    proxy_reg_arg_len);
2026 			stlu->stlu_meta_fname_size = proxy_reg_arg_len;
2027 		}
2028 		if (sbd_create_standby_lu(stlu, &err_ret) != 0) {
2029 			cmn_err(CE_WARN,
2030 			    "Unable to create standby logical unit for %s",
2031 			    stlu->stlu_meta_fname);
2032 			stret = STMF_FAILURE;
2033 		}
2034 		kmem_free(stlu, alloc_sz);
2035 		return (stret);
2036 	} else if (sret == SBD_SUCCESS) {
2037 		/*
2038 		 * if the lu is already registered, then the lu should now
2039 		 * be in standby mode
2040 		 */
2041 		sbd_it_data_t *it;
2042 		if (sl->sl_access_state != SBD_LU_STANDBY) {
2043 			mutex_enter(&sl->sl_lock);
2044 			sl->sl_access_state = SBD_LU_STANDBY;
2045 			for (it = sl->sl_it_list; it != NULL;
2046 			    it = it->sbd_it_next) {
2047 				it->sbd_it_ua_conditions |=
2048 				    SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2049 				it->sbd_it_flags &=
2050 				    ~SBD_IT_HAS_SCSI2_RESERVATION;
2051 				sl->sl_flags &= ~SL_LU_HAS_SCSI2_RESERVATION;
2052 			}
2053 			mutex_exit(&sl->sl_lock);
2054 			sbd_pgr_reset(sl);
2055 		}
2056 		sl->sl_trans_op = SL_OP_NONE;
2057 	} else {
2058 		cmn_err(CE_WARN, "could not find and lock logical unit");
2059 		stret = STMF_FAILURE;
2060 	}
2061 out:
2062 	return (stret);
2063 }
2064 
2065 /* ARGSUSED */
2066 stmf_status_t
2067 sbd_proxy_dereg_lu(uint8_t *luid, void *proxy_reg_arg,
2068     uint32_t proxy_reg_arg_len)
2069 {
2070 	sbd_delete_lu_t dlu = {0};
2071 	uint32_t err_ret;
2072 
2073 	if (luid == NULL) {
2074 		cmn_err(CE_WARN, "de-register lu request had null luid");
2075 		return (STMF_INVALID_ARG);
2076 	}
2077 
2078 	bcopy(luid, &dlu.dlu_guid, 16);
2079 
2080 	if (sbd_delete_lu(&dlu, (int)sizeof (dlu), &err_ret) != 0) {
2081 		cmn_err(CE_WARN, "failed to delete de-register lu request");
2082 		return (STMF_FAILURE);
2083 	}
2084 
2085 	return (STMF_SUCCESS);
2086 }
2087 
2088 int
2089 sbd_create_standby_lu(sbd_create_standby_lu_t *slu, uint32_t *err_ret)
2090 {
2091 	sbd_lu_t *sl;
2092 	stmf_lu_t *lu;
2093 	int ret = EIO;
2094 	int alloc_sz;
2095 
2096 	alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) +
2097 	    slu->stlu_meta_fname_size;
2098 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
2099 	if (lu == NULL) {
2100 		return (ENOMEM);
2101 	}
2102 	sl = (sbd_lu_t *)lu->lu_provider_private;
2103 	bzero(sl, alloc_sz);
2104 	sl->sl_lu = lu;
2105 	sl->sl_alloc_size = alloc_sz;
2106 
2107 	sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2108 	sl->sl_meta_filename = ((char *)sl) + sizeof (sbd_lu_t) +
2109 	    sizeof (sbd_pgr_t);
2110 
2111 	if (slu->stlu_meta_fname_size > 0) {
2112 		(void) strcpy(sl->sl_meta_filename, slu->stlu_meta_fname);
2113 	}
2114 	sl->sl_name = sl->sl_meta_filename;
2115 
2116 	sl->sl_device_id[3] = 16;
2117 	sl->sl_device_id[0] = 0xf1;
2118 	sl->sl_device_id[1] = 3;
2119 	sl->sl_device_id[2] = 0;
2120 	bcopy(slu->stlu_guid, sl->sl_device_id + 4, 16);
2121 	lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
2122 	sl->sl_access_state = SBD_LU_STANDBY;
2123 
2124 	rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2125 	mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2126 	mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2127 	rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2128 
2129 	sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
2130 
2131 	if (sbd_link_lu(sl) != SBD_SUCCESS) {
2132 		*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2133 		ret = EALREADY;
2134 		goto scs_err_out;
2135 	}
2136 
2137 	ret = sbd_populate_and_register_lu(sl, err_ret);
2138 	if (ret) {
2139 		goto scs_err_out;
2140 	}
2141 
2142 	sl->sl_trans_op = SL_OP_NONE;
2143 	atomic_add_32(&sbd_lu_count, 1);
2144 	return (0);
2145 
2146 scs_err_out:
2147 	return (sbd_close_delete_lu(sl, ret));
2148 }
2149 
2150 int
2151 sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret)
2152 {
2153 	sbd_lu_info_1_0_t *sli = NULL;
2154 	sbd_status_t sret;
2155 
2156 	sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2157 	    SMS_ID_LU_INFO_1_0);
2158 
2159 	if (sret != SBD_SUCCESS) {
2160 		*err_ret = SBD_RET_NO_META;
2161 		return (EIO);
2162 	}
2163 	if (sli->sli_data_order != SMS_DATA_ORDER) {
2164 		sbd_swap_lu_info_1_0(sli);
2165 		if (sli->sli_data_order != SMS_DATA_ORDER) {
2166 			kmem_free(sli, sli->sli_sms_header.sms_size);
2167 			*err_ret = SBD_RET_NO_META;
2168 			return (EIO);
2169 		}
2170 	}
2171 
2172 	sl->sl_flags |= SL_SHARED_META;
2173 	sl->sl_data_blocksize_shift = 9;
2174 	sl->sl_data_offset = SHARED_META_DATA_SIZE;
2175 	sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE;
2176 	sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size;
2177 	bcopy(sli->sli_lu_devid, sl->sl_device_id, 20);
2178 
2179 	kmem_free(sli, sli->sli_sms_header.sms_size);
2180 	return (0);
2181 }
2182 
2183 int
2184 sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
2185     int no_register, sbd_lu_t **slr)
2186 {
2187 	stmf_lu_t *lu;
2188 	sbd_lu_t *sl;
2189 	sbd_lu_info_1_1_t *sli = NULL;
2190 	int asz;
2191 	int ret = 0;
2192 	stmf_status_t stret;
2193 	int flag;
2194 	int wcd = 0;
2195 	int data_opened;
2196 	uint16_t sli_buf_sz;
2197 	uint8_t *sli_buf_copy = NULL;
2198 	enum vtype vt;
2199 	int standby = 0;
2200 	sbd_status_t sret;
2201 
2202 	if (no_register && slr == NULL) {
2203 		return (EINVAL);
2204 	}
2205 	ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0;
2206 	/*
2207 	 * check whether logical unit is already registered ALUA
2208 	 * For a standby logical unit, the meta filename is set. Use
2209 	 * that to search for an existing logical unit.
2210 	 */
2211 	sret = sbd_find_and_lock_lu(NULL, (uint8_t *)&(ilu->ilu_meta_fname),
2212 	    SL_OP_IMPORT_LU, &sl);
2213 
2214 	if (sret == SBD_SUCCESS) {
2215 		if (sl->sl_access_state != SBD_LU_ACTIVE) {
2216 			no_register = 1;
2217 			standby = 1;
2218 			lu = sl->sl_lu;
2219 			if (sl->sl_alias_alloc_size) {
2220 				kmem_free(sl->sl_alias,
2221 				    sl->sl_alias_alloc_size);
2222 				sl->sl_alias_alloc_size = 0;
2223 				sl->sl_alias = NULL;
2224 				lu->lu_alias = NULL;
2225 			}
2226 			if (sl->sl_meta_filename == NULL) {
2227 				sl->sl_meta_filename = sl->sl_data_filename;
2228 			} else if (sl->sl_data_fname_alloc_size) {
2229 				kmem_free(sl->sl_data_filename,
2230 				    sl->sl_data_fname_alloc_size);
2231 				sl->sl_data_fname_alloc_size = 0;
2232 			}
2233 			if (sl->sl_serial_no_alloc_size) {
2234 				kmem_free(sl->sl_serial_no,
2235 				    sl->sl_serial_no_alloc_size);
2236 				sl->sl_serial_no_alloc_size = 0;
2237 			}
2238 			if (sl->sl_mgmt_url_alloc_size) {
2239 				kmem_free(sl->sl_mgmt_url,
2240 				    sl->sl_mgmt_url_alloc_size);
2241 				sl->sl_mgmt_url_alloc_size = 0;
2242 			}
2243 		} else {
2244 			*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2245 			sl->sl_trans_op = SL_OP_NONE;
2246 			return (EALREADY);
2247 		}
2248 	} else if (sret == SBD_NOT_FOUND) {
2249 		asz = strlen(ilu->ilu_meta_fname) + 1;
2250 
2251 		lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU,
2252 		    sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0);
2253 		if (lu == NULL) {
2254 			return (ENOMEM);
2255 		}
2256 		sl = (sbd_lu_t *)lu->lu_provider_private;
2257 		bzero(sl, sizeof (*sl));
2258 		sl->sl_lu = lu;
2259 		sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
2260 		sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) +
2261 		    sizeof (sbd_pgr_t);
2262 		(void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname);
2263 		sl->sl_name = sl->sl_meta_filename;
2264 		rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
2265 		rw_init(&sl->sl_access_state_lock, NULL, RW_DRIVER, NULL);
2266 		mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
2267 		mutex_init(&sl->sl_metadata_lock, NULL, MUTEX_DRIVER, NULL);
2268 		sl->sl_trans_op = SL_OP_IMPORT_LU;
2269 	} else {
2270 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2271 		return (EIO);
2272 	}
2273 
2274 	/* we're only loading the metadata */
2275 	if (!no_register) {
2276 		if (sbd_link_lu(sl) != SBD_SUCCESS) {
2277 			*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
2278 			ret = EALREADY;
2279 			goto sim_err_out;
2280 		}
2281 	}
2282 	if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
2283 	    NULLVPP, &sl->sl_meta_vp)) != 0) {
2284 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
2285 		goto sim_err_out;
2286 	}
2287 	if (sbd_is_zvol(sl->sl_meta_filename)) {
2288 		sl->sl_flags |= SL_ZFS_META;
2289 		sl->sl_data_filename = sl->sl_meta_filename;
2290 	}
2291 	sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
2292 	VN_RELE(sl->sl_meta_vp);
2293 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
2294 		*err_ret = SBD_RET_WRONG_META_FILE_TYPE;
2295 		ret = EINVAL;
2296 		goto sim_err_out;
2297 	}
2298 	if (sl->sl_flags & SL_ZFS_META) {
2299 		if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) {
2300 			/* let see if metadata is in the 64k block */
2301 			sl->sl_flags &= ~SL_ZFS_META;
2302 		}
2303 	}
2304 	if (!(sl->sl_flags & SL_ZFS_META)) {
2305 		/* metadata is always writable */
2306 		flag = FREAD | FWRITE | FOFFMAX | FEXCL;
2307 		if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
2308 		    &sl->sl_meta_vp, 0, 0)) != 0) {
2309 			*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
2310 			goto sim_err_out;
2311 		}
2312 	}
2313 	if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) {
2314 		sl->sl_meta_blocksize_shift = 0;
2315 	} else {
2316 		sl->sl_meta_blocksize_shift = 9;
2317 	}
2318 	sl->sl_meta_offset = (sl->sl_flags & SL_ZFS_META) ? 0 : SBD_META_OFFSET;
2319 	sl->sl_flags |= SL_META_OPENED;
2320 
2321 	mutex_enter(&sl->sl_metadata_lock);
2322 	sret = sbd_load_meta_start(sl);
2323 	mutex_exit(&sl->sl_metadata_lock);
2324 	if (sret != SBD_SUCCESS) {
2325 		if (sret == SBD_META_CORRUPTED) {
2326 			*err_ret = SBD_RET_NO_META;
2327 		} else if (sret == SBD_NOT_SUPPORTED) {
2328 			*err_ret = SBD_RET_VERSION_NOT_SUPPORTED;
2329 		} else {
2330 			*err_ret = SBD_RET_NO_META;
2331 		}
2332 		ret = EINVAL;
2333 		goto sim_err_out;
2334 	}
2335 
2336 	/* Now lets see if we can read the most recent LU info */
2337 	sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
2338 	    SMS_ID_LU_INFO_1_1);
2339 	if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) {
2340 		ret = sbd_load_sli_1_0(sl, err_ret);
2341 		if (ret) {
2342 			goto sim_err_out;
2343 		}
2344 		goto sim_sli_loaded;
2345 	}
2346 	if (sret != SBD_SUCCESS) {
2347 		*err_ret = SBD_RET_NO_META;
2348 		ret = EIO;
2349 		goto sim_err_out;
2350 	}
2351 	/* load sli 1.1 */
2352 	if (sli->sli_data_order != SMS_DATA_ORDER) {
2353 		sbd_swap_lu_info_1_1(sli);
2354 		if (sli->sli_data_order != SMS_DATA_ORDER) {
2355 			*err_ret = SBD_RET_NO_META;
2356 			ret = EIO;
2357 			goto sim_err_out;
2358 		}
2359 	}
2360 
2361 	sli_buf_sz = sli->sli_sms_header.sms_size -
2362 	    sizeof (sbd_lu_info_1_1_t) + 8;
2363 	sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP);
2364 	bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz);
2365 	sli_buf_copy[sli_buf_sz] = 0;
2366 
2367 	/* Make sure all the offsets are within limits */
2368 	if (((sli->sli_flags & SLI_META_FNAME_VALID) &&
2369 	    (sli->sli_meta_fname_offset > sli_buf_sz)) ||
2370 	    ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
2371 	    (sli->sli_data_fname_offset > sli_buf_sz)) ||
2372 	    ((sli->sli_flags & SLI_MGMT_URL_VALID) &&
2373 	    (sli->sli_mgmt_url_offset > sli_buf_sz)) ||
2374 	    ((sli->sli_flags & SLI_SERIAL_VALID) &&
2375 	    ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
2376 	    ((sli->sli_flags & SLI_ALIAS_VALID) &&
2377 	    (sli->sli_alias_offset > sli_buf_sz))) {
2378 		*err_ret = SBD_RET_NO_META;
2379 		ret = EIO;
2380 		goto sim_err_out;
2381 	}
2382 
2383 	sl->sl_lu_size = sli->sli_lu_size;
2384 	sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift;
2385 	bcopy(sli->sli_device_id, sl->sl_device_id, 20);
2386 	if (sli->sli_flags & SLI_SERIAL_VALID) {
2387 		sl->sl_serial_no_size = sl->sl_serial_no_alloc_size =
2388 		    sli->sli_serial_size;
2389 		sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP);
2390 		bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no,
2391 		    sl->sl_serial_no_size);
2392 	}
2393 	if (sli->sli_flags & SLI_SEPARATE_META) {
2394 		sl->sl_total_data_size = sl->sl_lu_size;
2395 		if (sli->sli_flags & SLI_DATA_FNAME_VALID) {
2396 			sl->sl_data_fname_alloc_size = strlen((char *)
2397 			    sli_buf_copy + sli->sli_data_fname_offset) + 1;
2398 			sl->sl_data_filename = kmem_zalloc(
2399 			    sl->sl_data_fname_alloc_size, KM_SLEEP);
2400 			(void) strcpy(sl->sl_data_filename,
2401 			    (char *)sli_buf_copy + sli->sli_data_fname_offset);
2402 		}
2403 	} else {
2404 		if (sl->sl_flags & SL_ZFS_META) {
2405 			sl->sl_total_data_size = sl->sl_lu_size;
2406 			sl->sl_data_offset = 0;
2407 		} else {
2408 			sl->sl_total_data_size =
2409 			    sl->sl_lu_size + SHARED_META_DATA_SIZE;
2410 			sl->sl_data_offset = SHARED_META_DATA_SIZE;
2411 			sl->sl_flags |= SL_SHARED_META;
2412 		}
2413 	}
2414 	if (sli->sli_flags & SLI_ALIAS_VALID) {
2415 		sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy +
2416 		    sli->sli_alias_offset) + 1;
2417 		sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP);
2418 		(void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
2419 		    sli->sli_alias_offset);
2420 	}
2421 	if (sli->sli_flags & SLI_MGMT_URL_VALID) {
2422 		sl->sl_mgmt_url_alloc_size = strlen((char *)sli_buf_copy +
2423 		    sli->sli_mgmt_url_offset) + 1;
2424 		sl->sl_mgmt_url = kmem_alloc(sl->sl_mgmt_url_alloc_size,
2425 		    KM_SLEEP);
2426 		(void) strcpy(sl->sl_mgmt_url, (char *)sli_buf_copy +
2427 		    sli->sli_mgmt_url_offset);
2428 	}
2429 	if (sli->sli_flags & SLI_WRITE_PROTECTED) {
2430 		sl->sl_flags |= SL_WRITE_PROTECTED;
2431 	}
2432 	if (sli->sli_flags & SLI_VID_VALID) {
2433 		sl->sl_flags |= SL_VID_VALID;
2434 		bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
2435 	}
2436 	if (sli->sli_flags & SLI_PID_VALID) {
2437 		sl->sl_flags |= SL_PID_VALID;
2438 		bcopy(sli->sli_pid, sl->sl_product_id, 16);
2439 	}
2440 	if (sli->sli_flags & SLI_REV_VALID) {
2441 		sl->sl_flags |= SL_REV_VALID;
2442 		bcopy(sli->sli_rev, sl->sl_revision, 4);
2443 	}
2444 	if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) {
2445 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2446 	}
2447 sim_sli_loaded:
2448 	if ((sl->sl_flags & SL_SHARED_META) == 0) {
2449 		data_opened = 0;
2450 	} else {
2451 		data_opened = 1;
2452 		sl->sl_data_filename = sl->sl_meta_filename;
2453 		sl->sl_data_vp = sl->sl_meta_vp;
2454 		sl->sl_data_vtype = sl->sl_meta_vtype;
2455 	}
2456 
2457 	sret = sbd_pgr_meta_load(sl);
2458 	if (sret != SBD_SUCCESS) {
2459 		*err_ret = SBD_RET_NO_META;
2460 		ret = EIO;
2461 		goto sim_err_out;
2462 	}
2463 
2464 	ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0);
2465 	if (ret) {
2466 		goto sim_err_out;
2467 	}
2468 
2469 	/*
2470 	 * set write cache disable on the device
2471 	 * Note: this shouldn't fail on import unless the cache capabilities
2472 	 * of the device changed. If that happened, modify will need to
2473 	 * be used to set the cache flag appropriately after import is done.
2474 	 */
2475 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2476 		(void) sbd_wcd_set(1, sl);
2477 		wcd = 1;
2478 	/*
2479 	 * if not explicitly set, attempt to set it to enable, if that fails
2480 	 * get the current setting and use that
2481 	 */
2482 	} else {
2483 		sret = sbd_wcd_set(0, sl);
2484 		if (sret != SBD_SUCCESS) {
2485 			sbd_wcd_get(&wcd, sl);
2486 		}
2487 	}
2488 
2489 	if (wcd) {
2490 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
2491 		    SL_SAVED_WRITE_CACHE_DISABLE;
2492 	}
2493 
2494 	/* we're only loading the metadata */
2495 	if (!no_register) {
2496 		ret = sbd_populate_and_register_lu(sl, err_ret);
2497 		if (ret) {
2498 			goto sim_err_out;
2499 		}
2500 		atomic_add_32(&sbd_lu_count, 1);
2501 	}
2502 
2503 	bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
2504 	sl->sl_trans_op = SL_OP_NONE;
2505 
2506 	if (sli) {
2507 		kmem_free(sli, sli->sli_sms_header.sms_size);
2508 		sli = NULL;
2509 	}
2510 	if (sli_buf_copy) {
2511 		kmem_free(sli_buf_copy, sli_buf_sz + 1);
2512 		sli_buf_copy = NULL;
2513 	}
2514 	if (no_register && !standby) {
2515 		*slr = sl;
2516 	}
2517 
2518 	/*
2519 	 * if this was imported from standby, set the access state
2520 	 * to active.
2521 	 */
2522 	if (standby) {
2523 		sbd_it_data_t *it;
2524 		mutex_enter(&sl->sl_lock);
2525 		sl->sl_access_state = SBD_LU_ACTIVE;
2526 		for (it = sl->sl_it_list; it != NULL;
2527 		    it = it->sbd_it_next) {
2528 			it->sbd_it_ua_conditions |=
2529 			    SBD_UA_ASYMMETRIC_ACCESS_CHANGED;
2530 			it->sbd_it_ua_conditions |= SBD_UA_POR;
2531 			it->sbd_it_flags |=  SBD_IT_PGR_CHECK_FLAG;
2532 		}
2533 		mutex_exit(&sl->sl_lock);
2534 		/* call set access state */
2535 		stret = stmf_set_lu_access(lu, STMF_LU_ACTIVE);
2536 		if (stret != STMF_SUCCESS) {
2537 			*err_ret = SBD_RET_ACCESS_STATE_FAILED;
2538 			sl->sl_access_state = SBD_LU_STANDBY;
2539 			goto sim_err_out;
2540 		}
2541 		if (sl->sl_alias) {
2542 			lu->lu_alias = sl->sl_alias;
2543 		} else {
2544 			lu->lu_alias = sl->sl_name;
2545 		}
2546 	}
2547 	sl->sl_access_state = SBD_LU_ACTIVE;
2548 	return (0);
2549 
2550 sim_err_out:
2551 	if (sli) {
2552 		kmem_free(sli, sli->sli_sms_header.sms_size);
2553 		sli = NULL;
2554 	}
2555 	if (sli_buf_copy) {
2556 		kmem_free(sli_buf_copy, sli_buf_sz + 1);
2557 		sli_buf_copy = NULL;
2558 	}
2559 
2560 	if (standby) {
2561 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
2562 		sl->sl_trans_op = SL_OP_NONE;
2563 		return (EIO);
2564 	} else {
2565 		return (sbd_close_delete_lu(sl, ret));
2566 	}
2567 }
2568 
2569 int
2570 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
2571 {
2572 	sbd_lu_t *sl = NULL;
2573 	uint16_t alias_sz;
2574 	int ret = 0;
2575 	sbd_it_data_t *it;
2576 	sbd_status_t sret;
2577 	uint64_t old_size;
2578 	int modify_unregistered = 0;
2579 	int ua = 0;
2580 	sbd_import_lu_t *ilu;
2581 	stmf_lu_t *lu;
2582 	uint32_t ilu_sz;
2583 	uint32_t sz;
2584 
2585 	sz = struct_sz - sizeof (*mlu) + 8 + 1;
2586 
2587 	/* if there is data in the buf, null terminate it */
2588 	if (struct_sz > sizeof (*mlu)) {
2589 		mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2590 	}
2591 
2592 	*err_ret = 0;
2593 
2594 	/* Lets validate offsets */
2595 	if (((mlu->mlu_alias_valid) &&
2596 	    (mlu->mlu_alias_off >= sz)) ||
2597 	    ((mlu->mlu_mgmt_url_valid) &&
2598 	    (mlu->mlu_mgmt_url_off >= sz)) ||
2599 	    (mlu->mlu_by_fname) &&
2600 	    (mlu->mlu_fname_off >= sz)) {
2601 		return (EINVAL);
2602 	}
2603 
2604 	/*
2605 	 * We'll look for the device but if we don't find it registered,
2606 	 * we'll still try to modify the unregistered device.
2607 	 */
2608 	if (mlu->mlu_by_guid) {
2609 		sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL,
2610 		    SL_OP_MODIFY_LU, &sl);
2611 	} else if (mlu->mlu_by_fname) {
2612 		sret = sbd_find_and_lock_lu(NULL,
2613 		    (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]),
2614 		    SL_OP_MODIFY_LU, &sl);
2615 	} else {
2616 		return (EINVAL);
2617 	}
2618 
2619 
2620 	if (sret != SBD_SUCCESS) {
2621 		if (sret == SBD_BUSY) {
2622 			*err_ret = SBD_RET_LU_BUSY;
2623 			return (EBUSY);
2624 		} else if (sret != SBD_NOT_FOUND) {
2625 			return (EIO);
2626 		} else if (!mlu->mlu_by_fname) {
2627 			return (EINVAL);
2628 		}
2629 		/* Okay, try to import the device */
2630 		struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off]))
2631 		    + 1);
2632 		struct_sz += sizeof (sbd_import_lu_t) - 8;
2633 		ilu_sz = struct_sz;
2634 		ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
2635 		ilu->ilu_struct_size = struct_sz;
2636 		(void) strcpy(ilu->ilu_meta_fname,
2637 		    &(mlu->mlu_buf[mlu->mlu_fname_off]));
2638 		ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl);
2639 		kmem_free(ilu, ilu_sz);
2640 		if (ret != SBD_SUCCESS) {
2641 			return (ENOENT);
2642 		}
2643 		modify_unregistered = 1;
2644 	}
2645 
2646 	if (sl->sl_access_state != SBD_LU_ACTIVE) {
2647 		*err_ret = SBD_RET_ACCESS_STATE_FAILED;
2648 		ret = EINVAL;
2649 		goto smm_err_out;
2650 	}
2651 
2652 	/* check for write cache change */
2653 	if (mlu->mlu_writeback_cache_disable_valid) {
2654 		/* set wce on device */
2655 		sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl);
2656 		if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) {
2657 			*err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
2658 			ret = EFAULT;
2659 			goto smm_err_out;
2660 		}
2661 		mutex_enter(&sl->sl_lock);
2662 		if (!mlu->mlu_writeback_cache_disable) {
2663 			if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2664 				ua = 1;
2665 				sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
2666 				sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
2667 			}
2668 		} else {
2669 			if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
2670 				ua = 1;
2671 				sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2672 				sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
2673 			}
2674 		}
2675 		for (it = sl->sl_it_list; ua && it != NULL;
2676 		    it = it->sbd_it_next) {
2677 			it->sbd_it_ua_conditions |=
2678 			    SBD_UA_MODE_PARAMETERS_CHANGED;
2679 		}
2680 		mutex_exit(&sl->sl_lock);
2681 	}
2682 	ua = 0;
2683 
2684 	if (mlu->mlu_alias_valid) {
2685 		alias_sz = strlen((char *)mlu->mlu_buf +
2686 		    mlu->mlu_alias_off) + 1;
2687 		/*
2688 		 * Use the allocated buffer or alloc a new one.
2689 		 * Don't copy into sl_alias if sl_alias_alloc_size is 0
2690 		 * otherwise or you'll be writing over the data/metadata
2691 		 * filename.
2692 		 */
2693 		mutex_enter(&sl->sl_lock);
2694 		if (sl->sl_alias_alloc_size > 0 &&
2695 		    sl->sl_alias_alloc_size < alias_sz) {
2696 			kmem_free(sl->sl_alias,
2697 			    sl->sl_alias_alloc_size);
2698 			sl->sl_alias_alloc_size = 0;
2699 		}
2700 		if (sl->sl_alias_alloc_size == 0) {
2701 			sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP);
2702 			sl->sl_alias_alloc_size = alias_sz;
2703 		}
2704 		(void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf +
2705 		    mlu->mlu_alias_off);
2706 		lu = sl->sl_lu;
2707 		lu->lu_alias = sl->sl_alias;
2708 		mutex_exit(&sl->sl_lock);
2709 	}
2710 
2711 	if (mlu->mlu_mgmt_url_valid) {
2712 		uint16_t url_sz;
2713 
2714 		url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2715 		if (url_sz > 0)
2716 			url_sz++;
2717 
2718 		mutex_enter(&sl->sl_lock);
2719 		if (sl->sl_mgmt_url_alloc_size > 0 &&
2720 		    (url_sz == 0 || sl->sl_mgmt_url_alloc_size < url_sz)) {
2721 			kmem_free(sl->sl_mgmt_url, sl->sl_mgmt_url_alloc_size);
2722 			sl->sl_mgmt_url = NULL;
2723 			sl->sl_mgmt_url_alloc_size = 0;
2724 		}
2725 		if (url_sz > 0) {
2726 			if (sl->sl_mgmt_url_alloc_size == 0) {
2727 				sl->sl_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2728 				sl->sl_mgmt_url_alloc_size = url_sz;
2729 			}
2730 			(void) strcpy(sl->sl_mgmt_url, (char *)mlu->mlu_buf +
2731 			    mlu->mlu_mgmt_url_off);
2732 		}
2733 		for (it = sl->sl_it_list; it != NULL;
2734 		    it = it->sbd_it_next) {
2735 			it->sbd_it_ua_conditions |=
2736 			    SBD_UA_MODE_PARAMETERS_CHANGED;
2737 		}
2738 		mutex_exit(&sl->sl_lock);
2739 	}
2740 
2741 	if (mlu->mlu_write_protected_valid) {
2742 		mutex_enter(&sl->sl_lock);
2743 		if (mlu->mlu_write_protected) {
2744 			if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) {
2745 				ua = 1;
2746 				sl->sl_flags |= SL_WRITE_PROTECTED;
2747 			}
2748 		} else {
2749 			if (sl->sl_flags & SL_WRITE_PROTECTED) {
2750 				ua = 1;
2751 				sl->sl_flags &= ~SL_WRITE_PROTECTED;
2752 			}
2753 		}
2754 		for (it = sl->sl_it_list; ua && it != NULL;
2755 		    it = it->sbd_it_next) {
2756 			it->sbd_it_ua_conditions |=
2757 			    SBD_UA_MODE_PARAMETERS_CHANGED;
2758 		}
2759 		mutex_exit(&sl->sl_lock);
2760 	}
2761 
2762 	if (mlu->mlu_lu_size_valid) {
2763 		/*
2764 		 * validate lu size and set
2765 		 * For open file only (registered lu)
2766 		 */
2767 		mutex_enter(&sl->sl_lock);
2768 		old_size = sl->sl_lu_size;
2769 		sl->sl_lu_size = mlu->mlu_lu_size;
2770 		mutex_exit(&sl->sl_lock);
2771 		ret = sbd_open_data_file(sl, err_ret, 1, 1, 1);
2772 		if (ret) {
2773 			mutex_enter(&sl->sl_lock);
2774 			sl->sl_lu_size = old_size;
2775 			mutex_exit(&sl->sl_lock);
2776 			goto smm_err_out;
2777 		}
2778 		if (old_size != mlu->mlu_lu_size) {
2779 			mutex_enter(&sl->sl_lock);
2780 			for (it = sl->sl_it_list; it != NULL;
2781 			    it = it->sbd_it_next) {
2782 				it->sbd_it_ua_conditions |=
2783 				    SBD_UA_CAPACITY_CHANGED;
2784 			}
2785 			mutex_exit(&sl->sl_lock);
2786 		}
2787 	}
2788 
2789 	if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
2790 		*err_ret = SBD_RET_META_CREATION_FAILED;
2791 		ret = EIO;
2792 	}
2793 
2794 smm_err_out:
2795 	if (modify_unregistered) {
2796 		(void) sbd_close_delete_lu(sl, 0);
2797 	} else {
2798 		sl->sl_trans_op = SL_OP_NONE;
2799 	}
2800 	return (ret);
2801 }
2802 
2803 int
2804 sbd_set_global_props(sbd_global_props_t *mlu, int struct_sz,
2805     uint32_t *err_ret)
2806 {
2807 	sbd_lu_t *sl = NULL;
2808 	int ret = 0;
2809 	sbd_it_data_t *it;
2810 	uint32_t sz;
2811 
2812 	sz = struct_sz - sizeof (*mlu) + 8 + 1;
2813 
2814 	/* if there is data in the buf, null terminate it */
2815 	if (struct_sz > sizeof (*mlu)) {
2816 		mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
2817 	}
2818 
2819 	*err_ret = 0;
2820 
2821 	/* Lets validate offsets */
2822 	if (((mlu->mlu_mgmt_url_valid) &&
2823 	    (mlu->mlu_mgmt_url_off >= sz))) {
2824 		return (EINVAL);
2825 	}
2826 
2827 	if (mlu->mlu_mgmt_url_valid) {
2828 		uint16_t url_sz;
2829 
2830 		url_sz = strlen((char *)mlu->mlu_buf + mlu->mlu_mgmt_url_off);
2831 		if (url_sz > 0)
2832 			url_sz++;
2833 
2834 		rw_enter(&sbd_global_prop_lock, RW_WRITER);
2835 		if (sbd_mgmt_url_alloc_size > 0 &&
2836 		    (url_sz == 0 || sbd_mgmt_url_alloc_size < url_sz)) {
2837 			kmem_free(sbd_mgmt_url, sbd_mgmt_url_alloc_size);
2838 			sbd_mgmt_url = NULL;
2839 			sbd_mgmt_url_alloc_size = 0;
2840 		}
2841 		if (url_sz > 0) {
2842 			if (sbd_mgmt_url_alloc_size == 0) {
2843 				sbd_mgmt_url = kmem_alloc(url_sz, KM_SLEEP);
2844 				sbd_mgmt_url_alloc_size = url_sz;
2845 			}
2846 			(void) strcpy(sbd_mgmt_url, (char *)mlu->mlu_buf +
2847 			    mlu->mlu_mgmt_url_off);
2848 		}
2849 		/*
2850 		 * check each lu to determine whether a UA is needed.
2851 		 */
2852 		mutex_enter(&sbd_lock);
2853 		for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
2854 			if (sl->sl_mgmt_url) {
2855 				continue;
2856 			}
2857 			mutex_enter(&sl->sl_lock);
2858 			for (it = sl->sl_it_list; it != NULL;
2859 			    it = it->sbd_it_next) {
2860 				it->sbd_it_ua_conditions |=
2861 				    SBD_UA_MODE_PARAMETERS_CHANGED;
2862 			}
2863 			mutex_exit(&sl->sl_lock);
2864 		}
2865 		mutex_exit(&sbd_lock);
2866 		rw_exit(&sbd_global_prop_lock);
2867 	}
2868 	return (ret);
2869 }
2870 
2871 /* ARGSUSED */
2872 int
2873 sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret,
2874     stmf_state_change_info_t *ssi)
2875 {
2876 	int i;
2877 	stmf_status_t ret;
2878 
2879 	if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2880 	    !sl->sl_state_not_acked) {
2881 		goto sdl_do_dereg;
2882 	}
2883 
2884 	if ((sl->sl_state != STMF_STATE_ONLINE) ||
2885 	    sl->sl_state_not_acked) {
2886 		return (EBUSY);
2887 	}
2888 
2889 	ret = stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi);
2890 	if ((ret != STMF_SUCCESS) && (ret != STMF_ALREADY)) {
2891 		return (EBUSY);
2892 	}
2893 
2894 	for (i = 0; i < 500; i++) {
2895 		if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2896 		    !sl->sl_state_not_acked) {
2897 			goto sdl_do_dereg;
2898 		}
2899 		delay(drv_usectohz(10000));
2900 	}
2901 	return (EBUSY);
2902 
2903 sdl_do_dereg:;
2904 	if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS)
2905 		return (EBUSY);
2906 	atomic_add_32(&sbd_lu_count, -1);
2907 
2908 	return (sbd_close_delete_lu(sl, 0));
2909 }
2910 
2911 int
2912 sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret)
2913 {
2914 	sbd_lu_t *sl;
2915 	sbd_status_t sret;
2916 	stmf_state_change_info_t ssi;
2917 	int ret;
2918 
2919 	if (dlu->dlu_by_meta_name) {
2920 		((char *)dlu)[struct_sz - 1] = 0;
2921 		sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name,
2922 		    SL_OP_DELETE_LU, &sl);
2923 	} else {
2924 		sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL,
2925 		    SL_OP_DELETE_LU, &sl);
2926 	}
2927 	if (sret != SBD_SUCCESS) {
2928 		if (sret == SBD_BUSY) {
2929 			*err_ret = SBD_RET_LU_BUSY;
2930 			return (EBUSY);
2931 		} else if (sret == SBD_NOT_FOUND) {
2932 			*err_ret = SBD_RET_NOT_FOUND;
2933 			return (ENOENT);
2934 		}
2935 		return (EIO);
2936 	}
2937 
2938 	ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
2939 	ssi.st_additional_info = "sbd_delete_lu call (ioctl)";
2940 	ret = sbd_delete_locked_lu(sl, err_ret, &ssi);
2941 
2942 	if (ret) {
2943 		/* Once its locked, no need to grab mutex again */
2944 		sl->sl_trans_op = SL_OP_NONE;
2945 	}
2946 	return (ret);
2947 }
2948 
2949 sbd_status_t
2950 sbd_data_read(sbd_lu_t *sl, struct scsi_task *task,
2951     uint64_t offset, uint64_t size, uint8_t *buf)
2952 {
2953 	int ret;
2954 	long resid;
2955 	hrtime_t xfer_start, xfer_done;
2956 
2957 	if ((offset + size) > sl->sl_lu_size) {
2958 		return (SBD_IO_PAST_EOF);
2959 	}
2960 
2961 	offset += sl->sl_data_offset;
2962 
2963 	if ((offset + size) > sl->sl_data_readable_size) {
2964 		uint64_t store_end;
2965 		if (offset > sl->sl_data_readable_size) {
2966 			bzero(buf, size);
2967 			return (SBD_SUCCESS);
2968 		}
2969 		store_end = sl->sl_data_readable_size - offset;
2970 		bzero(buf + store_end, size - store_end);
2971 		size = store_end;
2972 	}
2973 
2974 	xfer_start = gethrtime();
2975 	stmf_lu_xfer_start(task);
2976 	DTRACE_PROBE5(backing__store__read__start, sbd_lu_t *, sl,
2977 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
2978 	    scsi_task_t *, task);
2979 
2980 	/*
2981 	 * Don't proceed if the device has been closed
2982 	 * This can occur on an access state change to standby or
2983 	 * a delete. The writer lock is acquired before closing the
2984 	 * lu.
2985 	 */
2986 	rw_enter(&sl->sl_access_state_lock, RW_READER);
2987 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
2988 		rw_exit(&sl->sl_access_state_lock);
2989 		return (SBD_FAILURE);
2990 	}
2991 	ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
2992 	    (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(),
2993 	    &resid);
2994 	rw_exit(&sl->sl_access_state_lock);
2995 
2996 	xfer_done = gethrtime() - xfer_start;
2997 	stmf_lu_xfer_done(task, B_TRUE /* read */, size, xfer_done);
2998 	DTRACE_PROBE6(backing__store__read__end, sbd_lu_t *, sl,
2999 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
3000 	    int, ret, scsi_task_t *, task);
3001 
3002 over_sl_data_read:
3003 	if (ret || resid) {
3004 		stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret,
3005 		    resid);
3006 		return (SBD_FAILURE);
3007 	}
3008 
3009 	return (SBD_SUCCESS);
3010 }
3011 
3012 sbd_status_t
3013 sbd_data_write(sbd_lu_t *sl, struct scsi_task *task,
3014     uint64_t offset, uint64_t size, uint8_t *buf)
3015 {
3016 	int ret;
3017 	long resid;
3018 	sbd_status_t sret = SBD_SUCCESS;
3019 	int ioflag;
3020 	hrtime_t xfer_start, xfer_done;
3021 
3022 	if ((offset + size) > sl->sl_lu_size) {
3023 		return (SBD_IO_PAST_EOF);
3024 	}
3025 
3026 	offset += sl->sl_data_offset;
3027 
3028 	if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3029 	    (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3030 		ioflag = FSYNC;
3031 	} else {
3032 		ioflag = 0;
3033 	}
3034 
3035 	xfer_start = gethrtime();
3036 	stmf_lu_xfer_start(task);
3037 	DTRACE_PROBE5(backing__store__write__start, sbd_lu_t *, sl,
3038 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
3039 	    scsi_task_t *, task);
3040 
3041 	/*
3042 	 * Don't proceed if the device has been closed
3043 	 * This can occur on an access state change to standby or
3044 	 * a delete. The writer lock is acquired before closing the
3045 	 * lu.
3046 	 */
3047 	rw_enter(&sl->sl_access_state_lock, RW_READER);
3048 	if ((sl->sl_flags & SL_MEDIA_LOADED) == 0) {
3049 		rw_exit(&sl->sl_access_state_lock);
3050 		return (SBD_FAILURE);
3051 	}
3052 	ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
3053 	    (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(),
3054 	    &resid);
3055 	rw_exit(&sl->sl_access_state_lock);
3056 
3057 	xfer_done = gethrtime() - xfer_start;
3058 	stmf_lu_xfer_done(task, B_FALSE /* write */, size, xfer_done);
3059 	DTRACE_PROBE6(backing__store__write__end, sbd_lu_t *, sl,
3060 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
3061 	    int, ret, scsi_task_t *, task);
3062 
3063 	if ((ret == 0) && (resid == 0) &&
3064 	    (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
3065 	    (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
3066 		sret = sbd_flush_data_cache(sl, 1);
3067 	}
3068 over_sl_data_write:
3069 
3070 	if ((ret || resid) || (sret != SBD_SUCCESS)) {
3071 		return (SBD_FAILURE);
3072 	} else if ((offset + size) > sl->sl_data_readable_size) {
3073 		uint64_t old_size, new_size;
3074 
3075 		do {
3076 			old_size = sl->sl_data_readable_size;
3077 			if ((offset + size) <= old_size)
3078 				break;
3079 			new_size = offset + size;
3080 		} while (atomic_cas_64(&sl->sl_data_readable_size, old_size,
3081 		    new_size) != old_size);
3082 	}
3083 
3084 	return (SBD_SUCCESS);
3085 }
3086 
3087 int
3088 sbd_get_global_props(sbd_global_props_t *oslp, uint32_t oslp_sz,
3089     uint32_t *err_ret)
3090 {
3091 	uint32_t sz = 0;
3092 	uint16_t off;
3093 
3094 	rw_enter(&sbd_global_prop_lock, RW_READER);
3095 	if (sbd_mgmt_url) {
3096 		sz += strlen(sbd_mgmt_url) + 1;
3097 	}
3098 	bzero(oslp, sizeof (*oslp) - 8);
3099 	oslp->mlu_buf_size_needed = sz;
3100 
3101 	if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3102 		*err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3103 		rw_exit(&sbd_global_prop_lock);
3104 		return (ENOMEM);
3105 	}
3106 
3107 	off = 0;
3108 	if (sbd_mgmt_url) {
3109 		oslp->mlu_mgmt_url_valid = 1;
3110 		oslp->mlu_mgmt_url_off = off;
3111 		(void) strcpy((char *)&oslp->mlu_buf[off], sbd_mgmt_url);
3112 		off += strlen(sbd_mgmt_url) + 1;
3113 	}
3114 
3115 	rw_exit(&sbd_global_prop_lock);
3116 	return (0);
3117 }
3118 
3119 int
3120 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
3121     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
3122 {
3123 	sbd_status_t sret;
3124 	sbd_lu_t *sl = NULL;
3125 	uint32_t sz;
3126 	uint16_t off;
3127 
3128 	if (islp->slp_input_guid) {
3129 		sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
3130 		    SL_OP_LU_PROPS, &sl);
3131 	} else {
3132 		((char *)islp)[islp_sz - 1] = 0;
3133 		sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
3134 		    SL_OP_LU_PROPS, &sl);
3135 	}
3136 	if (sret != SBD_SUCCESS) {
3137 		if (sret == SBD_BUSY) {
3138 			*err_ret = SBD_RET_LU_BUSY;
3139 			return (EBUSY);
3140 		} else if (sret == SBD_NOT_FOUND) {
3141 			*err_ret = SBD_RET_NOT_FOUND;
3142 			return (ENOENT);
3143 		}
3144 		return (EIO);
3145 	}
3146 
3147 	sz = strlen(sl->sl_name) + 1;
3148 	if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3149 		if (sl->sl_data_filename) {
3150 			sz += strlen(sl->sl_data_filename) + 1;
3151 		}
3152 	}
3153 	sz += sl->sl_serial_no_size;
3154 	if (sl->sl_alias) {
3155 		sz += strlen(sl->sl_alias) + 1;
3156 	}
3157 
3158 	rw_enter(&sbd_global_prop_lock, RW_READER);
3159 	if (sl->sl_mgmt_url) {
3160 		sz += strlen(sl->sl_mgmt_url) + 1;
3161 	} else if (sbd_mgmt_url) {
3162 		sz += strlen(sbd_mgmt_url) + 1;
3163 	}
3164 	bzero(oslp, sizeof (*oslp) - 8);
3165 	oslp->slp_buf_size_needed = sz;
3166 
3167 	if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
3168 		sl->sl_trans_op = SL_OP_NONE;
3169 		*err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
3170 		rw_exit(&sbd_global_prop_lock);
3171 		return (ENOMEM);
3172 	}
3173 
3174 	off = 0;
3175 	(void) strcpy((char *)oslp->slp_buf, sl->sl_name);
3176 	oslp->slp_meta_fname_off = off;
3177 	off += strlen(sl->sl_name) + 1;
3178 	if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
3179 		oslp->slp_meta_fname_valid = 1;
3180 		oslp->slp_separate_meta = 1;
3181 		if (sl->sl_data_filename) {
3182 			oslp->slp_data_fname_valid = 1;
3183 			oslp->slp_data_fname_off = off;
3184 			(void) strcpy((char *)&oslp->slp_buf[off],
3185 			    sl->sl_data_filename);
3186 			off += strlen(sl->sl_data_filename) + 1;
3187 		}
3188 	} else {
3189 		oslp->slp_data_fname_valid = 1;
3190 		oslp->slp_data_fname_off = oslp->slp_meta_fname_off;
3191 		if (sl->sl_flags & SL_ZFS_META) {
3192 			oslp->slp_zfs_meta = 1;
3193 		}
3194 	}
3195 	if (sl->sl_alias) {
3196 		oslp->slp_alias_valid = 1;
3197 		oslp->slp_alias_off = off;
3198 		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
3199 		off += strlen(sl->sl_alias) + 1;
3200 	}
3201 	if (sl->sl_mgmt_url) {
3202 		oslp->slp_mgmt_url_valid = 1;
3203 		oslp->slp_mgmt_url_off = off;
3204 		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_mgmt_url);
3205 		off += strlen(sl->sl_mgmt_url) + 1;
3206 	} else if (sbd_mgmt_url) {
3207 		oslp->slp_mgmt_url_valid = 1;
3208 		oslp->slp_mgmt_url_off = off;
3209 		(void) strcpy((char *)&oslp->slp_buf[off], sbd_mgmt_url);
3210 		off += strlen(sbd_mgmt_url) + 1;
3211 	}
3212 	if (sl->sl_serial_no_size) {
3213 		oslp->slp_serial_off = off;
3214 		bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
3215 		    sl->sl_serial_no_size);
3216 		oslp->slp_serial_size = sl->sl_serial_no_size;
3217 		oslp->slp_serial_valid = 1;
3218 		off += sl->sl_serial_no_size;
3219 	}
3220 
3221 	oslp->slp_lu_size = sl->sl_lu_size;
3222 	oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
3223 
3224 	oslp->slp_access_state = sl->sl_access_state;
3225 
3226 	if (sl->sl_flags & SL_VID_VALID) {
3227 		oslp->slp_lu_vid = 1;
3228 		bcopy(sl->sl_vendor_id, oslp->slp_vid, 8);
3229 	} else {
3230 		bcopy(sbd_vendor_id, oslp->slp_vid, 8);
3231 	}
3232 	if (sl->sl_flags & SL_PID_VALID) {
3233 		oslp->slp_lu_pid = 1;
3234 		bcopy(sl->sl_product_id, oslp->slp_pid, 16);
3235 	} else {
3236 		bcopy(sbd_product_id, oslp->slp_pid, 16);
3237 	}
3238 	if (sl->sl_flags & SL_REV_VALID) {
3239 		oslp->slp_lu_rev = 1;
3240 		bcopy(sl->sl_revision, oslp->slp_rev, 4);
3241 	} else {
3242 		bcopy(sbd_revision, oslp->slp_rev, 4);
3243 	}
3244 	bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
3245 
3246 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
3247 		oslp->slp_writeback_cache_disable_cur = 1;
3248 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
3249 		oslp->slp_writeback_cache_disable_saved = 1;
3250 	if (sl->sl_flags & SL_WRITE_PROTECTED)
3251 		oslp->slp_write_protected = 1;
3252 
3253 	sl->sl_trans_op = SL_OP_NONE;
3254 
3255 	rw_exit(&sbd_global_prop_lock);
3256 	return (0);
3257 }
3258 
3259 char *
3260 sbd_get_zvol_name(sbd_lu_t *sl)
3261 {
3262 	char *src;
3263 	char *p;
3264 
3265 	if (sl->sl_data_filename)
3266 		src = sl->sl_data_filename;
3267 	else
3268 		src = sl->sl_meta_filename;
3269 	/* There has to be a better way */
3270 	if (SBD_IS_ZVOL(src) != 0) {
3271 		ASSERT(0);
3272 	}
3273 	src += 14;
3274 	if (*src == '/')
3275 		src++;
3276 	p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
3277 	(void) strcpy(p, src);
3278 	return (p);
3279 }
3280 
3281 /*
3282  * this function creates a local metadata zvol property
3283  */
3284 sbd_status_t
3285 sbd_create_zfs_meta_object(sbd_lu_t *sl)
3286 {
3287 	/*
3288 	 * -allocate 1/2 the property size, the zfs property
3289 	 *  is 8k in size and stored as ascii hex string, all
3290 	 *  we needed is 4k buffer to store the binary data.
3291 	 * -initialize reader/write lock
3292 	 */
3293 	if ((sl->sl_zfs_meta = kmem_zalloc(ZAP_MAXVALUELEN / 2, KM_SLEEP))
3294 	    == NULL)
3295 		return (SBD_FAILURE);
3296 	rw_init(&sl->sl_zfs_meta_lock, NULL, RW_DRIVER, NULL);
3297 	return (SBD_SUCCESS);
3298 }
3299 
3300 char
3301 sbd_ctoi(char c)
3302 {
3303 	if ((c >= '0') && (c <= '9'))
3304 		c -= '0';
3305 	else if ((c >= 'A') && (c <= 'F'))
3306 		c = c - 'A' + 10;
3307 	else if ((c >= 'a') && (c <= 'f'))
3308 		c = c - 'a' + 10;
3309 	else
3310 		c = -1;
3311 	return (c);
3312 }
3313 
3314 /*
3315  * read zvol property and convert to binary
3316  */
3317 sbd_status_t
3318 sbd_open_zfs_meta(sbd_lu_t *sl)
3319 {
3320 	char		*meta = NULL, cl, ch;
3321 	int		i;
3322 	char		*tmp, *ptr;
3323 	uint64_t	rc = SBD_SUCCESS;
3324 	int		len;
3325 	char		*file;
3326 
3327 	if (sl->sl_zfs_meta == NULL) {
3328 		if (sbd_create_zfs_meta_object(sl) == SBD_FAILURE)
3329 			return (SBD_FAILURE);
3330 	} else {
3331 		bzero(sl->sl_zfs_meta, (ZAP_MAXVALUELEN / 2));
3332 	}
3333 
3334 	rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3335 	file = sbd_get_zvol_name(sl);
3336 	if (sbd_zvolget(file, &meta)) {
3337 		rc = SBD_FAILURE;
3338 		goto done;
3339 	}
3340 	tmp = meta;
3341 	/* convert ascii hex to binary meta */
3342 	len = strlen(meta);
3343 	ptr = sl->sl_zfs_meta;
3344 	for (i = 0; i < len; i += 2) {
3345 		ch = sbd_ctoi(*tmp++);
3346 		cl = sbd_ctoi(*tmp++);
3347 		if (ch == -1 || cl == -1) {
3348 			rc = SBD_FAILURE;
3349 			break;
3350 		}
3351 		*ptr++ = (ch << 4) + cl;
3352 	}
3353 done:
3354 	rw_exit(&sl->sl_zfs_meta_lock);
3355 	if (meta)
3356 		kmem_free(meta, len + 1);
3357 	kmem_free(file, strlen(file) + 1);
3358 	return (rc);
3359 }
3360 
3361 sbd_status_t
3362 sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3363 {
3364 	ASSERT(sl->sl_zfs_meta);
3365 	rw_enter(&sl->sl_zfs_meta_lock, RW_READER);
3366 	bcopy(&sl->sl_zfs_meta[off], buf, sz);
3367 	rw_exit(&sl->sl_zfs_meta_lock);
3368 	return (SBD_SUCCESS);
3369 }
3370 
3371 sbd_status_t
3372 sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
3373 {
3374 	char		*ptr, *ah_meta;
3375 	char		*dp = NULL;
3376 	int		i, num;
3377 	char		*file;
3378 
3379 	ASSERT(sl->sl_zfs_meta);
3380 	if ((off + sz) > (ZAP_MAXVALUELEN / 2 - 1)) {
3381 		return (SBD_META_CORRUPTED);
3382 	}
3383 	if ((off + sz) > sl->sl_meta_size_used) {
3384 		sl->sl_meta_size_used = off + sz;
3385 		if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
3386 			uint64_t meta_align =
3387 			    (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
3388 			sl->sl_total_meta_size = (sl->sl_meta_size_used +
3389 			    meta_align) & (~meta_align);
3390 		}
3391 	}
3392 	ptr = ah_meta = kmem_zalloc(ZAP_MAXVALUELEN, KM_SLEEP);
3393 	rw_enter(&sl->sl_zfs_meta_lock, RW_WRITER);
3394 	bcopy(buf, &sl->sl_zfs_meta[off], sz);
3395 	/* convert local copy to ascii hex */
3396 	dp = sl->sl_zfs_meta;
3397 	for (i = 0; i < sl->sl_total_meta_size; i++, dp++) {
3398 		num = ((*dp) >> 4) & 0xF;
3399 		*ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3400 		num = (*dp) & 0xF;
3401 		*ah_meta++ = (num < 10) ? (num + '0') : (num + ('a' - 10));
3402 	}
3403 	*ah_meta = NULL;
3404 	file = sbd_get_zvol_name(sl);
3405 	if (sbd_zvolset(file, (char *)ptr)) {
3406 		rw_exit(&sl->sl_zfs_meta_lock);
3407 		kmem_free(ptr, ZAP_MAXVALUELEN);
3408 		kmem_free(file, strlen(file) + 1);
3409 		return (SBD_META_CORRUPTED);
3410 	}
3411 	rw_exit(&sl->sl_zfs_meta_lock);
3412 	kmem_free(ptr, ZAP_MAXVALUELEN);
3413 	kmem_free(file, strlen(file) + 1);
3414 	return (SBD_SUCCESS);
3415 }
3416 
3417 int
3418 sbd_is_zvol(char *path)
3419 {
3420 	int is_zfs = 0;
3421 
3422 	if (SBD_IS_ZVOL(path) == 0)
3423 		is_zfs = 1;
3424 
3425 	return (is_zfs);
3426 }
3427 
3428 /*
3429  * set write cache disable
3430  * wcd - 1 = disable, 0 = enable
3431  */
3432 sbd_status_t
3433 sbd_wcd_set(int wcd, sbd_lu_t *sl)
3434 {
3435 	/* translate to wce bit */
3436 	int wce = wcd ? 0 : 1;
3437 	int ret;
3438 	sbd_status_t sret = SBD_SUCCESS;
3439 
3440 	mutex_enter(&sl->sl_lock);
3441 	sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3442 
3443 	if (sl->sl_data_vp->v_type == VREG) {
3444 		sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3445 		goto done;
3446 	}
3447 
3448 	ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL,
3449 	    kcred, NULL, NULL);
3450 	if (ret == 0) {
3451 		sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3452 		sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE;
3453 	} else {
3454 		sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
3455 		sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
3456 		sret = SBD_FAILURE;
3457 		goto done;
3458 	}
3459 
3460 done:
3461 	mutex_exit(&sl->sl_lock);
3462 	return (sret);
3463 }
3464 
3465 /*
3466  * get write cache disable
3467  * wcd - 1 = disable, 0 = enable
3468  */
3469 void
3470 sbd_wcd_get(int *wcd, sbd_lu_t *sl)
3471 {
3472 	int wce;
3473 	int ret;
3474 
3475 	if (sl->sl_data_vp->v_type == VREG) {
3476 		*wcd = 0;
3477 		return;
3478 	}
3479 
3480 	ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL,
3481 	    kcred, NULL, NULL);
3482 	/* if write cache get failed, assume disabled */
3483 	if (ret) {
3484 		*wcd = 1;
3485 	} else {
3486 		/* translate to wcd bit */
3487 		*wcd = wce ? 0 : 1;
3488 	}
3489 }
3490 
3491 int
3492 sbd_zvolget(char *zvol_name, char **comstarprop)
3493 {
3494 	ldi_handle_t	zfs_lh;
3495 	nvlist_t	*nv = NULL, *nv2;
3496 	zfs_cmd_t	*zc;
3497 	char		*ptr;
3498 	int size = 1024;
3499 	int unused;
3500 	int rc;
3501 
3502 	if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3503 	    &zfs_lh, sbd_zfs_ident)) != 0) {
3504 		cmn_err(CE_WARN, "ldi_open %d", rc);
3505 		return (ENXIO);
3506 	}
3507 
3508 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3509 	(void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3510 again:
3511 	zc->zc_nvlist_dst = (uint64_t)(intptr_t)kmem_alloc(size,
3512 	    KM_SLEEP);
3513 	zc->zc_nvlist_dst_size = size;
3514 	rc = ldi_ioctl(zfs_lh, ZFS_IOC_OBJSET_STATS, (intptr_t)zc,
3515 	    FKIOCTL, kcred, &unused);
3516 	/*
3517 	 * ENOMEM means the list is larger than what we've allocated
3518 	 * ldi_ioctl will fail with ENOMEM only once
3519 	 */
3520 	if (rc == ENOMEM) {
3521 		int newsize;
3522 		newsize = zc->zc_nvlist_dst_size;
3523 		kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3524 		size = newsize;
3525 		goto again;
3526 	} else if (rc != 0) {
3527 		goto out;
3528 	}
3529 	rc = nvlist_unpack((char *)(uintptr_t)zc->zc_nvlist_dst,
3530 	    zc->zc_nvlist_dst_size, &nv, 0);
3531 	ASSERT(rc == 0);	/* nvlist_unpack should not fail */
3532 	if ((rc = nvlist_lookup_nvlist(nv, "stmf_sbd_lu", &nv2)) == 0) {
3533 		rc = nvlist_lookup_string(nv2, ZPROP_VALUE, &ptr);
3534 		if (rc != 0) {
3535 			cmn_err(CE_WARN, "couldn't get value");
3536 		} else {
3537 			*comstarprop = kmem_alloc(strlen(ptr) + 1,
3538 			    KM_SLEEP);
3539 			(void) strcpy(*comstarprop, ptr);
3540 		}
3541 	}
3542 out:
3543 	if (nv != NULL)
3544 		nvlist_free(nv);
3545 	kmem_free((void *)(uintptr_t)zc->zc_nvlist_dst, size);
3546 	kmem_free(zc, sizeof (zfs_cmd_t));
3547 	(void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3548 
3549 	return (rc);
3550 }
3551 
3552 int
3553 sbd_zvolset(char *zvol_name, char *comstarprop)
3554 {
3555 	ldi_handle_t	zfs_lh;
3556 	nvlist_t	*nv;
3557 	char		*packed = NULL;
3558 	size_t		len;
3559 	zfs_cmd_t	*zc;
3560 	int unused;
3561 	int rc;
3562 
3563 	if ((rc = ldi_open_by_name("/dev/zfs", FREAD | FWRITE, kcred,
3564 	    &zfs_lh, sbd_zfs_ident)) != 0) {
3565 		cmn_err(CE_WARN, "ldi_open %d", rc);
3566 		return (ENXIO);
3567 	}
3568 	(void) nvlist_alloc(&nv, NV_UNIQUE_NAME, KM_SLEEP);
3569 	(void) nvlist_add_string(nv, "stmf_sbd_lu", comstarprop);
3570 	if ((rc = nvlist_pack(nv, &packed, &len, NV_ENCODE_NATIVE, KM_SLEEP))) {
3571 		goto out;
3572 	}
3573 
3574 	zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
3575 	(void) strlcpy(zc->zc_name, zvol_name, sizeof (zc->zc_name));
3576 	zc->zc_nvlist_src = (uint64_t)(intptr_t)packed;
3577 	zc->zc_nvlist_src_size = len;
3578 	rc = ldi_ioctl(zfs_lh, ZFS_IOC_SET_PROP, (intptr_t)zc,
3579 	    FKIOCTL, kcred, &unused);
3580 	if (rc != 0) {
3581 		cmn_err(CE_NOTE, "ioctl failed %d", rc);
3582 	}
3583 	kmem_free(zc, sizeof (zfs_cmd_t));
3584 	if (packed)
3585 		kmem_free(packed, len);
3586 out:
3587 	nvlist_free(nv);
3588 	(void) ldi_close(zfs_lh, FREAD|FWRITE, kcred);
3589 	return (rc);
3590 }
3591