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