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 2008 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/atomic.h>
36 #include <sys/nvpair.h>
37 
38 #include <stmf.h>
39 #include <lpif.h>
40 #include <stmf_ioctl.h>
41 #include <stmf_sbd.h>
42 #include <sbd_impl.h>
43 #include <stmf_sbd_ioctl.h>
44 
45 static int sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
46 static int sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
47 static int sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg,
48 	void **result);
49 static int sbd_open(dev_t *devp, int flag, int otype, cred_t *credp);
50 static int sbd_close(dev_t dev, int flag, int otype, cred_t *credp);
51 static int stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
52 	cred_t *credp, int *rval);
53 void sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags);
54 uint8_t sbd_calc_sum(uint8_t *buf, int size);
55 void sbd_swap_meta_start(sbd_meta_start_t *sm);
56 void sbd_swap_section_hdr(sm_section_hdr_t *h, uint8_t data_order);
57 void sbd_swap_sli_fields(sbd_lu_info_t *sli, uint8_t data_order);
58 int sbd_migrate_meta_from_v0_to_v1(sbd_store_t *sst);
59 
60 extern struct mod_ops mod_driverops;
61 
62 static stmf_lu_provider_t *sbd_lp;
63 static dev_info_t *sbd_dip;
64 static kmutex_t sbd_lock;
65 sbd_lu_t	*sbd_lu_list = NULL;
66 static int sbd_lu_count = 0;
67 static char sbd_name[] = "sbd";
68 static uint64_t	sbd_meta_offset	= 4096; /* offset to skip label */
69 
70 static struct cb_ops sbd_cb_ops = {
71 	sbd_open,			/* open */
72 	sbd_close,			/* close */
73 	nodev,				/* strategy */
74 	nodev,				/* print */
75 	nodev,				/* dump */
76 	nodev,				/* read */
77 	nodev,				/* write */
78 	stmf_sbd_ioctl,			/* ioctl */
79 	nodev,				/* devmap */
80 	nodev,				/* mmap */
81 	nodev,				/* segmap */
82 	nochpoll,			/* chpoll */
83 	ddi_prop_op,			/* cb_prop_op */
84 	0,				/* streamtab */
85 	D_NEW | D_MP,			/* cb_flag */
86 	CB_REV,				/* rev */
87 	nodev,				/* aread */
88 	nodev				/* awrite */
89 };
90 
91 static struct dev_ops sbd_ops = {
92 	DEVO_REV,
93 	0,
94 	sbd_getinfo,
95 	nulldev,		/* identify */
96 	nulldev,		/* probe */
97 	sbd_attach,
98 	sbd_detach,
99 	nodev,			/* reset */
100 	&sbd_cb_ops,
101 	NULL,			/* bus_ops */
102 	NULL			/* power */
103 };
104 
105 #define	SBD_NAME	"COMSTAR SBD"
106 
107 static struct modldrv modldrv = {
108 	&mod_driverops,
109 	SBD_NAME,
110 	&sbd_ops
111 };
112 
113 static struct modlinkage modlinkage = {
114 	MODREV_1,
115 	&modldrv,
116 	NULL
117 };
118 
119 int
120 _init(void)
121 {
122 	int ret;
123 
124 	ret = mod_install(&modlinkage);
125 	if (ret)
126 		return (ret);
127 	sbd_lp = (stmf_lu_provider_t *)stmf_alloc(STMF_STRUCT_LU_PROVIDER,
128 							0, 0);
129 	sbd_lp->lp_lpif_rev = LPIF_REV_1;
130 	sbd_lp->lp_instance = 0;
131 	sbd_lp->lp_name = sbd_name;
132 	sbd_lp->lp_cb = sbd_lp_cb;
133 
134 	if (stmf_register_lu_provider(sbd_lp) != STMF_SUCCESS) {
135 		(void) mod_remove(&modlinkage);
136 		stmf_free(sbd_lp);
137 		return (DDI_FAILURE);
138 	}
139 	mutex_init(&sbd_lock, NULL, MUTEX_DRIVER, NULL);
140 	return (0);
141 }
142 
143 int
144 _fini(void)
145 {
146 	int ret;
147 
148 	/*
149 	 * If we have registered lus, then make sure they are all offline
150 	 * if so then deregister them. This should drop the sbd_lu_count
151 	 * to zero.
152 	 */
153 	if (sbd_lu_count) {
154 		sbd_lu_t *slu;
155 
156 		/* See if all of them are offline */
157 		mutex_enter(&sbd_lock);
158 		for (slu = sbd_lu_list; slu != NULL; slu = slu->sl_next) {
159 			if ((slu->sl_state != STMF_STATE_OFFLINE) ||
160 			    slu->sl_state_not_acked) {
161 				mutex_exit(&sbd_lock);
162 				return (EBUSY);
163 			}
164 		}
165 		mutex_exit(&sbd_lock);
166 
167 		/* ok start deregistering them */
168 		while (sbd_lu_list) {
169 			sbd_store_t *sst = sbd_lu_list->sl_sst;
170 			if (sst->sst_deregister_lu(sst) != STMF_SUCCESS)
171 				return (EBUSY);
172 		}
173 	}
174 	ASSERT(sbd_lu_count == 0);
175 	if (stmf_deregister_lu_provider(sbd_lp) != STMF_SUCCESS)
176 		return (EBUSY);
177 	ret = mod_remove(&modlinkage);
178 	if (ret != 0) {
179 		(void) stmf_register_lu_provider(sbd_lp);
180 		return (ret);
181 	}
182 	stmf_free(sbd_lp);
183 	mutex_destroy(&sbd_lock);
184 	return (0);
185 }
186 
187 int
188 _info(struct modinfo *modinfop)
189 {
190 	return (mod_info(&modlinkage, modinfop));
191 }
192 
193 /* ARGSUSED */
194 static int
195 sbd_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
196 {
197 	switch (cmd) {
198 	case DDI_INFO_DEVT2DEVINFO:
199 		*result = sbd_dip;
200 		break;
201 	case DDI_INFO_DEVT2INSTANCE:
202 		*result = (void *)(uintptr_t)ddi_get_instance(dip);
203 		break;
204 	default:
205 		return (DDI_FAILURE);
206 	}
207 
208 	return (DDI_SUCCESS);
209 }
210 
211 static int
212 sbd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
213 {
214 	switch (cmd) {
215 	case DDI_ATTACH:
216 		sbd_dip = dip;
217 
218 		if (ddi_create_minor_node(dip, "admin", S_IFCHR, 0,
219 		    DDI_NT_STMF_LP, 0) != DDI_SUCCESS) {
220 			break;
221 		}
222 		ddi_report_dev(dip);
223 		return (DDI_SUCCESS);
224 	}
225 
226 	return (DDI_FAILURE);
227 }
228 
229 static int
230 sbd_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
231 {
232 	switch (cmd) {
233 	case DDI_DETACH:
234 		ddi_remove_minor_node(dip, 0);
235 		return (DDI_SUCCESS);
236 	}
237 
238 	return (DDI_FAILURE);
239 }
240 
241 /* ARGSUSED */
242 static int
243 sbd_open(dev_t *devp, int flag, int otype, cred_t *credp)
244 {
245 	if (otype != OTYP_CHR)
246 		return (EINVAL);
247 	return (0);
248 }
249 
250 /* ARGSUSED */
251 static int
252 sbd_close(dev_t dev, int flag, int otype, cred_t *credp)
253 {
254 	return (0);
255 }
256 
257 /*
258  * The ioctl code will be re written once the lun mapping and masking
259  * has been implemented and ioctl definitions have been cleanned up.
260  */
261 void *
262 sbd_ioctl_read_struct(intptr_t data, int mode)
263 {
264 	void *ptr;
265 	uint32_t s;
266 
267 	if (ddi_copyin((void *)data, &s, 4, mode))
268 		return (NULL);
269 	ptr = kmem_alloc(s, KM_SLEEP);
270 	if (ddi_copyin((void *)data, ptr, s, mode))
271 		return (NULL);
272 	return (ptr);
273 }
274 
275 int
276 sbd_ioctl_write_struct(intptr_t data, int mode, void *ptr)
277 {
278 	int *s = (int *)ptr;
279 	int ret = 0;
280 
281 	if (ddi_copyout(ptr, (void *)data, *s, mode)) {
282 		ret = EFAULT;
283 	}
284 
285 	kmem_free(ptr, *s);
286 	return (ret);
287 }
288 
289 /* ARGSUSED */
290 static int
291 stmf_sbd_ioctl(dev_t dev, int cmd, intptr_t data, int mode,
292 	cred_t *credp, int *rval)
293 {
294 	register_lu_cmd_t	*rlc;
295 	deregister_lu_cmd_t	*drlc;
296 	sbd_lu_list_t		*sll;
297 	sbd_lu_attr_t		*sla;
298 	sbd_lu_t		*slul;
299 	void			*p;
300 	int			ret = 0;
301 	int			ret1;
302 	int			cnt;
303 	int			max_times, idx;
304 	stmf_state_change_info_t ssi;
305 
306 	if (drv_priv(credp) != 0) {
307 		return (EPERM);
308 	}
309 
310 	ssi.st_rflags = STMF_RFLAG_USER_REQUEST;
311 	ssi.st_additional_info = NULL;
312 	if ((cmd != SBD_REGISTER_LU) && (cmd != SBD_GET_LU_ATTR) &&
313 	    (cmd != SBD_GET_LU_LIST) && (cmd != SBD_DEREGISTER_LU) &&
314 	    (cmd != SBD_MODIFY_LU)) {
315 		return (EINVAL);
316 	}
317 	if ((p = sbd_ioctl_read_struct(data, mode)) == NULL)
318 		return (EFAULT);
319 
320 	switch (cmd) {
321 	case SBD_REGISTER_LU:
322 		rlc = (register_lu_cmd_t *)p;
323 		((char *)p)[rlc->total_struct_size - 1] = 0;
324 		if (rlc->flags & RLC_LU_TYPE_MEMDISK) {
325 			if ((rlc->op_ret = memdisk_register_lu(rlc)) !=
326 			    STMF_SUCCESS) {
327 				ret = EIO;
328 			}
329 		} else if (rlc->flags & RLC_LU_TYPE_FILEDISK) {
330 			if ((rlc->op_ret = filedisk_register_lu(rlc)) !=
331 			    STMF_SUCCESS) {
332 				ret = EIO;
333 			}
334 		} else {
335 			ret = EINVAL;
336 			break;
337 		}
338 		break;
339 	case SBD_MODIFY_LU: {
340 		modify_lu_cmd_t *mlc = (modify_lu_cmd_t *)p;
341 		sbd_lu_t *slu;
342 		sbd_store_t *sst = NULL;
343 		if ((mlc->flags & RLC_LU_TYPE_FILEDISK) == 0) {
344 			ret = EINVAL;
345 			break;
346 		}
347 		if (mlc->name[0] != '\0') {
348 			mutex_enter(&sbd_lock);
349 			for (slu = sbd_lu_list; slu != NULL;
350 			    slu = slu->sl_next) {
351 				if (strcmp(slu->sl_sst->sst_alias,
352 				    mlc->name) == 0)
353 					break;
354 			}
355 			mutex_exit(&sbd_lock);
356 			if (slu == NULL) {
357 				/* not registered */
358 				sst = NULL;
359 			} else {
360 				sst = slu->sl_sst;
361 			}
362 		} else {
363 			mutex_enter(&sbd_lock);
364 			for (slu = sbd_lu_list; slu != NULL;
365 			    slu = slu->sl_next) {
366 				if (bcmp(slu->sl_lu->lu_id->ident,
367 				    mlc->guid, 16) == 0)
368 					break;
369 			}
370 			mutex_exit(&sbd_lock);
371 			if (slu == NULL) {
372 				/* not registered, this is not allowed */
373 				ret = ENODEV;
374 				break;
375 			}
376 			sst = slu->sl_sst;
377 		}
378 
379 		mlc->op_ret = filedisk_modify_lu(sst, mlc);
380 		if (mlc->op_ret != STMF_SUCCESS) {
381 			ret = EIO;
382 		}
383 		}
384 		break;
385 
386 	case SBD_DEREGISTER_LU:
387 		drlc = (deregister_lu_cmd_t *)p;
388 
389 		mutex_enter(&sbd_lock);
390 		for (slul = sbd_lu_list; slul != NULL; slul = slul->sl_next) {
391 			ret1 = bcmp(drlc->guid, slul->sl_lu->lu_id->ident, 16);
392 			if (ret1 == 0) {
393 				break;
394 			}
395 		}
396 
397 		if (slul == NULL) {
398 			mutex_exit(&sbd_lock);
399 
400 			stmf_trace(0, "sbd_ioctl: can't find specified LU");
401 			ret = ENODEV;
402 			break;
403 		}
404 
405 		if ((slul->sl_state == STMF_STATE_OFFLINE) &&
406 		    !slul->sl_state_not_acked) {
407 			mutex_exit(&sbd_lock);
408 
409 			goto do_lu_dereg;
410 		}
411 
412 		if (slul->sl_state != STMF_STATE_ONLINE) {
413 			mutex_exit(&sbd_lock);
414 
415 			ret = EBUSY;
416 			break;
417 		}
418 		mutex_exit(&sbd_lock);
419 
420 		ssi.st_additional_info = "DEREGLU offline LU now";
421 		(void) stmf_ctl(STMF_CMD_LU_OFFLINE, slul->sl_lu, &ssi);
422 		max_times = 50;
423 
424 		mutex_enter(&sbd_lock);
425 		for (idx = 0; idx < max_times; idx++) {
426 			if ((slul->sl_state == STMF_STATE_OFFLINE) &&
427 			    !slul->sl_state_not_acked) {
428 				break;
429 			}
430 			mutex_exit(&sbd_lock);
431 
432 			delay(drv_usectohz(100000));
433 
434 			mutex_enter(&sbd_lock);
435 		}
436 		mutex_exit(&sbd_lock);
437 
438 		if (idx == max_times) {
439 			stmf_trace(0, "sbd_ioctl: LU-%p can't go off", slul);
440 			ret = ETIMEDOUT;
441 		} else {
442 do_lu_dereg:
443 			if (slul->sl_sst->sst_deregister_lu(slul->sl_sst) !=
444 			    STMF_SUCCESS) {
445 				stmf_trace(0, "sbd_ioctl: sst_degregister_lu "
446 				    "sst-%p failed", slul->sl_sst);
447 				ret = ENOTSUP;
448 			}
449 		}
450 		break;
451 
452 	case SBD_GET_LU_LIST:
453 		sll = (sbd_lu_list_t *)p;
454 		cnt = sll->total_struct_size - sizeof (sbd_lu_list_t);
455 		if (cnt < 0) {
456 			ret = EINVAL;
457 			break;
458 		}
459 		cnt = (cnt >> 3) + 1;
460 		if (sll->count_in > cnt) {
461 			ret = EFAULT;
462 			break;
463 		}
464 		mutex_enter(&sbd_lock);
465 		sll->count_out = 0;
466 		for (slul = sbd_lu_list; slul != NULL; slul = slul->sl_next) {
467 			if (sll->count_out < sll->count_in) {
468 				sll->handles[sll->count_out] =
469 				    (uint64_t)(unsigned long)slul;
470 			}
471 			sll->count_out++;
472 		}
473 		mutex_exit(&sbd_lock);
474 		break;
475 	case SBD_GET_LU_ATTR:
476 		sla = (sbd_lu_attr_t *)p;
477 		if (sla->total_struct_size <
478 		    (sizeof (sbd_lu_attr_t) + sla->max_name_length - 7)) {
479 			ret = EFAULT;
480 			break;
481 		}
482 		mutex_enter(&sbd_lock);
483 		for (slul = sbd_lu_list; slul != NULL; slul = slul->sl_next) {
484 			if (sla->lu_handle == (uint64_t)(unsigned long)slul)
485 				break;
486 		}
487 		if (slul != NULL) {
488 			filedisk_fillout_attr(slul->sl_sst, sla);
489 			memdisk_fillout_attr(slul->sl_sst, sla);
490 			sla->total_size = slul->sl_sli->sli_total_store_size;
491 			sla->data_size = slul->sl_sli->sli_lu_data_size;
492 			bcopy(slul->sl_lu->lu_id->ident, sla->guid, 16);
493 		} else {
494 			ret = EINVAL;
495 		}
496 		mutex_exit(&sbd_lock);
497 		break;
498 
499 	default:
500 		return (ENOTTY);
501 	}
502 
503 	ret1 = sbd_ioctl_write_struct(data, mode, p);
504 	if (!ret)
505 		ret = ret1;
506 	return (ret);
507 }
508 
509 /* ARGSUSED */
510 void
511 sbd_lp_cb(stmf_lu_provider_t *lp, int cmd, void *arg, uint32_t flags)
512 {
513 	nvpair_t *np;
514 	register_lu_cmd_t *rlc = NULL;
515 	char *s;
516 	int rlc_size = 0;
517 	int sn;
518 
519 	if ((cmd != STMF_PROVIDER_DATA_UPDATED) || (arg == NULL)) {
520 		return;
521 	}
522 
523 	if ((flags & (STMF_PCB_STMF_ONLINING | STMF_PCB_PREG_COMPLETE)) == 0) {
524 		return;
525 	}
526 
527 	np = NULL;
528 	while ((np = nvlist_next_nvpair((nvlist_t *)arg, np)) != NULL) {
529 		if (nvpair_type(np) != DATA_TYPE_STRING) {
530 			continue;
531 		}
532 		if (nvpair_value_string(np, &s) != 0) {
533 			continue;
534 		}
535 		sn = sizeof (register_lu_cmd_t) - 8 + strlen(s) + 1;
536 		if (sn > rlc_size) {
537 			if (rlc_size) {
538 				kmem_free(rlc, rlc_size);
539 			}
540 			rlc_size = sn + 32; /* Make it a little bigger */
541 			rlc = (register_lu_cmd_t *)kmem_zalloc(rlc_size,
542 								KM_SLEEP);
543 		}
544 		bzero(rlc, rlc_size);
545 		rlc->total_struct_size = rlc_size;
546 		rlc->flags = RLC_LU_TYPE_FILEDISK | RLC_REGISTER_LU;
547 		(void) strcpy(rlc->name, s);
548 		(void) filedisk_register_lu(rlc);
549 	}
550 
551 	if (rlc) {
552 		kmem_free(rlc, rlc_size);
553 	}
554 }
555 
556 /* ARGSUSED */
557 sbd_store_t *
558 sbd_sst_alloc(uint32_t additional_size, uint32_t flags)
559 {
560 	uint32_t total_as;
561 	sbd_store_t *sst;
562 	stmf_lu_t *lu;
563 	sbd_lu_t *slu;
564 
565 	total_as = GET_STRUCT_SIZE(sbd_store_t) + GET_STRUCT_SIZE(sbd_lu_t) +
566 			((additional_size + 7) & ~7);
567 
568 	lu = (stmf_lu_t *)stmf_alloc(STMF_STRUCT_STMF_LU, total_as, 0);
569 	if (lu == NULL)
570 		return (NULL);
571 	sst = (sbd_store_t *)lu->lu_provider_private;
572 	sst->sst_sbd_private = GET_BYTE_OFFSET(sst,
573 				GET_STRUCT_SIZE(sbd_store_t));
574 	sst->sst_store_private = GET_BYTE_OFFSET(sst->sst_sbd_private,
575 					GET_STRUCT_SIZE(sbd_lu_t));
576 	slu = (sbd_lu_t *)sst->sst_sbd_private;
577 	slu->sl_sst = sst;
578 	slu->sl_lu = lu;
579 	slu->sl_total_allocation_size = total_as;
580 	mutex_init(&slu->sl_it_list_lock, NULL, MUTEX_DRIVER, NULL);
581 
582 	return (sst);
583 }
584 
585 void
586 sbd_sst_free(sbd_store_t *sst)
587 {
588 	sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
589 
590 	mutex_destroy(&slu->sl_it_list_lock);
591 	stmf_free(slu->sl_lu);
592 }
593 
594 #define	DATA_ALIGNMENT		0xfffffffffffff000
595 #define	DATA_BLOCK_SIZE		4 * 1024
596 
597 stmf_status_t
598 sbd_aligned_meta_write(struct sbd_store *sst, uint64_t offset,
599     uint64_t size, uint8_t *buf)
600 {
601 	uint64_t starting_off = offset & DATA_ALIGNMENT;
602 	uint64_t off_from_starting = offset & (~DATA_ALIGNMENT);
603 	uint64_t ending_off =
604 	    (offset + size + DATA_BLOCK_SIZE) & DATA_ALIGNMENT;
605 	uint64_t op_size = ending_off - starting_off;
606 	uint8_t *op_buf = (uint8_t *)kmem_zalloc(op_size, KM_SLEEP);
607 	stmf_status_t ret;
608 
609 	/* we should read first to avoid overwrite other data */
610 	if (sst->sst_meta_read) {
611 		ret = sst->sst_meta_read(sst, starting_off,
612 		    op_size, (uint8_t *)op_buf);
613 	} else {
614 		ret = sst->sst_data_read(sst, starting_off,
615 		    op_size, (uint8_t *)op_buf);
616 	}
617 	if (ret != STMF_SUCCESS)
618 		goto aligned_write_ret;
619 
620 	bcopy(buf, op_buf + off_from_starting, size);
621 
622 	if (sst->sst_meta_write) {
623 		ret = sst->sst_meta_write(sst, starting_off,
624 		    op_size, (uint8_t *)op_buf);
625 	} else {
626 		ret = sst->sst_data_write(sst, starting_off,
627 		    op_size, (uint8_t *)op_buf);
628 	}
629 
630 aligned_write_ret:
631 	if (op_buf)
632 		kmem_free(op_buf, op_size);
633 	return (ret);
634 }
635 
636 stmf_status_t
637 sbd_aligned_meta_read(struct sbd_store *sst, uint64_t offset,
638     uint64_t size, uint8_t *buf)
639 {
640 	uint64_t starting_off = offset & DATA_ALIGNMENT;
641 	uint64_t off_from_starting = offset & (~DATA_ALIGNMENT);
642 	uint64_t ending_off =
643 	    (offset + size + DATA_BLOCK_SIZE) & DATA_ALIGNMENT;
644 	uint64_t op_size = ending_off - starting_off;
645 	uint8_t *op_buf = (uint8_t *)kmem_zalloc(op_size, KM_SLEEP);
646 	stmf_status_t ret;
647 
648 	if (sst->sst_meta_read) {
649 		ret = sst->sst_meta_read(sst, starting_off,
650 		    op_size, (uint8_t *)op_buf);
651 	} else {
652 		ret = sst->sst_data_read(sst, starting_off,
653 		    op_size, (uint8_t *)op_buf);
654 	}
655 	if (ret != STMF_SUCCESS)
656 		goto aligned_read_ret;
657 	bcopy(op_buf + off_from_starting, buf, size);
658 
659 aligned_read_ret:
660 	if (op_buf)
661 		kmem_free(op_buf, op_size);
662 	return (ret);
663 }
664 
665 uint8_t
666 sbd_calc_sum(uint8_t *buf, int size)
667 {
668 	uint8_t s = 0;
669 
670 	while (size > 0)
671 		s += buf[--size];
672 
673 	return (s);
674 }
675 
676 void
677 sbd_swap_meta_start(sbd_meta_start_t *sm)
678 {
679 	sm->sm_magic		= BSWAP_64(sm->sm_magic);
680 	sm->sm_meta_size	= BSWAP_64(sm->sm_meta_size);
681 	sm->sm_meta_size_used	= BSWAP_64(sm->sm_meta_size_used);
682 	sm->sm_ver_major	= BSWAP_16(sm->sm_ver_major);
683 	sm->sm_ver_minor	= BSWAP_16(sm->sm_ver_minor);
684 	sm->sm_ver_subminor	= BSWAP_16(sm->sm_ver_subminor);
685 }
686 
687 void
688 sbd_swap_section_hdr(sm_section_hdr_t *h, uint8_t data_order)
689 {
690 	h->sms_offset		= BSWAP_64(h->sms_offset);
691 	h->sms_size		= BSWAP_32(h->sms_size);
692 	h->sms_id		= BSWAP_16(h->sms_id);
693 	h->sms_data_order	= data_order;
694 }
695 
696 void
697 sbd_swap_sli_fields(sbd_lu_info_t *sli, uint8_t data_order)
698 {
699 	sli->sli_total_store_size = BSWAP_64(sli->sli_total_store_size);
700 	sli->sli_total_meta_size = BSWAP_64(sli->sli_total_meta_size);
701 	sli->sli_lu_data_offset = BSWAP_64(sli->sli_lu_data_offset);
702 	sli->sli_lu_data_size = BSWAP_64(sli->sli_lu_data_size);
703 	sli->sli_flags = BSWAP_32(sli->sli_flags);
704 	sli->sli_blocksize = BSWAP_16(sli->sli_blocksize);
705 	sli->sli_data_order = data_order;
706 }
707 
708 /*
709  * will not modify sms.
710  */
711 uint64_t
712 sbd_find_section_offset(sbd_store_t *sst, sm_section_hdr_t *sms)
713 {
714 	stmf_status_t ret;
715 	sbd_lu_t *slu = (sbd_lu_t *)sst->sst_sbd_private;
716 	uint64_t ssize;
717 	uint64_t meta_end;
718 	sm_section_hdr_t smsh;
719 
720 	if (slu->sl_sm.sm_magic != SBD_MAGIC) {
721 		cmn_err(CE_PANIC, "sbd_find section called without reading the"
722 				" header first.");
723 	}
724 
725 	ssize = slu->sl_meta_offset + sizeof (sbd_meta_start_t);
726 	meta_end = slu->sl_sm.sm_meta_size_used;
727 	while (ssize < meta_end) {
728 		ret = sbd_aligned_meta_read(sst, ssize,
729 		    sizeof (sm_section_hdr_t), (uint8_t *)&smsh);
730 		if (ret != STMF_SUCCESS)
731 			return (0);
732 		if (smsh.sms_data_order != sms->sms_data_order) {
733 			sbd_swap_section_hdr(&smsh, sms->sms_data_order);
734 		}
735 		if (smsh.sms_id == sms->sms_id)
736 			return (smsh.sms_offset);
737 		ssize += smsh.sms_size;
738 	}
739 
740 	return (0);
741 }
742 
743 stmf_status_t
744 sbd_read_section(sbd_store_t *sst, sm_section_hdr_t *sms)
745 {
746 	stmf_status_t			ret;
747 	uint32_t			sz;
748 	uint8_t				osum, nsum;
749 
750 	if (sms->sms_offset == 0) {
751 		sms->sms_offset = sbd_find_section_offset(sst, sms);
752 		if (sms->sms_offset == 0)
753 			return (STMF_FAILURE);
754 	}
755 	sz = sms->sms_size;
756 
757 	ret = sbd_aligned_meta_read(sst, sms->sms_offset,
758 	    sms->sms_size, (uint8_t *)sms);
759 	if (ret != STMF_SUCCESS)
760 		return (ret);
761 
762 	osum = sms->sms_chksum;
763 	sms->sms_chksum = 0;
764 	nsum = sbd_calc_sum((uint8_t *)sms, sz);
765 	sms->sms_chksum = osum;
766 	if (osum != nsum) {
767 		return (STMF_FAILURE);
768 	}
769 	if (sms->sms_data_order != SMS_DATA_ORDER) {
770 		/* Adjust byte order of the header */
771 		sbd_swap_section_hdr(sms, SMS_DATA_ORDER);
772 	}
773 
774 	return (STMF_SUCCESS);
775 }
776 
777 stmf_status_t
778 sbd_write_section(sbd_store_t *sst, sm_section_hdr_t *sms)
779 {
780 	stmf_status_t		ret;
781 	sbd_lu_t		*slu = (sbd_lu_t *)sst->sst_sbd_private;
782 	sbd_lu_info_t		*sli = slu->sl_sli;
783 
784 	if (sms->sms_offset == 0) {
785 		sms->sms_offset = sbd_find_section_offset(sst, sms);
786 		if (sms->sms_offset == 0) {
787 			if (sli->sli_total_meta_size <
788 			    (slu->sl_sm.sm_meta_size_used + sms->sms_size)) {
789 				return (STMF_FAILURE);
790 			}
791 			sms->sms_offset = slu->sl_sm.sm_meta_size_used;
792 			slu->sl_sm.sm_meta_size_used += sms->sms_size;
793 			slu->sl_sm.sm_chksum = 0;
794 			slu->sl_sm.sm_chksum = sbd_calc_sum((uint8_t *)
795 			    &slu->sl_sm, sizeof (sbd_meta_start_t));
796 			ret = sbd_aligned_meta_write(sst, slu->sl_meta_offset,
797 			    sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm);
798 			if (ret != STMF_SUCCESS) {
799 				slu->sl_sm.sm_meta_size_used -= sms->sms_size;
800 				slu->sl_sm.sm_chksum = 0;
801 				slu->sl_sm.sm_chksum = sbd_calc_sum((uint8_t *)
802 				    &slu->sl_sm, sizeof (sbd_meta_start_t));
803 				return (STMF_FAILURE);
804 			}
805 		}
806 	}
807 
808 	sms->sms_chksum = 0;
809 	sms->sms_chksum = sbd_calc_sum((uint8_t *)sms, sms->sms_size);
810 	ret = sbd_aligned_meta_write(sst, sms->sms_offset,
811 	    sms->sms_size, (uint8_t *)sms);
812 
813 	return (ret);
814 }
815 
816 stmf_status_t
817 sbd_create_meta(sbd_store_t *sst, sst_init_data_t *sst_idata)
818 {
819 	sbd_lu_t	*slu = (sbd_lu_t *)sst->sst_sbd_private;
820 	sbd_lu_info_t	*sli;
821 	sm_section_hdr_t *h;
822 	stmf_status_t	ret;
823 	uint64_t	meta_size;
824 	uint64_t	lu_data_offset;
825 	uint64_t	lu_data_size;
826 	uint16_t	b;
827 
828 	/* Blocksize should be a non-zero power of 2 */
829 	b = sst_idata->sst_blocksize;
830 	if ((b < 2) || ((b & (b - 1)) != 0)) {
831 		return (STMF_INVALID_ARG);
832 	}
833 
834 	/* Store size should be nonzero multiple of blocksize */
835 	if ((sst_idata->sst_store_size == 0) ||
836 	    ((sst_idata->sst_store_size % b) != 0)) {
837 		return (STMF_INVALID_ARG);
838 	}
839 
840 	/*
841 	 * Total metadata size is size of metadata headers + size of
842 	 * sbd_lu_info_t + any space needed by the store implementation
843 	 * itself. We should also keep enough space for future expansions.
844 	 * Also metadat size should be rounded off to blocksize.
845 	 */
846 	/*
847 	 * meta_size = sizeof (sbd_meta_start_t ) + sizeof (sbd_lu_info_t) +
848 	 *		sst_idata->sst_store_meta_data_size;
849 	 */
850 	/*
851 	 * for now keep a static 64K for metasize. This should be enough to
852 	 * store metadata as well as any persistent reservations and keys.
853 	 */
854 	meta_size = 64 * 1024;
855 	meta_size = (meta_size + (uint64_t)(b - 1));
856 	meta_size /= (uint64_t)b;
857 	meta_size *= (uint64_t)b;
858 
859 	/*
860 	 * If metadata is not separate from user data then store size
861 	 * should be large enough to hold metadata. Also effective data
862 	 * size should be adjusted.
863 	 */
864 	if (sst->sst_meta_write == NULL) {
865 		if (meta_size >= sst_idata->sst_store_size)
866 			return (STMF_INVALID_ARG);
867 		lu_data_offset = meta_size;
868 		lu_data_size = sst_idata->sst_store_size - meta_size;
869 	}
870 
871 	/* Initialize the header and write it */
872 	bzero(&slu->sl_sm, sizeof (sbd_meta_start_t));
873 	slu->sl_sm.sm_magic = SBD_MAGIC;
874 	slu->sl_sm.sm_meta_size = meta_size;
875 	/*
876 	 * Note that we already included the size for sli even though
877 	 * it is going to be written in next step.
878 	 */
879 	slu->sl_sm.sm_meta_size_used = sbd_meta_offset +
880 	    sizeof (sbd_meta_start_t) + sizeof (sbd_lu_info_t);
881 	slu->sl_sm.sm_ver_major = 1;
882 	slu->sl_sm.sm_chksum = sbd_calc_sum((uint8_t *)&slu->sl_sm,
883 	    sizeof (sbd_meta_start_t));
884 
885 	ret = sbd_aligned_meta_write(sst, sbd_meta_offset,
886 	    sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm);
887 	if (ret != STMF_SUCCESS)
888 		return (ret);
889 
890 	slu->sl_meta_offset = sbd_meta_offset;
891 	slu->sl_sli = (sbd_lu_info_t *)kmem_zalloc(sizeof (sbd_lu_info_t),
892 							KM_SLEEP);
893 	sli = slu->sl_sli;
894 	h = &sli->sli_sms_header;
895 	h->sms_offset = sbd_meta_offset + sizeof (sbd_meta_start_t);
896 	h->sms_size = sizeof (sbd_lu_info_t);
897 	h->sms_id = SMS_ID_LU_INFO;
898 	h->sms_data_order = SMS_DATA_ORDER;
899 	sli->sli_total_store_size = sst_idata->sst_store_size;
900 	sli->sli_total_meta_size = meta_size;
901 	sli->sli_lu_data_offset = lu_data_offset;
902 	sli->sli_lu_data_size = lu_data_size;
903 	sli->sli_blocksize = sst_idata->sst_blocksize;
904 	sli->sli_data_order = SMS_DATA_ORDER;
905 	sli->sli_lu_devid[3] = 16;
906 	ret = stmf_scsilib_uniq_lu_id(COMPANY_ID_SUN, (scsi_devid_desc_t *)
907 					&sli->sli_lu_devid[0]);
908 
909 	if (ret == STMF_SUCCESS) {
910 		bcopy(&sli->sli_lu_devid[4], sst_idata->sst_guid, 16);
911 		ret = sbd_write_section(sst, (sm_section_hdr_t *)slu->sl_sli);
912 		if (ret != STMF_SUCCESS)
913 			cmn_err(CE_NOTE, "write section failed");
914 	} else {
915 		cmn_err(CE_NOTE, "scsilib failed %llx",
916 		    (unsigned long long)ret);
917 	}
918 
919 	kmem_free(slu->sl_sli, sizeof (sbd_lu_info_t));
920 	slu->sl_sli = NULL;
921 
922 	return (ret);
923 }
924 
925 /*
926  * Used to modify the total store size in meta for a LUN, We only
927  * check sst_idata->sst_store_size here.
928  * For LUN not registered, we will read meta data first
929  */
930 stmf_status_t
931 sbd_modify_meta(sbd_store_t *sst, sst_init_data_t *sst_idata)
932 {
933 	sbd_lu_t	*slu = (sbd_lu_t *)sst->sst_sbd_private;
934 	sbd_lu_info_t	*sli;
935 	stmf_status_t	ret;
936 	/* uint64_t	meta_size; */
937 	uint64_t	lu_data_size;
938 	sbd_it_data_t	*sid = NULL;
939 	uint64_t	meta_offset;
940 
941 
942 	if (sst->sst_meta_write == NULL) {
943 		if (slu->sl_sm.sm_meta_size >= sst_idata->sst_store_size)
944 			return (STMF_INVALID_ARG);
945 		lu_data_size = sst_idata->sst_store_size -
946 		    slu->sl_sm.sm_meta_size;
947 	}
948 
949 	/*
950 	 * use a copy here in order not to change anything if
951 	 * sbd_write_section() failed
952 	 */
953 	sli = (sbd_lu_info_t *)kmem_zalloc(sizeof (sbd_lu_info_t), KM_SLEEP);
954 	if (slu->sl_sli)
955 		bcopy(slu->sl_sli, sli, sizeof (sbd_lu_info_t));
956 	else { /* not registered, have to read meta data */
957 		meta_offset = sbd_meta_offset;
958 read_meta_header:
959 		ret = sbd_aligned_meta_read(sst, meta_offset,
960 		    sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm);
961 		if (ret != STMF_SUCCESS) {
962 			goto exit_modify_lu;
963 		}
964 		if (slu->sl_sm.sm_magic != SBD_MAGIC) {
965 			if (BSWAP_64(slu->sl_sm.sm_magic) != SBD_MAGIC) {
966 				if (!sbd_migrate_meta_from_v0_to_v1(sst)) {
967 					ret = STMF_INVALID_ARG;
968 					goto exit_modify_lu;
969 				}
970 				goto read_meta_header;
971 			}
972 			sbd_swap_meta_start(&slu->sl_sm);
973 		}
974 		slu->sl_meta_offset = meta_offset;
975 
976 		sli->sli_sms_header.sms_size = sizeof (sbd_lu_info_t);
977 		sli->sli_sms_header.sms_id = SMS_ID_LU_INFO;
978 		sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
979 
980 		ret = sbd_read_section(sst, (sm_section_hdr_t *)sli);
981 
982 		if (ret != STMF_SUCCESS)
983 			goto exit_modify_lu;
984 		if (sli->sli_data_order != SMS_DATA_ORDER) {
985 			sbd_swap_sli_fields(sli, SMS_DATA_ORDER);
986 		}
987 	}
988 
989 	sli->sli_total_store_size = sst_idata->sst_store_size;
990 	sli->sli_lu_data_size = lu_data_size;
991 	bcopy(&sli->sli_lu_devid[4], sst_idata->sst_guid, 16);
992 
993 	ret = sbd_write_section(sst, (sm_section_hdr_t *)sli);
994 	if (ret != STMF_SUCCESS)
995 		cmn_err(CE_NOTE, "write section failed");
996 	else if (slu->sl_sli) {
997 		/* for registered LU */
998 		slu->sl_sli->sli_total_store_size = sli->sli_total_store_size;
999 		slu->sl_sli->sli_lu_data_size = sli->sli_lu_data_size;
1000 		mutex_enter(&slu->sl_it_list_lock);
1001 		for (sid = slu->sl_it_list; sid; sid = sid->sbd_it_next) {
1002 			sid->sbd_it_ua_conditions |= SBD_UA_CAPACITY_CHANGED;
1003 		}
1004 		mutex_exit(&slu->sl_it_list_lock);
1005 	}
1006 exit_modify_lu:
1007 	kmem_free(sli, sizeof (sbd_lu_info_t));
1008 
1009 	return (ret);
1010 }
1011 
1012 /*
1013  * Added sst_idata here because with dynamic LUN, we can only get the
1014  * LUN size from meta data if we are registering LUN
1015  */
1016 stmf_status_t
1017 sbd_register_sst(sbd_store_t *sst, sst_init_data_t *sst_idata)
1018 {
1019 	sbd_lu_t	*slu = (sbd_lu_t *)sst->sst_sbd_private;
1020 	sbd_lu_info_t	*sli;
1021 	stmf_lu_t	*lu;
1022 	stmf_status_t	ret;
1023 	uint16_t	b;
1024 	uint64_t	meta_offset = sbd_meta_offset;
1025 
1026 	if (slu->sl_sli) {
1027 		cmn_err(CE_PANIC, "sbd_register_sst called with active data "
1028 		    " from an existing store");
1029 	}
1030 read_meta_header:
1031 	ret = sbd_aligned_meta_read(sst, meta_offset,
1032 	    sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm);
1033 	if (ret != STMF_SUCCESS) {
1034 		return (ret);
1035 	}
1036 	if (slu->sl_sm.sm_magic != SBD_MAGIC) {
1037 		if (BSWAP_64(slu->sl_sm.sm_magic) != SBD_MAGIC) {
1038 			if (!sbd_migrate_meta_from_v0_to_v1(sst))
1039 				return (STMF_INVALID_ARG);
1040 			goto read_meta_header;
1041 		}
1042 		sbd_swap_meta_start(&slu->sl_sm);
1043 		ret = sbd_aligned_meta_write(sst, meta_offset,
1044 		    sizeof (sbd_meta_start_t), (uint8_t *)&slu->sl_sm);
1045 		if (ret != STMF_SUCCESS)
1046 			return (ret);
1047 	}
1048 	slu->sl_meta_offset = meta_offset;
1049 
1050 	sli = (sbd_lu_info_t *)kmem_zalloc(sizeof (sbd_lu_info_t),
1051 								KM_SLEEP);
1052 	slu->sl_sli = sli;
1053 	sli->sli_sms_header.sms_size = sizeof (sbd_lu_info_t);
1054 	sli->sli_sms_header.sms_id = SMS_ID_LU_INFO;
1055 	sli->sli_sms_header.sms_data_order = SMS_DATA_ORDER;
1056 
1057 	ret = sbd_read_section(sst, (sm_section_hdr_t *)sli);
1058 
1059 	if (ret != STMF_SUCCESS) {
1060 		goto exit_store_online;
1061 	}
1062 
1063 	if (sli->sli_data_order != SMS_DATA_ORDER) {
1064 		sbd_swap_sli_fields(sli, SMS_DATA_ORDER);
1065 	}
1066 	bcopy(&sli->sli_lu_devid[4], sst_idata->sst_guid, 16);
1067 	b = sli->sli_blocksize;
1068 
1069 	/* Calculate shift factor to convert LBA to a linear offset */
1070 	for (slu->sl_shift_count = 0; b != 1; slu->sl_shift_count++)
1071 		b >>= 1;
1072 
1073 	/* Initialize LU and register it */
1074 	lu = slu->sl_lu;
1075 	lu->lu_id = (scsi_devid_desc_t *)&sli->sli_lu_devid[0];
1076 	lu->lu_alias = sst->sst_alias;
1077 	lu->lu_lp = sbd_lp;
1078 	lu->lu_task_alloc = sbd_task_alloc;
1079 	lu->lu_new_task = sbd_new_task;
1080 	lu->lu_dbuf_xfer_done = sbd_dbuf_xfer_done;
1081 	lu->lu_send_status_done = sbd_send_status_done;
1082 	lu->lu_task_free = sbd_task_free;
1083 	lu->lu_abort = sbd_abort;
1084 	lu->lu_ctl = sbd_ctl;
1085 	lu->lu_info = sbd_info;
1086 	slu->sl_state = STMF_STATE_OFFLINE;
1087 
1088 	if ((ret = stmf_register_lu(lu)) != STMF_SUCCESS) {
1089 		stmf_trace(0, "Failed to register with framework, ret=%llx",
1090 			ret);
1091 		goto exit_store_online;
1092 	}
1093 
1094 	mutex_enter(&sbd_lock);
1095 	slu->sl_next = sbd_lu_list;
1096 	sbd_lu_list = slu;
1097 	sbd_lu_count++;
1098 	mutex_exit(&sbd_lock);
1099 
1100 	if (sst_idata) {
1101 		sst_idata->sst_store_size = sli->sli_total_store_size;
1102 		sst_idata->sst_blocksize = sli->sli_blocksize;
1103 	}
1104 
1105 	return (STMF_SUCCESS);
1106 exit_store_online:;
1107 	kmem_free(slu->sl_sli, sizeof (sbd_lu_info_t));
1108 	slu->sl_sli = NULL;
1109 	return (ret);
1110 }
1111 
1112 stmf_status_t
1113 sbd_deregister_sst(sbd_store_t *sst)
1114 {
1115 	sbd_lu_t	*slu = (sbd_lu_t *)sst->sst_sbd_private;
1116 	sbd_lu_t	**ppslu;
1117 
1118 	if (slu->sl_state != STMF_STATE_OFFLINE)
1119 		return (STMF_BUSY);
1120 
1121 	if (stmf_deregister_lu(slu->sl_lu) != STMF_SUCCESS)
1122 		return (STMF_BUSY);
1123 
1124 	mutex_enter(&sbd_lock);
1125 	for (ppslu = &sbd_lu_list; (*ppslu) != NULL;
1126 					ppslu = &((*ppslu)->sl_next)) {
1127 		if ((*ppslu) == slu) {
1128 			*ppslu = (*ppslu)->sl_next;
1129 			sbd_lu_count--;
1130 			break;
1131 		}
1132 	}
1133 	mutex_exit(&sbd_lock);
1134 	if (slu->sl_sli) {
1135 		kmem_free(slu->sl_sli, sizeof (sbd_lu_info_t));
1136 		slu->sl_sli = NULL;
1137 	}
1138 	return (STMF_SUCCESS);
1139 }
1140 
1141 
1142 /*
1143  * Version 0 format of metadata was never integrated into solaris. It
1144  * was the format used by early opensolaris release until feb. 2008.
1145  * Subsequent opensolaris releases used version 1 and thats what
1146  * was integrated into solaris as well. At some point V0 stuff should be
1147  * completely removed.
1148  */
1149 int
1150 sbd_is_meta_v0(sbd_store_t *sst, uint64_t *meta_size, uint64_t *meta_offset)
1151 {
1152 	sbd_v0_meta_start_t m;
1153 
1154 	*meta_offset = 4096;
1155 v0_check:;
1156 	if (sbd_aligned_meta_read(sst, *meta_offset, 16, (uint8_t *)&m) !=
1157 	    STMF_SUCCESS) {
1158 		return (0);
1159 	}
1160 
1161 	if (m.sm_magic != SBD_V0_MAGIC) {
1162 		m.sm_magic = BSWAP_64(m.sm_magic);
1163 		if (m.sm_magic != SBD_V0_MAGIC) {
1164 			if (*meta_offset == 4096) {
1165 				*meta_offset = 0;
1166 				goto v0_check;
1167 			}
1168 			return (0);
1169 		}
1170 		m.sm_meta_size = BSWAP_64(m.sm_meta_size);
1171 	}
1172 
1173 	*meta_size = m.sm_meta_size;
1174 
1175 	return (1);
1176 }
1177 
1178 int
1179 sbd_migrate_meta_from_v0_to_v1(sbd_store_t *sst)
1180 {
1181 	uint64_t v0_meta_size;
1182 	uint64_t v0_meta_offset;
1183 	sbd_v0_lu_info_t *v0sli;
1184 	sbd_lu_info_t *sli;
1185 	sbd_meta_start_t *sm;
1186 	sm_section_hdr_t *h;
1187 	int ret = 0;
1188 
1189 	if (!sbd_is_meta_v0(sst, &v0_meta_size, &v0_meta_offset))
1190 		return (0);
1191 
1192 	v0sli = kmem_zalloc(sizeof (*v0sli), KM_SLEEP);
1193 	sm = kmem_zalloc(sizeof (*sm) + sizeof (*sli), KM_SLEEP);
1194 	sli = (sbd_lu_info_t *)(((uint8_t *)sm) + sizeof (*sm));
1195 	if (sbd_aligned_meta_read(sst, v0_meta_offset + 16, sizeof (*v0sli),
1196 	    (uint8_t *)v0sli) != STMF_SUCCESS) {
1197 		goto mv0v1_exit;
1198 	}
1199 	sm->sm_magic = SBD_MAGIC;
1200 	sm->sm_meta_size = v0_meta_size;
1201 	sm->sm_meta_size_used = sbd_meta_offset + sizeof (*sm) + sizeof (*sli);
1202 	sm->sm_ver_major = 1;
1203 	sm->sm_chksum = sbd_calc_sum((uint8_t *)sm, sizeof (sbd_meta_start_t));
1204 
1205 	h = &sli->sli_sms_header;
1206 	h->sms_offset = sbd_meta_offset + sizeof (*sm);
1207 	h->sms_size = sizeof (*sli);
1208 	h->sms_id = SMS_ID_LU_INFO;
1209 	h->sms_data_order = SMS_DATA_ORDER;
1210 	if (v0sli->sli_sms_header.sms_payload_data_order == SMS_DATA_ORDER) {
1211 		sli->sli_total_store_size = v0sli->sli_total_store_size;
1212 		sli->sli_total_meta_size = v0sli->sli_total_meta_size;
1213 		sli->sli_lu_data_offset = v0sli->sli_lu_data_offset;
1214 		sli->sli_lu_data_size = v0sli->sli_lu_data_size;
1215 	} else {
1216 		sli->sli_total_store_size =
1217 		    BSWAP_64(v0sli->sli_total_store_size);
1218 		sli->sli_total_meta_size =
1219 		    BSWAP_64(v0sli->sli_total_meta_size);
1220 		sli->sli_lu_data_offset =
1221 		    BSWAP_64(v0sli->sli_lu_data_offset);
1222 		sli->sli_lu_data_size =
1223 		    BSWAP_64(v0sli->sli_lu_data_size);
1224 	}
1225 	/* sli_flags were not used in v0 */
1226 	sli->sli_blocksize = 512;
1227 	sli->sli_data_order = SMS_DATA_ORDER;
1228 	bcopy(v0sli->sli_lu_devid, sli->sli_lu_devid, 20);
1229 	h->sms_chksum = sbd_calc_sum((uint8_t *)h, h->sms_size);
1230 
1231 	if (sbd_aligned_meta_write(sst, sbd_meta_offset,
1232 	    sizeof (*sm) + sizeof (*sli), (uint8_t *)sm) != STMF_SUCCESS) {
1233 		goto mv0v1_exit;
1234 	}
1235 
1236 	ret = 1;
1237 mv0v1_exit:
1238 	kmem_free(v0sli, sizeof (*v0sli));
1239 	kmem_free(sm, sizeof (*sm) + sizeof (*sli));
1240 
1241 	return (ret);
1242 }
1243