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