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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * iSCSI logical unit interfaces
26 */
27
28 #include "iscsi.h"
29 #include <sys/fs/dv_node.h> /* devfs_clean */
30 #include <sys/bootprops.h>
31 #include <sys/sysevent/eventdefs.h>
32 #include <sys/sysevent/dev.h>
33
34 /* tpgt bytes in string form */
35 #define TPGT_EXT_SIZE 5
36
37 /* logical unit number bytes in string form */
38 #define LUN_EXT_SIZE 10
39
40 /*
41 * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
42 * ',' + max str form of logical unit number (4 bytes).
43 */
44 #define ADDR_EXT_SIZE (1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
45
46 /* internal interfaces */
47 static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
48 uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
49 static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,
624 * be called to both offline and free the logical unit.
625 * (This operates soley on the solaris node states.
626 * iscsi_lun_destroy() should be called when attempting
627 * to free all iscsi lun resources.)
628 *
629 * This function can fail with ISCSI_STATUS_BUSY if the
630 * logical unit is in use. The user should unmount or
631 * close the device and perform the nameservice operation
632 * again if this occurs.
633 *
634 * If we fail to offline a LUN that we don't want to destroy,
635 * we will mark it with invalid state. If this LUN still
636 * exists on the target, we can have another chance to online
637 * it again when we do the LUN enumeration.
638 */
639 iscsi_status_t
640 iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
641 {
642 iscsi_status_t status = ISCSI_STATUS_SUCCESS;
643 int circ = 0;
644 dev_info_t *cdip, *pdip;
645 char *devname = NULL;
646 char *pathname = NULL;
647 int rval;
648 boolean_t offline = B_FALSE;
649 nvlist_t *attr_list = NULL;
650
651 ASSERT(ilp != NULL);
652 ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
653
654 /*
655 * Since we carry the logical units parent
656 * lock across the offline call it will not
657 * issue devfs_clean() and may fail with a
658 * devi_ref count > 0.
659 */
660 if (ilp->lun_pip == NULL) {
661 cdip = ilp->lun_dip;
662 } else {
663 cdip = mdi_pi_get_client(ilp->lun_pip);
664 }
665
666 if ((cdip != NULL) &&
667 (lun_free == B_TRUE) &&
668 (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
669 /*
670 * Make sure node is attached otherwise
671 * it won't have related cache nodes to
672 * clean up. i_ddi_devi_attached is
673 * similiar to i_ddi_node_state(cdip) >=
674 * DS_ATTACHED. We should clean up only
675 * when lun_free is set.
676 */
677 if (i_ddi_devi_attached(cdip)) {
678
679 /* Get parent dip */
680 pdip = ddi_get_parent(cdip);
681
682 /* Get full devname */
683 devname = kmem_alloc(MAXNAMELEN + 1, KM_SLEEP);
684 ndi_devi_enter(pdip, &circ);
685 (void) ddi_deviname(cdip, devname);
686 /* Release lock before devfs_clean() */
687 ndi_devi_exit(pdip, circ);
688
689 /* Clean cache */
690 (void) devfs_clean(pdip, devname + 1, DV_CLEAN_FORCE);
691 kmem_free(devname, MAXNAMELEN + 1);
692 }
693 }
694
695 if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
696 pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
697 (void) ddi_pathname(cdip, pathname);
698 }
699
700 /* Attempt to offline the logical units */
701 if (ilp->lun_pip != NULL) {
702
703 /* virt/mdi */
704 ndi_devi_enter(scsi_vhci_dip, &circ);
705 if ((lun_free == B_TRUE) &&
706 (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
707 rval = mdi_pi_offline(ilp->lun_pip,
708 NDI_DEVI_REMOVE);
709 } else {
710 rval = mdi_pi_offline(ilp->lun_pip, 0);
711 }
712
713 if (rval == MDI_SUCCESS) {
714 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
715 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
716 if (lun_free == B_TRUE) {
717 (void) mdi_prop_remove(ilp->lun_pip, NULL);
718 (void) mdi_pi_free(ilp->lun_pip, 0);
719 }
720 offline = B_TRUE;
721 } else {
722 status = ISCSI_STATUS_BUSY;
723 if (lun_free == B_FALSE) {
724 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
725 offline = B_TRUE;
726 }
727 }
728 ndi_devi_exit(scsi_vhci_dip, circ);
729
730 } else {
731
732 /* phys/ndi */
733 ndi_devi_enter(ihp->hba_dip, &circ);
734 if ((lun_free == B_TRUE) &&
735 (ilp->lun_state & ISCSI_LUN_STATE_ONLINE)) {
736 rval = ndi_devi_offline(
737 ilp->lun_dip, NDI_DEVI_REMOVE);
738 } else {
739 rval = ndi_devi_offline(
740 ilp->lun_dip, 0);
741 }
742 if (rval != NDI_SUCCESS) {
743 status = ISCSI_STATUS_BUSY;
744 if (lun_free == B_FALSE) {
745 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
746 offline = B_TRUE;
747 }
748 } else {
749 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
750 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
751 offline = B_TRUE;
752 }
753 ndi_devi_exit(ihp->hba_dip, circ);
754 }
755
756 if (offline == B_TRUE && pathname != NULL &&
757 ilp->lun_type == DTYPE_DIRECT) {
758 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
759 DDI_SUCCESS) {
760 kmem_free(pathname, MAXNAMELEN + 1);
761 return (status);
762 }
|
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 /*
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 */
27
28 /*
29 * Copyright 2018 Nexenta Systems, Inc.
30 */
31
32 /*
33 * iSCSI logical unit interfaces
34 */
35
36 #include "iscsi.h"
37 #include <sys/bootprops.h>
38 #include <sys/sysevent/eventdefs.h>
39 #include <sys/sysevent/dev.h>
40
41 /* tpgt bytes in string form */
42 #define TPGT_EXT_SIZE 5
43
44 /* logical unit number bytes in string form */
45 #define LUN_EXT_SIZE 10
46
47 /*
48 * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
49 * ',' + max str form of logical unit number (4 bytes).
50 */
51 #define ADDR_EXT_SIZE (1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
52
53 /* internal interfaces */
54 static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
55 uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
56 static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,
631 * be called to both offline and free the logical unit.
632 * (This operates soley on the solaris node states.
633 * iscsi_lun_destroy() should be called when attempting
634 * to free all iscsi lun resources.)
635 *
636 * This function can fail with ISCSI_STATUS_BUSY if the
637 * logical unit is in use. The user should unmount or
638 * close the device and perform the nameservice operation
639 * again if this occurs.
640 *
641 * If we fail to offline a LUN that we don't want to destroy,
642 * we will mark it with invalid state. If this LUN still
643 * exists on the target, we can have another chance to online
644 * it again when we do the LUN enumeration.
645 */
646 iscsi_status_t
647 iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
648 {
649 iscsi_status_t status = ISCSI_STATUS_SUCCESS;
650 int circ = 0;
651 dev_info_t *cdip;
652 char *pathname = NULL;
653 boolean_t offline = B_FALSE;
654 nvlist_t *attr_list = NULL;
655
656 ASSERT(ilp != NULL);
657 ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
658
659 if (ilp->lun_pip == NULL)
660 cdip = ilp->lun_dip;
661 else
662 cdip = mdi_pi_get_client(ilp->lun_pip);
663
664 if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
665 pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
666 (void) ddi_pathname(cdip, pathname);
667 }
668
669 /* Attempt to offline the logical units */
670 if (ilp->lun_pip != NULL) {
671 /* virt/mdi */
672 ndi_devi_enter(scsi_vhci_dip, &circ);
673 if (mdi_pi_offline(ilp->lun_pip, 0) == MDI_SUCCESS) {
674 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
675 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
676 if (lun_free == B_TRUE) {
677 (void) mdi_prop_remove(ilp->lun_pip, NULL);
678 (void) mdi_pi_free(ilp->lun_pip, 0);
679 }
680 offline = B_TRUE;
681 } else {
682 status = ISCSI_STATUS_BUSY;
683 if (lun_free == B_FALSE) {
684 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
685 offline = B_TRUE;
686 }
687 }
688 ndi_devi_exit(scsi_vhci_dip, circ);
689
690 } else {
691 /* phys/ndi */
692 int flags = NDI_DEVFS_CLEAN;
693
694 ndi_devi_enter(ihp->hba_dip, &circ);
695 if (lun_free == B_TRUE &&
696 (ilp->lun_state & ISCSI_LUN_STATE_ONLINE))
697 flags |= NDI_DEVI_REMOVE;
698 if (ndi_devi_offline(ilp->lun_dip, flags) != NDI_SUCCESS) {
699 status = ISCSI_STATUS_BUSY;
700 if (lun_free == B_FALSE) {
701 ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
702 offline = B_TRUE;
703 }
704 } else {
705 ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
706 ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
707 offline = B_TRUE;
708 }
709 ndi_devi_exit(ihp->hba_dip, circ);
710 }
711
712 if (offline == B_TRUE && pathname != NULL &&
713 ilp->lun_type == DTYPE_DIRECT) {
714 if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
715 DDI_SUCCESS) {
716 kmem_free(pathname, MAXNAMELEN + 1);
717 return (status);
718 }
|