xref: /illumos-gate/usr/src/uts/common/io/comstar/lu/stmf_sbd/sbd.c (revision 17f1e64a433a4ca00ffed7539e10c297580a7002)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/conf.h>
27 #include <sys/file.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
30 #include <sys/modctl.h>
31 #include <sys/scsi/scsi.h>
32 #include <sys/scsi/impl/scsi_reset_notify.h>
33 #include <sys/disp.h>
34 #include <sys/byteorder.h>
35 #include <sys/pathname.h>
36 #include <sys/atomic.h>
37 #include <sys/nvpair.h>
38 #include <sys/fs/zfs.h>
39 #include <sys/sdt.h>
40 #include <sys/dkio.h>
41 
42 #include <stmf.h>
43 #include <lpif.h>
44 #include <stmf_ioctl.h>
45 #include <stmf_sbd.h>
46 #include <sbd_impl.h>
47 #include <stmf_sbd_ioctl.h>
48 
49 
50 extern sbd_status_t sbd_pgr_meta_write(sbd_lu_t *sl);
51 extern sbd_status_t sbd_pgr_meta_load(sbd_lu_t *sl);
52 
53 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
54     void **result);
55 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
56 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
57 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp);
58 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp);
59 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
60     cred_t *credp, int *rval);
61 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags);
62 int sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
63     uint32_t *err_ret);
64 int sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
65     int no_register, sbd_lu_t **slr);
66 int sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret);
67 int sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret);
68 int sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
69     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret);
70 char *sbd_get_zvol_name(sbd_lu_t *sl);
71 sbd_status_t sbd_create_zfs_meta_object(sbd_lu_t *sl);
72 sbd_status_t sbd_open_zfs_meta(sbd_lu_t *sl);
73 void sbd_close_zfs_meta(sbd_lu_t *sl);
74 sbd_status_t sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
75     uint64_t off);
76 sbd_status_t sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz,
77     uint64_t off);
78 int sbd_is_zvol(char *path, vnode_t *vp);
79 int sbd_is_sbd_zvol(char *path, vnode_t *vp);
80 
81 static stmf_lu_provider_t *sbd_lp;
82 static sbd_lu_t		*sbd_lu_list = NULL;
83 static kmutex_t		sbd_lock;
84 static dev_info_t	*sbd_dip;
85 static uint32_t		sbd_lu_count = 0;
86 char sbd_vendor_id[]	= "SUN     ";
87 char sbd_product_id[]	= "COMSTAR         ";
88 char sbd_revision[]	= "1.0 ";
89 static char sbd_name[] = "sbd";
90 
91 static struct cb_ops sbd_cb_ops = {
92 	sbd_open,			/* open */
93 	sbd_close,			/* close */
94 	nodev,				/* strategy */
95 	nodev,				/* print */
96 	nodev,				/* dump */
97 	nodev,				/* read */
98 	nodev,				/* write */
99 	stmf_sbd_ioctl,			/* ioctl */
100 	nodev,				/* devmap */
101 	nodev,				/* mmap */
102 	nodev,				/* segmap */
103 	nochpoll,			/* chpoll */
104 	ddi_prop_op,			/* cb_prop_op */
105 	0,				/* streamtab */
106 	D_NEW | D_MP,			/* cb_flag */
107 	CB_REV,				/* rev */
108 	nodev,				/* aread */
109 	nodev				/* awrite */
110 };
111 
112 static struct dev_ops sbd_ops = {
113 	DEVO_REV,
114 	0,
115 	sbd_getinfo,
116 	nulldev,		/* identify */
117 	nulldev,		/* probe */
118 	sbd_attach,
119 	sbd_detach,
120 	nodev,			/* reset */
121 	&sbd_cb_ops,
122 	NULL,			/* bus_ops */
123 	NULL			/* power */
124 };
125 
126 #define	SBD_NAME	"COMSTAR SBD"
127 
128 static struct modldrv modldrv = {
129 	&mod_driverops,
130 	SBD_NAME,
131 	&sbd_ops
132 };
133 
134 static struct modlinkage modlinkage = {
135 	MODREV_1,
136 	&modldrv,
137 	NULL
138 };
139 
140 int
141 _init(void)
142 {
143 	int ret;
144 
145 	ret = mod_install(&modlinkage);
146 	if (ret)
147 		return (ret);
148 	sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER,
149 	    0, 0);
150 	sbd_lp->lp_lpif_rev = LPIF_REV_1;
151 	sbd_lp->lp_instance = 0;
152 	sbd_lp->lp_name = sbd_name;
153 	sbd_lp->lp_cb = sbd_lp_cb;
154 
155 	if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) {
156 		(void) mod_remove(&modlinkage);
157 		stmf_free(sbd_lp);
158 		return (EINVAL);
159 	}
160 	mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL);
161 	return (0);
162 }
163 
164 int
165 _fini(void)
166 {
167 	int ret;
168 
169 	/*
170 	 * If we have registered lus, then make sure they are all offline
171 	 * if so then deregister them. This should drop the sbd_lu_count
172 	 * to zero.
173 	 */
174 	if (sbd_lu_count) {
175 		sbd_lu_t *slu;
176 
177 		/* See if all of them are offline */
178 		mutex_enter(&sbd_lock);
179 		for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) {
180 			if ((slu->sl_state != STMF_STATE_OFFLINE) ||
181 			    slu->sl_state_not_acked) {
182 				mutex_exit(&sbd_lock);
183 				return (EBUSY);
184 			}
185 		}
186 		mutex_exit(&sbd_lock);
187 
188 #if 0
189 		/* ok start deregistering them */
190 		while (sbd_lu_list) {
191 			sbd_store_t *sst = sbd_lu_list->sl_sst;
192 			if (sst->sst_deregister_lu(sst) != STMF_SUCCESS)
193 				return (EBUSY);
194 		}
195 #endif
196 		return (EBUSY);
197 	}
198 	if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS)
199 		return (EBUSY);
200 	ret = mod_remove(&modlinkage);
201 	if (ret != 0) {
202 		(void) stmf_register_lu_provider(sbd_lp);
203 		return (ret);
204 	}
205 	stmf_free(sbd_lp);
206 	mutex_destroy(&sbd_lock);
207 	return (0);
208 }
209 
210 int
211 _info(struct modinfo *modinfop)
212 {
213 	return (mod_info(&modlinkage, modinfop));
214 }
215 
216 /* ARGSUSED */
217 static int
218 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
219 {
220 	switch (cmd) {
221 	case DDI_INFO_DEVT2DEVINFO:
222 		*result = sbd_dip;
223 		break;
224 	case DDI_INFO_DEVT2INSTANCE:
225 		*result = (void *)(uintptr_t)ddi_get_instance(sbd_dip);
226 		break;
227 	default:
228 		return (DDI_FAILURE);
229 	}
230 
231 	return (DDI_SUCCESS);
232 }
233 
234 static int
235 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
236 {
237 	switch (cmd) {
238 	case DDI_ATTACH:
239 		sbd_dip = dip;
240 
241 		if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
242 		    DDI_NT_STMF_LP, 0) != DDI_SUCCESS) {
243 			break;
244 		}
245 		ddi_report_dev(dip);
246 		return (DDI_SUCCESS);
247 	}
248 
249 	return (DDI_FAILURE);
250 }
251 
252 static int
253 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
254 {
255 	switch (cmd) {
256 	case DDI_DETACH:
257 		ddi_remove_minor_node(dip, 0);
258 		return (DDI_SUCCESS);
259 	}
260 
261 	return (DDI_FAILURE);
262 }
263 
264 /* ARGSUSED */
265 static int
266 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp)
267 {
268 	if (otype != OTYP_CHR)
269 		return (EINVAL);
270 	return (0);
271 }
272 
273 /* ARGSUSED */
274 static int
275 sbd_close(dev_t dev, int flag, int otype, cred_t *credp)
276 {
277 	return (0);
278 }
279 
280 /* ARGSUSED */
281 static int
282 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
283 	cred_t *credp, int *rval)
284 {
285 	stmf_iocdata_t		*iocd;
286 	void			*ibuf	= NULL;
287 	void			*obuf	= NULL;
288 	sbd_lu_t		*nsl;
289 	int			i;
290 	int			ret;
291 
292 	if (drv_priv(credp) != 0) {
293 		return (EPERM);
294 	}
295 
296 	ret = stmf_copyin_iocdata(data, mode, &iocd, &ibuf, &obuf);
297 	if (ret)
298 		return (ret);
299 	iocd->stmf_error = 0;
300 
301 	switch (cmd) {
302 	case SBD_IOCTL_CREATE_AND_REGISTER_LU:
303 		if (iocd->stmf_ibuf_size <
304 		    (sizeof (sbd_create_and_reg_lu_t) - 8)) {
305 			ret = EFAULT;
306 			break;
307 		}
308 		if ((iocd->stmf_obuf_size == 0) ||
309 		    (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
310 			ret = EINVAL;
311 			break;
312 		}
313 		ret = sbd_create_register_lu((sbd_create_and_reg_lu_t *)
314 		    ibuf, iocd->stmf_ibuf_size, &iocd->stmf_error);
315 		bcopy(ibuf, obuf, iocd->stmf_obuf_size);
316 		break;
317 	case SBD_IOCTL_IMPORT_LU:
318 		if (iocd->stmf_ibuf_size <
319 		    (sizeof (sbd_import_lu_t) - 8)) {
320 			ret = EFAULT;
321 			break;
322 		}
323 		if ((iocd->stmf_obuf_size == 0) ||
324 		    (iocd->stmf_obuf_size > iocd->stmf_ibuf_size)) {
325 			ret = EINVAL;
326 			break;
327 		}
328 		ret = sbd_import_lu((sbd_import_lu_t *)ibuf,
329 		    iocd->stmf_ibuf_size, &iocd->stmf_error, 0, NULL);
330 		bcopy(ibuf, obuf, iocd->stmf_obuf_size);
331 		break;
332 	case SBD_IOCTL_DELETE_LU:
333 		if (iocd->stmf_ibuf_size < (sizeof (sbd_delete_lu_t) - 8)) {
334 			ret = EFAULT;
335 			break;
336 		}
337 		if (iocd->stmf_obuf_size) {
338 			ret = EINVAL;
339 			break;
340 		}
341 		ret = sbd_delete_lu((sbd_delete_lu_t *)ibuf,
342 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
343 		break;
344 	case SBD_IOCTL_MODIFY_LU:
345 		if (iocd->stmf_ibuf_size < (sizeof (sbd_modify_lu_t) - 8)) {
346 			ret = EFAULT;
347 			break;
348 		}
349 		if (iocd->stmf_obuf_size) {
350 			ret = EINVAL;
351 			break;
352 		}
353 		ret = sbd_modify_lu((sbd_modify_lu_t *)ibuf,
354 		    iocd->stmf_ibuf_size, &iocd->stmf_error);
355 		break;
356 	case SBD_IOCTL_GET_LU_PROPS:
357 		if (iocd->stmf_ibuf_size < (sizeof (sbd_lu_props_t) - 8)) {
358 			ret = EFAULT;
359 			break;
360 		}
361 		if (iocd->stmf_obuf_size < sizeof (sbd_lu_props_t)) {
362 			ret = EINVAL;
363 			break;
364 		}
365 		ret = sbd_get_lu_props((sbd_lu_props_t *)ibuf,
366 		    iocd->stmf_ibuf_size, (sbd_lu_props_t *)obuf,
367 		    iocd->stmf_obuf_size, &iocd->stmf_error);
368 		break;
369 	case SBD_IOCTL_GET_LU_LIST:
370 		mutex_enter(&sbd_lock);
371 		iocd->stmf_obuf_max_nentries = sbd_lu_count;
372 		iocd->stmf_obuf_nentries = min((iocd->stmf_obuf_size >> 4),
373 		    sbd_lu_count);
374 		for (nsl = sbd_lu_list, i = 0; nsl &&
375 		    (i < iocd->stmf_obuf_nentries); i++, nsl = nsl->sl_next) {
376 			bcopy(nsl->sl_device_id + 4,
377 			    &(((uint8_t *)obuf)[i << 4]), 16);
378 		}
379 		mutex_exit(&sbd_lock);
380 		ret = 0;
381 		iocd->stmf_error = 0;
382 		break;
383 	default:
384 		ret = ENOTTY;
385 	}
386 
387 	if (ret == 0) {
388 		ret = stmf_copyout_iocdata(data, mode, iocd, obuf);
389 	} else if (iocd->stmf_error) {
390 		(void) stmf_copyout_iocdata(data, mode, iocd, obuf);
391 	}
392 	if (obuf) {
393 		kmem_free(obuf, iocd->stmf_obuf_size);
394 		obuf = NULL;
395 	}
396 	if (ibuf) {
397 		kmem_free(ibuf, iocd->stmf_ibuf_size);
398 		ibuf = NULL;
399 	}
400 	kmem_free(iocd, sizeof (stmf_iocdata_t));
401 	return (ret);
402 }
403 
404 /* ARGSUSED */
405 void
406 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags)
407 {
408 	nvpair_t	*np;
409 	char		*s;
410 	sbd_import_lu_t *ilu;
411 	uint32_t	ilu_sz;
412 	uint32_t	struct_sz;
413 	uint32_t	err_ret;
414 	int		iret;
415 
416 	if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
417 		return;
418 	}
419 
420 	if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) {
421 		return;
422 	}
423 
424 	np = NULL;
425 	ilu_sz = 1024;
426 	ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
427 	while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) {
428 		if (nvpair_type(np) != DATA_TYPE_STRING) {
429 			continue;
430 		}
431 		if (nvpair_value_string(np, &s) != 0) {
432 			continue;
433 		}
434 		struct_sz = max(8, strlen(s) + 1);
435 		struct_sz += sizeof (sbd_import_lu_t) - 8;
436 		if (struct_sz > ilu_sz) {
437 			kmem_free(ilu, ilu_sz);
438 			ilu_sz = struct_sz + 32;
439 			ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
440 		}
441 		ilu->ilu_struct_size = struct_sz;
442 		(void) strcpy(ilu->ilu_meta_fname, s);
443 		iret = sbd_import_lu(ilu, struct_sz, &err_ret, 0, NULL);
444 		if (iret) {
445 			stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, "
446 			    "err_ret = %d", iret, err_ret);
447 		} else {
448 			stmf_trace(0, "Imported the LU %s", nvpair_name(np));
449 		}
450 	}
451 
452 	if (ilu) {
453 		kmem_free(ilu, ilu_sz);
454 		ilu = NULL;
455 	}
456 }
457 
458 sbd_status_t
459 sbd_link_lu(sbd_lu_t *sl)
460 {
461 	sbd_lu_t *nsl;
462 
463 	mutex_enter(&sbd_lock);
464 	mutex_enter(&sl->sl_lock);
465 	ASSERT(sl->sl_trans_op != SL_OP_NONE);
466 
467 	if (sl->sl_flags & SL_LINKED) {
468 		mutex_exit(&sbd_lock);
469 		mutex_exit(&sl->sl_lock);
470 		return (SBD_ALREADY);
471 	}
472 	for (nsl = sbd_lu_list; nsl; nsl = nsl->sl_next) {
473 		if (strcmp(nsl->sl_name, sl->sl_name) == 0)
474 			break;
475 	}
476 	if (nsl) {
477 		mutex_exit(&sbd_lock);
478 		mutex_exit(&sl->sl_lock);
479 		return (SBD_ALREADY);
480 	}
481 	sl->sl_next = sbd_lu_list;
482 	sbd_lu_list = sl;
483 	sl->sl_flags |= SL_LINKED;
484 	mutex_exit(&sbd_lock);
485 	mutex_exit(&sl->sl_lock);
486 	return (SBD_SUCCESS);
487 }
488 
489 void
490 sbd_unlink_lu(sbd_lu_t *sl)
491 {
492 	sbd_lu_t **ppnsl;
493 
494 	mutex_enter(&sbd_lock);
495 	mutex_enter(&sl->sl_lock);
496 	ASSERT(sl->sl_trans_op != SL_OP_NONE);
497 
498 	ASSERT(sl->sl_flags & SL_LINKED);
499 	for (ppnsl = &sbd_lu_list; *ppnsl; ppnsl = &((*ppnsl)->sl_next)) {
500 		if (*ppnsl == sl)
501 			break;
502 	}
503 	ASSERT(*ppnsl);
504 	*ppnsl = (*ppnsl)->sl_next;
505 	sl->sl_flags &= ~SL_LINKED;
506 	mutex_exit(&sbd_lock);
507 	mutex_exit(&sl->sl_lock);
508 }
509 
510 sbd_status_t
511 sbd_find_and_lock_lu(uint8_t *guid, uint8_t *meta_name, uint8_t op,
512     sbd_lu_t **ppsl)
513 {
514 	sbd_lu_t *sl;
515 	int found = 0;
516 	sbd_status_t sret;
517 
518 	mutex_enter(&sbd_lock);
519 	for (sl = sbd_lu_list; sl; sl = sl->sl_next) {
520 		if (guid) {
521 			found = bcmp(sl->sl_device_id + 4, guid, 16) == 0;
522 		} else {
523 			found = strcmp(sl->sl_name, (char *)meta_name) == 0;
524 		}
525 		if (found)
526 			break;
527 	}
528 	if (!found) {
529 		mutex_exit(&sbd_lock);
530 		return (SBD_NOT_FOUND);
531 	}
532 	mutex_enter(&sl->sl_lock);
533 	if (sl->sl_trans_op == SL_OP_NONE) {
534 		sl->sl_trans_op = op;
535 		*ppsl = sl;
536 		sret = SBD_SUCCESS;
537 	} else {
538 		sret = SBD_BUSY;
539 	}
540 	mutex_exit(&sl->sl_lock);
541 	mutex_exit(&sbd_lock);
542 	return (sret);
543 }
544 
545 sbd_status_t
546 sbd_read_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
547 {
548 	uint64_t	meta_align;
549 	uint64_t	starting_off;
550 	uint64_t	data_off;
551 	uint64_t	ending_off;
552 	uint64_t	io_size;
553 	uint8_t		*io_buf;
554 	vnode_t		*vp;
555 	sbd_status_t	ret;
556 	ssize_t		resid;
557 	int		vret;
558 
559 	ASSERT(sl->sl_flags & SL_META_OPENED);
560 	if (sl->sl_flags & SL_SHARED_META) {
561 		meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
562 		vp = sl->sl_data_vp;
563 		ASSERT(vp);
564 	} else {
565 		meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
566 		if ((sl->sl_flags & SL_ZFS_META) == 0) {
567 			vp = sl->sl_meta_vp;
568 			ASSERT(vp);
569 		}
570 	}
571 	starting_off = offset & ~(meta_align);
572 	data_off = offset & meta_align;
573 	ending_off = (offset + size + meta_align) & (~meta_align);
574 	if (ending_off > sl->sl_meta_size_used) {
575 		bzero(buf, size);
576 		if (starting_off >= sl->sl_meta_size_used) {
577 			return (SBD_SUCCESS);
578 		}
579 		ending_off = (sl->sl_meta_size_used + meta_align) &
580 		    (~meta_align);
581 		if (size > (ending_off - (starting_off + data_off))) {
582 			size = ending_off - (starting_off + data_off);
583 		}
584 	}
585 	io_size = ending_off - starting_off;
586 	io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
587 	ASSERT((starting_off + io_size) <= sl->sl_total_meta_size);
588 
589 	if (sl->sl_flags & SL_ZFS_META) {
590 		if ((ret = sbd_read_zfs_meta(sl, io_buf, io_size,
591 		    starting_off)) != SBD_SUCCESS) {
592 			goto sbd_read_meta_failure;
593 		}
594 	} else {
595 		vret = vn_rdwr(UIO_READ, vp, (caddr_t)io_buf, (ssize_t)io_size,
596 		    (offset_t)starting_off, UIO_SYSSPACE, FRSYNC,
597 		    RLIM64_INFINITY, CRED(), &resid);
598 
599 		if (vret || resid) {
600 			ret = SBD_FILEIO_FAILURE | vret;
601 			goto sbd_read_meta_failure;
602 		}
603 	}
604 
605 	bcopy(io_buf + data_off, buf, size);
606 	ret = SBD_SUCCESS;
607 
608 sbd_read_meta_failure:
609 	kmem_free(io_buf, io_size);
610 	return (ret);
611 }
612 
613 sbd_status_t
614 sbd_write_meta(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
615 {
616 	uint64_t	meta_align;
617 	uint64_t	starting_off;
618 	uint64_t	data_off;
619 	uint64_t	ending_off;
620 	uint64_t	io_size;
621 	uint8_t		*io_buf;
622 	vnode_t		*vp;
623 	sbd_status_t	ret;
624 	ssize_t		resid;
625 	int		vret;
626 
627 	ASSERT(sl->sl_flags & SL_META_OPENED);
628 	if (sl->sl_flags & SL_SHARED_META) {
629 		meta_align = (((uint64_t)1) << sl->sl_data_blocksize_shift) - 1;
630 		vp = sl->sl_data_vp;
631 		ASSERT(vp);
632 	} else {
633 		meta_align = (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
634 		if ((sl->sl_flags & SL_ZFS_META) == 0) {
635 			vp = sl->sl_meta_vp;
636 			ASSERT(vp);
637 		}
638 	}
639 	starting_off = offset & ~(meta_align);
640 	data_off = offset & meta_align;
641 	ending_off = (offset + size + meta_align) & (~meta_align);
642 	io_size = ending_off - starting_off;
643 	io_buf = (uint8_t *)kmem_zalloc(io_size, KM_SLEEP);
644 	ret = sbd_read_meta(sl, starting_off, io_size, io_buf);
645 	if (ret != SBD_SUCCESS) {
646 		goto sbd_write_meta_failure;
647 	}
648 	bcopy(buf, io_buf + data_off, size);
649 	if (sl->sl_flags & SL_ZFS_META) {
650 		if ((ret = sbd_write_zfs_meta(sl, io_buf, io_size,
651 		    starting_off)) != SBD_SUCCESS) {
652 			goto sbd_write_meta_failure;
653 		}
654 	} else {
655 		vret = vn_rdwr(UIO_WRITE, vp, (caddr_t)io_buf, (ssize_t)io_size,
656 		    (offset_t)starting_off, UIO_SYSSPACE, FDSYNC,
657 		    RLIM64_INFINITY, CRED(), &resid);
658 
659 		if (vret || resid) {
660 			ret = SBD_FILEIO_FAILURE | vret;
661 			goto sbd_write_meta_failure;
662 		}
663 	}
664 
665 	ret = SBD_SUCCESS;
666 
667 sbd_write_meta_failure:
668 	kmem_free(io_buf, io_size);
669 	return (ret);
670 }
671 
672 uint8_t
673 sbd_calc_sum(uint8_t *buf, int size)
674 {
675 	uint8_t s = 0;
676 
677 	while (size > 0)
678 		s += buf[--size];
679 
680 	return (s);
681 }
682 
683 uint8_t
684 sbd_calc_section_sum(sm_section_hdr_t *sm, uint32_t sz)
685 {
686 	uint8_t s, o;
687 
688 	o = sm->sms_chksum;
689 	sm->sms_chksum = 0;
690 	s = sbd_calc_sum((uint8_t *)sm, sz);
691 	sm->sms_chksum = o;
692 
693 	return (s);
694 }
695 
696 uint32_t
697 sbd_strlen(char *str, uint32_t maxlen)
698 {
699 	uint32_t i;
700 
701 	for (i = 0; i < maxlen; i++) {
702 		if (str[i] == 0)
703 			return (i);
704 	}
705 	return (i);
706 }
707 
708 void
709 sbd_swap_meta_start(sbd_meta_start_t *sm)
710 {
711 	if (sm->sm_magic == SBD_MAGIC)
712 		return;
713 	sm->sm_magic		= BSWAP_64(sm->sm_magic);
714 	sm->sm_meta_size	= BSWAP_64(sm->sm_meta_size);
715 	sm->sm_meta_size_used	= BSWAP_64(sm->sm_meta_size_used);
716 	sm->sm_ver_major	= BSWAP_16(sm->sm_ver_major);
717 	sm->sm_ver_minor	= BSWAP_16(sm->sm_ver_minor);
718 	sm->sm_ver_subminor	= BSWAP_16(sm->sm_ver_subminor);
719 }
720 
721 void
722 sbd_swap_section_hdr(sm_section_hdr_t *sm)
723 {
724 	if (sm->sms_data_order == SMS_DATA_ORDER)
725 		return;
726 	sm->sms_offset		= BSWAP_64(sm->sms_offset);
727 	sm->sms_size		= BSWAP_32(sm->sms_size);
728 	sm->sms_id		= BSWAP_16(sm->sms_id);
729 	sm->sms_chksum		+= SMS_DATA_ORDER - sm->sms_data_order;
730 	sm->sms_data_order	= SMS_DATA_ORDER;
731 }
732 
733 void
734 sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t *sli)
735 {
736 	sbd_swap_section_hdr(&sli->sli_sms_header);
737 	if (sli->sli_data_order == SMS_DATA_ORDER)
738 		return;
739 	sli->sli_sms_header.sms_chksum	+= SMS_DATA_ORDER - sli->sli_data_order;
740 	sli->sli_data_order		= SMS_DATA_ORDER;
741 	sli->sli_total_store_size	= BSWAP_64(sli->sli_total_store_size);
742 	sli->sli_total_meta_size	= BSWAP_64(sli->sli_total_meta_size);
743 	sli->sli_lu_data_offset		= BSWAP_64(sli->sli_lu_data_offset);
744 	sli->sli_lu_data_size		= BSWAP_64(sli->sli_lu_data_size);
745 	sli->sli_flags			= BSWAP_32(sli->sli_flags);
746 	sli->sli_blocksize		= BSWAP_16(sli->sli_blocksize);
747 }
748 
749 void
750 sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t *sli)
751 {
752 	sbd_swap_section_hdr(&sli->sli_sms_header);
753 	if (sli->sli_data_order == SMS_DATA_ORDER)
754 		return;
755 	sli->sli_sms_header.sms_chksum	+= SMS_DATA_ORDER - sli->sli_data_order;
756 	sli->sli_data_order		= SMS_DATA_ORDER;
757 	sli->sli_flags			= BSWAP_32(sli->sli_flags);
758 	sli->sli_lu_size		= BSWAP_64(sli->sli_lu_size);
759 	sli->sli_meta_fname_offset	= BSWAP_16(sli->sli_meta_fname_offset);
760 	sli->sli_data_fname_offset	= BSWAP_16(sli->sli_data_fname_offset);
761 	sli->sli_serial_offset		= BSWAP_16(sli->sli_serial_offset);
762 	sli->sli_alias_offset		= BSWAP_16(sli->sli_alias_offset);
763 }
764 
765 sbd_status_t
766 sbd_load_section_hdr(sbd_lu_t *sl, sm_section_hdr_t *sms)
767 {
768 	sm_section_hdr_t h;
769 	uint64_t st;
770 	sbd_status_t ret;
771 
772 	for (st = SBD_META_OFFSET + sizeof (sbd_meta_start_t);
773 	    st < sl->sl_meta_size_used; st += h.sms_size) {
774 		if ((ret = sbd_read_meta(sl, st, sizeof (sm_section_hdr_t),
775 		    (uint8_t *)&h)) != SBD_SUCCESS) {
776 			return (ret);
777 		}
778 		if (h.sms_data_order != SMS_DATA_ORDER) {
779 			sbd_swap_section_hdr(&h);
780 		}
781 		if ((h.sms_data_order != SMS_DATA_ORDER) ||
782 		    (h.sms_offset != st) || (h.sms_size < sizeof (h)) ||
783 		    ((st + h.sms_size) > sl->sl_meta_size_used)) {
784 			return (SBD_META_CORRUPTED);
785 		}
786 		if (h.sms_id == sms->sms_id) {
787 			bcopy(&h, sms, sizeof (h));
788 			return (SBD_SUCCESS);
789 		}
790 	}
791 
792 	return (SBD_NOT_FOUND);
793 }
794 
795 sbd_status_t
796 sbd_load_meta_start(sbd_lu_t *sl)
797 {
798 	sbd_meta_start_t *sm;
799 	sbd_status_t ret;
800 
801 	/* Fake meta params initially */
802 	sl->sl_total_meta_size = (uint64_t)-1;
803 	sl->sl_meta_size_used = SBD_META_OFFSET + sizeof (sbd_meta_start_t);
804 
805 	sm = kmem_zalloc(sizeof (*sm), KM_SLEEP);
806 	ret = sbd_read_meta(sl, SBD_META_OFFSET, sizeof (*sm), (uint8_t *)sm);
807 	if (ret != SBD_SUCCESS) {
808 		goto load_meta_start_failed;
809 	}
810 
811 	if (sm->sm_magic != SBD_MAGIC) {
812 		sbd_swap_meta_start(sm);
813 	}
814 
815 	if ((sm->sm_magic != SBD_MAGIC) || (sbd_calc_sum((uint8_t *)sm,
816 	    sizeof (*sm) - 1) != sm->sm_chksum)) {
817 		ret = SBD_META_CORRUPTED;
818 		goto load_meta_start_failed;
819 	}
820 
821 	if (sm->sm_ver_major != SBD_VER_MAJOR) {
822 		ret = SBD_NOT_SUPPORTED;
823 		goto load_meta_start_failed;
824 	}
825 
826 	sl->sl_total_meta_size = sm->sm_meta_size;
827 	sl->sl_meta_size_used = sm->sm_meta_size_used;
828 	ret = SBD_SUCCESS;
829 
830 load_meta_start_failed:
831 	kmem_free(sm, sizeof (*sm));
832 	return (ret);
833 }
834 
835 sbd_status_t
836 sbd_write_meta_start(sbd_lu_t *sl, uint64_t meta_size, uint64_t meta_size_used)
837 {
838 	sbd_meta_start_t *sm;
839 	sbd_status_t ret;
840 
841 	sm = (sbd_meta_start_t *)kmem_zalloc(sizeof (sbd_meta_start_t),
842 	    KM_SLEEP);
843 
844 	sm->sm_magic = SBD_MAGIC;
845 	sm->sm_meta_size = meta_size;
846 	sm->sm_meta_size_used = meta_size_used;
847 	sm->sm_ver_major = SBD_VER_MAJOR;
848 	sm->sm_ver_minor = SBD_VER_MINOR;
849 	sm->sm_ver_subminor = SBD_VER_SUBMINOR;
850 	sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (*sm) - 1);
851 
852 	ret = sbd_write_meta(sl, SBD_META_OFFSET, sizeof (*sm), (uint8_t *)sm);
853 	kmem_free(sm, sizeof (*sm));
854 
855 	return (ret);
856 }
857 
858 sbd_status_t
859 sbd_read_meta_section(sbd_lu_t *sl, sm_section_hdr_t **ppsms, uint16_t sms_id)
860 {
861 	sbd_status_t ret;
862 	sm_section_hdr_t sms;
863 	int alloced = 0;
864 
865 	if (((*ppsms) == NULL) || ((*ppsms)->sms_offset == 0)) {
866 		bzero(&sms, sizeof (sm_section_hdr_t));
867 		sms.sms_id = sms_id;
868 		if ((ret = sbd_load_section_hdr(sl, &sms)) != SBD_SUCCESS) {
869 			return (ret);
870 		} else {
871 			if ((*ppsms) == NULL) {
872 				*ppsms = (sm_section_hdr_t *)kmem_zalloc(
873 				    sms.sms_size, KM_SLEEP);
874 				alloced = 1;
875 			}
876 			bcopy(&sms, *ppsms, sizeof (sm_section_hdr_t));
877 		}
878 	}
879 
880 	ret = sbd_read_meta(sl, (*ppsms)->sms_offset, (*ppsms)->sms_size,
881 	    (uint8_t *)(*ppsms));
882 	if (ret == SBD_SUCCESS) {
883 		uint8_t s;
884 		if ((*ppsms)->sms_data_order != SMS_DATA_ORDER)
885 			sbd_swap_section_hdr(*ppsms);
886 		if ((*ppsms)->sms_id != SMS_ID_UNUSED) {
887 			s = sbd_calc_section_sum(*ppsms, (*ppsms)->sms_size);
888 			if (s != (*ppsms)->sms_chksum)
889 				ret = SBD_META_CORRUPTED;
890 		}
891 	}
892 
893 	if ((ret != SBD_SUCCESS) && alloced)
894 		kmem_free(*ppsms, sms.sms_size);
895 	return (ret);
896 }
897 
898 sbd_status_t
899 sbd_write_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms)
900 {
901 	sm_section_hdr_t t;
902 	uint64_t off, s;
903 	uint64_t unused_start;
904 	sbd_status_t ret;
905 	uint8_t *cb;
906 	int update_meta_start = 0;
907 
908 write_meta_section_again:
909 	if (sms->sms_offset) {
910 		/* Verify that size has not changed */
911 		ret = sbd_read_meta(sl, sms->sms_offset, sizeof (t),
912 		    (uint8_t *)&t);
913 		if (ret != SBD_SUCCESS)
914 			return (ret);
915 		if (t.sms_data_order != SMS_DATA_ORDER) {
916 			sbd_swap_section_hdr(&t);
917 		}
918 		if (t.sms_id != sms->sms_id) {
919 			return (SBD_INVALID_ARG);
920 		}
921 		if (t.sms_size == sms->sms_size) {
922 			return (sbd_write_meta(sl, sms->sms_offset,
923 			    sms->sms_size, (uint8_t *)sms));
924 		}
925 		t.sms_id = SMS_ID_UNUSED;
926 		/*
927 		 * For unused sections we only use chksum of the header. for
928 		 * all other sections, the chksum is for the entire section.
929 		 */
930 		t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
931 		ret = sbd_write_meta(sl, t.sms_offset, sizeof (t),
932 		    (uint8_t *)&t);
933 		if (ret != SBD_SUCCESS)
934 			return (ret);
935 		sms->sms_offset = 0;
936 	} else {
937 		t.sms_id = sms->sms_id;
938 		t.sms_data_order = SMS_DATA_ORDER;
939 		ret = sbd_load_section_hdr(sl, &t);
940 		if (ret == SBD_SUCCESS) {
941 			sms->sms_offset = t.sms_offset;
942 			sms->sms_chksum =
943 			    sbd_calc_section_sum(sms, sms->sms_size);
944 			goto write_meta_section_again;
945 		} else if (ret != SBD_NOT_FOUND) {
946 			return (ret);
947 		}
948 	}
949 
950 	/*
951 	 * At this point we know that section does not already exist.
952 	 * find space large enough to hold the section or grow meta if
953 	 * possible.
954 	 */
955 	unused_start = 0;
956 	s = 0;
957 	for (off = SBD_META_OFFSET + sizeof (sbd_meta_start_t);
958 	    off < sl->sl_meta_size_used; off += t.sms_size) {
959 		ret = sbd_read_meta(sl, off, sizeof (t), (uint8_t *)&t);
960 		if (ret != SBD_SUCCESS)
961 			return (ret);
962 		if (t.sms_data_order != SMS_DATA_ORDER)
963 			sbd_swap_section_hdr(&t);
964 		if (t.sms_size == 0)
965 			return (SBD_META_CORRUPTED);
966 		if (t.sms_id == SMS_ID_UNUSED) {
967 			if (unused_start == 0)
968 				unused_start = off;
969 			s = t.sms_size - unused_start + off;
970 			if ((s == sms->sms_size) || (s >= (sms->sms_size +
971 			    sizeof (t)))) {
972 				break;
973 			} else {
974 				s = 0;
975 			}
976 		} else {
977 			unused_start = 0;
978 		}
979 	}
980 
981 	off = (unused_start == 0) ? sl->sl_meta_size_used : unused_start;
982 	if (s == 0) {
983 		s = sl->sl_total_meta_size - off;
984 		/* Lets see if we can expand the metadata */
985 		if (s >= sms->sms_size || !(sl->sl_flags & SL_SHARED_META)) {
986 			s = sms->sms_size;
987 			update_meta_start = 1;
988 		} else {
989 			s = 0;
990 		}
991 	}
992 
993 	if (s == 0)
994 		return (SBD_ALLOC_FAILURE);
995 
996 	sms->sms_offset = off;
997 	sms->sms_chksum = sbd_calc_section_sum(sms, sms->sms_size);
998 	/*
999 	 * Since we may have to write more than one section (current +
1000 	 * any unused), use a combined buffer.
1001 	 */
1002 	cb = kmem_zalloc(s, KM_SLEEP);
1003 	bcopy(sms, cb, sms->sms_size);
1004 	if (s > sms->sms_size) {
1005 		t.sms_offset = off + sms->sms_size;
1006 		t.sms_size = s - sms->sms_size;
1007 		t.sms_id = SMS_ID_UNUSED;
1008 		t.sms_data_order = SMS_DATA_ORDER;
1009 		t.sms_chksum = sbd_calc_section_sum(&t, sizeof (t));
1010 		bcopy(&t, cb + sms->sms_size, sizeof (t));
1011 	}
1012 	ret = sbd_write_meta(sl, off, s, cb);
1013 	kmem_free(cb, s);
1014 	if (ret != SBD_SUCCESS)
1015 		return (ret);
1016 
1017 	if (update_meta_start) {
1018 		uint64_t old_sz_used = sl->sl_meta_size_used; /* save a copy */
1019 		sl->sl_meta_size_used = off + s;
1020 		s = sl->sl_total_meta_size; /* save a copy */
1021 		if (sl->sl_total_meta_size < sl->sl_meta_size_used) {
1022 			uint64_t meta_align =
1023 			    (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
1024 			sl->sl_total_meta_size = (sl->sl_meta_size_used +
1025 			    meta_align) & (~meta_align);
1026 		}
1027 		ret = sbd_write_meta_start(sl, sl->sl_total_meta_size,
1028 		    sl->sl_meta_size_used);
1029 		if (ret != SBD_SUCCESS) {
1030 			sl->sl_meta_size_used = old_sz_used;
1031 			sl->sl_total_meta_size = s;
1032 		}
1033 	}
1034 	return (ret);
1035 }
1036 
1037 sbd_status_t
1038 sbd_delete_meta_section(sbd_lu_t *sl, sm_section_hdr_t *sms, uint16_t sms_id)
1039 {
1040 	/* Delete sms, if sms is NULL, search by sms_id */
1041 
1042 	sm_section_hdr_t hdr;
1043 	sbd_status_t ret;
1044 
1045 	if (sms == NULL) {
1046 		sms = &hdr;
1047 		sms->sms_data_order = SMS_DATA_ORDER;
1048 		sms->sms_id = sms_id;
1049 		ret = sbd_load_section_hdr(sl, sms);
1050 		if (ret != SBD_SUCCESS) {
1051 			return (ret);
1052 		}
1053 	}
1054 	sms->sms_id = SMS_ID_UNUSED;
1055 	return (sbd_write_meta(sl, sms->sms_offset,
1056 	    sizeof (sm_section_hdr_t), (uint8_t *)sms));
1057 }
1058 
1059 sbd_status_t
1060 sbd_write_lu_info(sbd_lu_t *sl)
1061 {
1062 	sbd_lu_info_1_1_t *sli;
1063 	int s;
1064 	uint8_t *p;
1065 	char *zvol_name = NULL;
1066 	sbd_status_t ret;
1067 
1068 	mutex_enter(&sl->sl_lock);
1069 
1070 	s = sl->sl_serial_no_size;
1071 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1072 		if (sl->sl_data_filename) {
1073 			s += strlen(sl->sl_data_filename) + 1;
1074 		}
1075 	}
1076 	if (sl->sl_flags & SL_ZFS_META) {
1077 		zvol_name = sbd_get_zvol_name(sl);
1078 		s += strlen(zvol_name) + 1;
1079 	}
1080 	if (sl->sl_alias) {
1081 		s += strlen(sl->sl_alias) + 1;
1082 	}
1083 	sli = (sbd_lu_info_1_1_t *)kmem_zalloc(sizeof (*sli) + s, KM_SLEEP);
1084 	p = sli->sli_buf;
1085 	if ((sl->sl_flags & (SL_SHARED_META | SL_ZFS_META)) == 0) {
1086 		sli->sli_flags |= SLI_SEPARATE_META;
1087 		(void) strcpy((char *)p, sl->sl_data_filename);
1088 		sli->sli_data_fname_offset =
1089 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1090 		sli->sli_flags |= SLI_DATA_FNAME_VALID;
1091 		p += strlen(sl->sl_data_filename) + 1;
1092 	}
1093 	if (sl->sl_flags & SL_ZFS_META) {
1094 		(void) strcpy((char *)p, zvol_name);
1095 		sli->sli_meta_fname_offset =
1096 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1097 		sli->sli_flags |= SLI_META_FNAME_VALID | SLI_ZFS_META;
1098 		p += strlen(zvol_name) + 1;
1099 		kmem_free(zvol_name, strlen(zvol_name) + 1);
1100 		zvol_name = NULL;
1101 	}
1102 	if (sl->sl_alias) {
1103 		(void) strcpy((char *)p, sl->sl_alias);
1104 		sli->sli_alias_offset =
1105 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1106 		sli->sli_flags |= SLI_ALIAS_VALID;
1107 		p += strlen(sl->sl_alias) + 1;
1108 	}
1109 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
1110 		sli->sli_flags |= SLI_WRITE_PROTECTED;
1111 	}
1112 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE) {
1113 		sli->sli_flags |= SLI_WRITEBACK_CACHE_DISABLE;
1114 	}
1115 	if (sl->sl_flags & SL_VID_VALID) {
1116 		bcopy(sl->sl_vendor_id, sli->sli_vid, 8);
1117 		sli->sli_flags |= SLI_VID_VALID;
1118 	}
1119 	if (sl->sl_flags & SL_PID_VALID) {
1120 		bcopy(sl->sl_product_id, sli->sli_pid, 16);
1121 		sli->sli_flags |= SLI_PID_VALID;
1122 	}
1123 	if (sl->sl_flags & SL_REV_VALID) {
1124 		bcopy(sl->sl_revision, sli->sli_rev, 4);
1125 		sli->sli_flags |= SLI_REV_VALID;
1126 	}
1127 	if (sl->sl_serial_no_size) {
1128 		bcopy(sl->sl_serial_no, p, sl->sl_serial_no_size);
1129 		sli->sli_serial_size = sl->sl_serial_no_size;
1130 		sli->sli_serial_offset =
1131 		    (uintptr_t)p - (uintptr_t)sli->sli_buf;
1132 		sli->sli_flags |= SLI_SERIAL_VALID;
1133 		p += sli->sli_serial_size;
1134 	}
1135 	sli->sli_lu_size = sl->sl_lu_size;
1136 	sli->sli_data_blocksize_shift = sl->sl_data_blocksize_shift;
1137 	sli->sli_data_order = SMS_DATA_ORDER;
1138 	bcopy(sl->sl_device_id, sli->sli_device_id, 20);
1139 
1140 	sli->sli_sms_header.sms_size = sizeof (*sli) + s;
1141 	sli->sli_sms_header.sms_id = SMS_ID_LU_INFO_1_1;
1142 	sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1143 
1144 	mutex_exit(&sl->sl_lock);
1145 	ret = sbd_write_meta_section(sl, (sm_section_hdr_t *)sli);
1146 	kmem_free(sli, sizeof (*sli) + s);
1147 	return (ret);
1148 }
1149 
1150 int
1151 sbd_populate_and_register_lu(sbd_lu_t *sl, uint32_t *err_ret)
1152 {
1153 	stmf_lu_t *lu = sl->sl_lu;
1154 	stmf_status_t ret;
1155 
1156 	lu->lu_id = (scsi_devid_desc_t *)sl->sl_device_id;
1157 	if (sl->sl_alias) {
1158 		lu->lu_alias = sl->sl_alias;
1159 	} else {
1160 		lu->lu_alias = sl->sl_name;
1161 	}
1162 	lu->lu_lp = sbd_lp;
1163 	lu->lu_task_alloc = sbd_task_alloc;
1164 	lu->lu_new_task = sbd_new_task;
1165 	lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
1166 	lu->lu_send_status_done = sbd_send_status_done;
1167 	lu->lu_task_free = sbd_task_free;
1168 	lu->lu_abort = sbd_abort;
1169 	lu->lu_ctl = sbd_ctl;
1170 	lu->lu_info = sbd_info;
1171 	sl->sl_state = STMF_STATE_OFFLINE;
1172 
1173 	if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
1174 		stmf_trace(0, "Failed to register with framework, ret=%llx",
1175 		    ret);
1176 		if (ret == STMF_ALREADY) {
1177 			*err_ret = SBD_RET_GUID_ALREADY_REGISTERED;
1178 		}
1179 		return (EIO);
1180 	}
1181 
1182 	*err_ret = 0;
1183 	return (0);
1184 }
1185 
1186 int
1187 sbd_open_data_file(sbd_lu_t *sl, uint32_t *err_ret, int lu_size_valid,
1188     int vp_valid, int keep_open)
1189 {
1190 	int ret;
1191 	int flag;
1192 	ulong_t	nbits;
1193 	uint64_t supported_size;
1194 	vattr_t vattr;
1195 	enum vtype vt;
1196 
1197 	mutex_enter(&sl->sl_lock);
1198 	if (vp_valid) {
1199 		goto odf_over_open;
1200 	}
1201 	if (sl->sl_data_filename[0] != '/') {
1202 		*err_ret = SBD_RET_DATA_PATH_NOT_ABSOLUTE;
1203 		mutex_exit(&sl->sl_lock);
1204 		return (EINVAL);
1205 	}
1206 	if ((ret = lookupname(sl->sl_data_filename, UIO_SYSSPACE, FOLLOW,
1207 	    NULLVPP, &sl->sl_data_vp)) != 0) {
1208 		*err_ret = SBD_RET_DATA_FILE_LOOKUP_FAILED;
1209 		mutex_exit(&sl->sl_lock);
1210 		return (ret);
1211 	}
1212 	sl->sl_data_vtype = vt = sl->sl_data_vp->v_type;
1213 	VN_RELE(sl->sl_data_vp);
1214 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1215 		*err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1216 		mutex_exit(&sl->sl_lock);
1217 		return (EINVAL);
1218 	}
1219 	if (sl->sl_flags & SL_WRITE_PROTECTED) {
1220 		flag = FREAD | FOFFMAX;
1221 	} else {
1222 		flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1223 	}
1224 	if ((ret = vn_open(sl->sl_data_filename, UIO_SYSSPACE, flag, 0,
1225 	    &sl->sl_data_vp, 0, 0)) != 0) {
1226 		*err_ret = SBD_RET_DATA_FILE_OPEN_FAILED;
1227 		mutex_exit(&sl->sl_lock);
1228 		return (ret);
1229 	}
1230 odf_over_open:
1231 	vattr.va_mask = AT_SIZE;
1232 	if ((ret = VOP_GETATTR(sl->sl_data_vp, &vattr, 0, CRED(), NULL)) != 0) {
1233 		*err_ret = SBD_RET_DATA_FILE_GETATTR_FAILED;
1234 		goto odf_close_data_and_exit;
1235 	}
1236 	if ((vt != VREG) && (vattr.va_size == 0)) {
1237 		/*
1238 		 * Its a zero byte block or char device. This cannot be
1239 		 * a raw disk.
1240 		 */
1241 		*err_ret = SBD_RET_WRONG_DATA_FILE_TYPE;
1242 		ret = EINVAL;
1243 		goto odf_close_data_and_exit;
1244 	}
1245 	/* sl_data_readable size includes any metadata. */
1246 	sl->sl_data_readable_size = vattr.va_size;
1247 	if (VOP_PATHCONF(sl->sl_data_vp, _PC_FILESIZEBITS, &nbits,
1248 	    CRED(), NULL) != 0) {
1249 		nbits = 0;
1250 	}
1251 	/* nbits cannot be greater than 64 */
1252 	sl->sl_data_fs_nbits = (uint8_t)nbits;
1253 	if (lu_size_valid) {
1254 		sl->sl_total_data_size = sl->sl_lu_size;
1255 		if (sl->sl_flags & SL_SHARED_META) {
1256 			sl->sl_total_data_size += SHARED_META_DATA_SIZE;
1257 		}
1258 		if ((nbits > 0) && (nbits < 64)) {
1259 			/*
1260 			 * The expression below is correct only if nbits is
1261 			 * positive and less than 64.
1262 			 */
1263 			supported_size = (((uint64_t)1) << nbits) - 1;
1264 			if (sl->sl_total_data_size > supported_size) {
1265 				*err_ret = SBD_RET_SIZE_NOT_SUPPORTED_BY_FS;
1266 				ret = EINVAL;
1267 				goto odf_close_data_and_exit;
1268 			}
1269 		}
1270 	} else {
1271 		sl->sl_total_data_size = vattr.va_size;
1272 		if (sl->sl_flags & SL_SHARED_META) {
1273 			if (vattr.va_size > SHARED_META_DATA_SIZE) {
1274 				sl->sl_lu_size = vattr.va_size -
1275 				    SHARED_META_DATA_SIZE;
1276 			} else {
1277 				*err_ret = SBD_RET_FILE_SIZE_ERROR;
1278 				ret = EINVAL;
1279 				goto odf_close_data_and_exit;
1280 			}
1281 		} else {
1282 			sl->sl_lu_size = vattr.va_size;
1283 		}
1284 	}
1285 	if (sl->sl_lu_size < SBD_MIN_LU_SIZE) {
1286 		*err_ret = SBD_RET_FILE_SIZE_ERROR;
1287 		ret = EINVAL;
1288 		goto odf_close_data_and_exit;
1289 	}
1290 	if (sl->sl_lu_size &
1291 	    ((((uint64_t)1) << sl->sl_data_blocksize_shift) - 1)) {
1292 		*err_ret = SBD_RET_FILE_ALIGN_ERROR;
1293 		ret = EINVAL;
1294 		goto odf_close_data_and_exit;
1295 	}
1296 	sl->sl_flags |= SL_MEDIA_LOADED;
1297 	mutex_exit(&sl->sl_lock);
1298 	return (0);
1299 
1300 odf_close_data_and_exit:
1301 	if (!keep_open) {
1302 		(void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1303 		VN_RELE(sl->sl_data_vp);
1304 	}
1305 	mutex_exit(&sl->sl_lock);
1306 	return (ret);
1307 }
1308 
1309 int
1310 sbd_close_delete_lu(sbd_lu_t *sl, int ret)
1311 {
1312 	int flag;
1313 
1314 	if (((sl->sl_flags & SL_SHARED_META) == 0) &&
1315 	    (sl->sl_flags & SL_META_OPENED)) {
1316 		if (sl->sl_flags & SL_ZFS_META) {
1317 			sbd_close_zfs_meta(sl);
1318 		} else {
1319 			flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1320 			(void) VOP_CLOSE(sl->sl_meta_vp, flag, 1, 0,
1321 			    CRED(), NULL);
1322 			VN_RELE(sl->sl_meta_vp);
1323 		}
1324 		sl->sl_flags &= ~SL_META_OPENED;
1325 	}
1326 	if (sl->sl_flags & SL_MEDIA_LOADED) {
1327 		if (sl->sl_flags & SL_WRITE_PROTECTED) {
1328 			flag = FREAD | FOFFMAX;
1329 		} else {
1330 			flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1331 		}
1332 		(void) VOP_CLOSE(sl->sl_data_vp, flag, 1, 0, CRED(), NULL);
1333 		VN_RELE(sl->sl_data_vp);
1334 		sl->sl_flags &= ~SL_MEDIA_LOADED;
1335 		if (sl->sl_flags & SL_SHARED_META) {
1336 			sl->sl_flags &= ~SL_META_OPENED;
1337 		}
1338 	}
1339 	if (sl->sl_flags & SL_LINKED)
1340 		sbd_unlink_lu(sl);
1341 	mutex_destroy(&sl->sl_lock);
1342 	rw_destroy(&sl->sl_pgr->pgr_lock);
1343 	if (sl->sl_serial_no_alloc_size) {
1344 		kmem_free(sl->sl_serial_no, sl->sl_serial_no_alloc_size);
1345 	}
1346 	if (sl->sl_data_fname_alloc_size) {
1347 		kmem_free(sl->sl_data_filename, sl->sl_data_fname_alloc_size);
1348 	}
1349 	if (sl->sl_alias_alloc_size) {
1350 		kmem_free(sl->sl_alias, sl->sl_alias_alloc_size);
1351 	}
1352 	stmf_free(sl->sl_lu);
1353 	return (ret);
1354 }
1355 
1356 int
1357 sbd_create_register_lu(sbd_create_and_reg_lu_t *slu, int struct_sz,
1358     uint32_t *err_ret)
1359 {
1360 	char *namebuf;
1361 	sbd_lu_t *sl;
1362 	stmf_lu_t *lu;
1363 	sbd_status_t sret;
1364 	char *p;
1365 	int sz;
1366 	int alloc_sz;
1367 	int ret = EIO;
1368 	int flag;
1369 	int wcd = 0;
1370 	enum vtype vt;
1371 
1372 	sz = struct_sz - sizeof (sbd_create_and_reg_lu_t) + 8 + 1;
1373 
1374 	*err_ret = 0;
1375 
1376 	/* Lets validate various offsets */
1377 	if (((slu->slu_meta_fname_valid) &&
1378 	    (slu->slu_meta_fname_off >= sz)) ||
1379 	    (slu->slu_data_fname_off >= sz) ||
1380 	    ((slu->slu_alias_valid) &&
1381 	    (slu->slu_alias_off >= sz)) ||
1382 	    ((slu->slu_serial_valid) &&
1383 	    ((slu->slu_serial_off + slu->slu_serial_size) >= sz))) {
1384 		return (EINVAL);
1385 	}
1386 
1387 	namebuf = kmem_zalloc(sz, KM_SLEEP);
1388 	bcopy(slu->slu_buf, namebuf, sz - 1);
1389 	namebuf[sz - 1] = 0;
1390 
1391 	alloc_sz = sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1392 	if (slu->slu_meta_fname_valid) {
1393 		alloc_sz += strlen(namebuf + slu->slu_meta_fname_off) + 1;
1394 	}
1395 	alloc_sz += strlen(namebuf + slu->slu_data_fname_off) + 1;
1396 	if (slu->slu_alias_valid) {
1397 		alloc_sz += strlen(namebuf + slu->slu_alias_off) + 1;
1398 	}
1399 	if (slu->slu_serial_valid) {
1400 		alloc_sz += slu->slu_serial_size;
1401 	}
1402 
1403 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, alloc_sz, 0);
1404 	if (lu == NULL) {
1405 		kmem_free(namebuf, sz);
1406 		return (ENOMEM);
1407 	}
1408 	sl = (sbd_lu_t *)lu->lu_provider_private;
1409 	bzero(sl, alloc_sz);
1410 	sl->sl_lu = lu;
1411 	sl->sl_alloc_size = alloc_sz;
1412 	sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
1413 	rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
1414 	mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
1415 	p = ((char *)sl) + sizeof (sbd_lu_t) + sizeof (sbd_pgr_t);
1416 	sl->sl_data_filename = p;
1417 	(void) strcpy(sl->sl_data_filename, namebuf + slu->slu_data_fname_off);
1418 	p += strlen(sl->sl_data_filename) + 1;
1419 	if (slu->slu_meta_fname_valid) {
1420 		sl->sl_alias = sl->sl_name = sl->sl_meta_filename = p;
1421 		(void) strcpy(sl->sl_meta_filename, namebuf +
1422 		    slu->slu_meta_fname_off);
1423 		p += strlen(sl->sl_meta_filename) + 1;
1424 	} else {
1425 		sl->sl_alias = sl->sl_name = sl->sl_data_filename;
1426 		if (sbd_is_zvol(sl->sl_data_filename, NULL)) {
1427 			sl->sl_flags |= SL_ZFS_META;
1428 		} else {
1429 			sl->sl_flags |= SL_SHARED_META;
1430 			sl->sl_data_offset = SHARED_META_DATA_SIZE;
1431 			sl->sl_total_meta_size = SHARED_META_DATA_SIZE;
1432 			sl->sl_meta_size_used = 0;
1433 		}
1434 	}
1435 	if (slu->slu_alias_valid) {
1436 		sl->sl_alias = p;
1437 		(void) strcpy(p, namebuf + slu->slu_alias_off);
1438 		p += strlen(sl->sl_alias) + 1;
1439 	}
1440 	if (slu->slu_serial_valid) {
1441 		sl->sl_serial_no = (uint8_t *)p;
1442 		bcopy(namebuf + slu->slu_serial_off, sl->sl_serial_no,
1443 		    slu->slu_serial_size);
1444 		sl->sl_serial_no_size = slu->slu_serial_size;
1445 		p += slu->slu_serial_size;
1446 	}
1447 	kmem_free(namebuf, sz);
1448 	if (slu->slu_vid_valid) {
1449 		bcopy(slu->slu_vid, sl->sl_vendor_id, 8);
1450 		sl->sl_flags |= SL_VID_VALID;
1451 	}
1452 	if (slu->slu_pid_valid) {
1453 		bcopy(slu->slu_pid, sl->sl_product_id, 16);
1454 		sl->sl_flags |= SL_PID_VALID;
1455 	}
1456 	if (slu->slu_rev_valid) {
1457 		bcopy(slu->slu_rev, sl->sl_revision, 4);
1458 		sl->sl_flags |= SL_REV_VALID;
1459 	}
1460 	if (slu->slu_write_protected) {
1461 		sl->sl_flags |= SL_WRITE_PROTECTED;
1462 	}
1463 	if (slu->slu_writeback_cache_disable) {
1464 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1465 		    SL_SAVED_WRITE_CACHE_DISABLE;
1466 	}
1467 
1468 	if (slu->slu_blksize_valid) {
1469 		if ((slu->slu_blksize & (slu->slu_blksize - 1)) ||
1470 		    (slu->slu_blksize > (32 * 1024)) ||
1471 		    (slu->slu_blksize == 0)) {
1472 			*err_ret = SBD_RET_INVALID_BLKSIZE;
1473 			ret = EINVAL;
1474 			goto scm_err_out;
1475 		}
1476 		while ((1 << sl->sl_data_blocksize_shift) != slu->slu_blksize) {
1477 			sl->sl_data_blocksize_shift++;
1478 		}
1479 	} else {
1480 		sl->sl_data_blocksize_shift = 9;	/* 512 by default */
1481 		slu->slu_blksize = 512;
1482 	}
1483 
1484 	/* Now lets start creating meta */
1485 	sl->sl_trans_op = SL_OP_CREATE_REGISTER_LU;
1486 	if (sbd_link_lu(sl) != SBD_SUCCESS) {
1487 		*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
1488 		ret = EALREADY;
1489 		goto scm_err_out;
1490 	}
1491 
1492 	/* 1st focus on the data store */
1493 	if (slu->slu_lu_size_valid) {
1494 		sl->sl_lu_size = slu->slu_lu_size;
1495 	}
1496 	ret = sbd_open_data_file(sl, err_ret, slu->slu_lu_size_valid, 0, 0);
1497 	slu->slu_ret_filesize_nbits = sl->sl_data_fs_nbits;
1498 	slu->slu_lu_size = sl->sl_lu_size;
1499 	if (ret) {
1500 		goto scm_err_out;
1501 	}
1502 
1503 	/*
1504 	 * set write cache disable on the device
1505 	 * if it fails, we'll support it using sync/flush
1506 	 */
1507 	if (slu->slu_writeback_cache_disable) {
1508 		(void) sbd_wcd_set(1, sl);
1509 		wcd = 1;
1510 	/*
1511 	 * Attempt to set it to enable, if that fails and it was explicitly set
1512 	 * return an error, otherwise get the current setting and use that
1513 	 */
1514 	} else {
1515 		sret = sbd_wcd_set(0, sl);
1516 		if (slu->slu_writeback_cache_disable_valid &&
1517 		    sret != SBD_SUCCESS) {
1518 			*err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
1519 			ret = EFAULT;
1520 			goto scm_err_out;
1521 		}
1522 		if (sret != SBD_SUCCESS) {
1523 			sbd_wcd_get(&wcd, sl);
1524 		}
1525 	}
1526 
1527 	if (wcd) {
1528 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1529 		    SL_SAVED_WRITE_CACHE_DISABLE;
1530 	}
1531 
1532 	if (sl->sl_flags & SL_SHARED_META) {
1533 		goto over_meta_open;
1534 	}
1535 	if (sl->sl_flags & SL_ZFS_META) {
1536 		if (sbd_create_zfs_meta_object(sl) != SBD_SUCCESS) {
1537 			*err_ret = SBD_RET_ZFS_META_CREATE_FAILED;
1538 			ret = EIO;
1539 			goto scm_err_out;
1540 		}
1541 		sl->sl_meta_blocksize_shift = 0;
1542 		goto over_meta_create;
1543 	}
1544 	if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
1545 	    NULLVPP, &sl->sl_meta_vp)) != 0) {
1546 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
1547 		goto scm_err_out;
1548 	}
1549 	sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
1550 	VN_RELE(sl->sl_meta_vp);
1551 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1552 		*err_ret = SBD_RET_WRONG_META_FILE_TYPE;
1553 		ret = EINVAL;
1554 		goto scm_err_out;
1555 	}
1556 	if (vt == VREG) {
1557 		sl->sl_meta_blocksize_shift = 0;
1558 	} else {
1559 		sl->sl_meta_blocksize_shift = 9;
1560 	}
1561 	flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1562 	if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
1563 	    &sl->sl_meta_vp, 0, 0)) != 0) {
1564 		*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1565 		goto scm_err_out;
1566 	}
1567 over_meta_create:
1568 	sl->sl_total_meta_size = SBD_META_OFFSET + sizeof (sbd_meta_start_t);
1569 	sl->sl_total_meta_size +=
1570 	    (((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1;
1571 	sl->sl_total_meta_size &=
1572 	    ~((((uint64_t)1) << sl->sl_meta_blocksize_shift) - 1);
1573 	sl->sl_meta_size_used = 0;
1574 over_meta_open:
1575 	sl->sl_flags |= SL_META_OPENED;
1576 
1577 	sl->sl_device_id[3] = 16;
1578 	if (slu->slu_guid_valid) {
1579 		sl->sl_device_id[0] = 0xf1;
1580 		sl->sl_device_id[1] = 3;
1581 		sl->sl_device_id[2] = 0;
1582 		bcopy(slu->slu_guid, sl->sl_device_id + 4, 16);
1583 	} else {
1584 		if (!slu->slu_company_id_valid)
1585 			slu->slu_company_id = COMPANY_ID_SUN;
1586 		if (stmf_scsilib_uniq_lu_id(slu->slu_company_id,
1587 		    (scsi_devid_desc_t *)&sl->sl_device_id[0]) !=
1588 		    STMF_SUCCESS) {
1589 			*err_ret = SBD_RET_META_CREATION_FAILED;
1590 			ret = EIO;
1591 			goto scm_err_out;
1592 		}
1593 		bcopy(sl->sl_device_id + 4, slu->slu_guid, 16);
1594 	}
1595 
1596 	/* Lets create the meta now */
1597 	if (sbd_write_meta_start(sl, sl->sl_total_meta_size,
1598 	    sizeof (sbd_meta_start_t)) != SBD_SUCCESS) {
1599 		*err_ret = SBD_RET_META_CREATION_FAILED;
1600 		ret = EIO;
1601 		goto scm_err_out;
1602 	}
1603 	sl->sl_meta_size_used = SBD_META_OFFSET + sizeof (sbd_meta_start_t);
1604 
1605 	if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
1606 		*err_ret = SBD_RET_META_CREATION_FAILED;
1607 		ret = EIO;
1608 		goto scm_err_out;
1609 	}
1610 
1611 	if (sbd_pgr_meta_write(sl) != SBD_SUCCESS) {
1612 		*err_ret = SBD_RET_META_CREATION_FAILED;
1613 		ret = EIO;
1614 		goto scm_err_out;
1615 	}
1616 
1617 	ret = sbd_populate_and_register_lu(sl, err_ret);
1618 	if (ret) {
1619 		goto scm_err_out;
1620 	}
1621 
1622 	sl->sl_trans_op = SL_OP_NONE;
1623 	atomic_add_32(&sbd_lu_count, 1);
1624 	return (0);
1625 
1626 scm_err_out:
1627 	return (sbd_close_delete_lu(sl, ret));
1628 }
1629 
1630 int
1631 sbd_load_sli_1_0(sbd_lu_t *sl, uint32_t *err_ret)
1632 {
1633 	sbd_lu_info_1_0_t *sli = NULL;
1634 	sbd_status_t sret;
1635 
1636 	sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
1637 	    SMS_ID_LU_INFO_1_0);
1638 
1639 	if (sret != SBD_SUCCESS) {
1640 		*err_ret = SBD_RET_NO_META;
1641 		return (EIO);
1642 	}
1643 	if (sli->sli_data_order != SMS_DATA_ORDER) {
1644 		sbd_swap_lu_info_1_0(sli);
1645 		if (sli->sli_data_order != SMS_DATA_ORDER) {
1646 			kmem_free(sli, sli->sli_sms_header.sms_size);
1647 			*err_ret = SBD_RET_NO_META;
1648 			return (EIO);
1649 		}
1650 	}
1651 
1652 	sl->sl_flags |= SL_SHARED_META;
1653 	sl->sl_data_blocksize_shift = 9;
1654 	sl->sl_data_offset = SHARED_META_DATA_SIZE;
1655 	sl->sl_lu_size = sli->sli_total_store_size - SHARED_META_DATA_SIZE;
1656 	sl->sl_total_data_size = SHARED_META_DATA_SIZE + sl->sl_lu_size;
1657 	bcopy(sli->sli_lu_devid, sl->sl_device_id, 20);
1658 
1659 	kmem_free(sli, sli->sli_sms_header.sms_size);
1660 	return (0);
1661 }
1662 
1663 int
1664 sbd_import_lu(sbd_import_lu_t *ilu, int struct_sz, uint32_t *err_ret,
1665     int no_register, sbd_lu_t **slr)
1666 {
1667 	stmf_lu_t *lu;
1668 	sbd_lu_t *sl;
1669 	sbd_lu_info_1_1_t *sli = NULL;
1670 	int asz;
1671 	int ret = 0;
1672 	int flag;
1673 	int wcd = 0;
1674 	int data_opened;
1675 	uint16_t sli_buf_sz;
1676 	uint8_t *sli_buf_copy = NULL;
1677 	enum vtype vt;
1678 	sbd_status_t sret;
1679 
1680 	if (no_register && slr == NULL) {
1681 		return (EINVAL);
1682 	}
1683 	ilu->ilu_meta_fname[struct_sz - sizeof (*ilu) + 8 - 1] = 0;
1684 	asz = strlen(ilu->ilu_meta_fname) + 1;
1685 
1686 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU,
1687 	    sizeof (sbd_lu_t) + sizeof (sbd_pgr_t) + asz, 0);
1688 	if (lu == NULL) {
1689 		return (ENOMEM);
1690 	}
1691 	sl = (sbd_lu_t *)lu->lu_provider_private;
1692 	bzero(sl, sizeof (*sl));
1693 	sl->sl_lu = lu;
1694 	sl->sl_pgr = (sbd_pgr_t *)(sl + 1);
1695 	sl->sl_meta_filename = ((char *)sl) + sizeof (*sl) + sizeof (sbd_pgr_t);
1696 	(void) strcpy(sl->sl_meta_filename, ilu->ilu_meta_fname);
1697 	sl->sl_name = sl->sl_meta_filename;
1698 	rw_init(&sl->sl_pgr->pgr_lock, NULL, RW_DRIVER, NULL);
1699 	mutex_init(&sl->sl_lock, NULL, MUTEX_DRIVER, NULL);
1700 	sl->sl_trans_op = SL_OP_IMPORT_LU;
1701 	/* we're only loading the metadata */
1702 	if (!no_register) {
1703 		if (sbd_link_lu(sl) != SBD_SUCCESS) {
1704 			*err_ret = SBD_RET_FILE_ALREADY_REGISTERED;
1705 			ret = EALREADY;
1706 			goto sim_err_out;
1707 		}
1708 	}
1709 	if ((ret = lookupname(sl->sl_meta_filename, UIO_SYSSPACE, FOLLOW,
1710 	    NULLVPP, &sl->sl_meta_vp)) != 0) {
1711 		*err_ret = SBD_RET_META_FILE_LOOKUP_FAILED;
1712 		goto sim_err_out;
1713 	}
1714 	if (sbd_is_sbd_zvol(sl->sl_meta_filename, sl->sl_meta_vp)) {
1715 		sl->sl_flags |= SL_ZFS_META;
1716 		sl->sl_data_filename = sl->sl_meta_filename;
1717 	}
1718 	sl->sl_meta_vtype = vt = sl->sl_meta_vp->v_type;
1719 	VN_RELE(sl->sl_meta_vp);
1720 	if ((vt != VREG) && (vt != VCHR) && (vt != VBLK)) {
1721 		*err_ret = SBD_RET_WRONG_META_FILE_TYPE;
1722 		ret = EINVAL;
1723 		goto sim_err_out;
1724 	}
1725 	if (sl->sl_flags & SL_ZFS_META) {
1726 		if (sbd_open_zfs_meta(sl) != SBD_SUCCESS) {
1727 			ret = EIO;
1728 			*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1729 			goto sim_err_out;
1730 		}
1731 	} else {
1732 		/* metadata is always writable */
1733 		flag = FREAD | FWRITE | FOFFMAX | FEXCL;
1734 		if ((ret = vn_open(sl->sl_meta_filename, UIO_SYSSPACE, flag, 0,
1735 		    &sl->sl_meta_vp, 0, 0)) != 0) {
1736 			*err_ret = SBD_RET_META_FILE_OPEN_FAILED;
1737 			goto sim_err_out;
1738 		}
1739 	}
1740 	if ((sl->sl_flags & SL_ZFS_META) || (vt == VREG)) {
1741 		sl->sl_meta_blocksize_shift = 0;
1742 	} else {
1743 		sl->sl_meta_blocksize_shift = 9;
1744 	}
1745 	sl->sl_flags |= SL_META_OPENED;
1746 
1747 	sret = sbd_load_meta_start(sl);
1748 	if (sret != SBD_SUCCESS) {
1749 		if (sret == SBD_META_CORRUPTED) {
1750 			*err_ret = SBD_RET_NO_META;
1751 		} else if (sret == SBD_NOT_SUPPORTED) {
1752 			*err_ret = SBD_RET_VERSION_NOT_SUPPORTED;
1753 		} else {
1754 			*err_ret = SBD_RET_NO_META;
1755 		}
1756 		ret = EINVAL;
1757 		goto sim_err_out;
1758 	}
1759 
1760 	/* Now lets see if we can read the most recent LU info */
1761 	sret = sbd_read_meta_section(sl, (sm_section_hdr_t **)&sli,
1762 	    SMS_ID_LU_INFO_1_1);
1763 	if ((sret == SBD_NOT_FOUND) && ((sl->sl_flags & SL_ZFS_META) == 0)) {
1764 		ret = sbd_load_sli_1_0(sl, err_ret);
1765 		if (ret)
1766 			goto sim_err_out;
1767 		goto sim_sli_loaded;
1768 	}
1769 	if (sret != SBD_SUCCESS) {
1770 		*err_ret = SBD_RET_NO_META;
1771 		ret = EIO;
1772 		goto sim_err_out;
1773 	}
1774 	/* load sli 1.1 */
1775 	if (sli->sli_data_order != SMS_DATA_ORDER) {
1776 		sbd_swap_lu_info_1_1(sli);
1777 		if (sli->sli_data_order != SMS_DATA_ORDER) {
1778 			*err_ret = SBD_RET_NO_META;
1779 			ret = EIO;
1780 			goto sim_err_out;
1781 		}
1782 	}
1783 
1784 	sli_buf_sz = sli->sli_sms_header.sms_size -
1785 	    sizeof (sbd_lu_info_1_1_t) + 8;
1786 	sli_buf_copy = kmem_alloc(sli_buf_sz + 1, KM_SLEEP);
1787 	bcopy(sli->sli_buf, sli_buf_copy, sli_buf_sz);
1788 	sli_buf_copy[sli_buf_sz] = 0;
1789 
1790 	/* Make sure all the offsets are within limits */
1791 	if (((sli->sli_flags & SLI_META_FNAME_VALID) &&
1792 	    (sli->sli_meta_fname_offset > sli_buf_sz)) ||
1793 	    ((sli->sli_flags & SLI_DATA_FNAME_VALID) &&
1794 	    (sli->sli_data_fname_offset > sli_buf_sz)) ||
1795 	    ((sli->sli_flags & SLI_SERIAL_VALID) &&
1796 	    ((sli->sli_serial_offset + sli->sli_serial_size) > sli_buf_sz)) ||
1797 	    ((sli->sli_flags & SLI_ALIAS_VALID) &&
1798 	    (sli->sli_alias_offset > sli_buf_sz))) {
1799 		*err_ret = SBD_RET_NO_META;
1800 		ret = EIO;
1801 		goto sim_err_out;
1802 	}
1803 
1804 	if (sl->sl_flags & SL_ZFS_META) {
1805 		/* Verify that its the right zfs node and not some clone */
1806 		int same_zvol;
1807 		char *zvol_name = sbd_get_zvol_name(sl);
1808 
1809 		if ((sli->sli_flags & (SLI_ZFS_META |
1810 		    SLI_META_FNAME_VALID)) == 0) {
1811 			*err_ret = SBD_RET_NO_META;
1812 			ret = EIO;
1813 			goto sim_err_out;
1814 		}
1815 		zvol_name = sbd_get_zvol_name(sl);
1816 		if (strcmp(zvol_name, (char *)sli_buf_copy +
1817 		    sli->sli_meta_fname_offset) != 0)
1818 			same_zvol = 0;
1819 		else
1820 			same_zvol = 1;
1821 		kmem_free(zvol_name, strlen(zvol_name) + 1);
1822 		if (!same_zvol) {
1823 			*err_ret = SBD_ZVOL_META_NAME_MISMATCH;
1824 			ret = EINVAL;
1825 			goto sim_err_out;
1826 		}
1827 	}
1828 	sl->sl_lu_size = sli->sli_lu_size;
1829 	sl->sl_data_blocksize_shift = sli->sli_data_blocksize_shift;
1830 	bcopy(sli->sli_device_id, sl->sl_device_id, 20);
1831 	if (sli->sli_flags & SLI_SERIAL_VALID) {
1832 		sl->sl_serial_no_size = sl->sl_serial_no_alloc_size =
1833 		    sli->sli_serial_size;
1834 		sl->sl_serial_no = kmem_zalloc(sli->sli_serial_size, KM_SLEEP);
1835 		bcopy(sli_buf_copy + sli->sli_serial_offset, sl->sl_serial_no,
1836 		    sl->sl_serial_no_size);
1837 	}
1838 	if (sli->sli_flags & SLI_SEPARATE_META) {
1839 		sl->sl_total_data_size = sl->sl_lu_size;
1840 		if (sli->sli_flags & SLI_DATA_FNAME_VALID) {
1841 			sl->sl_data_fname_alloc_size = strlen((char *)
1842 			    sli_buf_copy + sli->sli_data_fname_offset) + 1;
1843 			sl->sl_data_filename = kmem_zalloc(
1844 			    sl->sl_data_fname_alloc_size, KM_SLEEP);
1845 			(void) strcpy(sl->sl_data_filename,
1846 			    (char *)sli_buf_copy + sli->sli_data_fname_offset);
1847 		}
1848 	} else {
1849 		if (sl->sl_flags & SL_ZFS_META) {
1850 			sl->sl_total_data_size = sl->sl_lu_size;
1851 			sl->sl_data_offset = 0;
1852 		} else {
1853 			sl->sl_total_data_size =
1854 			    sl->sl_lu_size + SHARED_META_DATA_SIZE;
1855 			sl->sl_data_offset = SHARED_META_DATA_SIZE;
1856 			sl->sl_flags |= SL_SHARED_META;
1857 		}
1858 	}
1859 	if (sli->sli_flags & SLI_ALIAS_VALID) {
1860 		sl->sl_alias_alloc_size = strlen((char *)sli_buf_copy +
1861 		    sli->sli_alias_offset) + 1;
1862 		sl->sl_alias = kmem_alloc(sl->sl_alias_alloc_size, KM_SLEEP);
1863 		(void) strcpy(sl->sl_alias, (char *)sli_buf_copy +
1864 		    sli->sli_alias_offset);
1865 	}
1866 	if (sli->sli_flags & SLI_WRITE_PROTECTED) {
1867 		sl->sl_flags |= SL_WRITE_PROTECTED;
1868 	}
1869 	if (sli->sli_flags & SLI_VID_VALID) {
1870 		sl->sl_flags |= SL_VID_VALID;
1871 		bcopy(sli->sli_vid, sl->sl_vendor_id, 8);
1872 	}
1873 	if (sli->sli_flags & SLI_PID_VALID) {
1874 		sl->sl_flags |= SL_PID_VALID;
1875 		bcopy(sli->sli_pid, sl->sl_product_id, 16);
1876 	}
1877 	if (sli->sli_flags & SLI_REV_VALID) {
1878 		sl->sl_flags |= SL_REV_VALID;
1879 		bcopy(sli->sli_rev, sl->sl_revision, 4);
1880 	}
1881 	if (sli->sli_flags & SLI_WRITEBACK_CACHE_DISABLE) {
1882 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
1883 	}
1884 sim_sli_loaded:
1885 	if ((sl->sl_flags & SL_SHARED_META) == 0) {
1886 		data_opened = 0;
1887 	} else {
1888 		data_opened = 1;
1889 		sl->sl_data_filename = sl->sl_meta_filename;
1890 		sl->sl_data_vp = sl->sl_meta_vp;
1891 		sl->sl_data_vtype = sl->sl_meta_vtype;
1892 	}
1893 
1894 	sret = sbd_pgr_meta_load(sl);
1895 	if (sret != SBD_SUCCESS) {
1896 		*err_ret = SBD_RET_NO_META;
1897 		ret = EIO;
1898 		goto sim_err_out;
1899 	}
1900 
1901 	ret = sbd_open_data_file(sl, err_ret, 1, data_opened, 0);
1902 	if (ret)
1903 		goto sim_err_out;
1904 
1905 	/*
1906 	 * set write cache disable on the device
1907 	 * Note: this shouldn't fail on import unless the cache capabilities
1908 	 * of the device changed. If that happened, modify will need to
1909 	 * be used to set the cache flag appropriately after import is done.
1910 	 */
1911 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
1912 		(void) sbd_wcd_set(1, sl);
1913 		wcd = 1;
1914 	/*
1915 	 * if not explicitly set, attempt to set it to enable, if that fails
1916 	 * get the current setting and use that
1917 	 */
1918 	} else {
1919 		sret = sbd_wcd_set(0, sl);
1920 		if (sret != SBD_SUCCESS) {
1921 			sbd_wcd_get(&wcd, sl);
1922 		}
1923 	}
1924 
1925 	if (wcd) {
1926 		sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE |
1927 		    SL_SAVED_WRITE_CACHE_DISABLE;
1928 	}
1929 
1930 	/* we're only loading the metadata */
1931 	if (!no_register) {
1932 		ret = sbd_populate_and_register_lu(sl, err_ret);
1933 		if (ret)
1934 			goto sim_err_out;
1935 		atomic_add_32(&sbd_lu_count, 1);
1936 	}
1937 
1938 	bcopy(sl->sl_device_id + 4, ilu->ilu_ret_guid, 16);
1939 	sl->sl_trans_op = SL_OP_NONE;
1940 	if (sli) {
1941 		kmem_free(sli, sli->sli_sms_header.sms_size);
1942 		sli = NULL;
1943 	}
1944 	if (sli_buf_copy) {
1945 		kmem_free(sli_buf_copy, sli_buf_sz + 1);
1946 		sli_buf_copy = NULL;
1947 	}
1948 	if (no_register) {
1949 		*slr = sl;
1950 	}
1951 	return (0);
1952 
1953 sim_err_out:
1954 	if (sli) {
1955 		kmem_free(sli, sli->sli_sms_header.sms_size);
1956 		sli = NULL;
1957 	}
1958 	if (sli_buf_copy) {
1959 		kmem_free(sli_buf_copy, sli_buf_sz + 1);
1960 		sli_buf_copy = NULL;
1961 	}
1962 	return (sbd_close_delete_lu(sl, ret));
1963 }
1964 
1965 int
1966 sbd_modify_lu(sbd_modify_lu_t *mlu, int struct_sz, uint32_t *err_ret)
1967 {
1968 	sbd_lu_t *sl = NULL;
1969 	int alias_sz;
1970 	int ret = 0;
1971 	sbd_it_data_t *it;
1972 	sbd_status_t sret;
1973 	uint64_t old_size;
1974 	int modify_unregistered = 0;
1975 	int ua = 0;
1976 	sbd_import_lu_t *ilu;
1977 	stmf_lu_t *lu;
1978 	uint32_t ilu_sz;
1979 	uint32_t sz;
1980 
1981 	sz = struct_sz - sizeof (*mlu) + 8 + 1;
1982 
1983 	/* if there is data in the buf, null terminate it */
1984 	if (struct_sz > sizeof (*mlu)) {
1985 		mlu->mlu_buf[struct_sz - sizeof (*mlu) + 8 - 1] = 0;
1986 	}
1987 
1988 	*err_ret = 0;
1989 
1990 	/* Lets validate offsets */
1991 	if (((mlu->mlu_alias_valid) &&
1992 	    (mlu->mlu_alias_off >= sz)) ||
1993 	    (mlu->mlu_by_fname) &&
1994 	    (mlu->mlu_fname_off >= sz)) {
1995 		return (EINVAL);
1996 	}
1997 
1998 	/*
1999 	 * We'll look for the device but if we don't find it registered,
2000 	 * we'll still try to modify the unregistered device.
2001 	 */
2002 	if (mlu->mlu_by_guid) {
2003 		sret = sbd_find_and_lock_lu(mlu->mlu_input_guid, NULL,
2004 		    SL_OP_MODIFY_LU, &sl);
2005 	} else if (mlu->mlu_by_fname) {
2006 		sret = sbd_find_and_lock_lu(NULL,
2007 		    (uint8_t *)&(mlu->mlu_buf[mlu->mlu_fname_off]),
2008 		    SL_OP_MODIFY_LU, &sl);
2009 	} else {
2010 		return (EINVAL);
2011 	}
2012 
2013 
2014 	if (sret != SBD_SUCCESS) {
2015 		if (sret == SBD_BUSY) {
2016 			*err_ret = SBD_RET_LU_BUSY;
2017 			return (EBUSY);
2018 		} else if (sret != SBD_NOT_FOUND) {
2019 			return (EIO);
2020 		} else if (!mlu->mlu_by_fname) {
2021 			return (EINVAL);
2022 		}
2023 		/* Okay, try to import the device */
2024 		struct_sz = max(8, strlen(&(mlu->mlu_buf[mlu->mlu_fname_off]))
2025 		    + 1);
2026 		struct_sz += sizeof (sbd_import_lu_t) - 8;
2027 		ilu_sz = struct_sz;
2028 		ilu = (sbd_import_lu_t *)kmem_zalloc(ilu_sz, KM_SLEEP);
2029 		ilu->ilu_struct_size = struct_sz;
2030 		(void) strcpy(ilu->ilu_meta_fname,
2031 		    &(mlu->mlu_buf[mlu->mlu_fname_off]));
2032 		ret = sbd_import_lu(ilu, struct_sz, err_ret, 1, &sl);
2033 		kmem_free(ilu, ilu_sz);
2034 		if (ret != SBD_SUCCESS) {
2035 			return (ENOENT);
2036 		}
2037 		modify_unregistered = 1;
2038 	}
2039 
2040 	/* check for write cache change */
2041 	if (mlu->mlu_writeback_cache_disable_valid) {
2042 		/* set wce on device */
2043 		sret = sbd_wcd_set(mlu->mlu_writeback_cache_disable, sl);
2044 		if (!mlu->mlu_writeback_cache_disable && sret != SBD_SUCCESS) {
2045 			*err_ret = SBD_RET_WRITE_CACHE_SET_FAILED;
2046 			ret = EFAULT;
2047 			goto smm_err_out;
2048 		}
2049 		mutex_enter(&sl->sl_lock);
2050 		if (!mlu->mlu_writeback_cache_disable) {
2051 			if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) {
2052 				ua = 1;
2053 				sl->sl_flags &= ~SL_WRITEBACK_CACHE_DISABLE;
2054 				sl->sl_flags &= ~SL_SAVED_WRITE_CACHE_DISABLE;
2055 			}
2056 		} else {
2057 			if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) == 0) {
2058 				ua = 1;
2059 				sl->sl_flags |= SL_WRITEBACK_CACHE_DISABLE;
2060 				sl->sl_flags |= SL_SAVED_WRITE_CACHE_DISABLE;
2061 			}
2062 		}
2063 		for (it = sl->sl_it_list; ua && it != NULL;
2064 		    it = it->sbd_it_next) {
2065 			it->sbd_it_ua_conditions |=
2066 			    SBD_UA_MODE_PARAMETERS_CHANGED;
2067 		}
2068 		mutex_exit(&sl->sl_lock);
2069 	}
2070 	ua = 0;
2071 
2072 	if (mlu->mlu_alias_valid) {
2073 		alias_sz = strlen((char *)mlu->mlu_buf +
2074 		    mlu->mlu_alias_off) + 1;
2075 		/*
2076 		 * Use the allocated buffer or alloc a new one.
2077 		 * Don't copy into sl_alias if sl_alias_alloc_size is 0
2078 		 * otherwise or you'll be writing over the data/metadata
2079 		 * filename.
2080 		 */
2081 		mutex_enter(&sl->sl_lock);
2082 		if (sl->sl_alias_alloc_size > 0 &&
2083 		    sl->sl_alias_alloc_size < alias_sz) {
2084 			kmem_free(sl->sl_alias,
2085 			    sl->sl_alias_alloc_size);
2086 			sl->sl_alias_alloc_size = 0;
2087 		}
2088 		if (sl->sl_alias_alloc_size == 0) {
2089 			sl->sl_alias = kmem_alloc(alias_sz, KM_SLEEP);
2090 			sl->sl_alias_alloc_size = alias_sz;
2091 		}
2092 		(void) strcpy(sl->sl_alias, (char *)mlu->mlu_buf +
2093 		    mlu->mlu_alias_off);
2094 		lu = sl->sl_lu;
2095 		lu->lu_alias = sl->sl_alias;
2096 		mutex_exit(&sl->sl_lock);
2097 	}
2098 
2099 
2100 	if (mlu->mlu_write_protected_valid) {
2101 		mutex_enter(&sl->sl_lock);
2102 		if (mlu->mlu_write_protected) {
2103 			if ((sl->sl_flags & SL_WRITE_PROTECTED) == 0) {
2104 				ua = 1;
2105 				sl->sl_flags |= SL_WRITE_PROTECTED;
2106 			}
2107 		} else {
2108 			if (sl->sl_flags & SL_WRITE_PROTECTED) {
2109 				ua = 1;
2110 				sl->sl_flags &= ~SL_WRITE_PROTECTED;
2111 			}
2112 		}
2113 		for (it = sl->sl_it_list; ua && it != NULL;
2114 		    it = it->sbd_it_next) {
2115 			it->sbd_it_ua_conditions |=
2116 			    SBD_UA_MODE_PARAMETERS_CHANGED;
2117 		}
2118 		mutex_exit(&sl->sl_lock);
2119 	}
2120 
2121 	if (mlu->mlu_lu_size_valid) {
2122 		/*
2123 		 * validate lu size and set
2124 		 * For open file only (registered lu)
2125 		 */
2126 		mutex_enter(&sl->sl_lock);
2127 		old_size = sl->sl_lu_size;
2128 		sl->sl_lu_size = mlu->mlu_lu_size;
2129 		mutex_exit(&sl->sl_lock);
2130 		ret = sbd_open_data_file(sl, err_ret, 1, 1, 1);
2131 		if (ret) {
2132 			mutex_enter(&sl->sl_lock);
2133 			sl->sl_lu_size = old_size;
2134 			mutex_exit(&sl->sl_lock);
2135 			goto smm_err_out;
2136 		}
2137 		if (old_size != mlu->mlu_lu_size) {
2138 			mutex_enter(&sl->sl_lock);
2139 			for (it = sl->sl_it_list; it != NULL;
2140 			    it = it->sbd_it_next) {
2141 				it->sbd_it_ua_conditions |=
2142 				    SBD_UA_CAPACITY_CHANGED;
2143 			}
2144 			mutex_exit(&sl->sl_lock);
2145 		}
2146 	}
2147 
2148 	if (sbd_write_lu_info(sl) != SBD_SUCCESS) {
2149 		*err_ret = SBD_RET_META_CREATION_FAILED;
2150 		ret = EIO;
2151 	}
2152 
2153 smm_err_out:
2154 	if (modify_unregistered) {
2155 		(void) sbd_close_delete_lu(sl, 0);
2156 	} else {
2157 		sl->sl_trans_op = SL_OP_NONE;
2158 	}
2159 	return (ret);
2160 }
2161 
2162 /* ARGSUSED */
2163 int
2164 sbd_delete_locked_lu(sbd_lu_t *sl, uint32_t *err_ret,
2165     stmf_state_change_info_t *ssi)
2166 {
2167 	int i;
2168 
2169 	if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2170 	    !sl->sl_state_not_acked) {
2171 		goto sdl_do_dereg;
2172 	}
2173 
2174 	if ((sl->sl_state != STMF_STATE_ONLINE) ||
2175 	    sl->sl_state_not_acked) {
2176 		return (EBUSY);
2177 	}
2178 	if (stmf_ctl(STMF_CMD_LU_OFFLINE, sl->sl_lu, ssi) != STMF_SUCCESS) {
2179 		return (EBUSY);
2180 	}
2181 
2182 	for (i = 0; i < 500; i++) {
2183 		if (sl->sl_state == STMF_STATE_OFFLINE)
2184 			break;
2185 		delay(drv_usectohz(10000));
2186 	}
2187 
2188 	if ((sl->sl_state == STMF_STATE_OFFLINE) &&
2189 	    !sl->sl_state_not_acked) {
2190 		goto sdl_do_dereg;
2191 	}
2192 
2193 	return (EBUSY);
2194 sdl_do_dereg:;
2195 	if (stmf_deregister_lu(sl->sl_lu) != STMF_SUCCESS)
2196 		return (EBUSY);
2197 	atomic_add_32(&sbd_lu_count, -1);
2198 
2199 	return (sbd_close_delete_lu(sl, 0));
2200 }
2201 
2202 int
2203 sbd_delete_lu(sbd_delete_lu_t *dlu, int struct_sz, uint32_t *err_ret)
2204 {
2205 	sbd_lu_t *sl;
2206 	sbd_status_t sret;
2207 	stmf_state_change_info_t ssi;
2208 	int ret;
2209 
2210 	if (dlu->dlu_by_meta_name) {
2211 		((char *)dlu)[struct_sz - 1] = 0;
2212 		sret = sbd_find_and_lock_lu(NULL, dlu->dlu_meta_name,
2213 		    SL_OP_DELETE_LU, &sl);
2214 	} else {
2215 		sret = sbd_find_and_lock_lu(dlu->dlu_guid, NULL,
2216 		    SL_OP_DELETE_LU, &sl);
2217 	}
2218 	if (sret != SBD_SUCCESS) {
2219 		if (sret == SBD_BUSY) {
2220 			*err_ret = SBD_RET_LU_BUSY;
2221 			return (EBUSY);
2222 		} else if (sret == SBD_NOT_FOUND) {
2223 			*err_ret = SBD_RET_NOT_FOUND;
2224 			return (ENOENT);
2225 		}
2226 		return (EIO);
2227 	}
2228 
2229 	ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
2230 	ssi.st_additional_info = "sbd_delete_lu call (ioctl)";
2231 	ret = sbd_delete_locked_lu(sl, err_ret, &ssi);
2232 
2233 	if (ret) {
2234 		/* Once its locked, no need to grab mutex again */
2235 		sl->sl_trans_op = SL_OP_NONE;
2236 	}
2237 	return (ret);
2238 }
2239 
2240 sbd_status_t
2241 sbd_data_read(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
2242 {
2243 	int ret;
2244 	long resid;
2245 
2246 	if ((offset + size) > sl->sl_lu_size) {
2247 		return (SBD_IO_PAST_EOF);
2248 	}
2249 
2250 	offset += sl->sl_data_offset;
2251 
2252 	if ((offset + size) > sl->sl_data_readable_size) {
2253 		uint64_t store_end;
2254 		if (offset > sl->sl_data_readable_size) {
2255 			bzero(buf, size);
2256 			return (SBD_SUCCESS);
2257 		}
2258 		store_end = sl->sl_data_readable_size - offset;
2259 		bzero(buf + store_end, size - store_end);
2260 		size = store_end;
2261 	}
2262 
2263 	DTRACE_PROBE4(backing__store__read__start, sbd_lu_t *, sl,
2264 	    uint8_t *, buf, uint64_t, size, uint64_t, offset);
2265 
2266 	ret = vn_rdwr(UIO_READ, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
2267 	    (offset_t)offset, UIO_SYSSPACE, 0, RLIM64_INFINITY, CRED(),
2268 	    &resid);
2269 
2270 	DTRACE_PROBE5(backing__store__read__end, sbd_lu_t *, sl,
2271 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
2272 	    int, ret);
2273 
2274 over_sl_data_read:
2275 	if (ret || resid) {
2276 		stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret,
2277 		    resid);
2278 		return (SBD_FAILURE);
2279 	}
2280 
2281 	return (SBD_SUCCESS);
2282 }
2283 
2284 sbd_status_t
2285 sbd_data_write(sbd_lu_t *sl, uint64_t offset, uint64_t size, uint8_t *buf)
2286 {
2287 	int ret;
2288 	long resid;
2289 	sbd_status_t sret = SBD_SUCCESS;
2290 	int ioflag;
2291 
2292 	if ((offset + size) > sl->sl_lu_size) {
2293 		return (SBD_IO_PAST_EOF);
2294 	}
2295 
2296 	offset += sl->sl_data_offset;
2297 
2298 	if ((sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
2299 	    (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
2300 		ioflag = FSYNC;
2301 	} else {
2302 		ioflag = 0;
2303 	}
2304 
2305 	DTRACE_PROBE4(backing__store__write__start, sbd_lu_t *, sl,
2306 	    uint8_t *, buf, uint64_t, size, uint64_t, offset);
2307 
2308 	ret = vn_rdwr(UIO_WRITE, sl->sl_data_vp, (caddr_t)buf, (ssize_t)size,
2309 	    (offset_t)offset, UIO_SYSSPACE, ioflag, RLIM64_INFINITY, CRED(),
2310 	    &resid);
2311 
2312 	DTRACE_PROBE5(backing__store__write__end, sbd_lu_t *, sl,
2313 	    uint8_t *, buf, uint64_t, size, uint64_t, offset,
2314 	    int, ret);
2315 
2316 	if ((ret == 0) && (resid == 0) &&
2317 	    (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE) &&
2318 	    (sl->sl_flags & SL_FLUSH_ON_DISABLED_WRITECACHE)) {
2319 		sret = sbd_flush_data_cache(sl, 1);
2320 	}
2321 over_sl_data_write:
2322 
2323 	if ((ret || resid) || (sret != SBD_SUCCESS)) {
2324 		return (SBD_FAILURE);
2325 	} else if ((offset + size) > sl->sl_data_readable_size) {
2326 		uint64_t old_size, new_size;
2327 
2328 		do {
2329 			old_size = sl->sl_data_readable_size;
2330 			if ((offset + size) <= old_size)
2331 				break;
2332 			new_size = offset + size;
2333 		} while (atomic_cas_64(&sl->sl_data_readable_size, old_size,
2334 		    new_size) != old_size);
2335 	}
2336 
2337 	return (SBD_SUCCESS);
2338 }
2339 
2340 int
2341 sbd_get_lu_props(sbd_lu_props_t *islp, uint32_t islp_sz,
2342     sbd_lu_props_t *oslp, uint32_t oslp_sz, uint32_t *err_ret)
2343 {
2344 	sbd_status_t sret;
2345 	sbd_lu_t *sl = NULL;
2346 	uint32_t sz;
2347 	uint16_t off;
2348 
2349 	if (islp->slp_input_guid) {
2350 		sret = sbd_find_and_lock_lu(islp->slp_guid, NULL,
2351 		    SL_OP_LU_PROPS, &sl);
2352 	} else {
2353 		((char *)islp)[islp_sz - 1] = 0;
2354 		sret = sbd_find_and_lock_lu(NULL, islp->slp_buf,
2355 		    SL_OP_LU_PROPS, &sl);
2356 	}
2357 	if (sret != SBD_SUCCESS) {
2358 		if (sret == SBD_BUSY) {
2359 			*err_ret = SBD_RET_LU_BUSY;
2360 			return (EBUSY);
2361 		} else if (sret == SBD_NOT_FOUND) {
2362 			*err_ret = SBD_RET_NOT_FOUND;
2363 			return (ENOENT);
2364 		}
2365 		return (EIO);
2366 	}
2367 
2368 	sz = strlen(sl->sl_name) + 1;
2369 	if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
2370 		if (sl->sl_data_filename) {
2371 			sz += strlen(sl->sl_data_filename) + 1;
2372 		}
2373 	}
2374 	sz += sl->sl_serial_no_size;
2375 	if (sl->sl_alias) {
2376 		sz += strlen(sl->sl_alias) + 1;
2377 	}
2378 
2379 	bzero(oslp, sizeof (*oslp) - 8);
2380 	oslp->slp_buf_size_needed = sz;
2381 
2382 	if (sz > (oslp_sz - sizeof (*oslp) + 8)) {
2383 		sl->sl_trans_op = SL_OP_NONE;
2384 		*err_ret = SBD_RET_INSUFFICIENT_BUF_SPACE;
2385 		return (ENOMEM);
2386 	}
2387 
2388 	off = 0;
2389 	(void) strcpy((char *)oslp->slp_buf, sl->sl_name);
2390 	oslp->slp_meta_fname_off = off;
2391 	off += strlen(sl->sl_name) + 1;
2392 	if ((sl->sl_flags & (SL_ZFS_META | SL_SHARED_META)) == 0) {
2393 		oslp->slp_meta_fname_valid = 1;
2394 		oslp->slp_separate_meta = 1;
2395 		if (sl->sl_data_filename) {
2396 			oslp->slp_data_fname_valid = 1;
2397 			oslp->slp_data_fname_off = off;
2398 			(void) strcpy((char *)&oslp->slp_buf[off],
2399 			    sl->sl_data_filename);
2400 			off += strlen(sl->sl_data_filename) + 1;
2401 		}
2402 	} else {
2403 		oslp->slp_data_fname_valid = 1;
2404 		oslp->slp_data_fname_off = oslp->slp_meta_fname_off;
2405 		if (sl->sl_flags & SL_ZFS_META) {
2406 			oslp->slp_zfs_meta = 1;
2407 		}
2408 	}
2409 	if (sl->sl_alias) {
2410 		oslp->slp_alias_valid = 1;
2411 		oslp->slp_alias_off = off;
2412 		(void) strcpy((char *)&oslp->slp_buf[off], sl->sl_alias);
2413 		off += strlen(sl->sl_alias) + 1;
2414 	}
2415 	if (sl->sl_serial_no_size) {
2416 		oslp->slp_serial_off = off;
2417 		bcopy(sl->sl_serial_no, &oslp->slp_buf[off],
2418 		    sl->sl_serial_no_size);
2419 		oslp->slp_serial_size = sl->sl_serial_no_size;
2420 		oslp->slp_serial_valid = 1;
2421 		off += sl->sl_serial_no_size;
2422 	}
2423 
2424 	oslp->slp_lu_size = sl->sl_lu_size;
2425 	oslp->slp_blksize = ((uint16_t)1) << sl->sl_data_blocksize_shift;
2426 
2427 	if (sl->sl_flags & SL_VID_VALID) {
2428 		oslp->slp_lu_vid = 1;
2429 		bcopy(sl->sl_vendor_id, oslp->slp_vid, 8);
2430 	} else {
2431 		bcopy(sbd_vendor_id, oslp->slp_vid, 8);
2432 	}
2433 	if (sl->sl_flags & SL_PID_VALID) {
2434 		oslp->slp_lu_pid = 1;
2435 		bcopy(sl->sl_product_id, oslp->slp_pid, 16);
2436 	} else {
2437 		bcopy(sbd_product_id, oslp->slp_pid, 16);
2438 	}
2439 	if (sl->sl_flags & SL_REV_VALID) {
2440 		oslp->slp_lu_rev = 1;
2441 		bcopy(sl->sl_revision, oslp->slp_rev, 4);
2442 	} else {
2443 		bcopy(sbd_revision, oslp->slp_rev, 4);
2444 	}
2445 	bcopy(sl->sl_device_id + 4, oslp->slp_guid, 16);
2446 
2447 	if (sl->sl_flags & SL_WRITEBACK_CACHE_DISABLE)
2448 		oslp->slp_writeback_cache_disable_cur = 1;
2449 	if (sl->sl_flags & SL_SAVED_WRITE_CACHE_DISABLE)
2450 		oslp->slp_writeback_cache_disable_saved = 1;
2451 	if (sl->sl_flags & SL_WRITE_PROTECTED)
2452 		oslp->slp_write_protected = 1;
2453 
2454 	sl->sl_trans_op = SL_OP_NONE;
2455 
2456 	return (0);
2457 }
2458 
2459 int
2460 sbd_path_to_zfs_meta(char *src, char *dst)
2461 {
2462 	if (strncmp(src, "/dev/zvol", 9) != 0)
2463 		return (0);
2464 
2465 	src += 14;
2466 	if (*src == '/')
2467 		src++;
2468 	(void) strcpy(dst, "/var/tmp/");
2469 	(void) strcat(dst, src);
2470 	*(strrchr(dst, '/')) = '_';
2471 	(void) strcat(dst, ".mat");
2472 
2473 	return (1);
2474 }
2475 
2476 char *
2477 sbd_get_zvol_name(sbd_lu_t *sl)
2478 {
2479 	char *src;
2480 	char *p;
2481 
2482 	if (sl->sl_data_filename)
2483 		src = sl->sl_data_filename;
2484 	else
2485 		src = sl->sl_meta_filename;
2486 	/* There has to be a better way */
2487 	if (strncmp(src, "/dev/zvol", 9) != 0) {
2488 		ASSERT(0);
2489 	}
2490 	src += 14;
2491 	if (*src == '/')
2492 		src++;
2493 	p = (char *)kmem_alloc(strlen(src) + 1, KM_SLEEP);
2494 	(void) strcpy(p, src);
2495 	return (p);
2496 }
2497 
2498 sbd_status_t
2499 sbd_create_zfs_meta_object(sbd_lu_t *sl)
2500 {
2501 	int flag;
2502 	int ret;
2503 	char zmt[40];
2504 
2505 	ASSERT(sl->sl_zfs_meta_vp == NULL);
2506 	ASSERT(sl->sl_data_filename);
2507 	if (!sbd_path_to_zfs_meta(sl->sl_data_filename, zmt)) {
2508 		stmf_trace(0, "--- sbd_path_to_zfs_meta failed for %s", zmt);
2509 		return (SBD_FAILURE);
2510 	}
2511 
2512 	flag = FREAD | FWRITE | FOFFMAX | FEXCL | FCREAT | FTRUNC;
2513 	if ((ret = vn_open(zmt, UIO_SYSSPACE, flag, 0600, &sl->sl_zfs_meta_vp,
2514 	    CRCREAT, 0)) != 0) {
2515 		stmf_trace(0, "--- vn_open failed for create, ret = %d", ret);
2516 		return (SBD_FAILURE);
2517 	}
2518 	return (SBD_SUCCESS);
2519 }
2520 
2521 sbd_status_t
2522 sbd_open_zfs_meta(sbd_lu_t *sl)
2523 {
2524 	int flag;
2525 	char zmt[40];
2526 
2527 	ASSERT(sl->sl_zfs_meta_vp == NULL);
2528 	ASSERT(sl->sl_data_filename);
2529 	if (!sbd_path_to_zfs_meta(sl->sl_data_filename, zmt)) {
2530 		return (SBD_FAILURE);
2531 	}
2532 
2533 	flag = FREAD | FWRITE | FOFFMAX | FEXCL;
2534 	if (vn_open(zmt, UIO_SYSSPACE, flag, 0,
2535 	    &sl->sl_zfs_meta_vp, 0, 0) != 0) {
2536 		return (SBD_FAILURE);
2537 	}
2538 	return (SBD_SUCCESS);
2539 }
2540 
2541 void
2542 sbd_close_zfs_meta(sbd_lu_t *sl)
2543 {
2544 	int flag;
2545 
2546 	flag = FREAD | FWRITE | FOFFMAX | FEXCL;
2547 	(void) VOP_CLOSE(sl->sl_zfs_meta_vp, flag, 1, 0, CRED(), NULL);
2548 	VN_RELE(sl->sl_zfs_meta_vp);
2549 	sl->sl_zfs_meta_vp = NULL;
2550 }
2551 
2552 sbd_status_t
2553 sbd_read_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
2554 {
2555 	int ret;
2556 	long resid;
2557 
2558 	ASSERT(sl->sl_zfs_meta_vp);
2559 	ret = vn_rdwr(UIO_READ, sl->sl_zfs_meta_vp, (caddr_t)buf, (ssize_t)sz,
2560 	    (offset_t)off, UIO_SYSSPACE, FSYNC, RLIM64_INFINITY, CRED(),
2561 	    &resid);
2562 	if (ret || resid) {
2563 		return (SBD_FAILURE);
2564 	}
2565 	return (SBD_SUCCESS);
2566 }
2567 
2568 sbd_status_t
2569 sbd_write_zfs_meta(sbd_lu_t *sl, uint8_t *buf, uint64_t sz, uint64_t off)
2570 {
2571 	int ret;
2572 	long resid;
2573 
2574 	ASSERT(sl->sl_zfs_meta_vp);
2575 	ret = vn_rdwr(UIO_WRITE, sl->sl_zfs_meta_vp, (caddr_t)buf, (ssize_t)sz,
2576 	    (offset_t)off, UIO_SYSSPACE, FSYNC, RLIM64_INFINITY, CRED(),
2577 	    &resid);
2578 	if (ret || resid) {
2579 		return (SBD_FAILURE);
2580 	}
2581 	return (SBD_SUCCESS);
2582 }
2583 
2584 /* zvol metadata code to still be implemented */
2585 int
2586 /* LINTED E_FUNC_ARG_UNUSED */
2587 sbd_is_zvol(char *path, vnode_t *vp)
2588 {
2589 	return (0);
2590 #if 0
2591 	int is_zfs = 0;
2592 	vnode_t *zvp;
2593 	vattr_t vattr;
2594 
2595 	if (vp != NULL) {
2596 		zvp = vp;
2597 		goto over_zvp_open;
2598 	}
2599 	if (lookupname(path, UIO_SYSSPACE, FOLLOW, NULLVPP, &zvp) != 0) {
2600 		return (0);
2601 	}
2602 over_zvp_open:
2603 	vattr.va_mask = AT_RDEV;
2604 	if (VOP_GETATTR(zvp, &vattr, 0, kcred, NULL) == 0) {
2605 		is_zfs = (getmajor(vattr.va_rdev) ==
2606 		    ddi_name_to_major(ZFS_DRIVER)) ? 1 : 0;
2607 	}
2608 	if (vp == NULL) {
2609 		VN_RELE(zvp);
2610 	}
2611 
2612 	return (is_zfs);
2613 #endif
2614 }
2615 
2616 /*
2617  * set write cache disable
2618  * wcd - 1 = disable, 0 = enable
2619  */
2620 sbd_status_t
2621 sbd_wcd_set(int wcd, sbd_lu_t *sl)
2622 {
2623 	/* translate to wce bit */
2624 	int wce = wcd ? 0 : 1;
2625 	int ret;
2626 	sbd_status_t sret = SBD_SUCCESS;
2627 
2628 	mutex_enter(&sl->sl_lock);
2629 	sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
2630 
2631 	if (sl->sl_data_vp->v_type == VREG) {
2632 		sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
2633 		goto done;
2634 	}
2635 
2636 	ret = VOP_IOCTL(sl->sl_data_vp, DKIOCSETWCE, (intptr_t)&wce, FKIOCTL,
2637 	    kcred, NULL, NULL);
2638 	if (ret == 0) {
2639 		sl->sl_flags &= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
2640 		sl->sl_flags &= ~SL_FLUSH_ON_DISABLED_WRITECACHE;
2641 	} else {
2642 		sl->sl_flags |= SL_WRITEBACK_CACHE_SET_UNSUPPORTED;
2643 		sl->sl_flags |= SL_FLUSH_ON_DISABLED_WRITECACHE;
2644 		sret = SBD_FAILURE;
2645 		goto done;
2646 	}
2647 
2648 done:
2649 	mutex_exit(&sl->sl_lock);
2650 	return (sret);
2651 }
2652 
2653 /*
2654  * get write cache disable
2655  * wcd - 1 = disable, 0 = enable
2656  */
2657 void
2658 sbd_wcd_get(int *wcd, sbd_lu_t *sl)
2659 {
2660 	int wce;
2661 	int ret;
2662 
2663 	if (sl->sl_data_vp->v_type == VREG) {
2664 		*wcd = 0;
2665 		return;
2666 	}
2667 
2668 	ret = VOP_IOCTL(sl->sl_data_vp, DKIOCGETWCE, (intptr_t)&wce, FKIOCTL,
2669 	    kcred, NULL, NULL);
2670 	/* if write cache get failed, assume disabled */
2671 	if (ret) {
2672 		*wcd = 1;
2673 	} else {
2674 		/* translate to wcd bit */
2675 		*wcd = wce ? 0 : 1;
2676 	}
2677 }
2678 
2679 
2680 /*
2681  * check for a zvol with sbd metadata object.
2682  */
2683 int
2684 sbd_is_sbd_zvol(char *path, vnode_t *vp)
2685 {
2686 	char zmt[40];
2687 	vnode_t *zvp;
2688 
2689 	if (!sbd_is_zvol(path, vp)) {
2690 		return (0);
2691 	}
2692 	if (!sbd_path_to_zfs_meta(path, zmt)) {
2693 		return (0);
2694 	}
2695 
2696 	if (lookupname(zmt, UIO_SYSSPACE, FOLLOW, NULLVPP, &zvp) != 0) {
2697 		return (0);
2698 	}
2699 	VN_RELE(zvp);
2700 	return (1);
2701 }
2702