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