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