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.
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.
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]
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2013 by Delphix. All rights reserved.
28 #include <sys/sysmacros.h>
32 #include <sys/sunddi.h>
33 #include <sys/modctl.h>
34 #include <sys/scsi/scsi.h>
35 #include <sys/scsi/impl/scsi_reset_notify.h>
37 #include <sys/byteorder.h>
38 #include <sys/pathname.h>
39 #include <sys/atomic.h>
40 #include <sys/nvpair.h>
41 #include <sys/fs/zfs.h>
44 #include <sys/zfs_ioctl.h>
48 #include <sys/stmf_ioctl.h>
49 #include <sys/stmf_sbd_ioctl.h>
54 #define SBD_IS_ZVOL(zvol) (strncmp("/dev/zvol", zvol, 9))
56 extern sbd_status_t
sbd_pgr_meta_init(sbd_lu_t
*sl
);
57 extern sbd_status_t
sbd_pgr_meta_load(sbd_lu_t
*sl
);
58 extern void sbd_pgr_reset(sbd_lu_t
*sl
);
60 static int sbd_getinfo(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
,
62 static int sbd_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
);
63 static int sbd_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
);
64 static int sbd_open(dev_t
*devp
, int flag
, int otype
, cred_t
*credp
);
65 static int sbd_close(dev_t dev
, int flag
, int otype
, cred_t
*credp
);
66 static int stmf_sbd_ioctl(dev_t dev
, int cmd
, intptr_t data
, int mode
,
67 cred_t
*credp
, int *rval
);
68 void sbd_lp_cb(stmf_lu_provider_t
*lp
, int cmd
, void *arg
, uint32_t flags
);
69 stmf_status_t
sbd_proxy_reg_lu(uint8_t *luid
, void *proxy_reg_arg
,
70 uint32_t proxy_reg_arg_len
);
71 stmf_status_t
sbd_proxy_dereg_lu(uint8_t *luid
, void *proxy_reg_arg
,
72 uint32_t proxy_reg_arg_len
);
73 stmf_status_t
sbd_proxy_msg(uint8_t *luid
, void *proxy_arg
,
74 uint32_t proxy_arg_len
, uint32_t type
);
75 int sbd_create_register_lu(sbd_create_and_reg_lu_t
*slu
, int struct_sz
,
77 int sbd_create_standby_lu(sbd_create_standby_lu_t
*slu
, uint32_t *err_ret
);
78 int sbd_set_lu_standby(sbd_set_lu_standby_t
*stlu
, uint32_t *err_ret
);
79 int sbd_import_lu(sbd_import_lu_t
*ilu
, int struct_sz
, uint32_t *err_ret
,
80 int no_register
, sbd_lu_t
**slr
);
81 int sbd_import_active_lu(sbd_import_lu_t
*ilu
, sbd_lu_t
*sl
, uint32_t *err_ret
);
82 int sbd_delete_lu(sbd_delete_lu_t
*dlu
, int struct_sz
, uint32_t *err_ret
);
83 int sbd_modify_lu(sbd_modify_lu_t
*mlu
, int struct_sz
, uint32_t *err_ret
);
84 int sbd_set_global_props(sbd_global_props_t
*mlu
, int struct_sz
,
86 int sbd_get_global_props(sbd_global_props_t
*oslp
, uint32_t oslp_sz
,
88 int sbd_get_lu_props(sbd_lu_props_t
*islp
, uint32_t islp_sz
,
89 sbd_lu_props_t
*oslp
, uint32_t oslp_sz
, uint32_t *err_ret
);
90 static char *sbd_get_zvol_name(sbd_lu_t
*);
91 static int sbd_get_unmap_props(sbd_unmap_props_t
*sup
, sbd_unmap_props_t
*osup
,
93 sbd_status_t
sbd_create_zfs_meta_object(sbd_lu_t
*sl
);
94 sbd_status_t
sbd_open_zfs_meta(sbd_lu_t
*sl
);
95 sbd_status_t
sbd_read_zfs_meta(sbd_lu_t
*sl
, uint8_t *buf
, uint64_t sz
,
97 sbd_status_t
sbd_write_zfs_meta(sbd_lu_t
*sl
, uint8_t *buf
, uint64_t sz
,
99 sbd_status_t
sbd_update_zfs_prop(sbd_lu_t
*sl
);
100 int sbd_is_zvol(char *path
);
101 int sbd_zvolget(char *zvol_name
, char **comstarprop
);
102 int sbd_zvolset(char *zvol_name
, char *comstarprop
);
103 char sbd_ctoi(char c
);
104 void sbd_close_lu(sbd_lu_t
*sl
);
106 static ldi_ident_t sbd_zfs_ident
;
107 static stmf_lu_provider_t
*sbd_lp
;
108 static sbd_lu_t
*sbd_lu_list
= NULL
;
109 static kmutex_t sbd_lock
;
110 static dev_info_t
*sbd_dip
;
111 static uint32_t sbd_lu_count
= 0;
113 /* Global property settings for the logical unit */
114 char sbd_vendor_id
[] = "SUN ";
115 char sbd_product_id
[] = "COMSTAR ";
116 char sbd_revision
[] = "1.0 ";
117 char *sbd_mgmt_url
= NULL
;
118 uint16_t sbd_mgmt_url_alloc_size
= 0;
119 krwlock_t sbd_global_prop_lock
;
121 static char sbd_name
[] = "sbd";
123 static struct cb_ops sbd_cb_ops
= {
125 sbd_close
, /* close */
126 nodev
, /* strategy */
131 stmf_sbd_ioctl
, /* ioctl */
135 nochpoll
, /* chpoll */
136 ddi_prop_op
, /* cb_prop_op */
138 D_NEW
| D_MP
, /* cb_flag */
144 static struct dev_ops sbd_ops
= {
148 nulldev
, /* identify */
158 #define SBD_NAME "COMSTAR SBD"
160 static struct modldrv modldrv
= {
166 static struct modlinkage modlinkage
= {
177 ret
= mod_install(&modlinkage
);
180 sbd_lp
= (stmf_lu_provider_t
*)stmf_alloc(STMF_STRUCT_LU_PROVIDER
,
182 sbd_lp
->lp_lpif_rev
= LPIF_REV_2
;
183 sbd_lp
->lp_instance
= 0;
184 sbd_lp
->lp_name
= sbd_name
;
185 sbd_lp
->lp_cb
= sbd_lp_cb
;
186 sbd_lp
->lp_alua_support
= 1;
187 sbd_lp
->lp_proxy_msg
= sbd_proxy_msg
;
188 sbd_zfs_ident
= ldi_ident_from_anon();
190 if (stmf_register_lu_provider(sbd_lp
) != STMF_SUCCESS
) {
191 (void) mod_remove(&modlinkage
);
195 mutex_init(&sbd_lock
, NULL
, MUTEX_DRIVER
, NULL
);
196 rw_init(&sbd_global_prop_lock
, NULL
, RW_DRIVER
, NULL
);
206 * If we have registered lus, then make sure they are all offline
207 * if so then deregister them. This should drop the sbd_lu_count
213 /* See if all of them are offline */
214 mutex_enter(&sbd_lock
);
215 for (slu
= sbd_lu_list
; slu
!= NULL
; slu
= slu
->sl_next
) {
216 if ((slu
->sl_state
!= STMF_STATE_OFFLINE
) ||
217 slu
->sl_state_not_acked
) {
218 mutex_exit(&sbd_lock
);
222 mutex_exit(&sbd_lock
);
225 /* ok start deregistering them */
226 while (sbd_lu_list
) {
227 sbd_store_t
*sst
= sbd_lu_list
->sl_sst
;
228 if (sst
->sst_deregister_lu(sst
) != STMF_SUCCESS
)
234 if (stmf_deregister_lu_provider(sbd_lp
) != STMF_SUCCESS
)
236 ret
= mod_remove(&modlinkage
);
238 (void) stmf_register_lu_provider(sbd_lp
);
242 mutex_destroy(&sbd_lock
);
243 rw_destroy(&sbd_global_prop_lock
);
244 ldi_ident_release(sbd_zfs_ident
);
249 _info(struct modinfo
*modinfop
)
251 return (mod_info(&modlinkage
, modinfop
));
256 sbd_getinfo(dev_info_t
*dip
, ddi_info_cmd_t cmd
, void *arg
, void **result
)
259 case DDI_INFO_DEVT2DEVINFO
:
262 case DDI_INFO_DEVT2INSTANCE
:
263 *result
= (void *)(uintptr_t)ddi_get_instance(sbd_dip
);
266 return (DDI_FAILURE
);
269 return (DDI_SUCCESS
);
273 sbd_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
279 if (ddi_create_minor_node(dip
, "admin", S_IFCHR
, 0,
280 DDI_NT_STMF_LP
, 0) != DDI_SUCCESS
) {
284 return (DDI_SUCCESS
);
287 return (DDI_FAILURE
);
291 sbd_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
295 ddi_remove_minor_node(dip
, 0);
296 return (DDI_SUCCESS
);
299 return (DDI_FAILURE
);
304 sbd_open(dev_t
*devp
, int flag
, int otype
, cred_t
*credp
)
306 if (otype
!= OTYP_CHR
)
313 sbd_close(dev_t dev
, int flag
, int otype
, cred_t
*credp
)
320 stmf_sbd_ioctl(dev_t dev
, int cmd
, intptr_t data
, int mode
,
321 cred_t
*credp
, int *rval
)
323 stmf_iocdata_t
*iocd
;
330 if (drv_priv(credp
) != 0) {
334 ret
= stmf_copyin_iocdata(data
, mode
, &iocd
, &ibuf
, &obuf
);
337 iocd
->stmf_error
= 0;
340 case SBD_IOCTL_CREATE_AND_REGISTER_LU
:
341 if (iocd
->stmf_ibuf_size
<
342 (sizeof (sbd_create_and_reg_lu_t
) - 8)) {
346 if ((iocd
->stmf_obuf_size
== 0) ||
347 (iocd
->stmf_obuf_size
> iocd
->stmf_ibuf_size
)) {
351 ret
= sbd_create_register_lu((sbd_create_and_reg_lu_t
*)
352 ibuf
, iocd
->stmf_ibuf_size
, &iocd
->stmf_error
);
353 bcopy(ibuf
, obuf
, iocd
->stmf_obuf_size
);
355 case SBD_IOCTL_SET_LU_STANDBY
:
356 if (iocd
->stmf_ibuf_size
< sizeof (sbd_set_lu_standby_t
)) {
360 if (iocd
->stmf_obuf_size
) {
364 ret
= sbd_set_lu_standby((sbd_set_lu_standby_t
*)ibuf
,
367 case SBD_IOCTL_IMPORT_LU
:
368 if (iocd
->stmf_ibuf_size
<
369 (sizeof (sbd_import_lu_t
) - 8)) {
373 if ((iocd
->stmf_obuf_size
== 0) ||
374 (iocd
->stmf_obuf_size
> iocd
->stmf_ibuf_size
)) {
378 ret
= sbd_import_lu((sbd_import_lu_t
*)ibuf
,
379 iocd
->stmf_ibuf_size
, &iocd
->stmf_error
, 0, NULL
);
380 bcopy(ibuf
, obuf
, iocd
->stmf_obuf_size
);
382 case SBD_IOCTL_DELETE_LU
:
383 if (iocd
->stmf_ibuf_size
< (sizeof (sbd_delete_lu_t
) - 8)) {
387 if (iocd
->stmf_obuf_size
) {
391 ret
= sbd_delete_lu((sbd_delete_lu_t
*)ibuf
,
392 iocd
->stmf_ibuf_size
, &iocd
->stmf_error
);
394 case SBD_IOCTL_MODIFY_LU
:
395 if (iocd
->stmf_ibuf_size
< (sizeof (sbd_modify_lu_t
) - 8)) {
399 if (iocd
->stmf_obuf_size
) {
403 ret
= sbd_modify_lu((sbd_modify_lu_t
*)ibuf
,
404 iocd
->stmf_ibuf_size
, &iocd
->stmf_error
);
406 case SBD_IOCTL_SET_GLOBAL_LU
:
407 if (iocd
->stmf_ibuf_size
< (sizeof (sbd_global_props_t
) - 8)) {
411 if (iocd
->stmf_obuf_size
) {
415 ret
= sbd_set_global_props((sbd_global_props_t
*)ibuf
,
416 iocd
->stmf_ibuf_size
, &iocd
->stmf_error
);
418 case SBD_IOCTL_GET_GLOBAL_LU
:
419 if (iocd
->stmf_ibuf_size
) {
423 if (iocd
->stmf_obuf_size
< sizeof (sbd_global_props_t
)) {
427 ret
= sbd_get_global_props((sbd_global_props_t
*)obuf
,
428 iocd
->stmf_obuf_size
, &iocd
->stmf_error
);
430 case SBD_IOCTL_GET_LU_PROPS
:
431 if (iocd
->stmf_ibuf_size
< (sizeof (sbd_lu_props_t
) - 8)) {
435 if (iocd
->stmf_obuf_size
< sizeof (sbd_lu_props_t
)) {
439 ret
= sbd_get_lu_props((sbd_lu_props_t
*)ibuf
,
440 iocd
->stmf_ibuf_size
, (sbd_lu_props_t
*)obuf
,
441 iocd
->stmf_obuf_size
, &iocd
->stmf_error
);
443 case SBD_IOCTL_GET_LU_LIST
:
444 mutex_enter(&sbd_lock
);
445 iocd
->stmf_obuf_max_nentries
= sbd_lu_count
;
446 iocd
->stmf_obuf_nentries
= min((iocd
->stmf_obuf_size
>> 4),
448 for (nsl
= sbd_lu_list
, i
= 0; nsl
&&
449 (i
< iocd
->stmf_obuf_nentries
); i
++, nsl
= nsl
->sl_next
) {
450 bcopy(nsl
->sl_device_id
+ 4,
451 &(((uint8_t *)obuf
)[i
<< 4]), 16);
453 mutex_exit(&sbd_lock
);
455 iocd
->stmf_error
= 0;
457 case SBD_IOCTL_GET_UNMAP_PROPS
:
458 if (iocd
->stmf_ibuf_size
< sizeof (sbd_unmap_props_t
)) {
462 if (iocd
->stmf_obuf_size
< sizeof (sbd_unmap_props_t
)) {
466 ret
= sbd_get_unmap_props((sbd_unmap_props_t
*)ibuf
,
467 (sbd_unmap_props_t
*)obuf
, &iocd
->stmf_error
);
474 ret
= stmf_copyout_iocdata(data
, mode
, iocd
, obuf
);
475 } else if (iocd
->stmf_error
) {
476 (void) stmf_copyout_iocdata(data
, mode
, iocd
, obuf
);
479 kmem_free(obuf
, iocd
->stmf_obuf_size
);
483 kmem_free(ibuf
, iocd
->stmf_ibuf_size
);
486 kmem_free(iocd
, sizeof (stmf_iocdata_t
));
492 sbd_lp_cb(stmf_lu_provider_t
*lp
, int cmd
, void *arg
, uint32_t flags
)
496 sbd_import_lu_t
*ilu
;
502 if ((cmd
!= STMF_PROVIDER_DATA_UPDATED
) || (arg
== NULL
)) {
506 if ((flags
& (STMF_PCB_STMF_ONLINING
| STMF_PCB_PREG_COMPLETE
)) == 0) {
512 ilu
= (sbd_import_lu_t
*)kmem_zalloc(ilu_sz
, KM_SLEEP
);
513 while ((np
= nvlist_next_nvpair((nvlist_t
*)arg
, np
)) != NULL
) {
514 if (nvpair_type(np
) != DATA_TYPE_STRING
) {
517 if (nvpair_value_string(np
, &s
) != 0) {
520 struct_sz
= max(8, strlen(s
) + 1);
521 struct_sz
+= sizeof (sbd_import_lu_t
) - 8;
522 if (struct_sz
> ilu_sz
) {
523 kmem_free(ilu
, ilu_sz
);
524 ilu_sz
= struct_sz
+ 32;
525 ilu
= (sbd_import_lu_t
*)kmem_zalloc(ilu_sz
, KM_SLEEP
);
527 ilu
->ilu_struct_size
= struct_sz
;
528 (void) strcpy(ilu
->ilu_meta_fname
, s
);
529 iret
= sbd_import_lu(ilu
, struct_sz
, &err_ret
, 0, NULL
);
531 stmf_trace(0, "sbd_lp_cb: import_lu failed, ret = %d, "
532 "err_ret = %d", iret
, err_ret
);
534 stmf_trace(0, "Imported the LU %s", nvpair_name(np
));
539 kmem_free(ilu
, ilu_sz
);
545 sbd_link_lu(sbd_lu_t
*sl
)
549 mutex_enter(&sbd_lock
);
550 mutex_enter(&sl
->sl_lock
);
551 ASSERT(sl
->sl_trans_op
!= SL_OP_NONE
);
553 if (sl
->sl_flags
& SL_LINKED
) {
554 mutex_exit(&sbd_lock
);
555 mutex_exit(&sl
->sl_lock
);
556 return (SBD_ALREADY
);
558 for (nsl
= sbd_lu_list
; nsl
; nsl
= nsl
->sl_next
) {
559 if (strcmp(nsl
->sl_name
, sl
->sl_name
) == 0)
563 mutex_exit(&sbd_lock
);
564 mutex_exit(&sl
->sl_lock
);
565 return (SBD_ALREADY
);
567 sl
->sl_next
= sbd_lu_list
;
569 sl
->sl_flags
|= SL_LINKED
;
570 mutex_exit(&sbd_lock
);
571 mutex_exit(&sl
->sl_lock
);
572 return (SBD_SUCCESS
);
576 sbd_unlink_lu(sbd_lu_t
*sl
)
580 mutex_enter(&sbd_lock
);
581 mutex_enter(&sl
->sl_lock
);
582 ASSERT(sl
->sl_trans_op
!= SL_OP_NONE
);
584 ASSERT(sl
->sl_flags
& SL_LINKED
);
585 for (ppnsl
= &sbd_lu_list
; *ppnsl
; ppnsl
= &((*ppnsl
)->sl_next
)) {
590 *ppnsl
= (*ppnsl
)->sl_next
;
591 sl
->sl_flags
&= ~SL_LINKED
;
592 mutex_exit(&sbd_lock
);
593 mutex_exit(&sl
->sl_lock
);
597 sbd_find_and_lock_lu(uint8_t *guid
, uint8_t *meta_name
, uint8_t op
,
604 mutex_enter(&sbd_lock
);
605 for (sl
= sbd_lu_list
; sl
; sl
= sl
->sl_next
) {
607 found
= bcmp(sl
->sl_device_id
+ 4, guid
, 16) == 0;
609 found
= strcmp(sl
->sl_name
, (char *)meta_name
) == 0;
615 mutex_exit(&sbd_lock
);
616 return (SBD_NOT_FOUND
);
618 mutex_enter(&sl
->sl_lock
);
619 if (sl
->sl_trans_op
== SL_OP_NONE
) {
620 sl
->sl_trans_op
= op
;
626 mutex_exit(&sl
->sl_lock
);
627 mutex_exit(&sbd_lock
);
632 sbd_read_meta(sbd_lu_t
*sl
, uint64_t offset
, uint64_t size
, uint8_t *buf
)
635 uint64_t starting_off
;
645 ASSERT(sl
->sl_flags
& SL_META_OPENED
);
646 if (sl
->sl_flags
& SL_SHARED_META
) {
647 meta_align
= (((uint64_t)1) << sl
->sl_data_blocksize_shift
) - 1;
651 meta_align
= (((uint64_t)1) << sl
->sl_meta_blocksize_shift
) - 1;
652 if ((sl
->sl_flags
& SL_ZFS_META
) == 0) {
657 starting_off
= offset
& ~(meta_align
);
658 data_off
= offset
& meta_align
;
659 ending_off
= (offset
+ size
+ meta_align
) & (~meta_align
);
660 if (ending_off
> sl
->sl_meta_size_used
) {
662 if (starting_off
>= sl
->sl_meta_size_used
) {
663 return (SBD_SUCCESS
);
665 ending_off
= (sl
->sl_meta_size_used
+ meta_align
) &
667 if (size
> (ending_off
- (starting_off
+ data_off
))) {
668 size
= ending_off
- (starting_off
+ data_off
);
671 io_size
= ending_off
- starting_off
;
672 io_buf
= kmem_zalloc(io_size
, KM_SLEEP
);
673 ASSERT((starting_off
+ io_size
) <= sl
->sl_total_meta_size
);
676 * Don't proceed if the device has been closed
677 * This can occur on an access state change to standby or
678 * a delete. The writer lock is acquired before closing the
679 * lu. If importing, reading the metadata is valid, hence
680 * the check on SL_OP_IMPORT_LU.
682 rw_enter(&sl
->sl_access_state_lock
, RW_READER
);
683 if ((sl
->sl_flags
& SL_MEDIA_LOADED
) == 0 &&
684 sl
->sl_trans_op
!= SL_OP_IMPORT_LU
) {
685 rw_exit(&sl
->sl_access_state_lock
);
686 ret
= SBD_FILEIO_FAILURE
;
687 goto sbd_read_meta_failure
;
689 if (sl
->sl_flags
& SL_ZFS_META
) {
690 if ((ret
= sbd_read_zfs_meta(sl
, io_buf
, io_size
,
691 starting_off
)) != SBD_SUCCESS
) {
692 rw_exit(&sl
->sl_access_state_lock
);
693 goto sbd_read_meta_failure
;
696 vret
= vn_rdwr(UIO_READ
, vp
, (caddr_t
)io_buf
, (ssize_t
)io_size
,
697 (offset_t
)starting_off
, UIO_SYSSPACE
, FRSYNC
,
698 RLIM64_INFINITY
, CRED(), &resid
);
701 ret
= SBD_FILEIO_FAILURE
| vret
;
702 rw_exit(&sl
->sl_access_state_lock
);
703 goto sbd_read_meta_failure
;
706 rw_exit(&sl
->sl_access_state_lock
);
708 bcopy(io_buf
+ data_off
, buf
, size
);
711 sbd_read_meta_failure
:
712 kmem_free(io_buf
, io_size
);
717 sbd_write_meta(sbd_lu_t
*sl
, uint64_t offset
, uint64_t size
, uint8_t *buf
)
720 uint64_t starting_off
;
730 ASSERT(sl
->sl_flags
& SL_META_OPENED
);
731 if (sl
->sl_flags
& SL_SHARED_META
) {
732 meta_align
= (((uint64_t)1) << sl
->sl_data_blocksize_shift
) - 1;
736 meta_align
= (((uint64_t)1) << sl
->sl_meta_blocksize_shift
) - 1;
737 if ((sl
->sl_flags
& SL_ZFS_META
) == 0) {
742 starting_off
= offset
& ~(meta_align
);
743 data_off
= offset
& meta_align
;
744 ending_off
= (offset
+ size
+ meta_align
) & (~meta_align
);
745 io_size
= ending_off
- starting_off
;
746 io_buf
= kmem_zalloc(io_size
, KM_SLEEP
);
747 ret
= sbd_read_meta(sl
, starting_off
, io_size
, io_buf
);
748 if (ret
!= SBD_SUCCESS
) {
749 goto sbd_write_meta_failure
;
751 bcopy(buf
, io_buf
+ data_off
, size
);
753 * Don't proceed if the device has been closed
754 * This can occur on an access state change to standby or
755 * a delete. The writer lock is acquired before closing the
756 * lu. If importing, reading the metadata is valid, hence
757 * the check on SL_OP_IMPORT_LU.
759 rw_enter(&sl
->sl_access_state_lock
, RW_READER
);
760 if ((sl
->sl_flags
& SL_MEDIA_LOADED
) == 0 &&
761 sl
->sl_trans_op
!= SL_OP_IMPORT_LU
) {
762 rw_exit(&sl
->sl_access_state_lock
);
763 ret
= SBD_FILEIO_FAILURE
;
764 goto sbd_write_meta_failure
;
766 if (sl
->sl_flags
& SL_ZFS_META
) {
767 if ((ret
= sbd_write_zfs_meta(sl
, io_buf
, io_size
,
768 starting_off
)) != SBD_SUCCESS
) {
769 rw_exit(&sl
->sl_access_state_lock
);
770 goto sbd_write_meta_failure
;
773 vret
= vn_rdwr(UIO_WRITE
, vp
, (caddr_t
)io_buf
, (ssize_t
)io_size
,
774 (offset_t
)starting_off
, UIO_SYSSPACE
, FDSYNC
,
775 RLIM64_INFINITY
, CRED(), &resid
);
778 ret
= SBD_FILEIO_FAILURE
| vret
;
779 rw_exit(&sl
->sl_access_state_lock
);
780 goto sbd_write_meta_failure
;
783 rw_exit(&sl
->sl_access_state_lock
);
787 sbd_write_meta_failure
:
788 kmem_free(io_buf
, io_size
);
793 sbd_calc_sum(uint8_t *buf
, int size
)
804 sbd_calc_section_sum(sm_section_hdr_t
*sm
, uint32_t sz
)
810 s
= sbd_calc_sum((uint8_t *)sm
, sz
);
817 sbd_strlen(char *str
, uint32_t maxlen
)
821 for (i
= 0; i
< maxlen
; i
++) {
829 sbd_swap_meta_start(sbd_meta_start_t
*sm
)
831 if (sm
->sm_magic
== SBD_MAGIC
)
833 sm
->sm_magic
= BSWAP_64(sm
->sm_magic
);
834 sm
->sm_meta_size
= BSWAP_64(sm
->sm_meta_size
);
835 sm
->sm_meta_size_used
= BSWAP_64(sm
->sm_meta_size_used
);
836 sm
->sm_ver_major
= BSWAP_16(sm
->sm_ver_major
);
837 sm
->sm_ver_minor
= BSWAP_16(sm
->sm_ver_minor
);
838 sm
->sm_ver_subminor
= BSWAP_16(sm
->sm_ver_subminor
);
842 sbd_swap_section_hdr(sm_section_hdr_t
*sm
)
844 if (sm
->sms_data_order
== SMS_DATA_ORDER
)
846 sm
->sms_offset
= BSWAP_64(sm
->sms_offset
);
847 sm
->sms_size
= BSWAP_32(sm
->sms_size
);
848 sm
->sms_id
= BSWAP_16(sm
->sms_id
);
849 sm
->sms_chksum
+= SMS_DATA_ORDER
- sm
->sms_data_order
;
850 sm
->sms_data_order
= SMS_DATA_ORDER
;
854 sbd_swap_lu_info_1_0(sbd_lu_info_1_0_t
*sli
)
856 sbd_swap_section_hdr(&sli
->sli_sms_header
);
857 if (sli
->sli_data_order
== SMS_DATA_ORDER
)
859 sli
->sli_sms_header
.sms_chksum
+= SMS_DATA_ORDER
- sli
->sli_data_order
;
860 sli
->sli_data_order
= SMS_DATA_ORDER
;
861 sli
->sli_total_store_size
= BSWAP_64(sli
->sli_total_store_size
);
862 sli
->sli_total_meta_size
= BSWAP_64(sli
->sli_total_meta_size
);
863 sli
->sli_lu_data_offset
= BSWAP_64(sli
->sli_lu_data_offset
);
864 sli
->sli_lu_data_size
= BSWAP_64(sli
->sli_lu_data_size
);
865 sli
->sli_flags
= BSWAP_32(sli
->sli_flags
);
866 sli
->sli_blocksize
= BSWAP_16(sli
->sli_blocksize
);
870 sbd_swap_lu_info_1_1(sbd_lu_info_1_1_t
*sli
)
872 sbd_swap_section_hdr(&sli
->sli_sms_header
);
873 if (sli
->sli_data_order
== SMS_DATA_ORDER
)
875 sli
->sli_sms_header
.sms_chksum
+= SMS_DATA_ORDER
- sli
->sli_data_order
;
876 sli
->sli_data_order
= SMS_DATA_ORDER
;
877 sli
->sli_flags
= BSWAP_32(sli
->sli_flags
);
878 sli
->sli_lu_size
= BSWAP_64(sli
->sli_lu_size
);
879 sli
->sli_meta_fname_offset
= BSWAP_64(sli
->sli_meta_fname_offset
);
880 sli
->sli_data_fname_offset
= BSWAP_64(sli
->sli_data_fname_offset
);
881 sli
->sli_serial_offset
= BSWAP_64(sli
->sli_serial_offset
);
882 sli
->sli_alias_offset
= BSWAP_64(sli
->sli_alias_offset
);
883 sli
->sli_mgmt_url_offset
= BSWAP_64(sli
->sli_mgmt_url_offset
);
887 sbd_load_section_hdr(sbd_lu_t
*sl
, sm_section_hdr_t
*sms
)
893 for (st
= sl
->sl_meta_offset
+ sizeof (sbd_meta_start_t
);
894 st
< sl
->sl_meta_size_used
; st
+= h
.sms_size
) {
895 if ((ret
= sbd_read_meta(sl
, st
, sizeof (sm_section_hdr_t
),
896 (uint8_t *)&h
)) != SBD_SUCCESS
) {
899 if (h
.sms_data_order
!= SMS_DATA_ORDER
) {
900 sbd_swap_section_hdr(&h
);
902 if ((h
.sms_data_order
!= SMS_DATA_ORDER
) ||
903 (h
.sms_offset
!= st
) || (h
.sms_size
< sizeof (h
)) ||
904 ((st
+ h
.sms_size
) > sl
->sl_meta_size_used
)) {
905 return (SBD_META_CORRUPTED
);
907 if (h
.sms_id
== sms
->sms_id
) {
908 bcopy(&h
, sms
, sizeof (h
));
909 return (SBD_SUCCESS
);
913 return (SBD_NOT_FOUND
);
917 sbd_load_meta_start(sbd_lu_t
*sl
)
919 sbd_meta_start_t
*sm
;
922 /* Fake meta params initially */
923 sl
->sl_total_meta_size
= (uint64_t)-1;
924 sl
->sl_meta_size_used
= sl
->sl_meta_offset
+ sizeof (sbd_meta_start_t
);
926 sm
= kmem_zalloc(sizeof (*sm
), KM_SLEEP
);
927 ret
= sbd_read_meta(sl
, sl
->sl_meta_offset
, sizeof (*sm
),
929 if (ret
!= SBD_SUCCESS
) {
930 goto load_meta_start_failed
;
933 if (sm
->sm_magic
!= SBD_MAGIC
) {
934 sbd_swap_meta_start(sm
);
937 if ((sm
->sm_magic
!= SBD_MAGIC
) || (sbd_calc_sum((uint8_t *)sm
,
938 sizeof (*sm
) - 1) != sm
->sm_chksum
)) {
939 ret
= SBD_META_CORRUPTED
;
940 goto load_meta_start_failed
;
943 if (sm
->sm_ver_major
!= SBD_VER_MAJOR
) {
944 ret
= SBD_NOT_SUPPORTED
;
945 goto load_meta_start_failed
;
948 sl
->sl_total_meta_size
= sm
->sm_meta_size
;
949 sl
->sl_meta_size_used
= sm
->sm_meta_size_used
;
952 load_meta_start_failed
:
953 kmem_free(sm
, sizeof (*sm
));
958 sbd_write_meta_start(sbd_lu_t
*sl
, uint64_t meta_size
, uint64_t meta_size_used
)
960 sbd_meta_start_t
*sm
;
963 sm
= (sbd_meta_start_t
*)kmem_zalloc(sizeof (sbd_meta_start_t
),
966 sm
->sm_magic
= SBD_MAGIC
;
967 sm
->sm_meta_size
= meta_size
;
968 sm
->sm_meta_size_used
= meta_size_used
;
969 sm
->sm_ver_major
= SBD_VER_MAJOR
;
970 sm
->sm_ver_minor
= SBD_VER_MINOR
;
971 sm
->sm_ver_subminor
= SBD_VER_SUBMINOR
;
972 sm
->sm_chksum
= sbd_calc_sum((uint8_t *)sm
, sizeof (*sm
) - 1);
974 ret
= sbd_write_meta(sl
, sl
->sl_meta_offset
, sizeof (*sm
),
976 kmem_free(sm
, sizeof (*sm
));
982 sbd_read_meta_section(sbd_lu_t
*sl
, sm_section_hdr_t
**ppsms
, uint16_t sms_id
)
985 sm_section_hdr_t sms
;
988 mutex_enter(&sl
->sl_metadata_lock
);
989 if (((*ppsms
) == NULL
) || ((*ppsms
)->sms_offset
== 0)) {
990 bzero(&sms
, sizeof (sm_section_hdr_t
));
992 if ((ret
= sbd_load_section_hdr(sl
, &sms
)) != SBD_SUCCESS
) {
993 mutex_exit(&sl
->sl_metadata_lock
);
996 if ((*ppsms
) == NULL
) {
997 *ppsms
= (sm_section_hdr_t
*)kmem_zalloc(
998 sms
.sms_size
, KM_SLEEP
);
1001 bcopy(&sms
, *ppsms
, sizeof (sm_section_hdr_t
));
1005 ret
= sbd_read_meta(sl
, (*ppsms
)->sms_offset
, (*ppsms
)->sms_size
,
1006 (uint8_t *)(*ppsms
));
1007 if (ret
== SBD_SUCCESS
) {
1009 if ((*ppsms
)->sms_data_order
!= SMS_DATA_ORDER
)
1010 sbd_swap_section_hdr(*ppsms
);
1011 if ((*ppsms
)->sms_id
!= SMS_ID_UNUSED
) {
1012 s
= sbd_calc_section_sum(*ppsms
, (*ppsms
)->sms_size
);
1013 if (s
!= (*ppsms
)->sms_chksum
)
1014 ret
= SBD_META_CORRUPTED
;
1017 mutex_exit(&sl
->sl_metadata_lock
);
1019 if ((ret
!= SBD_SUCCESS
) && alloced
)
1020 kmem_free(*ppsms
, sms
.sms_size
);
1025 sbd_load_section_hdr_unbuffered(sbd_lu_t
*sl
, sm_section_hdr_t
*sms
)
1030 * Bypass buffering and re-read the meta data from permanent storage.
1032 if (sl
->sl_flags
& SL_ZFS_META
) {
1033 if ((ret
= sbd_open_zfs_meta(sl
)) != SBD_SUCCESS
) {
1037 /* Re-get the meta sizes into sl */
1038 if ((ret
= sbd_load_meta_start(sl
)) != SBD_SUCCESS
) {
1041 return (sbd_load_section_hdr(sl
, sms
));
1045 sbd_write_meta_section(sbd_lu_t
*sl
, sm_section_hdr_t
*sms
)
1049 uint64_t unused_start
;
1051 sbd_status_t write_meta_ret
= SBD_SUCCESS
;
1053 int meta_size_changed
= 0;
1054 sm_section_hdr_t sms_before_unused
= {0};
1056 mutex_enter(&sl
->sl_metadata_lock
);
1057 write_meta_section_again
:
1058 if (sms
->sms_offset
) {
1060 * If the section already exists and the size is the
1061 * same as this new data then overwrite in place. If
1062 * the sizes are different then mark the existing as
1063 * unused and look for free space.
1065 ret
= sbd_read_meta(sl
, sms
->sms_offset
, sizeof (t
),
1067 if (ret
!= SBD_SUCCESS
) {
1068 mutex_exit(&sl
->sl_metadata_lock
);
1071 if (t
.sms_data_order
!= SMS_DATA_ORDER
) {
1072 sbd_swap_section_hdr(&t
);
1074 if (t
.sms_id
!= sms
->sms_id
) {
1075 mutex_exit(&sl
->sl_metadata_lock
);
1076 return (SBD_INVALID_ARG
);
1078 if (t
.sms_size
== sms
->sms_size
) {
1079 ret
= sbd_write_meta(sl
, sms
->sms_offset
,
1080 sms
->sms_size
, (uint8_t *)sms
);
1081 mutex_exit(&sl
->sl_metadata_lock
);
1084 sms_before_unused
= t
;
1086 t
.sms_id
= SMS_ID_UNUSED
;
1088 * For unused sections we only use chksum of the header. for
1089 * all other sections, the chksum is for the entire section.
1091 t
.sms_chksum
= sbd_calc_section_sum(&t
, sizeof (t
));
1092 ret
= sbd_write_meta(sl
, t
.sms_offset
, sizeof (t
),
1094 if (ret
!= SBD_SUCCESS
) {
1095 mutex_exit(&sl
->sl_metadata_lock
);
1098 sms
->sms_offset
= 0;
1100 /* Section location is unknown, search for it. */
1101 t
.sms_id
= sms
->sms_id
;
1102 t
.sms_data_order
= SMS_DATA_ORDER
;
1103 ret
= sbd_load_section_hdr(sl
, &t
);
1104 if (ret
== SBD_SUCCESS
) {
1105 sms
->sms_offset
= t
.sms_offset
;
1107 sbd_calc_section_sum(sms
, sms
->sms_size
);
1108 goto write_meta_section_again
;
1109 } else if (ret
!= SBD_NOT_FOUND
) {
1110 mutex_exit(&sl
->sl_metadata_lock
);
1116 * At this point we know that section does not already exist.
1117 * Find space large enough to hold the section or grow meta if
1121 s
= 0; /* size of space found */
1124 * Search all sections for unused space of sufficient size.
1125 * The first one found is taken. Contiguous unused sections
1128 for (off
= sl
->sl_meta_offset
+ sizeof (sbd_meta_start_t
);
1129 off
< sl
->sl_meta_size_used
; off
+= t
.sms_size
) {
1130 ret
= sbd_read_meta(sl
, off
, sizeof (t
), (uint8_t *)&t
);
1131 if (ret
!= SBD_SUCCESS
) {
1132 mutex_exit(&sl
->sl_metadata_lock
);
1135 if (t
.sms_data_order
!= SMS_DATA_ORDER
)
1136 sbd_swap_section_hdr(&t
);
1137 if (t
.sms_size
== 0) {
1138 mutex_exit(&sl
->sl_metadata_lock
);
1139 return (SBD_META_CORRUPTED
);
1141 if (t
.sms_id
== SMS_ID_UNUSED
) {
1142 if (unused_start
== 0)
1145 * Calculate size of the unused space, break out
1146 * if it satisfies the requirement.
1148 s
= t
.sms_size
- unused_start
+ off
;
1149 if ((s
== sms
->sms_size
) || (s
>= (sms
->sms_size
+
1160 off
= (unused_start
== 0) ? sl
->sl_meta_size_used
: unused_start
;
1162 * If none found, how much room is at the end?
1163 * See if the data can be expanded.
1166 s
= sl
->sl_total_meta_size
- off
;
1167 if (s
>= sms
->sms_size
|| !(sl
->sl_flags
& SL_SHARED_META
)) {
1169 meta_size_changed
= 1;
1176 mutex_exit(&sl
->sl_metadata_lock
);
1177 return (SBD_ALLOC_FAILURE
);
1180 sms
->sms_offset
= off
;
1181 sms
->sms_chksum
= sbd_calc_section_sum(sms
, sms
->sms_size
);
1183 * Since we may have to write more than one section (current +
1184 * any unused), use a combined buffer.
1186 cb
= kmem_zalloc(s
, KM_SLEEP
);
1187 bcopy(sms
, cb
, sms
->sms_size
);
1188 if (s
> sms
->sms_size
) {
1189 t
.sms_offset
= off
+ sms
->sms_size
;
1190 t
.sms_size
= s
- sms
->sms_size
;
1191 t
.sms_id
= SMS_ID_UNUSED
;
1192 t
.sms_data_order
= SMS_DATA_ORDER
;
1193 t
.sms_chksum
= sbd_calc_section_sum(&t
, sizeof (t
));
1194 bcopy(&t
, cb
+ sms
->sms_size
, sizeof (t
));
1197 * Two write events & statuses take place. Failure writing the
1198 * meta section takes precedence, can possibly be rolled back,
1199 * & gets reported. Else return status from writing the meta start.
1201 ret
= SBD_SUCCESS
; /* Set a default, it's not always loaded below. */
1202 if (meta_size_changed
) {
1203 uint64_t old_meta_size
;
1204 uint64_t old_sz_used
= sl
->sl_meta_size_used
; /* save a copy */
1205 old_meta_size
= sl
->sl_total_meta_size
; /* save a copy */
1207 write_meta_ret
= sbd_write_meta(sl
, off
, s
, cb
);
1208 if (write_meta_ret
== SBD_SUCCESS
) {
1209 sl
->sl_meta_size_used
= off
+ s
;
1210 if (sl
->sl_total_meta_size
< sl
->sl_meta_size_used
) {
1211 uint64_t meta_align
=
1213 sl
->sl_meta_blocksize_shift
) - 1;
1214 sl
->sl_total_meta_size
=
1215 (sl
->sl_meta_size_used
+ meta_align
) &
1218 ret
= sbd_write_meta_start(sl
, sl
->sl_total_meta_size
,
1219 sl
->sl_meta_size_used
);
1220 if (ret
!= SBD_SUCCESS
) {
1221 sl
->sl_meta_size_used
= old_sz_used
;
1222 sl
->sl_total_meta_size
= old_meta_size
;
1225 sl
->sl_meta_size_used
= old_sz_used
;
1226 sl
->sl_total_meta_size
= old_meta_size
;
1229 write_meta_ret
= sbd_write_meta(sl
, off
, s
, cb
);
1231 if ((write_meta_ret
!= SBD_SUCCESS
) &&
1232 (sms_before_unused
.sms_offset
!= 0)) {
1233 sm_section_hdr_t new_sms
;
1234 sm_section_hdr_t
*unused_sms
;
1236 * On failure writing the meta section attempt to undo
1237 * the change to unused.
1238 * Re-read the meta data from permanent storage.
1239 * The section id can't exist for undo to be possible.
1240 * Read what should be the entire old section data and
1241 * insure the old data's still present by validating
1242 * against it's old checksum.
1244 new_sms
.sms_id
= sms
->sms_id
;
1245 new_sms
.sms_data_order
= SMS_DATA_ORDER
;
1246 if (sbd_load_section_hdr_unbuffered(sl
, &new_sms
) !=
1250 unused_sms
= kmem_zalloc(sms_before_unused
.sms_size
, KM_SLEEP
);
1251 if (sbd_read_meta(sl
, sms_before_unused
.sms_offset
,
1252 sms_before_unused
.sms_size
,
1253 (uint8_t *)unused_sms
) != SBD_SUCCESS
) {
1256 if (unused_sms
->sms_data_order
!= SMS_DATA_ORDER
) {
1257 sbd_swap_section_hdr(unused_sms
);
1259 if (unused_sms
->sms_id
!= SMS_ID_UNUSED
) {
1262 if (unused_sms
->sms_offset
!= sms_before_unused
.sms_offset
) {
1265 if (unused_sms
->sms_size
!= sms_before_unused
.sms_size
) {
1268 unused_sms
->sms_id
= sms_before_unused
.sms_id
;
1269 if (sbd_calc_section_sum(unused_sms
,
1270 sizeof (sm_section_hdr_t
)) !=
1271 sbd_calc_section_sum(&sms_before_unused
,
1272 sizeof (sm_section_hdr_t
))) {
1275 unused_sms
->sms_chksum
=
1276 sbd_calc_section_sum(unused_sms
, unused_sms
->sms_size
);
1277 if (unused_sms
->sms_chksum
!= sms_before_unused
.sms_chksum
) {
1280 (void) sbd_write_meta(sl
, unused_sms
->sms_offset
,
1281 sizeof (sm_section_hdr_t
), (uint8_t *)unused_sms
);
1284 mutex_exit(&sl
->sl_metadata_lock
);
1286 if (write_meta_ret
!= SBD_SUCCESS
) {
1287 return (write_meta_ret
);
1293 sbd_write_lu_info(sbd_lu_t
*sl
)
1295 sbd_lu_info_1_1_t
*sli
;
1298 char *zvol_name
= NULL
;
1301 mutex_enter(&sl
->sl_lock
);
1303 s
= sl
->sl_serial_no_size
;
1304 if ((sl
->sl_flags
& (SL_SHARED_META
| SL_ZFS_META
)) == 0) {
1305 if (sl
->sl_data_filename
) {
1306 s
+= strlen(sl
->sl_data_filename
) + 1;
1309 if (sl
->sl_flags
& SL_ZFS_META
) {
1310 zvol_name
= sbd_get_zvol_name(sl
);
1311 s
+= strlen(zvol_name
) + 1;
1314 s
+= strlen(sl
->sl_alias
) + 1;
1316 if (sl
->sl_mgmt_url
) {
1317 s
+= strlen(sl
->sl_mgmt_url
) + 1;
1319 sli
= (sbd_lu_info_1_1_t
*)kmem_zalloc(sizeof (*sli
) + s
, KM_SLEEP
);
1321 if ((sl
->sl_flags
& (SL_SHARED_META
| SL_ZFS_META
)) == 0) {
1322 sli
->sli_flags
|= SLI_SEPARATE_META
;
1323 (void) strcpy((char *)p
, sl
->sl_data_filename
);
1324 sli
->sli_data_fname_offset
=
1325 (uintptr_t)p
- (uintptr_t)sli
->sli_buf
;
1326 sli
->sli_flags
|= SLI_DATA_FNAME_VALID
;
1327 p
+= strlen(sl
->sl_data_filename
) + 1;
1329 if (sl
->sl_flags
& SL_ZFS_META
) {
1330 (void) strcpy((char *)p
, zvol_name
);
1331 sli
->sli_meta_fname_offset
=
1332 (uintptr_t)p
- (uintptr_t)sli
->sli_buf
;
1333 sli
->sli_flags
|= SLI_META_FNAME_VALID
| SLI_ZFS_META
;
1334 p
+= strlen(zvol_name
) + 1;
1335 kmem_free(zvol_name
, strlen(zvol_name
) + 1);
1339 (void) strcpy((char *)p
, sl
->sl_alias
);
1340 sli
->sli_alias_offset
=
1341 (uintptr_t)p
- (uintptr_t)sli
->sli_buf
;
1342 sli
->sli_flags
|= SLI_ALIAS_VALID
;
1343 p
+= strlen(sl
->sl_alias
) + 1;
1345 if (sl
->sl_mgmt_url
) {
1346 (void) strcpy((char *)p
, sl
->sl_mgmt_url
);
1347 sli
->sli_mgmt_url_offset
=
1348 (uintptr_t)p
- (uintptr_t)sli
->sli_buf
;
1349 sli
->sli_flags
|= SLI_MGMT_URL_VALID
;
1350 p
+= strlen(sl
->sl_mgmt_url
) + 1;
1352 if (sl
->sl_flags
& SL_WRITE_PROTECTED
) {
1353 sli
->sli_flags
|= SLI_WRITE_PROTECTED
;
1355 if (sl
->sl_flags
& SL_SAVED_WRITE_CACHE_DISABLE
) {
1356 sli
->sli_flags
|= SLI_WRITEBACK_CACHE_DISABLE
;
1358 if (sl
->sl_flags
& SL_VID_VALID
) {
1359 bcopy(sl
->sl_vendor_id
, sli
->sli_vid
, 8);
1360 sli
->sli_flags
|= SLI_VID_VALID
;
1362 if (sl
->sl_flags
& SL_PID_VALID
) {
1363 bcopy(sl
->sl_product_id
, sli
->sli_pid
, 16);
1364 sli
->sli_flags
|= SLI_PID_VALID
;
1366 if (sl
->sl_flags
& SL_REV_VALID
) {
1367 bcopy(sl
->sl_revision
, sli
->sli_rev
, 4);
1368 sli
->sli_flags
|= SLI_REV_VALID
;
1370 if (sl
->sl_serial_no_size
) {
1371 bcopy(sl
->sl_serial_no
, p
, sl
->sl_serial_no_size
);
1372 sli
->sli_serial_size
= sl
->sl_serial_no_size
;
1373 sli
->sli_serial_offset
=
1374 (uintptr_t)p
- (uintptr_t)sli
->sli_buf
;
1375 sli
->sli_flags
|= SLI_SERIAL_VALID
;
1376 p
+= sli
->sli_serial_size
;
1378 sli
->sli_lu_size
= sl
->sl_lu_size
;
1379 sli
->sli_data_blocksize_shift
= sl
->sl_data_blocksize_shift
;
1380 sli
->sli_data_order
= SMS_DATA_ORDER
;
1381 bcopy(sl
->sl_device_id
, sli
->sli_device_id
, 20);
1383 sli
->sli_sms_header
.sms_size
= sizeof (*sli
) + s
;
1384 sli
->sli_sms_header
.sms_id
= SMS_ID_LU_INFO_1_1
;
1385 sli
->sli_sms_header
.sms_data_order
= SMS_DATA_ORDER
;
1387 mutex_exit(&sl
->sl_lock
);
1388 ret
= sbd_write_meta_section(sl
, (sm_section_hdr_t
*)sli
);
1389 kmem_free(sli
, sizeof (*sli
) + s
);
1394 * Will scribble SL_UNMAP_ENABLED into sl_flags if we succeed.
1397 do_unmap_setup(sbd_lu_t
*sl
)
1399 ASSERT((sl
->sl_flags
& SL_UNMAP_ENABLED
) == 0);
1401 if ((sl
->sl_flags
& SL_ZFS_META
) == 0)
1402 return; /* No UNMAP for you. */
1404 sl
->sl_flags
|= SL_UNMAP_ENABLED
;
1408 sbd_populate_and_register_lu(sbd_lu_t
*sl
, uint32_t *err_ret
)
1410 stmf_lu_t
*lu
= sl
->sl_lu
;
1415 lu
->lu_id
= (scsi_devid_desc_t
*)sl
->sl_device_id
;
1417 lu
->lu_alias
= sl
->sl_alias
;
1419 lu
->lu_alias
= sl
->sl_name
;
1421 if (sl
->sl_access_state
== SBD_LU_STANDBY
) {
1422 /* call set access state */
1423 ret
= stmf_set_lu_access(lu
, STMF_LU_STANDBY
);
1424 if (ret
!= STMF_SUCCESS
) {
1425 *err_ret
= SBD_RET_ACCESS_STATE_FAILED
;
1429 /* set proxy_reg_cb_arg to meta filename */
1430 if (sl
->sl_meta_filename
) {
1431 lu
->lu_proxy_reg_arg
= sl
->sl_meta_filename
;
1432 lu
->lu_proxy_reg_arg_len
= strlen(sl
->sl_meta_filename
) + 1;
1434 lu
->lu_proxy_reg_arg
= sl
->sl_data_filename
;
1435 lu
->lu_proxy_reg_arg_len
= strlen(sl
->sl_data_filename
) + 1;
1438 lu
->lu_task_alloc
= sbd_task_alloc
;
1439 lu
->lu_new_task
= sbd_new_task
;
1440 lu
->lu_dbuf_xfer_done
= sbd_dbuf_xfer_done
;
1441 lu
->lu_send_status_done
= sbd_send_status_done
;
1442 lu
->lu_task_free
= sbd_task_free
;
1443 lu
->lu_abort
= sbd_abort
;
1444 lu
->lu_dbuf_free
= sbd_dbuf_free
;
1445 lu
->lu_ctl
= sbd_ctl
;
1446 lu
->lu_info
= sbd_info
;
1447 sl
->sl_state
= STMF_STATE_OFFLINE
;
1449 if ((ret
= stmf_register_lu(lu
)) != STMF_SUCCESS
) {
1450 stmf_trace(0, "Failed to register with framework, ret=%llx",
1452 if (ret
== STMF_ALREADY
) {
1453 *err_ret
= SBD_RET_GUID_ALREADY_REGISTERED
;
1463 sbd_open_data_file(sbd_lu_t
*sl
, uint32_t *err_ret
, int lu_size_valid
,
1464 int vp_valid
, int keep_open
)
1469 uint64_t supported_size
;
1472 struct dk_cinfo dki
;
1475 mutex_enter(&sl
->sl_lock
);
1479 if (sl
->sl_data_filename
[0] != '/') {
1480 *err_ret
= SBD_RET_DATA_PATH_NOT_ABSOLUTE
;
1481 mutex_exit(&sl
->sl_lock
);
1484 if ((ret
= lookupname(sl
->sl_data_filename
, UIO_SYSSPACE
, FOLLOW
,
1485 NULLVPP
, &sl
->sl_data_vp
)) != 0) {
1486 *err_ret
= SBD_RET_DATA_FILE_LOOKUP_FAILED
;
1487 mutex_exit(&sl
->sl_lock
);
1490 sl
->sl_data_vtype
= vt
= sl
->sl_data_vp
->v_type
;
1491 VN_RELE(sl
->sl_data_vp
);
1492 if ((vt
!= VREG
) && (vt
!= VCHR
) && (vt
!= VBLK
)) {
1493 *err_ret
= SBD_RET_WRONG_DATA_FILE_TYPE
;
1494 mutex_exit(&sl
->sl_lock
);
1497 if (sl
->sl_flags
& SL_WRITE_PROTECTED
) {
1498 flag
= FREAD
| FOFFMAX
;
1500 flag
= FREAD
| FWRITE
| FOFFMAX
| FEXCL
;
1502 if ((ret
= vn_open(sl
->sl_data_filename
, UIO_SYSSPACE
, flag
, 0,
1503 &sl
->sl_data_vp
, 0, 0)) != 0) {
1504 *err_ret
= SBD_RET_DATA_FILE_OPEN_FAILED
;
1505 mutex_exit(&sl
->sl_lock
);
1509 vattr
.va_mask
= VATTR_SIZE
;
1510 if ((ret
= fop_getattr(sl
->sl_data_vp
, &vattr
, 0, CRED(), NULL
)) != 0) {
1511 *err_ret
= SBD_RET_DATA_FILE_GETATTR_FAILED
;
1512 goto odf_close_data_and_exit
;
1514 if ((vt
!= VREG
) && (vattr
.va_size
== 0)) {
1516 * Its a zero byte block or char device. This cannot be
1519 *err_ret
= SBD_RET_WRONG_DATA_FILE_TYPE
;
1521 goto odf_close_data_and_exit
;
1523 /* sl_data_readable size includes any metadata. */
1524 sl
->sl_data_readable_size
= vattr
.va_size
;
1526 if (fop_pathconf(sl
->sl_data_vp
, _PC_FILESIZEBITS
, &nbits
,
1527 CRED(), NULL
) != 0) {
1530 /* nbits cannot be greater than 64 */
1531 sl
->sl_data_fs_nbits
= (uint8_t)nbits
;
1532 if (lu_size_valid
) {
1533 sl
->sl_total_data_size
= sl
->sl_lu_size
;
1534 if (sl
->sl_flags
& SL_SHARED_META
) {
1535 sl
->sl_total_data_size
+= SHARED_META_DATA_SIZE
;
1537 if ((nbits
> 0) && (nbits
< 64)) {
1539 * The expression below is correct only if nbits is
1540 * positive and less than 64.
1542 supported_size
= (((uint64_t)1) << nbits
) - 1;
1543 if (sl
->sl_total_data_size
> supported_size
) {
1544 *err_ret
= SBD_RET_SIZE_NOT_SUPPORTED_BY_FS
;
1546 goto odf_close_data_and_exit
;
1550 sl
->sl_total_data_size
= vattr
.va_size
;
1551 if (sl
->sl_flags
& SL_SHARED_META
) {
1552 if (vattr
.va_size
> SHARED_META_DATA_SIZE
) {
1553 sl
->sl_lu_size
= vattr
.va_size
-
1554 SHARED_META_DATA_SIZE
;
1556 *err_ret
= SBD_RET_FILE_SIZE_ERROR
;
1558 goto odf_close_data_and_exit
;
1561 sl
->sl_lu_size
= vattr
.va_size
;
1564 if (sl
->sl_lu_size
< SBD_MIN_LU_SIZE
) {
1565 *err_ret
= SBD_RET_FILE_SIZE_ERROR
;
1567 goto odf_close_data_and_exit
;
1569 if (sl
->sl_lu_size
&
1570 ((((uint64_t)1) << sl
->sl_data_blocksize_shift
) - 1)) {
1571 *err_ret
= SBD_RET_FILE_ALIGN_ERROR
;
1573 goto odf_close_data_and_exit
;
1576 * Get the minor device for direct zvol access
1578 if (sl
->sl_flags
& SL_ZFS_META
) {
1579 if ((ret
= fop_ioctl(sl
->sl_data_vp
, DKIOCINFO
, (intptr_t)&dki
,
1580 FKIOCTL
, kcred
, &unused
, NULL
)) != 0) {
1581 cmn_err(CE_WARN
, "ioctl(DKIOCINFO) failed %d", ret
);
1582 /* zvol reserves 0, so this would fail later */
1583 sl
->sl_zvol_minor
= 0;
1585 sl
->sl_zvol_minor
= dki
.dki_unit
;
1586 if (sbd_zvol_get_volume_params(sl
) == 0)
1587 sl
->sl_flags
|= SL_CALL_ZVOL
;
1590 sl
->sl_flags
|= SL_MEDIA_LOADED
;
1591 mutex_exit(&sl
->sl_lock
);
1594 odf_close_data_and_exit
:
1596 (void) fop_close(sl
->sl_data_vp
, flag
, 1, 0, CRED(), NULL
);
1597 VN_RELE(sl
->sl_data_vp
);
1599 mutex_exit(&sl
->sl_lock
);
1604 sbd_close_lu(sbd_lu_t
*sl
)
1608 if (((sl
->sl_flags
& SL_SHARED_META
) == 0) &&
1609 (sl
->sl_flags
& SL_META_OPENED
)) {
1610 if (sl
->sl_flags
& SL_ZFS_META
) {
1611 rw_destroy(&sl
->sl_zfs_meta_lock
);
1612 if (sl
->sl_zfs_meta
) {
1613 kmem_free(sl
->sl_zfs_meta
, ZAP_MAXVALUELEN
/ 2);
1614 sl
->sl_zfs_meta
= NULL
;
1617 flag
= FREAD
| FWRITE
| FOFFMAX
| FEXCL
;
1618 (void) fop_close(sl
->sl_meta_vp
, flag
, 1, 0,
1620 VN_RELE(sl
->sl_meta_vp
);
1622 sl
->sl_flags
&= ~SL_META_OPENED
;
1624 if (sl
->sl_flags
& SL_MEDIA_LOADED
) {
1625 if (sl
->sl_flags
& SL_WRITE_PROTECTED
) {
1626 flag
= FREAD
| FOFFMAX
;
1628 flag
= FREAD
| FWRITE
| FOFFMAX
| FEXCL
;
1630 (void) fop_close(sl
->sl_data_vp
, flag
, 1, 0, CRED(), NULL
);
1631 VN_RELE(sl
->sl_data_vp
);
1632 sl
->sl_flags
&= ~SL_MEDIA_LOADED
;
1633 if (sl
->sl_flags
& SL_SHARED_META
) {
1634 sl
->sl_flags
&= ~SL_META_OPENED
;
1640 sbd_set_lu_standby(sbd_set_lu_standby_t
*stlu
, uint32_t *err_ret
)
1644 stmf_status_t stret
;
1645 uint8_t old_access_state
;
1647 sret
= sbd_find_and_lock_lu(stlu
->stlu_guid
, NULL
,
1648 SL_OP_MODIFY_LU
, &sl
);
1649 if (sret
!= SBD_SUCCESS
) {
1650 if (sret
== SBD_BUSY
) {
1651 *err_ret
= SBD_RET_LU_BUSY
;
1653 } else if (sret
== SBD_NOT_FOUND
) {
1654 *err_ret
= SBD_RET_NOT_FOUND
;
1657 *err_ret
= SBD_RET_ACCESS_STATE_FAILED
;
1661 old_access_state
= sl
->sl_access_state
;
1662 sl
->sl_access_state
= SBD_LU_TRANSITION_TO_STANDBY
;
1663 stret
= stmf_set_lu_access((stmf_lu_t
*)sl
->sl_lu
, STMF_LU_STANDBY
);
1664 if (stret
!= STMF_SUCCESS
) {
1665 sl
->sl_trans_op
= SL_OP_NONE
;
1666 *err_ret
= SBD_RET_ACCESS_STATE_FAILED
;
1667 sl
->sl_access_state
= old_access_state
;
1672 * acquire the writer lock here to ensure we're not pulling
1673 * the rug from the vn_rdwr to the backing store
1675 rw_enter(&sl
->sl_access_state_lock
, RW_WRITER
);
1677 rw_exit(&sl
->sl_access_state_lock
);
1679 sl
->sl_trans_op
= SL_OP_NONE
;
1684 sbd_close_delete_lu(sbd_lu_t
*sl
, int ret
)
1688 * acquire the writer lock here to ensure we're not pulling
1689 * the rug from the vn_rdwr to the backing store
1691 rw_enter(&sl
->sl_access_state_lock
, RW_WRITER
);
1693 rw_exit(&sl
->sl_access_state_lock
);
1695 if (sl
->sl_flags
& SL_LINKED
)
1697 mutex_destroy(&sl
->sl_metadata_lock
);
1698 mutex_destroy(&sl
->sl_lock
);
1699 rw_destroy(&sl
->sl_pgr
->pgr_lock
);
1700 rw_destroy(&sl
->sl_access_state_lock
);
1701 if (sl
->sl_serial_no_alloc_size
) {
1702 kmem_free(sl
->sl_serial_no
, sl
->sl_serial_no_alloc_size
);
1704 if (sl
->sl_data_fname_alloc_size
) {
1705 kmem_free(sl
->sl_data_filename
, sl
->sl_data_fname_alloc_size
);
1707 if (sl
->sl_alias_alloc_size
) {
1708 kmem_free(sl
->sl_alias
, sl
->sl_alias_alloc_size
);
1710 if (sl
->sl_mgmt_url_alloc_size
) {
1711 kmem_free(sl
->sl_mgmt_url
, sl
->sl_mgmt_url_alloc_size
);
1713 stmf_free(sl
->sl_lu
);
1718 sbd_create_register_lu(sbd_create_and_reg_lu_t
*slu
, int struct_sz
,
1733 sz
= struct_sz
- sizeof (sbd_create_and_reg_lu_t
) + 8 + 1;
1737 /* Lets validate various offsets */
1738 if (((slu
->slu_meta_fname_valid
) &&
1739 (slu
->slu_meta_fname_off
>= sz
)) ||
1740 (slu
->slu_data_fname_off
>= sz
) ||
1741 ((slu
->slu_alias_valid
) &&
1742 (slu
->slu_alias_off
>= sz
)) ||
1743 ((slu
->slu_mgmt_url_valid
) &&
1744 (slu
->slu_mgmt_url_off
>= sz
)) ||
1745 ((slu
->slu_serial_valid
) &&
1746 ((slu
->slu_serial_off
+ slu
->slu_serial_size
) >= sz
))) {
1750 namebuf
= kmem_zalloc(sz
, KM_SLEEP
);
1751 bcopy(slu
->slu_buf
, namebuf
, sz
- 1);
1752 namebuf
[sz
- 1] = 0;
1754 alloc_sz
= sizeof (sbd_lu_t
) + sizeof (sbd_pgr_t
);
1755 if (slu
->slu_meta_fname_valid
) {
1756 alloc_sz
+= strlen(namebuf
+ slu
->slu_meta_fname_off
) + 1;
1758 alloc_sz
+= strlen(namebuf
+ slu
->slu_data_fname_off
) + 1;
1759 if (slu
->slu_alias_valid
) {
1760 alloc_sz
+= strlen(namebuf
+ slu
->slu_alias_off
) + 1;
1762 if (slu
->slu_mgmt_url_valid
) {
1763 alloc_sz
+= strlen(namebuf
+ slu
->slu_mgmt_url_off
) + 1;
1765 if (slu
->slu_serial_valid
) {
1766 alloc_sz
+= slu
->slu_serial_size
;
1769 lu
= (stmf_lu_t
*)stmf_alloc(STMF_STRUCT_STMF_LU
, alloc_sz
, 0);
1771 kmem_free(namebuf
, sz
);
1774 sl
= (sbd_lu_t
*)lu
->lu_provider_private
;
1775 bzero(sl
, alloc_sz
);
1777 sl
->sl_alloc_size
= alloc_sz
;
1778 sl
->sl_pgr
= (sbd_pgr_t
*)(sl
+ 1);
1779 rw_init(&sl
->sl_pgr
->pgr_lock
, NULL
, RW_DRIVER
, NULL
);
1780 mutex_init(&sl
->sl_lock
, NULL
, MUTEX_DRIVER
, NULL
);
1781 mutex_init(&sl
->sl_metadata_lock
, NULL
, MUTEX_DRIVER
, NULL
);
1782 rw_init(&sl
->sl_access_state_lock
, NULL
, RW_DRIVER
, NULL
);
1783 p
= ((char *)sl
) + sizeof (sbd_lu_t
) + sizeof (sbd_pgr_t
);
1784 sl
->sl_data_filename
= p
;
1785 (void) strcpy(sl
->sl_data_filename
, namebuf
+ slu
->slu_data_fname_off
);
1786 p
+= strlen(sl
->sl_data_filename
) + 1;
1787 sl
->sl_meta_offset
= SBD_META_OFFSET
;
1788 sl
->sl_access_state
= SBD_LU_ACTIVE
;
1789 if (slu
->slu_meta_fname_valid
) {
1790 sl
->sl_alias
= sl
->sl_name
= sl
->sl_meta_filename
= p
;
1791 (void) strcpy(sl
->sl_meta_filename
, namebuf
+
1792 slu
->slu_meta_fname_off
);
1793 p
+= strlen(sl
->sl_meta_filename
) + 1;
1795 sl
->sl_alias
= sl
->sl_name
= sl
->sl_data_filename
;
1796 if (sbd_is_zvol(sl
->sl_data_filename
)) {
1797 sl
->sl_flags
|= SL_ZFS_META
;
1798 sl
->sl_meta_offset
= 0;
1800 sl
->sl_flags
|= SL_SHARED_META
;
1801 sl
->sl_data_offset
= SHARED_META_DATA_SIZE
;
1802 sl
->sl_total_meta_size
= SHARED_META_DATA_SIZE
;
1803 sl
->sl_meta_size_used
= 0;
1806 if (slu
->slu_alias_valid
) {
1808 (void) strcpy(p
, namebuf
+ slu
->slu_alias_off
);
1809 p
+= strlen(sl
->sl_alias
) + 1;
1811 if (slu
->slu_mgmt_url_valid
) {
1812 sl
->sl_mgmt_url
= p
;
1813 (void) strcpy(p
, namebuf
+ slu
->slu_mgmt_url_off
);
1814 p
+= strlen(sl
->sl_mgmt_url
) + 1;
1816 if (slu
->slu_serial_valid
) {
1817 sl
->sl_serial_no
= (uint8_t *)p
;
1818 bcopy(namebuf
+ slu
->slu_serial_off
, sl
->sl_serial_no
,
1819 slu
->slu_serial_size
);
1820 sl
->sl_serial_no_size
= slu
->slu_serial_size
;
1821 p
+= slu
->slu_serial_size
;
1823 kmem_free(namebuf
, sz
);
1824 if (slu
->slu_vid_valid
) {
1825 bcopy(slu
->slu_vid
, sl
->sl_vendor_id
, 8);
1826 sl
->sl_flags
|= SL_VID_VALID
;
1828 if (slu
->slu_pid_valid
) {
1829 bcopy(slu
->slu_pid
, sl
->sl_product_id
, 16);
1830 sl
->sl_flags
|= SL_PID_VALID
;
1832 if (slu
->slu_rev_valid
) {
1833 bcopy(slu
->slu_rev
, sl
->sl_revision
, 4);
1834 sl
->sl_flags
|= SL_REV_VALID
;
1836 if (slu
->slu_write_protected
) {
1837 sl
->sl_flags
|= SL_WRITE_PROTECTED
;
1839 if (slu
->slu_blksize_valid
) {
1840 if (!ISP2(slu
->slu_blksize
) ||
1841 (slu
->slu_blksize
> (32 * 1024)) ||
1842 (slu
->slu_blksize
== 0)) {
1843 *err_ret
= SBD_RET_INVALID_BLKSIZE
;
1847 while ((1 << sl
->sl_data_blocksize_shift
) != slu
->slu_blksize
) {
1848 sl
->sl_data_blocksize_shift
++;
1851 sl
->sl_data_blocksize_shift
= 9; /* 512 by default */
1852 slu
->slu_blksize
= 512;
1855 /* Now lets start creating meta */
1856 sl
->sl_trans_op
= SL_OP_CREATE_REGISTER_LU
;
1857 if (sbd_link_lu(sl
) != SBD_SUCCESS
) {
1858 *err_ret
= SBD_RET_FILE_ALREADY_REGISTERED
;
1863 /* 1st focus on the data store */
1864 if (slu
->slu_lu_size_valid
) {
1865 sl
->sl_lu_size
= slu
->slu_lu_size
;
1867 ret
= sbd_open_data_file(sl
, err_ret
, slu
->slu_lu_size_valid
, 0, 0);
1868 slu
->slu_ret_filesize_nbits
= sl
->sl_data_fs_nbits
;
1869 slu
->slu_lu_size
= sl
->sl_lu_size
;
1875 * Check if we were explicitly asked to disable/enable write
1876 * cache on the device, otherwise get current device setting.
1878 if (slu
->slu_writeback_cache_disable_valid
) {
1879 if (slu
->slu_writeback_cache_disable
) {
1881 * Set write cache disable on the device. If it fails,
1882 * we'll support it using sync/flush.
1884 (void) sbd_wcd_set(1, sl
);
1888 * Set write cache enable on the device. If it fails,
1891 if (sbd_wcd_set(0, sl
) != SBD_SUCCESS
) {
1892 *err_ret
= SBD_RET_WRITE_CACHE_SET_FAILED
;
1898 sbd_wcd_get(&wcd
, sl
);
1902 sl
->sl_flags
|= SL_WRITEBACK_CACHE_DISABLE
|
1903 SL_SAVED_WRITE_CACHE_DISABLE
;
1906 if (sl
->sl_flags
& SL_SHARED_META
) {
1907 goto over_meta_open
;
1909 if (sl
->sl_flags
& SL_ZFS_META
) {
1910 if (sbd_create_zfs_meta_object(sl
) != SBD_SUCCESS
) {
1911 *err_ret
= SBD_RET_ZFS_META_CREATE_FAILED
;
1915 sl
->sl_meta_blocksize_shift
= 0;
1916 goto over_meta_create
;
1918 if ((ret
= lookupname(sl
->sl_meta_filename
, UIO_SYSSPACE
, FOLLOW
,
1919 NULLVPP
, &sl
->sl_meta_vp
)) != 0) {
1920 *err_ret
= SBD_RET_META_FILE_LOOKUP_FAILED
;
1923 sl
->sl_meta_vtype
= vt
= sl
->sl_meta_vp
->v_type
;
1924 VN_RELE(sl
->sl_meta_vp
);
1925 if ((vt
!= VREG
) && (vt
!= VCHR
) && (vt
!= VBLK
)) {
1926 *err_ret
= SBD_RET_WRONG_META_FILE_TYPE
;
1931 sl
->sl_meta_blocksize_shift
= 0;
1933 sl
->sl_meta_blocksize_shift
= 9;
1935 flag
= FREAD
| FWRITE
| FOFFMAX
| FEXCL
;
1936 if ((ret
= vn_open(sl
->sl_meta_filename
, UIO_SYSSPACE
, flag
, 0,
1937 &sl
->sl_meta_vp
, 0, 0)) != 0) {
1938 *err_ret
= SBD_RET_META_FILE_OPEN_FAILED
;
1942 sl
->sl_total_meta_size
= sl
->sl_meta_offset
+ sizeof (sbd_meta_start_t
);
1943 sl
->sl_total_meta_size
+=
1944 (((uint64_t)1) << sl
->sl_meta_blocksize_shift
) - 1;
1945 sl
->sl_total_meta_size
&=
1946 ~((((uint64_t)1) << sl
->sl_meta_blocksize_shift
) - 1);
1947 sl
->sl_meta_size_used
= 0;
1949 sl
->sl_flags
|= SL_META_OPENED
;
1951 sl
->sl_device_id
[3] = 16;
1952 if (slu
->slu_guid_valid
) {
1953 sl
->sl_device_id
[0] = 0xf1;
1954 sl
->sl_device_id
[1] = 3;
1955 sl
->sl_device_id
[2] = 0;
1956 bcopy(slu
->slu_guid
, sl
->sl_device_id
+ 4, 16);
1958 if (slu
->slu_host_id_valid
)
1959 hid
= slu
->slu_host_id
;
1960 if (!slu
->slu_company_id_valid
)
1961 slu
->slu_company_id
= COMPANY_ID_SUN
;
1962 if (stmf_scsilib_uniq_lu_id2(slu
->slu_company_id
, hid
,
1963 (scsi_devid_desc_t
*)&sl
->sl_device_id
[0]) !=
1965 *err_ret
= SBD_RET_META_CREATION_FAILED
;
1969 bcopy(sl
->sl_device_id
+ 4, slu
->slu_guid
, 16);
1972 /* Lets create the meta now */
1973 mutex_enter(&sl
->sl_metadata_lock
);
1974 if (sbd_write_meta_start(sl
, sl
->sl_total_meta_size
,
1975 sizeof (sbd_meta_start_t
)) != SBD_SUCCESS
) {
1976 mutex_exit(&sl
->sl_metadata_lock
);
1977 *err_ret
= SBD_RET_META_CREATION_FAILED
;
1981 mutex_exit(&sl
->sl_metadata_lock
);
1982 sl
->sl_meta_size_used
= sl
->sl_meta_offset
+ sizeof (sbd_meta_start_t
);
1984 if (sbd_write_lu_info(sl
) != SBD_SUCCESS
) {
1985 *err_ret
= SBD_RET_META_CREATION_FAILED
;
1990 if (sbd_pgr_meta_init(sl
) != SBD_SUCCESS
) {
1991 *err_ret
= SBD_RET_META_CREATION_FAILED
;
1997 * Update the zvol separately as this need only be called upon
1998 * completion of the metadata initialization.
2000 if (sl
->sl_flags
& SL_ZFS_META
) {
2001 if (sbd_update_zfs_prop(sl
) != SBD_SUCCESS
) {
2002 *err_ret
= SBD_RET_META_CREATION_FAILED
;
2008 ret
= sbd_populate_and_register_lu(sl
, err_ret
);
2013 sl
->sl_trans_op
= SL_OP_NONE
;
2014 atomic_inc_32(&sbd_lu_count
);
2018 return (sbd_close_delete_lu(sl
, ret
));
2022 sbd_proxy_msg(uint8_t *luid
, void *proxy_arg
, uint32_t proxy_arg_len
,
2026 case STMF_MSG_LU_ACTIVE
:
2027 return (sbd_proxy_reg_lu(luid
, proxy_arg
,
2029 case STMF_MSG_LU_REGISTER
:
2030 return (sbd_proxy_reg_lu(luid
, proxy_arg
,
2032 case STMF_MSG_LU_DEREGISTER
:
2033 return (sbd_proxy_dereg_lu(luid
, proxy_arg
,
2036 return (STMF_INVALID_ARG
);
2042 * register a standby logical unit
2043 * proxy_reg_arg contains the meta filename
2046 sbd_proxy_reg_lu(uint8_t *luid
, void *proxy_reg_arg
, uint32_t proxy_reg_arg_len
)
2050 sbd_create_standby_lu_t
*stlu
;
2052 uint32_t err_ret
= 0;
2053 stmf_status_t stret
= STMF_SUCCESS
;
2056 return (STMF_INVALID_ARG
);
2060 sret
= sbd_find_and_lock_lu(luid
, NULL
, SL_OP_MODIFY_LU
, &sl
);
2061 } while (sret
== SBD_BUSY
);
2063 if (sret
== SBD_NOT_FOUND
) {
2064 alloc_sz
= sizeof (*stlu
) + proxy_reg_arg_len
- 8;
2065 stlu
= (sbd_create_standby_lu_t
*)kmem_zalloc(alloc_sz
,
2067 bcopy(luid
, stlu
->stlu_guid
, 16);
2068 if (proxy_reg_arg_len
) {
2069 bcopy(proxy_reg_arg
, stlu
->stlu_meta_fname
,
2071 stlu
->stlu_meta_fname_size
= proxy_reg_arg_len
;
2073 if (sbd_create_standby_lu(stlu
, &err_ret
) != 0) {
2075 "Unable to create standby logical unit for %s",
2076 stlu
->stlu_meta_fname
);
2077 stret
= STMF_FAILURE
;
2079 kmem_free(stlu
, alloc_sz
);
2081 } else if (sret
== SBD_SUCCESS
) {
2083 * if the lu is already registered, then the lu should now
2084 * be in standby mode
2087 if (sl
->sl_access_state
!= SBD_LU_STANDBY
) {
2088 mutex_enter(&sl
->sl_lock
);
2089 sl
->sl_access_state
= SBD_LU_STANDBY
;
2090 for (it
= sl
->sl_it_list
; it
!= NULL
;
2091 it
= it
->sbd_it_next
) {
2092 it
->sbd_it_ua_conditions
|=
2093 SBD_UA_ASYMMETRIC_ACCESS_CHANGED
;
2095 ~SBD_IT_HAS_SCSI2_RESERVATION
;
2096 sl
->sl_flags
&= ~SL_LU_HAS_SCSI2_RESERVATION
;
2098 mutex_exit(&sl
->sl_lock
);
2101 sl
->sl_trans_op
= SL_OP_NONE
;
2103 cmn_err(CE_WARN
, "could not find and lock logical unit");
2104 stret
= STMF_FAILURE
;
2112 sbd_proxy_dereg_lu(uint8_t *luid
, void *proxy_reg_arg
,
2113 uint32_t proxy_reg_arg_len
)
2115 sbd_delete_lu_t dlu
= {0};
2119 cmn_err(CE_WARN
, "de-register lu request had null luid");
2120 return (STMF_INVALID_ARG
);
2123 bcopy(luid
, &dlu
.dlu_guid
, 16);
2125 if (sbd_delete_lu(&dlu
, (int)sizeof (dlu
), &err_ret
) != 0) {
2126 cmn_err(CE_WARN
, "failed to delete de-register lu request");
2127 return (STMF_FAILURE
);
2130 return (STMF_SUCCESS
);
2134 sbd_create_standby_lu(sbd_create_standby_lu_t
*slu
, uint32_t *err_ret
)
2141 alloc_sz
= sizeof (sbd_lu_t
) + sizeof (sbd_pgr_t
) +
2142 slu
->stlu_meta_fname_size
;
2143 lu
= (stmf_lu_t
*)stmf_alloc(STMF_STRUCT_STMF_LU
, alloc_sz
, 0);
2147 sl
= (sbd_lu_t
*)lu
->lu_provider_private
;
2148 bzero(sl
, alloc_sz
);
2150 sl
->sl_alloc_size
= alloc_sz
;
2152 sl
->sl_pgr
= (sbd_pgr_t
*)(sl
+ 1);
2153 sl
->sl_meta_filename
= ((char *)sl
) + sizeof (sbd_lu_t
) +
2156 if (slu
->stlu_meta_fname_size
> 0) {
2157 (void) strcpy(sl
->sl_meta_filename
, slu
->stlu_meta_fname
);
2159 sl
->sl_name
= sl
->sl_meta_filename
;
2161 sl
->sl_device_id
[3] = 16;
2162 sl
->sl_device_id
[0] = 0xf1;
2163 sl
->sl_device_id
[1] = 3;
2164 sl
->sl_device_id
[2] = 0;
2165 bcopy(slu
->stlu_guid
, sl
->sl_device_id
+ 4, 16);
2166 lu
->lu_id
= (scsi_devid_desc_t
*)sl
->sl_device_id
;
2167 sl
->sl_access_state
= SBD_LU_STANDBY
;
2169 rw_init(&sl
->sl_pgr
->pgr_lock
, NULL
, RW_DRIVER
, NULL
);
2170 mutex_init(&sl
->sl_lock
, NULL
, MUTEX_DRIVER
, NULL
);
2171 mutex_init(&sl
->sl_metadata_lock
, NULL
, MUTEX_DRIVER
, NULL
);
2172 rw_init(&sl
->sl_access_state_lock
, NULL
, RW_DRIVER
, NULL
);
2174 sl
->sl_trans_op
= SL_OP_CREATE_REGISTER_LU
;
2176 if (sbd_link_lu(sl
) != SBD_SUCCESS
) {
2177 *err_ret
= SBD_RET_FILE_ALREADY_REGISTERED
;
2182 ret
= sbd_populate_and_register_lu(sl
, err_ret
);
2187 sl
->sl_trans_op
= SL_OP_NONE
;
2188 atomic_inc_32(&sbd_lu_count
);
2192 return (sbd_close_delete_lu(sl
, ret
));
2196 sbd_load_sli_1_0(sbd_lu_t
*sl
, uint32_t *err_ret
)
2198 sbd_lu_info_1_0_t
*sli
= NULL
;
2201 sret
= sbd_read_meta_section(sl
, (sm_section_hdr_t
**)&sli
,
2202 SMS_ID_LU_INFO_1_0
);
2204 if (sret
!= SBD_SUCCESS
) {
2205 *err_ret
= SBD_RET_NO_META
;
2208 if (sli
->sli_data_order
!= SMS_DATA_ORDER
) {
2209 sbd_swap_lu_info_1_0(sli
);
2210 if (sli
->sli_data_order
!= SMS_DATA_ORDER
) {
2211 kmem_free(sli
, sli
->sli_sms_header
.sms_size
);
2212 *err_ret
= SBD_RET_NO_META
;
2217 sl
->sl_flags
|= SL_SHARED_META
;
2218 sl
->sl_data_blocksize_shift
= 9;
2219 sl
->sl_data_offset
= SHARED_META_DATA_SIZE
;
2220 sl
->sl_lu_size
= sli
->sli_total_store_size
- SHARED_META_DATA_SIZE
;
2221 sl
->sl_total_data_size
= SHARED_META_DATA_SIZE
+ sl
->sl_lu_size
;
2222 bcopy(sli
->sli_lu_devid
, sl
->sl_device_id
, 20);
2224 kmem_free(sli
, sli
->sli_sms_header
.sms_size
);
2229 sbd_import_lu(sbd_import_lu_t
*ilu
, int struct_sz
, uint32_t *err_ret
,
2230 int no_register
, sbd_lu_t
**slr
)
2234 sbd_lu_info_1_1_t
*sli
= NULL
;
2237 stmf_status_t stret
;
2241 uint16_t sli_buf_sz
;
2242 uint8_t *sli_buf_copy
= NULL
;
2247 if (no_register
&& slr
== NULL
) {
2250 ilu
->ilu_meta_fname
[struct_sz
- sizeof (*ilu
) + 8 - 1] = 0;
2252 * check whether logical unit is already registered ALUA
2253 * For a standby logical unit, the meta filename is set. Use
2254 * that to search for an existing logical unit.
2256 sret
= sbd_find_and_lock_lu(NULL
, (uint8_t *)&(ilu
->ilu_meta_fname
),
2257 SL_OP_IMPORT_LU
, &sl
);
2259 if (sret
== SBD_SUCCESS
) {
2260 if (sl
->sl_access_state
!= SBD_LU_ACTIVE
) {
2264 if (sl
->sl_alias_alloc_size
) {
2265 kmem_free(sl
->sl_alias
,
2266 sl
->sl_alias_alloc_size
);
2267 sl
->sl_alias_alloc_size
= 0;
2268 sl
->sl_alias
= NULL
;
2269 lu
->lu_alias
= NULL
;
2271 if (sl
->sl_meta_filename
== NULL
) {
2272 sl
->sl_meta_filename
= sl
->sl_data_filename
;
2273 } else if (sl
->sl_data_fname_alloc_size
) {
2274 kmem_free(sl
->sl_data_filename
,
2275 sl
->sl_data_fname_alloc_size
);
2276 sl
->sl_data_fname_alloc_size
= 0;
2278 if (sl
->sl_serial_no_alloc_size
) {
2279 kmem_free(sl
->sl_serial_no
,
2280 sl
->sl_serial_no_alloc_size
);
2281 sl
->sl_serial_no_alloc_size
= 0;
2283 if (sl
->sl_mgmt_url_alloc_size
) {
2284 kmem_free(sl
->sl_mgmt_url
,
2285 sl
->sl_mgmt_url_alloc_size
);
2286 sl
->sl_mgmt_url_alloc_size
= 0;
2289 *err_ret
= SBD_RET_FILE_ALREADY_REGISTERED
;
2290 bcopy(sl
->sl_device_id
+ 4, ilu
->ilu_ret_guid
, 16);
2291 sl
->sl_trans_op
= SL_OP_NONE
;
2294 } else if (sret
== SBD_NOT_FOUND
) {
2295 asz
= strlen(ilu
->ilu_meta_fname
) + 1;
2297 lu
= (stmf_lu_t
*)stmf_alloc(STMF_STRUCT_STMF_LU
,
2298 sizeof (sbd_lu_t
) + sizeof (sbd_pgr_t
) + asz
, 0);
2302 sl
= (sbd_lu_t
*)lu
->lu_provider_private
;
2303 bzero(sl
, sizeof (*sl
));
2305 sl
->sl_pgr
= (sbd_pgr_t
*)(sl
+ 1);
2306 sl
->sl_meta_filename
= ((char *)sl
) + sizeof (*sl
) +
2308 (void) strcpy(sl
->sl_meta_filename
, ilu
->ilu_meta_fname
);
2309 sl
->sl_name
= sl
->sl_meta_filename
;
2310 rw_init(&sl
->sl_pgr
->pgr_lock
, NULL
, RW_DRIVER
, NULL
);
2311 rw_init(&sl
->sl_access_state_lock
, NULL
, RW_DRIVER
, NULL
);
2312 mutex_init(&sl
->sl_lock
, NULL
, MUTEX_DRIVER
, NULL
);
2313 mutex_init(&sl
->sl_metadata_lock
, NULL
, MUTEX_DRIVER
, NULL
);
2314 sl
->sl_trans_op
= SL_OP_IMPORT_LU
;
2316 *err_ret
= SBD_RET_META_FILE_LOOKUP_FAILED
;
2320 /* we're only loading the metadata */
2322 if (sbd_link_lu(sl
) != SBD_SUCCESS
) {
2323 *err_ret
= SBD_RET_FILE_ALREADY_REGISTERED
;
2324 bcopy(sl
->sl_device_id
+ 4, ilu
->ilu_ret_guid
, 16);
2329 if ((ret
= lookupname(sl
->sl_meta_filename
, UIO_SYSSPACE
, FOLLOW
,
2330 NULLVPP
, &sl
->sl_meta_vp
)) != 0) {
2331 *err_ret
= SBD_RET_META_FILE_LOOKUP_FAILED
;
2334 if (sbd_is_zvol(sl
->sl_meta_filename
)) {
2335 sl
->sl_flags
|= SL_ZFS_META
;
2336 sl
->sl_data_filename
= sl
->sl_meta_filename
;
2338 sl
->sl_meta_vtype
= vt
= sl
->sl_meta_vp
->v_type
;
2339 VN_RELE(sl
->sl_meta_vp
);
2340 if ((vt
!= VREG
) && (vt
!= VCHR
) && (vt
!= VBLK
)) {
2341 *err_ret
= SBD_RET_WRONG_META_FILE_TYPE
;
2345 if (sl
->sl_flags
& SL_ZFS_META
) {
2346 if (sbd_open_zfs_meta(sl
) != SBD_SUCCESS
) {
2347 /* let see if metadata is in the 64k block */
2348 sl
->sl_flags
&= ~SL_ZFS_META
;
2351 if (!(sl
->sl_flags
& SL_ZFS_META
)) {
2352 /* metadata is always writable */
2353 flag
= FREAD
| FWRITE
| FOFFMAX
| FEXCL
;
2354 if ((ret
= vn_open(sl
->sl_meta_filename
, UIO_SYSSPACE
, flag
, 0,
2355 &sl
->sl_meta_vp
, 0, 0)) != 0) {
2356 *err_ret
= SBD_RET_META_FILE_OPEN_FAILED
;
2360 if ((sl
->sl_flags
& SL_ZFS_META
) || (vt
== VREG
)) {
2361 sl
->sl_meta_blocksize_shift
= 0;
2363 sl
->sl_meta_blocksize_shift
= 9;
2365 sl
->sl_meta_offset
= (sl
->sl_flags
& SL_ZFS_META
) ? 0 : SBD_META_OFFSET
;
2366 sl
->sl_flags
|= SL_META_OPENED
;
2368 mutex_enter(&sl
->sl_metadata_lock
);
2369 sret
= sbd_load_meta_start(sl
);
2370 mutex_exit(&sl
->sl_metadata_lock
);
2371 if (sret
!= SBD_SUCCESS
) {
2372 if (sret
== SBD_META_CORRUPTED
) {
2373 *err_ret
= SBD_RET_NO_META
;
2374 } else if (sret
== SBD_NOT_SUPPORTED
) {
2375 *err_ret
= SBD_RET_VERSION_NOT_SUPPORTED
;
2377 *err_ret
= SBD_RET_NO_META
;
2383 /* Now lets see if we can read the most recent LU info */
2384 sret
= sbd_read_meta_section(sl
, (sm_section_hdr_t
**)&sli
,
2385 SMS_ID_LU_INFO_1_1
);
2386 if ((sret
== SBD_NOT_FOUND
) && ((sl
->sl_flags
& SL_ZFS_META
) == 0)) {
2387 ret
= sbd_load_sli_1_0(sl
, err_ret
);
2391 goto sim_sli_loaded
;
2393 if (sret
!= SBD_SUCCESS
) {
2394 *err_ret
= SBD_RET_NO_META
;
2399 if (sli
->sli_data_order
!= SMS_DATA_ORDER
) {
2400 sbd_swap_lu_info_1_1(sli
);
2401 if (sli
->sli_data_order
!= SMS_DATA_ORDER
) {
2402 *err_ret
= SBD_RET_NO_META
;
2408 sli_buf_sz
= sli
->sli_sms_header
.sms_size
-
2409 sizeof (sbd_lu_info_1_1_t
) + 8;
2410 sli_buf_copy
= kmem_alloc(sli_buf_sz
+ 1, KM_SLEEP
);
2411 bcopy(sli
->sli_buf
, sli_buf_copy
, sli_buf_sz
);
2412 sli_buf_copy
[sli_buf_sz
] = 0;
2414 /* Make sure all the offsets are within limits */
2415 if (((sli
->sli_flags
& SLI_META_FNAME_VALID
) &&
2416 (sli
->sli_meta_fname_offset
> sli_buf_sz
)) ||
2417 ((sli
->sli_flags
& SLI_DATA_FNAME_VALID
) &&
2418 (sli
->sli_data_fname_offset
> sli_buf_sz
)) ||
2419 ((sli
->sli_flags
& SLI_MGMT_URL_VALID
) &&
2420 (sli
->sli_mgmt_url_offset
> sli_buf_sz
)) ||
2421 ((sli
->sli_flags
& SLI_SERIAL_VALID
) &&
2422 ((sli
->sli_serial_offset
+ sli
->sli_serial_size
) > sli_buf_sz
)) ||
2423 ((sli
->sli_flags
& SLI_ALIAS_VALID
) &&
2424 (sli
->sli_alias_offset
> sli_buf_sz
))) {
2425 *err_ret
= SBD_RET_NO_META
;
2430 sl
->sl_lu_size
= sli
->sli_lu_size
;
2431 sl
->sl_data_blocksize_shift
= sli
->sli_data_blocksize_shift
;
2432 bcopy(sli
->sli_device_id
, sl
->sl_device_id
, 20);
2433 if (sli
->sli_flags
& SLI_SERIAL_VALID
) {
2434 sl
->sl_serial_no_size
= sl
->sl_serial_no_alloc_size
=
2435 sli
->sli_serial_size
;
2436 sl
->sl_serial_no
= kmem_zalloc(sli
->sli_serial_size
, KM_SLEEP
);
2437 bcopy(sli_buf_copy
+ sli
->sli_serial_offset
, sl
->sl_serial_no
,
2438 sl
->sl_serial_no_size
);
2440 if (sli
->sli_flags
& SLI_SEPARATE_META
) {
2441 sl
->sl_total_data_size
= sl
->sl_lu_size
;
2442 if (sli
->sli_flags
& SLI_DATA_FNAME_VALID
) {
2443 sl
->sl_data_fname_alloc_size
= strlen((char *)
2444 sli_buf_copy
+ sli
->sli_data_fname_offset
) + 1;
2445 sl
->sl_data_filename
= kmem_zalloc(
2446 sl
->sl_data_fname_alloc_size
, KM_SLEEP
);
2447 (void) strcpy(sl
->sl_data_filename
,
2448 (char *)sli_buf_copy
+ sli
->sli_data_fname_offset
);
2451 if (sl
->sl_flags
& SL_ZFS_META
) {
2452 sl
->sl_total_data_size
= sl
->sl_lu_size
;
2453 sl
->sl_data_offset
= 0;
2455 sl
->sl_total_data_size
=
2456 sl
->sl_lu_size
+ SHARED_META_DATA_SIZE
;
2457 sl
->sl_data_offset
= SHARED_META_DATA_SIZE
;
2458 sl
->sl_flags
|= SL_SHARED_META
;
2461 if (sli
->sli_flags
& SLI_ALIAS_VALID
) {
2462 sl
->sl_alias_alloc_size
= strlen((char *)sli_buf_copy
+
2463 sli
->sli_alias_offset
) + 1;
2464 sl
->sl_alias
= kmem_alloc(sl
->sl_alias_alloc_size
, KM_SLEEP
);
2465 (void) strcpy(sl
->sl_alias
, (char *)sli_buf_copy
+
2466 sli
->sli_alias_offset
);
2468 if (sli
->sli_flags
& SLI_MGMT_URL_VALID
) {
2469 sl
->sl_mgmt_url_alloc_size
= strlen((char *)sli_buf_copy
+
2470 sli
->sli_mgmt_url_offset
) + 1;
2471 sl
->sl_mgmt_url
= kmem_alloc(sl
->sl_mgmt_url_alloc_size
,
2473 (void) strcpy(sl
->sl_mgmt_url
, (char *)sli_buf_copy
+
2474 sli
->sli_mgmt_url_offset
);
2476 if (sli
->sli_flags
& SLI_WRITE_PROTECTED
) {
2477 sl
->sl_flags
|= SL_WRITE_PROTECTED
;
2479 if (sli
->sli_flags
& SLI_VID_VALID
) {
2480 sl
->sl_flags
|= SL_VID_VALID
;
2481 bcopy(sli
->sli_vid
, sl
->sl_vendor_id
, 8);
2483 if (sli
->sli_flags
& SLI_PID_VALID
) {
2484 sl
->sl_flags
|= SL_PID_VALID
;
2485 bcopy(sli
->sli_pid
, sl
->sl_product_id
, 16);
2487 if (sli
->sli_flags
& SLI_REV_VALID
) {
2488 sl
->sl_flags
|= SL_REV_VALID
;
2489 bcopy(sli
->sli_rev
, sl
->sl_revision
, 4);
2491 if (sli
->sli_flags
& SLI_WRITEBACK_CACHE_DISABLE
) {
2492 sl
->sl_flags
|= SL_WRITEBACK_CACHE_DISABLE
;
2495 if ((sl
->sl_flags
& SL_SHARED_META
) == 0) {
2499 sl
->sl_data_filename
= sl
->sl_meta_filename
;
2500 sl
->sl_data_vp
= sl
->sl_meta_vp
;
2501 sl
->sl_data_vtype
= sl
->sl_meta_vtype
;
2504 sret
= sbd_pgr_meta_load(sl
);
2505 if (sret
!= SBD_SUCCESS
) {
2506 *err_ret
= SBD_RET_NO_META
;
2511 ret
= sbd_open_data_file(sl
, err_ret
, 1, data_opened
, 0);
2517 * set write cache disable on the device
2518 * Note: this shouldn't fail on import unless the cache capabilities
2519 * of the device changed. If that happened, modify will need to
2520 * be used to set the cache flag appropriately after import is done.
2522 if (sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
) {
2523 (void) sbd_wcd_set(1, sl
);
2526 * if not explicitly set, attempt to set it to enable, if that fails
2527 * get the current setting and use that
2530 sret
= sbd_wcd_set(0, sl
);
2531 if (sret
!= SBD_SUCCESS
) {
2532 sbd_wcd_get(&wcd
, sl
);
2537 sl
->sl_flags
|= SL_WRITEBACK_CACHE_DISABLE
|
2538 SL_SAVED_WRITE_CACHE_DISABLE
;
2541 /* we're only loading the metadata */
2543 ret
= sbd_populate_and_register_lu(sl
, err_ret
);
2547 atomic_inc_32(&sbd_lu_count
);
2550 bcopy(sl
->sl_device_id
+ 4, ilu
->ilu_ret_guid
, 16);
2551 sl
->sl_trans_op
= SL_OP_NONE
;
2554 kmem_free(sli
, sli
->sli_sms_header
.sms_size
);
2558 kmem_free(sli_buf_copy
, sli_buf_sz
+ 1);
2559 sli_buf_copy
= NULL
;
2561 if (no_register
&& !standby
) {
2566 * if this was imported from standby, set the access state
2571 mutex_enter(&sl
->sl_lock
);
2572 sl
->sl_access_state
= SBD_LU_ACTIVE
;
2573 for (it
= sl
->sl_it_list
; it
!= NULL
;
2574 it
= it
->sbd_it_next
) {
2575 it
->sbd_it_ua_conditions
|=
2576 SBD_UA_ASYMMETRIC_ACCESS_CHANGED
;
2577 it
->sbd_it_ua_conditions
|= SBD_UA_POR
;
2578 it
->sbd_it_flags
|= SBD_IT_PGR_CHECK_FLAG
;
2580 mutex_exit(&sl
->sl_lock
);
2581 /* call set access state */
2582 stret
= stmf_set_lu_access(lu
, STMF_LU_ACTIVE
);
2583 if (stret
!= STMF_SUCCESS
) {
2584 *err_ret
= SBD_RET_ACCESS_STATE_FAILED
;
2585 sl
->sl_access_state
= SBD_LU_STANDBY
;
2589 lu
->lu_alias
= sl
->sl_alias
;
2591 lu
->lu_alias
= sl
->sl_name
;
2594 sl
->sl_access_state
= SBD_LU_ACTIVE
;
2599 kmem_free(sli
, sli
->sli_sms_header
.sms_size
);
2603 kmem_free(sli_buf_copy
, sli_buf_sz
+ 1);
2604 sli_buf_copy
= NULL
;
2608 *err_ret
= SBD_RET_ACCESS_STATE_FAILED
;
2609 sl
->sl_trans_op
= SL_OP_NONE
;
2612 return (sbd_close_delete_lu(sl
, ret
));
2617 sbd_modify_lu(sbd_modify_lu_t
*mlu
, int struct_sz
, uint32_t *err_ret
)
2619 sbd_lu_t
*sl
= NULL
;
2625 int modify_unregistered
= 0;
2627 sbd_import_lu_t
*ilu
;
2632 sz
= struct_sz
- sizeof (*mlu
) + 8 + 1;
2634 /* if there is data in the buf, null terminate it */
2635 if (struct_sz
> sizeof (*mlu
)) {
2636 mlu
->mlu_buf
[struct_sz
- sizeof (*mlu
) + 8 - 1] = 0;
2641 /* Lets validate offsets */
2642 if (((mlu
->mlu_alias_valid
) &&
2643 (mlu
->mlu_alias_off
>= sz
)) ||
2644 ((mlu
->mlu_mgmt_url_valid
) &&
2645 (mlu
->mlu_mgmt_url_off
>= sz
)) ||
2646 (mlu
->mlu_by_fname
) &&
2647 (mlu
->mlu_fname_off
>= sz
)) {
2652 * We'll look for the device but if we don't find it registered,
2653 * we'll still try to modify the unregistered device.
2655 if (mlu
->mlu_by_guid
) {
2656 sret
= sbd_find_and_lock_lu(mlu
->mlu_input_guid
, NULL
,
2657 SL_OP_MODIFY_LU
, &sl
);
2658 } else if (mlu
->mlu_by_fname
) {
2659 sret
= sbd_find_and_lock_lu(NULL
,
2660 (uint8_t *)&(mlu
->mlu_buf
[mlu
->mlu_fname_off
]),
2661 SL_OP_MODIFY_LU
, &sl
);
2667 if (sret
!= SBD_SUCCESS
) {
2668 if (sret
== SBD_BUSY
) {
2669 *err_ret
= SBD_RET_LU_BUSY
;
2671 } else if (sret
!= SBD_NOT_FOUND
) {
2673 } else if (!mlu
->mlu_by_fname
) {
2676 /* Okay, try to import the device */
2677 struct_sz
= max(8, strlen(&(mlu
->mlu_buf
[mlu
->mlu_fname_off
]))
2679 struct_sz
+= sizeof (sbd_import_lu_t
) - 8;
2681 ilu
= (sbd_import_lu_t
*)kmem_zalloc(ilu_sz
, KM_SLEEP
);
2682 ilu
->ilu_struct_size
= struct_sz
;
2683 (void) strcpy(ilu
->ilu_meta_fname
,
2684 &(mlu
->mlu_buf
[mlu
->mlu_fname_off
]));
2685 ret
= sbd_import_lu(ilu
, struct_sz
, err_ret
, 1, &sl
);
2686 kmem_free(ilu
, ilu_sz
);
2687 if (ret
!= SBD_SUCCESS
) {
2690 modify_unregistered
= 1;
2693 if (sl
->sl_access_state
!= SBD_LU_ACTIVE
) {
2694 *err_ret
= SBD_RET_ACCESS_STATE_FAILED
;
2699 /* check for write cache change */
2700 if (mlu
->mlu_writeback_cache_disable_valid
) {
2701 /* set wce on device */
2702 sret
= sbd_wcd_set(mlu
->mlu_writeback_cache_disable
, sl
);
2703 if (!mlu
->mlu_writeback_cache_disable
&& sret
!= SBD_SUCCESS
) {
2704 *err_ret
= SBD_RET_WRITE_CACHE_SET_FAILED
;
2708 mutex_enter(&sl
->sl_lock
);
2709 if (!mlu
->mlu_writeback_cache_disable
) {
2710 if (sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
) {
2712 sl
->sl_flags
&= ~SL_WRITEBACK_CACHE_DISABLE
;
2713 sl
->sl_flags
&= ~SL_SAVED_WRITE_CACHE_DISABLE
;
2716 if ((sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
) == 0) {
2718 sl
->sl_flags
|= SL_WRITEBACK_CACHE_DISABLE
;
2719 sl
->sl_flags
|= SL_SAVED_WRITE_CACHE_DISABLE
;
2722 for (it
= sl
->sl_it_list
; ua
&& it
!= NULL
;
2723 it
= it
->sbd_it_next
) {
2724 it
->sbd_it_ua_conditions
|=
2725 SBD_UA_MODE_PARAMETERS_CHANGED
;
2727 mutex_exit(&sl
->sl_lock
);
2731 if (mlu
->mlu_alias_valid
) {
2732 alias_sz
= strlen((char *)mlu
->mlu_buf
+
2733 mlu
->mlu_alias_off
) + 1;
2735 * Use the allocated buffer or alloc a new one.
2736 * Don't copy into sl_alias if sl_alias_alloc_size is 0
2737 * otherwise or you'll be writing over the data/metadata
2740 mutex_enter(&sl
->sl_lock
);
2741 if (sl
->sl_alias_alloc_size
> 0 &&
2742 sl
->sl_alias_alloc_size
< alias_sz
) {
2743 kmem_free(sl
->sl_alias
,
2744 sl
->sl_alias_alloc_size
);
2745 sl
->sl_alias_alloc_size
= 0;
2747 if (sl
->sl_alias_alloc_size
== 0) {
2748 sl
->sl_alias
= kmem_alloc(alias_sz
, KM_SLEEP
);
2749 sl
->sl_alias_alloc_size
= alias_sz
;
2751 (void) strcpy(sl
->sl_alias
, (char *)mlu
->mlu_buf
+
2752 mlu
->mlu_alias_off
);
2754 lu
->lu_alias
= sl
->sl_alias
;
2755 mutex_exit(&sl
->sl_lock
);
2758 if (mlu
->mlu_mgmt_url_valid
) {
2761 url_sz
= strlen((char *)mlu
->mlu_buf
+ mlu
->mlu_mgmt_url_off
);
2765 mutex_enter(&sl
->sl_lock
);
2766 if (sl
->sl_mgmt_url_alloc_size
> 0 &&
2767 (url_sz
== 0 || sl
->sl_mgmt_url_alloc_size
< url_sz
)) {
2768 kmem_free(sl
->sl_mgmt_url
, sl
->sl_mgmt_url_alloc_size
);
2769 sl
->sl_mgmt_url
= NULL
;
2770 sl
->sl_mgmt_url_alloc_size
= 0;
2773 if (sl
->sl_mgmt_url_alloc_size
== 0) {
2774 sl
->sl_mgmt_url
= kmem_alloc(url_sz
, KM_SLEEP
);
2775 sl
->sl_mgmt_url_alloc_size
= url_sz
;
2777 (void) strcpy(sl
->sl_mgmt_url
, (char *)mlu
->mlu_buf
+
2778 mlu
->mlu_mgmt_url_off
);
2780 for (it
= sl
->sl_it_list
; it
!= NULL
;
2781 it
= it
->sbd_it_next
) {
2782 it
->sbd_it_ua_conditions
|=
2783 SBD_UA_MODE_PARAMETERS_CHANGED
;
2785 mutex_exit(&sl
->sl_lock
);
2788 if (mlu
->mlu_write_protected_valid
) {
2789 mutex_enter(&sl
->sl_lock
);
2790 if (mlu
->mlu_write_protected
) {
2791 if ((sl
->sl_flags
& SL_WRITE_PROTECTED
) == 0) {
2793 sl
->sl_flags
|= SL_WRITE_PROTECTED
;
2796 if (sl
->sl_flags
& SL_WRITE_PROTECTED
) {
2798 sl
->sl_flags
&= ~SL_WRITE_PROTECTED
;
2801 for (it
= sl
->sl_it_list
; ua
&& it
!= NULL
;
2802 it
= it
->sbd_it_next
) {
2803 it
->sbd_it_ua_conditions
|=
2804 SBD_UA_MODE_PARAMETERS_CHANGED
;
2806 mutex_exit(&sl
->sl_lock
);
2809 if (mlu
->mlu_lu_size_valid
) {
2811 * validate lu size and set
2812 * For open file only (registered lu)
2814 mutex_enter(&sl
->sl_lock
);
2815 old_size
= sl
->sl_lu_size
;
2816 sl
->sl_lu_size
= mlu
->mlu_lu_size
;
2817 mutex_exit(&sl
->sl_lock
);
2818 ret
= sbd_open_data_file(sl
, err_ret
, 1, 1, 1);
2820 mutex_enter(&sl
->sl_lock
);
2821 sl
->sl_lu_size
= old_size
;
2822 mutex_exit(&sl
->sl_lock
);
2825 if (old_size
!= mlu
->mlu_lu_size
) {
2826 mutex_enter(&sl
->sl_lock
);
2827 for (it
= sl
->sl_it_list
; it
!= NULL
;
2828 it
= it
->sbd_it_next
) {
2829 it
->sbd_it_ua_conditions
|=
2830 SBD_UA_CAPACITY_CHANGED
;
2832 mutex_exit(&sl
->sl_lock
);
2836 if (sbd_write_lu_info(sl
) != SBD_SUCCESS
) {
2837 *err_ret
= SBD_RET_META_CREATION_FAILED
;
2842 if (modify_unregistered
) {
2843 (void) sbd_close_delete_lu(sl
, 0);
2845 sl
->sl_trans_op
= SL_OP_NONE
;
2851 sbd_set_global_props(sbd_global_props_t
*mlu
, int struct_sz
,
2854 sbd_lu_t
*sl
= NULL
;
2859 sz
= struct_sz
- sizeof (*mlu
) + 8 + 1;
2861 /* if there is data in the buf, null terminate it */
2862 if (struct_sz
> sizeof (*mlu
)) {
2863 mlu
->mlu_buf
[struct_sz
- sizeof (*mlu
) + 8 - 1] = 0;
2868 /* Lets validate offsets */
2869 if (((mlu
->mlu_mgmt_url_valid
) &&
2870 (mlu
->mlu_mgmt_url_off
>= sz
))) {
2874 if (mlu
->mlu_mgmt_url_valid
) {
2877 url_sz
= strlen((char *)mlu
->mlu_buf
+ mlu
->mlu_mgmt_url_off
);
2881 rw_enter(&sbd_global_prop_lock
, RW_WRITER
);
2882 if (sbd_mgmt_url_alloc_size
> 0 &&
2883 (url_sz
== 0 || sbd_mgmt_url_alloc_size
< url_sz
)) {
2884 kmem_free(sbd_mgmt_url
, sbd_mgmt_url_alloc_size
);
2885 sbd_mgmt_url
= NULL
;
2886 sbd_mgmt_url_alloc_size
= 0;
2889 if (sbd_mgmt_url_alloc_size
== 0) {
2890 sbd_mgmt_url
= kmem_alloc(url_sz
, KM_SLEEP
);
2891 sbd_mgmt_url_alloc_size
= url_sz
;
2893 (void) strcpy(sbd_mgmt_url
, (char *)mlu
->mlu_buf
+
2894 mlu
->mlu_mgmt_url_off
);
2897 * check each lu to determine whether a UA is needed.
2899 mutex_enter(&sbd_lock
);
2900 for (sl
= sbd_lu_list
; sl
; sl
= sl
->sl_next
) {
2901 if (sl
->sl_mgmt_url
) {
2904 mutex_enter(&sl
->sl_lock
);
2905 for (it
= sl
->sl_it_list
; it
!= NULL
;
2906 it
= it
->sbd_it_next
) {
2907 it
->sbd_it_ua_conditions
|=
2908 SBD_UA_MODE_PARAMETERS_CHANGED
;
2910 mutex_exit(&sl
->sl_lock
);
2912 mutex_exit(&sbd_lock
);
2913 rw_exit(&sbd_global_prop_lock
);
2920 sbd_delete_locked_lu(sbd_lu_t
*sl
, uint32_t *err_ret
,
2921 stmf_state_change_info_t
*ssi
)
2926 if ((sl
->sl_state
== STMF_STATE_OFFLINE
) &&
2927 !sl
->sl_state_not_acked
) {
2931 if ((sl
->sl_state
!= STMF_STATE_ONLINE
) ||
2932 sl
->sl_state_not_acked
) {
2936 ret
= stmf_ctl(STMF_CMD_LU_OFFLINE
, sl
->sl_lu
, ssi
);
2937 if ((ret
!= STMF_SUCCESS
) && (ret
!= STMF_ALREADY
)) {
2941 for (i
= 0; i
< 500; i
++) {
2942 if ((sl
->sl_state
== STMF_STATE_OFFLINE
) &&
2943 !sl
->sl_state_not_acked
) {
2946 delay(drv_usectohz(10000));
2951 if (stmf_deregister_lu(sl
->sl_lu
) != STMF_SUCCESS
)
2953 atomic_dec_32(&sbd_lu_count
);
2955 return (sbd_close_delete_lu(sl
, 0));
2959 sbd_delete_lu(sbd_delete_lu_t
*dlu
, int struct_sz
, uint32_t *err_ret
)
2963 stmf_state_change_info_t ssi
;
2966 if (dlu
->dlu_by_meta_name
) {
2967 ((char *)dlu
)[struct_sz
- 1] = 0;
2968 sret
= sbd_find_and_lock_lu(NULL
, dlu
->dlu_meta_name
,
2969 SL_OP_DELETE_LU
, &sl
);
2971 sret
= sbd_find_and_lock_lu(dlu
->dlu_guid
, NULL
,
2972 SL_OP_DELETE_LU
, &sl
);
2974 if (sret
!= SBD_SUCCESS
) {
2975 if (sret
== SBD_BUSY
) {
2976 *err_ret
= SBD_RET_LU_BUSY
;
2978 } else if (sret
== SBD_NOT_FOUND
) {
2979 *err_ret
= SBD_RET_NOT_FOUND
;
2985 ssi
.st_rflags
= STMF_RFLAG_USER_REQUEST
;
2986 ssi
.st_additional_info
= "sbd_delete_lu call (ioctl)";
2987 ret
= sbd_delete_locked_lu(sl
, err_ret
, &ssi
);
2990 /* Once its locked, no need to grab mutex again */
2991 sl
->sl_trans_op
= SL_OP_NONE
;
2997 sbd_data_read(sbd_lu_t
*sl
, struct scsi_task
*task
,
2998 uint64_t offset
, uint64_t size
, uint8_t *buf
)
3003 if ((offset
+ size
) > sl
->sl_lu_size
) {
3004 return (SBD_IO_PAST_EOF
);
3007 offset
+= sl
->sl_data_offset
;
3009 if ((offset
+ size
) > sl
->sl_data_readable_size
) {
3011 if (offset
> sl
->sl_data_readable_size
) {
3013 return (SBD_SUCCESS
);
3015 store_end
= sl
->sl_data_readable_size
- offset
;
3016 bzero(buf
+ store_end
, size
- store_end
);
3020 DTRACE_PROBE5(backing__store__read__start
, sbd_lu_t
*, sl
,
3021 uint8_t *, buf
, uint64_t, size
, uint64_t, offset
,
3022 scsi_task_t
*, task
);
3025 * Don't proceed if the device has been closed
3026 * This can occur on an access state change to standby or
3027 * a delete. The writer lock is acquired before closing the
3030 rw_enter(&sl
->sl_access_state_lock
, RW_READER
);
3031 if ((sl
->sl_flags
& SL_MEDIA_LOADED
) == 0) {
3032 rw_exit(&sl
->sl_access_state_lock
);
3033 return (SBD_FAILURE
);
3035 ret
= vn_rdwr(UIO_READ
, sl
->sl_data_vp
, (caddr_t
)buf
, (ssize_t
)size
,
3036 (offset_t
)offset
, UIO_SYSSPACE
, 0, RLIM64_INFINITY
, CRED(),
3038 rw_exit(&sl
->sl_access_state_lock
);
3040 DTRACE_PROBE6(backing__store__read__end
, sbd_lu_t
*, sl
,
3041 uint8_t *, buf
, uint64_t, size
, uint64_t, offset
,
3042 int, ret
, scsi_task_t
*, task
);
3046 stmf_trace(0, "UIO_READ failed, ret = %d, resid = %d", ret
,
3048 return (SBD_FAILURE
);
3051 return (SBD_SUCCESS
);
3055 sbd_data_write(sbd_lu_t
*sl
, struct scsi_task
*task
,
3056 uint64_t offset
, uint64_t size
, uint8_t *buf
)
3060 sbd_status_t sret
= SBD_SUCCESS
;
3063 if ((offset
+ size
) > sl
->sl_lu_size
) {
3064 return (SBD_IO_PAST_EOF
);
3067 offset
+= sl
->sl_data_offset
;
3069 if ((sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
) &&
3070 (sl
->sl_flags
& SL_FLUSH_ON_DISABLED_WRITECACHE
)) {
3076 DTRACE_PROBE5(backing__store__write__start
, sbd_lu_t
*, sl
,
3077 uint8_t *, buf
, uint64_t, size
, uint64_t, offset
,
3078 scsi_task_t
*, task
);
3081 * Don't proceed if the device has been closed
3082 * This can occur on an access state change to standby or
3083 * a delete. The writer lock is acquired before closing the
3086 rw_enter(&sl
->sl_access_state_lock
, RW_READER
);
3087 if ((sl
->sl_flags
& SL_MEDIA_LOADED
) == 0) {
3088 rw_exit(&sl
->sl_access_state_lock
);
3089 return (SBD_FAILURE
);
3091 ret
= vn_rdwr(UIO_WRITE
, sl
->sl_data_vp
, (caddr_t
)buf
, (ssize_t
)size
,
3092 (offset_t
)offset
, UIO_SYSSPACE
, ioflag
, RLIM64_INFINITY
, CRED(),
3094 rw_exit(&sl
->sl_access_state_lock
);
3096 DTRACE_PROBE6(backing__store__write__end
, sbd_lu_t
*, sl
,
3097 uint8_t *, buf
, uint64_t, size
, uint64_t, offset
,
3098 int, ret
, scsi_task_t
*, task
);
3100 if ((ret
== 0) && (resid
== 0) &&
3101 (sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
) &&
3102 (sl
->sl_flags
& SL_FLUSH_ON_DISABLED_WRITECACHE
)) {
3103 sret
= sbd_flush_data_cache(sl
, 1);
3107 if ((ret
|| resid
) || (sret
!= SBD_SUCCESS
)) {
3108 return (SBD_FAILURE
);
3109 } else if ((offset
+ size
) > sl
->sl_data_readable_size
) {
3110 uint64_t old_size
, new_size
;
3113 old_size
= sl
->sl_data_readable_size
;
3114 if ((offset
+ size
) <= old_size
)
3116 new_size
= offset
+ size
;
3117 } while (atomic_cas_64(&sl
->sl_data_readable_size
, old_size
,
3118 new_size
) != old_size
);
3121 return (SBD_SUCCESS
);
3125 sbd_get_global_props(sbd_global_props_t
*oslp
, uint32_t oslp_sz
,
3131 rw_enter(&sbd_global_prop_lock
, RW_READER
);
3133 sz
+= strlen(sbd_mgmt_url
) + 1;
3135 bzero(oslp
, sizeof (*oslp
) - 8);
3136 oslp
->mlu_buf_size_needed
= sz
;
3138 if (sz
> (oslp_sz
- sizeof (*oslp
) + 8)) {
3139 *err_ret
= SBD_RET_INSUFFICIENT_BUF_SPACE
;
3140 rw_exit(&sbd_global_prop_lock
);
3146 oslp
->mlu_mgmt_url_valid
= 1;
3147 oslp
->mlu_mgmt_url_off
= off
;
3148 (void) strcpy((char *)&oslp
->mlu_buf
[off
], sbd_mgmt_url
);
3149 off
+= strlen(sbd_mgmt_url
) + 1;
3152 rw_exit(&sbd_global_prop_lock
);
3157 sbd_get_unmap_props(sbd_unmap_props_t
*sup
,
3158 sbd_unmap_props_t
*osup
, uint32_t *err_ret
)
3161 sbd_lu_t
*sl
= NULL
;
3163 if (sup
->sup_guid_valid
) {
3164 sret
= sbd_find_and_lock_lu(sup
->sup_guid
,
3165 NULL
, SL_OP_LU_PROPS
, &sl
);
3167 sret
= sbd_find_and_lock_lu(NULL
,
3168 (uint8_t *)sup
->sup_zvol_path
, SL_OP_LU_PROPS
,
3171 if (sret
!= SBD_SUCCESS
) {
3172 if (sret
== SBD_BUSY
) {
3173 *err_ret
= SBD_RET_LU_BUSY
;
3175 } else if (sret
== SBD_NOT_FOUND
) {
3176 *err_ret
= SBD_RET_NOT_FOUND
;
3182 sup
->sup_found_lu
= 1;
3183 sup
->sup_guid_valid
= 1;
3184 bcopy(sl
->sl_device_id
+ 4, sup
->sup_guid
, 16);
3185 if (sl
->sl_flags
& SL_UNMAP_ENABLED
)
3186 sup
->sup_unmap_enabled
= 1;
3188 sup
->sup_unmap_enabled
= 0;
3191 sl
->sl_trans_op
= SL_OP_NONE
;
3197 sbd_get_lu_props(sbd_lu_props_t
*islp
, uint32_t islp_sz
,
3198 sbd_lu_props_t
*oslp
, uint32_t oslp_sz
, uint32_t *err_ret
)
3201 sbd_lu_t
*sl
= NULL
;
3205 if (islp
->slp_input_guid
) {
3206 sret
= sbd_find_and_lock_lu(islp
->slp_guid
, NULL
,
3207 SL_OP_LU_PROPS
, &sl
);
3209 ((char *)islp
)[islp_sz
- 1] = 0;
3210 sret
= sbd_find_and_lock_lu(NULL
, islp
->slp_buf
,
3211 SL_OP_LU_PROPS
, &sl
);
3213 if (sret
!= SBD_SUCCESS
) {
3214 if (sret
== SBD_BUSY
) {
3215 *err_ret
= SBD_RET_LU_BUSY
;
3217 } else if (sret
== SBD_NOT_FOUND
) {
3218 *err_ret
= SBD_RET_NOT_FOUND
;
3224 sz
= strlen(sl
->sl_name
) + 1;
3225 if ((sl
->sl_flags
& (SL_ZFS_META
| SL_SHARED_META
)) == 0) {
3226 if (sl
->sl_data_filename
) {
3227 sz
+= strlen(sl
->sl_data_filename
) + 1;
3230 sz
+= sl
->sl_serial_no_size
;
3232 sz
+= strlen(sl
->sl_alias
) + 1;
3235 rw_enter(&sbd_global_prop_lock
, RW_READER
);
3236 if (sl
->sl_mgmt_url
) {
3237 sz
+= strlen(sl
->sl_mgmt_url
) + 1;
3238 } else if (sbd_mgmt_url
) {
3239 sz
+= strlen(sbd_mgmt_url
) + 1;
3241 bzero(oslp
, sizeof (*oslp
) - 8);
3242 oslp
->slp_buf_size_needed
= sz
;
3244 if (sz
> (oslp_sz
- sizeof (*oslp
) + 8)) {
3245 sl
->sl_trans_op
= SL_OP_NONE
;
3246 *err_ret
= SBD_RET_INSUFFICIENT_BUF_SPACE
;
3247 rw_exit(&sbd_global_prop_lock
);
3252 (void) strcpy((char *)oslp
->slp_buf
, sl
->sl_name
);
3253 oslp
->slp_meta_fname_off
= off
;
3254 off
+= strlen(sl
->sl_name
) + 1;
3255 if ((sl
->sl_flags
& (SL_ZFS_META
| SL_SHARED_META
)) == 0) {
3256 oslp
->slp_meta_fname_valid
= 1;
3257 oslp
->slp_separate_meta
= 1;
3258 if (sl
->sl_data_filename
) {
3259 oslp
->slp_data_fname_valid
= 1;
3260 oslp
->slp_data_fname_off
= off
;
3261 (void) strcpy((char *)&oslp
->slp_buf
[off
],
3262 sl
->sl_data_filename
);
3263 off
+= strlen(sl
->sl_data_filename
) + 1;
3266 oslp
->slp_data_fname_valid
= 1;
3267 oslp
->slp_data_fname_off
= oslp
->slp_meta_fname_off
;
3268 if (sl
->sl_flags
& SL_ZFS_META
) {
3269 oslp
->slp_zfs_meta
= 1;
3273 oslp
->slp_alias_valid
= 1;
3274 oslp
->slp_alias_off
= off
;
3275 (void) strcpy((char *)&oslp
->slp_buf
[off
], sl
->sl_alias
);
3276 off
+= strlen(sl
->sl_alias
) + 1;
3278 if (sl
->sl_mgmt_url
) {
3279 oslp
->slp_mgmt_url_valid
= 1;
3280 oslp
->slp_mgmt_url_off
= off
;
3281 (void) strcpy((char *)&oslp
->slp_buf
[off
], sl
->sl_mgmt_url
);
3282 off
+= strlen(sl
->sl_mgmt_url
) + 1;
3283 } else if (sbd_mgmt_url
) {
3284 oslp
->slp_mgmt_url_valid
= 1;
3285 oslp
->slp_mgmt_url_off
= off
;
3286 (void) strcpy((char *)&oslp
->slp_buf
[off
], sbd_mgmt_url
);
3287 off
+= strlen(sbd_mgmt_url
) + 1;
3289 if (sl
->sl_serial_no_size
) {
3290 oslp
->slp_serial_off
= off
;
3291 bcopy(sl
->sl_serial_no
, &oslp
->slp_buf
[off
],
3292 sl
->sl_serial_no_size
);
3293 oslp
->slp_serial_size
= sl
->sl_serial_no_size
;
3294 oslp
->slp_serial_valid
= 1;
3295 off
+= sl
->sl_serial_no_size
;
3298 oslp
->slp_lu_size
= sl
->sl_lu_size
;
3299 oslp
->slp_blksize
= ((uint16_t)1) << sl
->sl_data_blocksize_shift
;
3301 oslp
->slp_access_state
= sl
->sl_access_state
;
3303 if (sl
->sl_flags
& SL_VID_VALID
) {
3304 oslp
->slp_lu_vid
= 1;
3305 bcopy(sl
->sl_vendor_id
, oslp
->slp_vid
, 8);
3307 bcopy(sbd_vendor_id
, oslp
->slp_vid
, 8);
3309 if (sl
->sl_flags
& SL_PID_VALID
) {
3310 oslp
->slp_lu_pid
= 1;
3311 bcopy(sl
->sl_product_id
, oslp
->slp_pid
, 16);
3313 bcopy(sbd_product_id
, oslp
->slp_pid
, 16);
3315 if (sl
->sl_flags
& SL_REV_VALID
) {
3316 oslp
->slp_lu_rev
= 1;
3317 bcopy(sl
->sl_revision
, oslp
->slp_rev
, 4);
3319 bcopy(sbd_revision
, oslp
->slp_rev
, 4);
3321 bcopy(sl
->sl_device_id
+ 4, oslp
->slp_guid
, 16);
3323 if (sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
)
3324 oslp
->slp_writeback_cache_disable_cur
= 1;
3325 if (sl
->sl_flags
& SL_SAVED_WRITE_CACHE_DISABLE
)
3326 oslp
->slp_writeback_cache_disable_saved
= 1;
3327 if (sl
->sl_flags
& SL_WRITE_PROTECTED
)
3328 oslp
->slp_write_protected
= 1;
3330 sl
->sl_trans_op
= SL_OP_NONE
;
3332 rw_exit(&sbd_global_prop_lock
);
3337 * Returns an allocated string with the "<pool>/..." form of the zvol name.
3340 sbd_get_zvol_name(sbd_lu_t
*sl
)
3345 if (sl
->sl_data_filename
)
3346 src
= sl
->sl_data_filename
;
3348 src
= sl
->sl_meta_filename
;
3349 /* There has to be a better way */
3350 if (SBD_IS_ZVOL(src
) != 0) {
3353 src
+= 14; /* Past /dev/zvol/dsk/ */
3355 src
++; /* or /dev/zvol/rdsk/ */
3356 p
= kmem_alloc(strlen(src
) + 1, KM_SLEEP
);
3357 (void) strcpy(p
, src
);
3362 * this function creates a local metadata zvol property
3365 sbd_create_zfs_meta_object(sbd_lu_t
*sl
)
3368 * -allocate 1/2 the property size, the zfs property
3369 * is 8k in size and stored as ascii hex string, all
3370 * we needed is 4k buffer to store the binary data.
3371 * -initialize reader/write lock
3373 if ((sl
->sl_zfs_meta
= kmem_zalloc(ZAP_MAXVALUELEN
/ 2, KM_SLEEP
))
3375 return (SBD_FAILURE
);
3376 rw_init(&sl
->sl_zfs_meta_lock
, NULL
, RW_DRIVER
, NULL
);
3377 return (SBD_SUCCESS
);
3383 if ((c
>= '0') && (c
<= '9'))
3385 else if ((c
>= 'A') && (c
<= 'F'))
3387 else if ((c
>= 'a') && (c
<= 'f'))
3395 * read zvol property and convert to binary
3398 sbd_open_zfs_meta(sbd_lu_t
*sl
)
3400 char *meta
= NULL
, cl
, ch
;
3403 uint64_t rc
= SBD_SUCCESS
;
3407 if (sl
->sl_zfs_meta
== NULL
) {
3408 if (sbd_create_zfs_meta_object(sl
) == SBD_FAILURE
)
3409 return (SBD_FAILURE
);
3411 bzero(sl
->sl_zfs_meta
, (ZAP_MAXVALUELEN
/ 2));
3414 rw_enter(&sl
->sl_zfs_meta_lock
, RW_WRITER
);
3415 file
= sbd_get_zvol_name(sl
);
3416 if (sbd_zvolget(file
, &meta
)) {
3421 /* convert ascii hex to binary meta */
3423 ptr
= sl
->sl_zfs_meta
;
3424 for (i
= 0; i
< len
; i
+= 2) {
3425 ch
= sbd_ctoi(*tmp
++);
3426 cl
= sbd_ctoi(*tmp
++);
3427 if (ch
== -1 || cl
== -1) {
3431 *ptr
++ = (ch
<< 4) + cl
;
3434 rw_exit(&sl
->sl_zfs_meta_lock
);
3436 kmem_free(meta
, len
+ 1);
3437 kmem_free(file
, strlen(file
) + 1);
3442 sbd_read_zfs_meta(sbd_lu_t
*sl
, uint8_t *buf
, uint64_t sz
, uint64_t off
)
3444 ASSERT(sl
->sl_zfs_meta
);
3445 rw_enter(&sl
->sl_zfs_meta_lock
, RW_READER
);
3446 bcopy(&sl
->sl_zfs_meta
[off
], buf
, sz
);
3447 rw_exit(&sl
->sl_zfs_meta_lock
);
3448 return (SBD_SUCCESS
);
3452 sbd_write_zfs_meta(sbd_lu_t
*sl
, uint8_t *buf
, uint64_t sz
, uint64_t off
)
3454 ASSERT(sl
->sl_zfs_meta
);
3455 if ((off
+ sz
) > (ZAP_MAXVALUELEN
/ 2 - 1)) {
3456 return (SBD_META_CORRUPTED
);
3458 if ((off
+ sz
) > sl
->sl_meta_size_used
) {
3459 sl
->sl_meta_size_used
= off
+ sz
;
3460 if (sl
->sl_total_meta_size
< sl
->sl_meta_size_used
) {
3461 uint64_t meta_align
=
3462 (((uint64_t)1) << sl
->sl_meta_blocksize_shift
) - 1;
3463 sl
->sl_total_meta_size
= (sl
->sl_meta_size_used
+
3464 meta_align
) & (~meta_align
);
3467 rw_enter(&sl
->sl_zfs_meta_lock
, RW_WRITER
);
3468 bcopy(buf
, &sl
->sl_zfs_meta
[off
], sz
);
3469 rw_exit(&sl
->sl_zfs_meta_lock
);
3471 * During creation of a logical unit, sbd_update_zfs_prop will be
3472 * called separately to avoid multiple calls as each meta section
3473 * create/update will result in a call to sbd_write_zfs_meta().
3474 * We only need to update the zvol once during create.
3476 mutex_enter(&sl
->sl_lock
);
3477 if (sl
->sl_trans_op
!= SL_OP_CREATE_REGISTER_LU
) {
3478 mutex_exit(&sl
->sl_lock
);
3479 return (sbd_update_zfs_prop(sl
));
3481 mutex_exit(&sl
->sl_lock
);
3482 return (SBD_SUCCESS
);
3486 sbd_update_zfs_prop(sbd_lu_t
*sl
)
3488 char *ptr
, *ah_meta
;
3492 sbd_status_t ret
= SBD_SUCCESS
;
3494 ASSERT(sl
->sl_zfs_meta
);
3495 ptr
= ah_meta
= kmem_zalloc(ZAP_MAXVALUELEN
, KM_SLEEP
);
3496 rw_enter(&sl
->sl_zfs_meta_lock
, RW_READER
);
3497 /* convert local copy to ascii hex */
3498 dp
= sl
->sl_zfs_meta
;
3499 for (i
= 0; i
< sl
->sl_total_meta_size
; i
++, dp
++) {
3500 num
= ((*dp
) >> 4) & 0xF;
3501 *ah_meta
++ = (num
< 10) ? (num
+ '0') : (num
+ ('a' - 10));
3503 *ah_meta
++ = (num
< 10) ? (num
+ '0') : (num
+ ('a' - 10));
3506 file
= sbd_get_zvol_name(sl
);
3507 if (sbd_zvolset(file
, (char *)ptr
)) {
3508 ret
= SBD_META_CORRUPTED
;
3510 rw_exit(&sl
->sl_zfs_meta_lock
);
3511 kmem_free(ptr
, ZAP_MAXVALUELEN
);
3512 kmem_free(file
, strlen(file
) + 1);
3517 sbd_is_zvol(char *path
)
3521 if (SBD_IS_ZVOL(path
) == 0)
3528 * set write cache disable
3529 * wcd - 1 = disable, 0 = enable
3532 sbd_wcd_set(int wcd
, sbd_lu_t
*sl
)
3534 /* translate to wce bit */
3535 int wce
= wcd
? 0 : 1;
3537 sbd_status_t sret
= SBD_SUCCESS
;
3539 mutex_enter(&sl
->sl_lock
);
3540 sl
->sl_flags
&= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED
;
3542 if (sl
->sl_data_vp
->v_type
== VREG
) {
3543 sl
->sl_flags
|= SL_FLUSH_ON_DISABLED_WRITECACHE
;
3547 ret
= fop_ioctl(sl
->sl_data_vp
, DKIOCSETWCE
, (intptr_t)&wce
, FKIOCTL
,
3550 sl
->sl_flags
&= ~SL_WRITEBACK_CACHE_SET_UNSUPPORTED
;
3551 sl
->sl_flags
&= ~SL_FLUSH_ON_DISABLED_WRITECACHE
;
3553 sl
->sl_flags
|= SL_WRITEBACK_CACHE_SET_UNSUPPORTED
;
3554 sl
->sl_flags
|= SL_FLUSH_ON_DISABLED_WRITECACHE
;
3560 mutex_exit(&sl
->sl_lock
);
3565 * get write cache disable
3566 * wcd - 1 = disable, 0 = enable
3569 sbd_wcd_get(int *wcd
, sbd_lu_t
*sl
)
3574 if (sl
->sl_data_vp
->v_type
== VREG
) {
3579 ret
= fop_ioctl(sl
->sl_data_vp
, DKIOCGETWCE
, (intptr_t)&wce
, FKIOCTL
,
3581 /* if write cache get failed, assume disabled */
3585 /* translate to wcd bit */
3591 sbd_zvolget(char *zvol_name
, char **comstarprop
)
3593 ldi_handle_t zfs_lh
;
3594 nvlist_t
*nv
= NULL
, *nv2
;
3601 if ((rc
= ldi_open_by_name("/dev/zfs", FREAD
| FWRITE
, kcred
,
3602 &zfs_lh
, sbd_zfs_ident
)) != 0) {
3603 cmn_err(CE_WARN
, "ldi_open %d", rc
);
3607 zc
= kmem_zalloc(sizeof (zfs_cmd_t
), KM_SLEEP
);
3608 (void) strlcpy(zc
->zc_name
, zvol_name
, sizeof (zc
->zc_name
));
3610 zc
->zc_nvlist_dst
= (uint64_t)(intptr_t)kmem_alloc(size
,
3612 zc
->zc_nvlist_dst_size
= size
;
3613 rc
= ldi_ioctl(zfs_lh
, ZFS_IOC_OBJSET_STATS
, (intptr_t)zc
,
3614 FKIOCTL
, kcred
, &unused
);
3616 * ENOMEM means the list is larger than what we've allocated
3617 * ldi_ioctl will fail with ENOMEM only once
3621 newsize
= zc
->zc_nvlist_dst_size
;
3622 kmem_free((void *)(uintptr_t)zc
->zc_nvlist_dst
, size
);
3625 } else if (rc
!= 0) {
3628 rc
= nvlist_unpack((char *)(uintptr_t)zc
->zc_nvlist_dst
,
3629 zc
->zc_nvlist_dst_size
, &nv
, 0);
3630 ASSERT(rc
== 0); /* nvlist_unpack should not fail */
3631 if ((rc
= nvlist_lookup_nvlist(nv
, "stmf_sbd_lu", &nv2
)) == 0) {
3632 rc
= nvlist_lookup_string(nv2
, ZPROP_VALUE
, &ptr
);
3634 cmn_err(CE_WARN
, "couldn't get value");
3636 *comstarprop
= kmem_alloc(strlen(ptr
) + 1,
3638 (void) strcpy(*comstarprop
, ptr
);
3643 kmem_free((void *)(uintptr_t)zc
->zc_nvlist_dst
, size
);
3644 kmem_free(zc
, sizeof (zfs_cmd_t
));
3645 (void) ldi_close(zfs_lh
, FREAD
|FWRITE
, kcred
);
3651 sbd_zvolset(char *zvol_name
, char *comstarprop
)
3653 ldi_handle_t zfs_lh
;
3655 char *packed
= NULL
;
3661 if ((rc
= ldi_open_by_name("/dev/zfs", FREAD
| FWRITE
, kcred
,
3662 &zfs_lh
, sbd_zfs_ident
)) != 0) {
3663 cmn_err(CE_WARN
, "ldi_open %d", rc
);
3666 (void) nvlist_alloc(&nv
, NV_UNIQUE_NAME
, KM_SLEEP
);
3667 (void) nvlist_add_string(nv
, "stmf_sbd_lu", comstarprop
);
3668 if ((rc
= nvlist_pack(nv
, &packed
, &len
, NV_ENCODE_NATIVE
, KM_SLEEP
))) {
3672 zc
= kmem_zalloc(sizeof (zfs_cmd_t
), KM_SLEEP
);
3673 (void) strlcpy(zc
->zc_name
, zvol_name
, sizeof (zc
->zc_name
));
3674 zc
->zc_nvlist_src
= (uint64_t)(intptr_t)packed
;
3675 zc
->zc_nvlist_src_size
= len
;
3676 rc
= ldi_ioctl(zfs_lh
, ZFS_IOC_SET_PROP
, (intptr_t)zc
,
3677 FKIOCTL
, kcred
, &unused
);
3679 cmn_err(CE_NOTE
, "ioctl failed %d", rc
);
3681 kmem_free(zc
, sizeof (zfs_cmd_t
));
3683 kmem_free(packed
, len
);
3686 (void) ldi_close(zfs_lh
, FREAD
|FWRITE
, kcred
);
3691 * Unmap a region in a volume. Currently only supported for zvols.
3692 * The list of extents to be freed is passed in a dkioc_free_list_t
3693 * which the caller is responsible for destroying.
3696 sbd_unmap(sbd_lu_t
*sl
, dkioc_free_list_t
*dfl
)
3702 if (dfl
->dfl_num_exts
== 0)
3706 * TODO: unmap performance may be improved by not doing the synchronous
3707 * removal of the blocks and writing of the metadata. The
3708 * transaction is in the zil so the state should be stable.
3710 dfl
->dfl_flags
= (sl
->sl_flags
& SL_WRITEBACK_CACHE_DISABLE
) ?
3713 /* Use the data vnode we have to send a fop_ioctl(). */
3714 vp
= sl
->sl_data_vp
;
3716 cmn_err(CE_WARN
, "Cannot unmap - no vnode pointer.");
3720 return (fop_ioctl(vp
, DKIOCFREE
, (intptr_t)dfl
, FKIOCTL
, kcred
,