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