1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
225295a27aSJack Meng * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
2461dfa509SRick McNeal */
2561dfa509SRick McNeal
2661dfa509SRick McNeal /*
2761dfa509SRick McNeal * Copyright 2019 Nexenta Systems, Inc.
28*3fe80ca4SDan Cross * Copyright 2023 Oxide Computer Company
2961dfa509SRick McNeal */
3061dfa509SRick McNeal
3161dfa509SRick McNeal /*
32fcf3ce44SJohn Forte * iSCSI logical unit interfaces
33fcf3ce44SJohn Forte */
34fcf3ce44SJohn Forte
35fcf3ce44SJohn Forte #include "iscsi.h"
366cefaae1SJack Meng #include <sys/bootprops.h>
37c60a6da3Sbing zhao - Sun Microsystems - Beijing China #include <sys/sysevent/eventdefs.h>
38c60a6da3Sbing zhao - Sun Microsystems - Beijing China #include <sys/sysevent/dev.h>
39fcf3ce44SJohn Forte
40fcf3ce44SJohn Forte /* tpgt bytes in string form */
41fcf3ce44SJohn Forte #define TPGT_EXT_SIZE 5
42fcf3ce44SJohn Forte
43fcf3ce44SJohn Forte /* logical unit number bytes in string form */
44fcf3ce44SJohn Forte #define LUN_EXT_SIZE 10
45fcf3ce44SJohn Forte
46fcf3ce44SJohn Forte /*
47fcf3ce44SJohn Forte * Addition addr size of size of ',' + max str form of tpgt (2 bytes) +
48fcf3ce44SJohn Forte * ',' + max str form of logical unit number (4 bytes).
49fcf3ce44SJohn Forte */
50fcf3ce44SJohn Forte #define ADDR_EXT_SIZE (1 + TPGT_EXT_SIZE + 1 + LUN_EXT_SIZE)
51fcf3ce44SJohn Forte
52fcf3ce44SJohn Forte /* internal interfaces */
53fcf3ce44SJohn Forte static iscsi_status_t iscsi_lun_virt_create(iscsi_sess_t *isp,
54fcf3ce44SJohn Forte uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
55fcf3ce44SJohn Forte static iscsi_status_t iscsi_lun_phys_create(iscsi_sess_t *isp,
56fcf3ce44SJohn Forte uint16_t lun_num, iscsi_lun_t *ilp, struct scsi_inquiry *inq);
57fcf3ce44SJohn Forte
58fcf3ce44SJohn Forte extern dev_info_t *scsi_vhci_dip;
596cefaae1SJack Meng extern ib_boot_prop_t *iscsiboot_prop;
60fcf3ce44SJohn Forte
61fcf3ce44SJohn Forte /*
62fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
63fcf3ce44SJohn Forte * | External Connection Interfaces |
64fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
65fcf3ce44SJohn Forte */
66fcf3ce44SJohn Forte
67fcf3ce44SJohn Forte
68fcf3ce44SJohn Forte /*
69fcf3ce44SJohn Forte * iscsi_lun_create - This function will create a lun mapping.
70fcf3ce44SJohn Forte * logic specific to MPxIO vs. NDI node creation is switched
71fcf3ce44SJohn Forte * out to a helper function.
72fcf3ce44SJohn Forte */
73fcf3ce44SJohn Forte iscsi_status_t
iscsi_lun_create(iscsi_sess_t * isp,uint16_t lun_num,uint8_t lun_addr_type,struct scsi_inquiry * inq,char * guid)74fcf3ce44SJohn Forte iscsi_lun_create(iscsi_sess_t *isp, uint16_t lun_num, uint8_t lun_addr_type,
75fcf3ce44SJohn Forte struct scsi_inquiry *inq, char *guid)
76fcf3ce44SJohn Forte {
77fcf3ce44SJohn Forte iscsi_status_t rtn = ISCSI_STATUS_INTERNAL_ERROR;
78fcf3ce44SJohn Forte iscsi_hba_t *ihp = NULL;
79fcf3ce44SJohn Forte iscsi_lun_t *ilp = NULL;
80fcf3ce44SJohn Forte iscsi_lun_t *ilp_tmp = NULL;
81fcf3ce44SJohn Forte char *addr = NULL;
826cefaae1SJack Meng uint16_t boot_lun_num = 0;
836cefaae1SJack Meng uint64_t *lun_num_ptr = NULL;
84b7a38285Sbing zhao - Sun Microsystems - Beijing China uint32_t oid_tmp = 0;
85fcf3ce44SJohn Forte
86fcf3ce44SJohn Forte ASSERT(isp != NULL);
87fcf3ce44SJohn Forte ihp = isp->sess_hba;
88fcf3ce44SJohn Forte ASSERT(ihp != NULL);
89fcf3ce44SJohn Forte
90b7a38285Sbing zhao - Sun Microsystems - Beijing China mutex_enter(&iscsi_oid_mutex);
91b7a38285Sbing zhao - Sun Microsystems - Beijing China oid_tmp = iscsi_oid++;
92b7a38285Sbing zhao - Sun Microsystems - Beijing China mutex_exit(&iscsi_oid_mutex);
93b7a38285Sbing zhao - Sun Microsystems - Beijing China
94b7a38285Sbing zhao - Sun Microsystems - Beijing China rw_enter(&isp->sess_lun_list_rwlock, RW_WRITER);
95b7a38285Sbing zhao - Sun Microsystems - Beijing China /*
96b7a38285Sbing zhao - Sun Microsystems - Beijing China * Check whether it has already existed in the list.
97b7a38285Sbing zhao - Sun Microsystems - Beijing China */
98b7a38285Sbing zhao - Sun Microsystems - Beijing China for (ilp_tmp = isp->sess_lun_list; ilp_tmp != NULL;
99b7a38285Sbing zhao - Sun Microsystems - Beijing China ilp_tmp = ilp_tmp->lun_next) {
100b7a38285Sbing zhao - Sun Microsystems - Beijing China if (ilp_tmp->lun_num == lun_num) {
101b7a38285Sbing zhao - Sun Microsystems - Beijing China /*
102b7a38285Sbing zhao - Sun Microsystems - Beijing China * The logic unit has already existed in the list,
103b7a38285Sbing zhao - Sun Microsystems - Beijing China * return with success.
104b7a38285Sbing zhao - Sun Microsystems - Beijing China */
105b7a38285Sbing zhao - Sun Microsystems - Beijing China rw_exit(&isp->sess_lun_list_rwlock);
106b7a38285Sbing zhao - Sun Microsystems - Beijing China return (ISCSI_STATUS_SUCCESS);
107b7a38285Sbing zhao - Sun Microsystems - Beijing China }
108b7a38285Sbing zhao - Sun Microsystems - Beijing China }
109b7a38285Sbing zhao - Sun Microsystems - Beijing China
110fcf3ce44SJohn Forte addr = kmem_zalloc((strlen((char *)isp->sess_name) +
111fcf3ce44SJohn Forte ADDR_EXT_SIZE + 1), KM_SLEEP);
112fcf3ce44SJohn Forte (void) snprintf(addr,
113fcf3ce44SJohn Forte (strlen((char *)isp->sess_name) +
114fcf3ce44SJohn Forte ADDR_EXT_SIZE + 1),
115fcf3ce44SJohn Forte "%02X%02X%s%04X,%d", isp->sess_isid[4],
116fcf3ce44SJohn Forte isp->sess_isid[5], isp->sess_name,
1176cefaae1SJack Meng isp->sess_tpgt_nego & 0xFFFF, lun_num);
118fcf3ce44SJohn Forte
119fcf3ce44SJohn Forte /* allocate space for lun struct */
120fcf3ce44SJohn Forte ilp = kmem_zalloc(sizeof (iscsi_lun_t), KM_SLEEP);
121fcf3ce44SJohn Forte ilp->lun_sig = ISCSI_SIG_LUN;
12291dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
12391dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
124fcf3ce44SJohn Forte
125fcf3ce44SJohn Forte /* initialize common LU information */
126fcf3ce44SJohn Forte ilp->lun_num = lun_num;
127fcf3ce44SJohn Forte ilp->lun_addr_type = lun_addr_type;
128fcf3ce44SJohn Forte ilp->lun_sess = isp;
129fcf3ce44SJohn Forte ilp->lun_addr = addr;
130c60a6da3Sbing zhao - Sun Microsystems - Beijing China ilp->lun_type = inq->inq_dtype & DTYPE_MASK;
131b7a38285Sbing zhao - Sun Microsystems - Beijing China ilp->lun_oid = oid_tmp;
13261dfa509SRick McNeal /*
13361dfa509SRick McNeal * Setting refcnt to 1 is the first hold for the LUN structure.
13461dfa509SRick McNeal */
13561dfa509SRick McNeal ilp->lun_refcnt = 1;
13661dfa509SRick McNeal mutex_init(&ilp->lun_mutex, NULL, MUTEX_DRIVER, NULL);
137fcf3ce44SJohn Forte
138fcf3ce44SJohn Forte bcopy(inq->inq_vid, ilp->lun_vid, sizeof (inq->inq_vid));
139fcf3ce44SJohn Forte bcopy(inq->inq_pid, ilp->lun_pid, sizeof (inq->inq_pid));
140fcf3ce44SJohn Forte
141fcf3ce44SJohn Forte /* store GUID if valid one exists */
142fcf3ce44SJohn Forte if (guid != NULL) {
143fcf3ce44SJohn Forte ilp->lun_guid_size = strlen(guid) + 1;
144fcf3ce44SJohn Forte ilp->lun_guid = kmem_zalloc(ilp->lun_guid_size, KM_SLEEP);
145fcf3ce44SJohn Forte (void) strcpy(ilp->lun_guid, guid);
146fcf3ce44SJohn Forte } else {
147fcf3ce44SJohn Forte ilp->lun_guid_size = 0;
148fcf3ce44SJohn Forte ilp->lun_guid = NULL;
149fcf3ce44SJohn Forte }
150fcf3ce44SJohn Forte
151fcf3ce44SJohn Forte /*
152fcf3ce44SJohn Forte * We need to add the lun to our lists now because during the
153fcf3ce44SJohn Forte * lun creation we will get called back into multiple times
154fcf3ce44SJohn Forte * depending on the createion type. These callbacks will
155fcf3ce44SJohn Forte * occur via our tran_init_lun, tran_get_name, tran_get_bus_addr,
156fcf3ce44SJohn Forte * tran_init_pkt, tran_start.
157fcf3ce44SJohn Forte */
158fcf3ce44SJohn Forte if (isp->sess_lun_list == NULL) {
159fcf3ce44SJohn Forte isp->sess_lun_list = ilp;
160fcf3ce44SJohn Forte } else {
161fcf3ce44SJohn Forte ilp->lun_next = isp->sess_lun_list;
162fcf3ce44SJohn Forte isp->sess_lun_list = ilp;
163fcf3ce44SJohn Forte }
164fcf3ce44SJohn Forte
165fcf3ce44SJohn Forte /* Attempt to create a scsi_vhci binding if GUID is available */
166fcf3ce44SJohn Forte if ((ihp->hba_mpxio_enabled == B_TRUE) &&
167fcf3ce44SJohn Forte (guid != NULL)) {
168fcf3ce44SJohn Forte rtn = iscsi_lun_virt_create(isp, lun_num, ilp, inq);
169fcf3ce44SJohn Forte }
170fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rtn)) {
171fcf3ce44SJohn Forte /* unable to bind under scsi_vhci, failback to ndi */
172fcf3ce44SJohn Forte rtn = iscsi_lun_phys_create(isp, lun_num, ilp, inq);
173fcf3ce44SJohn Forte }
174fcf3ce44SJohn Forte
175fcf3ce44SJohn Forte /*
176fcf3ce44SJohn Forte * If NOT successful we need to remove the lun from the
177fcf3ce44SJohn Forte * session and free any related resources.
178fcf3ce44SJohn Forte */
179fcf3ce44SJohn Forte if (!ISCSI_SUCCESS(rtn)) {
180fcf3ce44SJohn Forte if (ilp == isp->sess_lun_list) {
181fcf3ce44SJohn Forte /* if head, set head to our next */
182fcf3ce44SJohn Forte isp->sess_lun_list = ilp->lun_next;
183fcf3ce44SJohn Forte } else {
184fcf3ce44SJohn Forte /* if not head, set prev lun's next to our next */
185fcf3ce44SJohn Forte for (ilp_tmp = isp->sess_lun_list; ilp_tmp;
186fcf3ce44SJohn Forte ilp_tmp = ilp_tmp->lun_next) {
187fcf3ce44SJohn Forte if (ilp_tmp->lun_next == ilp) {
188fcf3ce44SJohn Forte ilp_tmp->lun_next = ilp->lun_next;
189fcf3ce44SJohn Forte break;
190fcf3ce44SJohn Forte }
191fcf3ce44SJohn Forte }
192fcf3ce44SJohn Forte }
193fcf3ce44SJohn Forte
194fcf3ce44SJohn Forte kmem_free(ilp->lun_addr,
195fcf3ce44SJohn Forte (strlen((char *)isp->sess_name) +
196fcf3ce44SJohn Forte ADDR_EXT_SIZE + 1));
197fcf3ce44SJohn Forte ilp->lun_addr = NULL;
198fcf3ce44SJohn Forte
199fcf3ce44SJohn Forte if (ilp->lun_guid != NULL) {
200fcf3ce44SJohn Forte kmem_free(ilp->lun_guid, ilp->lun_guid_size);
201fcf3ce44SJohn Forte ilp->lun_guid = NULL;
202fcf3ce44SJohn Forte }
20361dfa509SRick McNeal mutex_destroy(&ilp->lun_mutex);
204fcf3ce44SJohn Forte kmem_free(ilp, sizeof (iscsi_lun_t));
205fcf3ce44SJohn Forte } else {
20691dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
20791dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
208fcf3ce44SJohn Forte ilp->lun_time_online = ddi_get_time();
2096cefaae1SJack Meng
2106cefaae1SJack Meng /* Check whether this is the required LUN for iscsi boot */
2116cefaae1SJack Meng if (iscsiboot_prop != NULL && isp->sess_boot == B_TRUE &&
2126cefaae1SJack Meng iscsiboot_prop->boot_tgt.lun_online == 0) {
2136cefaae1SJack Meng lun_num_ptr =
2146cefaae1SJack Meng (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
2156cefaae1SJack Meng boot_lun_num = (uint16_t)(*lun_num_ptr);
2166cefaae1SJack Meng if (boot_lun_num == ilp->lun_num) {
2176cefaae1SJack Meng /*
2186cefaae1SJack Meng * During iscsi boot, the boot lun has been
2196cefaae1SJack Meng * online, we should set the "online flag".
2206cefaae1SJack Meng */
2216cefaae1SJack Meng iscsiboot_prop->boot_tgt.lun_online = 1;
2226cefaae1SJack Meng }
2236cefaae1SJack Meng }
224fcf3ce44SJohn Forte }
225fcf3ce44SJohn Forte rw_exit(&isp->sess_lun_list_rwlock);
226fcf3ce44SJohn Forte
227fcf3ce44SJohn Forte return (rtn);
228fcf3ce44SJohn Forte }
229fcf3ce44SJohn Forte
23061dfa509SRick McNeal void
iscsi_lun_hold(iscsi_lun_t * ilp)23161dfa509SRick McNeal iscsi_lun_hold(iscsi_lun_t *ilp)
23261dfa509SRick McNeal {
23361dfa509SRick McNeal mutex_enter(&ilp->lun_mutex);
23461dfa509SRick McNeal /*
23561dfa509SRick McNeal * By design lun_refcnt should never be zero when this routine
23661dfa509SRick McNeal * is called. When the LUN is created the refcnt is set to 1.
23761dfa509SRick McNeal * If iscsi_lun_rele is called and the refcnt goes to zero the
23861dfa509SRick McNeal * structure will be freed so this method shouldn't be called
23961dfa509SRick McNeal * afterwards.
24061dfa509SRick McNeal */
24161dfa509SRick McNeal ASSERT(ilp->lun_refcnt > 0);
24261dfa509SRick McNeal ilp->lun_refcnt++;
24361dfa509SRick McNeal mutex_exit(&ilp->lun_mutex);
24461dfa509SRick McNeal }
24561dfa509SRick McNeal
24661dfa509SRick McNeal void
iscsi_lun_rele(iscsi_lun_t * ilp)24761dfa509SRick McNeal iscsi_lun_rele(iscsi_lun_t *ilp)
24861dfa509SRick McNeal {
24961dfa509SRick McNeal ASSERT(ilp != NULL);
25061dfa509SRick McNeal
25161dfa509SRick McNeal mutex_enter(&ilp->lun_mutex);
25261dfa509SRick McNeal ASSERT(ilp->lun_refcnt > 0);
25361dfa509SRick McNeal if (--ilp->lun_refcnt == 0) {
25461dfa509SRick McNeal iscsi_sess_t *isp;
25561dfa509SRick McNeal
25661dfa509SRick McNeal isp = ilp->lun_sess;
25761dfa509SRick McNeal ASSERT(isp != NULL);
25861dfa509SRick McNeal
25961dfa509SRick McNeal /* ---- release its memory ---- */
26061dfa509SRick McNeal kmem_free(ilp->lun_addr, (strlen((char *)isp->sess_name) +
26161dfa509SRick McNeal ADDR_EXT_SIZE + 1));
26261dfa509SRick McNeal
26361dfa509SRick McNeal if (ilp->lun_guid != NULL) {
26461dfa509SRick McNeal kmem_free(ilp->lun_guid, ilp->lun_guid_size);
26561dfa509SRick McNeal }
26661dfa509SRick McNeal mutex_destroy(&ilp->lun_mutex);
26761dfa509SRick McNeal kmem_free(ilp, sizeof (iscsi_lun_t));
26861dfa509SRick McNeal } else {
26961dfa509SRick McNeal mutex_exit(&ilp->lun_mutex);
27061dfa509SRick McNeal }
27161dfa509SRick McNeal }
27261dfa509SRick McNeal
27361dfa509SRick McNeal /*
27461dfa509SRick McNeal * iscsi_lun_cmd_cancel -- as the name implies, cancel all commands for the lun
27561dfa509SRick McNeal *
27661dfa509SRick McNeal * This code is similar to the timeout function with a lot less checking of
27761dfa509SRick McNeal * state before sending the ABORT event for commands on the pending queue.
27861dfa509SRick McNeal *
27961dfa509SRick McNeal * This function is only used by iscsi_lun_destroy().
28061dfa509SRick McNeal */
28161dfa509SRick McNeal static void
iscsi_lun_cmd_cancel(iscsi_lun_t * ilp)28261dfa509SRick McNeal iscsi_lun_cmd_cancel(iscsi_lun_t *ilp)
28361dfa509SRick McNeal {
28461dfa509SRick McNeal iscsi_sess_t *isp;
28561dfa509SRick McNeal iscsi_cmd_t *icmdp, *nicmdp;
28661dfa509SRick McNeal
28761dfa509SRick McNeal isp = ilp->lun_sess;
28861dfa509SRick McNeal rw_enter(&isp->sess_state_rwlock, RW_READER);
28961dfa509SRick McNeal mutex_enter(&isp->sess_queue_pending.mutex);
29061dfa509SRick McNeal for (icmdp = isp->sess_queue_pending.head;
29161dfa509SRick McNeal icmdp; icmdp = nicmdp) {
29261dfa509SRick McNeal nicmdp = icmdp->cmd_next;
29361dfa509SRick McNeal
29461dfa509SRick McNeal /*
29561dfa509SRick McNeal * For commands on the pending queue we can go straight
29661dfa509SRick McNeal * to and abort request which will free the command
29761dfa509SRick McNeal * and call back to the complete function.
29861dfa509SRick McNeal */
29961dfa509SRick McNeal iscsi_cmd_state_machine(icmdp, ISCSI_CMD_EVENT_E4, isp);
30061dfa509SRick McNeal }
30161dfa509SRick McNeal mutex_exit(&isp->sess_queue_pending.mutex);
30261dfa509SRick McNeal rw_exit(&isp->sess_state_rwlock);
30361dfa509SRick McNeal }
30461dfa509SRick McNeal
305fcf3ce44SJohn Forte /*
306fcf3ce44SJohn Forte * iscsi_lun_destroy - offline and remove lun
307fcf3ce44SJohn Forte *
308fcf3ce44SJohn Forte * This interface is called when a name service change has
309fcf3ce44SJohn Forte * occured and the storage is no longer available to this
310fcf3ce44SJohn Forte * initiator. This function will offline and free the
311fcf3ce44SJohn Forte * solaris node resources. Then it will free all iscsi lun
312fcf3ce44SJohn Forte * resources.
313fcf3ce44SJohn Forte *
314fcf3ce44SJohn Forte * This function can fail with ISCSI_STATUS_BUSY if the
315fcf3ce44SJohn Forte * logical unit is in use. The user should unmount or
316fcf3ce44SJohn Forte * close the device and perform the nameservice operation
317fcf3ce44SJohn Forte * again if this occurs.
318fcf3ce44SJohn Forte */
319fcf3ce44SJohn Forte iscsi_status_t
iscsi_lun_destroy(iscsi_hba_t * ihp,iscsi_lun_t * ilp)320fcf3ce44SJohn Forte iscsi_lun_destroy(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
321fcf3ce44SJohn Forte {
322fcf3ce44SJohn Forte iscsi_status_t status = ISCSI_STATUS_SUCCESS;
323fcf3ce44SJohn Forte iscsi_sess_t *isp = NULL;
324fcf3ce44SJohn Forte iscsi_lun_t *t_ilp = NULL;
325fcf3ce44SJohn Forte
326fcf3ce44SJohn Forte ASSERT(ilp != NULL);
327fcf3ce44SJohn Forte isp = ilp->lun_sess;
328fcf3ce44SJohn Forte ASSERT(isp != NULL);
329fcf3ce44SJohn Forte
33061dfa509SRick McNeal /* flush all outstanding commands first */
33161dfa509SRick McNeal iscsi_lun_cmd_cancel(ilp);
33261dfa509SRick McNeal
333fcf3ce44SJohn Forte /* attempt to offline and free solaris node */
334fcf3ce44SJohn Forte status = iscsi_lun_offline(ihp, ilp, B_TRUE);
335fcf3ce44SJohn Forte
336fcf3ce44SJohn Forte /* If we successfully unplumbed the lun remove it from our lists */
337fcf3ce44SJohn Forte if (ISCSI_SUCCESS(status)) {
338fcf3ce44SJohn Forte if (isp->sess_lun_list == ilp) {
339fcf3ce44SJohn Forte /* target first item in list */
340fcf3ce44SJohn Forte isp->sess_lun_list = ilp->lun_next;
341fcf3ce44SJohn Forte } else {
342fcf3ce44SJohn Forte /*
343fcf3ce44SJohn Forte * search session list for ilp pointing
344fcf3ce44SJohn Forte * to lun being removed. Then
345fcf3ce44SJohn Forte * update that luns next pointer.
346fcf3ce44SJohn Forte */
347fcf3ce44SJohn Forte t_ilp = isp->sess_lun_list;
348fcf3ce44SJohn Forte while (t_ilp->lun_next != NULL) {
349fcf3ce44SJohn Forte if (t_ilp->lun_next == ilp) {
350fcf3ce44SJohn Forte break;
351fcf3ce44SJohn Forte }
352fcf3ce44SJohn Forte t_ilp = t_ilp->lun_next;
353fcf3ce44SJohn Forte }
354fcf3ce44SJohn Forte if (t_ilp->lun_next == ilp) {
355fcf3ce44SJohn Forte t_ilp->lun_next = ilp->lun_next;
356fcf3ce44SJohn Forte } else {
357fcf3ce44SJohn Forte /* couldn't find session */
358fcf3ce44SJohn Forte ASSERT(FALSE);
359fcf3ce44SJohn Forte }
360fcf3ce44SJohn Forte }
361fcf3ce44SJohn Forte
36261dfa509SRick McNeal iscsi_lun_rele(ilp);
363fcf3ce44SJohn Forte }
364fcf3ce44SJohn Forte
365fcf3ce44SJohn Forte return (status);
366fcf3ce44SJohn Forte }
367fcf3ce44SJohn Forte
368fcf3ce44SJohn Forte /*
369fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
370fcf3ce44SJohn Forte * | External Logical Unit Interfaces |
371fcf3ce44SJohn Forte * +--------------------------------------------------------------------+
372fcf3ce44SJohn Forte */
373fcf3ce44SJohn Forte
374fcf3ce44SJohn Forte /*
375fcf3ce44SJohn Forte * iscsi_lun_virt_create - Creates solaris logical unit via MDI
376fcf3ce44SJohn Forte */
377fcf3ce44SJohn Forte static iscsi_status_t
iscsi_lun_virt_create(iscsi_sess_t * isp,uint16_t lun_num,iscsi_lun_t * ilp,struct scsi_inquiry * inq)378fcf3ce44SJohn Forte iscsi_lun_virt_create(iscsi_sess_t *isp, uint16_t lun_num, iscsi_lun_t *ilp,
379fcf3ce44SJohn Forte struct scsi_inquiry *inq)
380fcf3ce44SJohn Forte {
381fcf3ce44SJohn Forte iscsi_status_t rtn = ISCSI_STATUS_INTERNAL_ERROR;
382fcf3ce44SJohn Forte int mdi_rtn = MDI_FAILURE;
383fcf3ce44SJohn Forte iscsi_hba_t *ihp = NULL;
384fcf3ce44SJohn Forte mdi_pathinfo_t *pip = NULL;
385fcf3ce44SJohn Forte char *nodename = NULL;
386fcf3ce44SJohn Forte char **compatible = NULL;
387fcf3ce44SJohn Forte int ncompatible = 0;
388fcf3ce44SJohn Forte
389fcf3ce44SJohn Forte ASSERT(isp != NULL);
390fcf3ce44SJohn Forte ASSERT(ilp != NULL);
391fcf3ce44SJohn Forte ihp = isp->sess_hba;
392fcf3ce44SJohn Forte ASSERT(ihp != NULL);
393fcf3ce44SJohn Forte
394fcf3ce44SJohn Forte /*
395fcf3ce44SJohn Forte * Generate compatible property
396fcf3ce44SJohn Forte */
397fcf3ce44SJohn Forte scsi_hba_nodename_compatible_get(inq, "vhci",
398fcf3ce44SJohn Forte inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
399fcf3ce44SJohn Forte
400fcf3ce44SJohn Forte /* if nodename can't be determined then print a message and skip it */
401fcf3ce44SJohn Forte if (nodename == NULL) {
402fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver found no compatible driver "
403fcf3ce44SJohn Forte "for %s lun %d dtype:0x%02x", isp->sess_name, lun_num,
404fcf3ce44SJohn Forte inq->inq_dtype);
405fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
406fcf3ce44SJohn Forte }
407fcf3ce44SJohn Forte
408fcf3ce44SJohn Forte /*
409fcf3ce44SJohn Forte *
410fcf3ce44SJohn Forte */
411*3fe80ca4SDan Cross ndi_devi_enter(scsi_vhci_dip);
412fcf3ce44SJohn Forte mdi_rtn = mdi_pi_alloc_compatible(ihp->hba_dip, nodename,
413fcf3ce44SJohn Forte ilp->lun_guid, ilp->lun_addr, compatible, ncompatible,
414fcf3ce44SJohn Forte 0, &pip);
415fcf3ce44SJohn Forte
416fcf3ce44SJohn Forte if (mdi_rtn == MDI_SUCCESS) {
417fcf3ce44SJohn Forte mdi_pi_set_phci_private(pip, (caddr_t)ilp);
418fcf3ce44SJohn Forte
419fcf3ce44SJohn Forte if (mdi_prop_update_string(pip, MDI_GUID,
420fcf3ce44SJohn Forte ilp->lun_guid) != DDI_SUCCESS) {
421fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
422fcf3ce44SJohn Forte "property for %s lun %d (MDI_GUID)",
423fcf3ce44SJohn Forte isp->sess_name, lun_num);
424fcf3ce44SJohn Forte mdi_rtn = MDI_FAILURE;
425fcf3ce44SJohn Forte goto virt_create_done;
426fcf3ce44SJohn Forte }
427fcf3ce44SJohn Forte
428fcf3ce44SJohn Forte if (mdi_prop_update_int(pip, TARGET_PROP,
429fcf3ce44SJohn Forte isp->sess_oid) != DDI_SUCCESS) {
430fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
431fcf3ce44SJohn Forte "property for %s lun %d (TARGET_PROP)",
432fcf3ce44SJohn Forte isp->sess_name, lun_num);
433fcf3ce44SJohn Forte mdi_rtn = MDI_FAILURE;
434fcf3ce44SJohn Forte goto virt_create_done;
435fcf3ce44SJohn Forte }
436fcf3ce44SJohn Forte
437fcf3ce44SJohn Forte if (mdi_prop_update_int(pip, LUN_PROP,
438fcf3ce44SJohn Forte ilp->lun_num) != DDI_SUCCESS) {
439fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
440fcf3ce44SJohn Forte "property for %s lun %d (LUN_PROP)",
441fcf3ce44SJohn Forte isp->sess_name, lun_num);
442fcf3ce44SJohn Forte mdi_rtn = MDI_FAILURE;
443fcf3ce44SJohn Forte goto virt_create_done;
444fcf3ce44SJohn Forte }
445fcf3ce44SJohn Forte
446fcf3ce44SJohn Forte if (mdi_prop_update_string_array(pip, "compatible",
447fcf3ce44SJohn Forte compatible, ncompatible) !=
448fcf3ce44SJohn Forte DDI_PROP_SUCCESS) {
449fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
450fcf3ce44SJohn Forte "property for %s lun %d (COMPATIBLE)",
451fcf3ce44SJohn Forte isp->sess_name, lun_num);
452fcf3ce44SJohn Forte mdi_rtn = MDI_FAILURE;
453fcf3ce44SJohn Forte goto virt_create_done;
454fcf3ce44SJohn Forte }
455fcf3ce44SJohn Forte
456fcf3ce44SJohn Forte mdi_rtn = mdi_pi_online(pip, 0);
457fcf3ce44SJohn Forte if (mdi_rtn == MDI_NOT_SUPPORTED) {
458fcf3ce44SJohn Forte mdi_rtn = MDI_FAILURE;
459fcf3ce44SJohn Forte goto virt_create_done;
460fcf3ce44SJohn Forte }
461fcf3ce44SJohn Forte
462fcf3ce44SJohn Forte ilp->lun_pip = pip;
463fcf3ce44SJohn Forte ilp->lun_dip = NULL;
464fcf3ce44SJohn Forte
465fcf3ce44SJohn Forte virt_create_done:
466fcf3ce44SJohn Forte
467fcf3ce44SJohn Forte if (pip && mdi_rtn != MDI_SUCCESS) {
468fcf3ce44SJohn Forte ilp->lun_pip = NULL;
469fcf3ce44SJohn Forte ilp->lun_dip = NULL;
470fcf3ce44SJohn Forte (void) mdi_prop_remove(pip, NULL);
471fcf3ce44SJohn Forte (void) mdi_pi_free(pip, 0);
472fcf3ce44SJohn Forte } else {
473fcf3ce44SJohn Forte rtn = ISCSI_STATUS_SUCCESS;
474fcf3ce44SJohn Forte }
475fcf3ce44SJohn Forte }
476*3fe80ca4SDan Cross ndi_devi_exit(scsi_vhci_dip);
477fcf3ce44SJohn Forte
478fcf3ce44SJohn Forte scsi_hba_nodename_compatible_free(nodename, compatible);
479fcf3ce44SJohn Forte
480fcf3ce44SJohn Forte return (rtn);
481fcf3ce44SJohn Forte }
482fcf3ce44SJohn Forte
483fcf3ce44SJohn Forte
484fcf3ce44SJohn Forte /*
485fcf3ce44SJohn Forte * iscsi_lun_phys_create - creates solaris logical unit via NDI
486fcf3ce44SJohn Forte */
487fcf3ce44SJohn Forte static iscsi_status_t
iscsi_lun_phys_create(iscsi_sess_t * isp,uint16_t lun_num,iscsi_lun_t * ilp,struct scsi_inquiry * inq)488fcf3ce44SJohn Forte iscsi_lun_phys_create(iscsi_sess_t *isp, uint16_t lun_num,
489fcf3ce44SJohn Forte iscsi_lun_t *ilp, struct scsi_inquiry *inq)
490fcf3ce44SJohn Forte {
491fcf3ce44SJohn Forte iscsi_status_t rtn = ISCSI_STATUS_INTERNAL_ERROR;
492fcf3ce44SJohn Forte int ndi_rtn = NDI_FAILURE;
493fcf3ce44SJohn Forte iscsi_hba_t *ihp = NULL;
494fcf3ce44SJohn Forte dev_info_t *lun_dip = NULL;
495fcf3ce44SJohn Forte char *nodename = NULL;
496fcf3ce44SJohn Forte char **compatible = NULL;
497fcf3ce44SJohn Forte int ncompatible = 0;
498fcf3ce44SJohn Forte char *scsi_binding_set = NULL;
499fcf3ce44SJohn Forte char instance[32];
500fcf3ce44SJohn Forte
501fcf3ce44SJohn Forte ASSERT(isp != NULL);
502fcf3ce44SJohn Forte ASSERT(ilp != NULL);
503fcf3ce44SJohn Forte ihp = isp->sess_hba;
504fcf3ce44SJohn Forte ASSERT(ihp != NULL);
505fcf3ce44SJohn Forte ASSERT(inq != NULL);
506fcf3ce44SJohn Forte
507fcf3ce44SJohn Forte /* get the 'scsi-binding-set' property */
508fcf3ce44SJohn Forte if (ddi_prop_lookup_string(DDI_DEV_T_ANY, isp->sess_hba->hba_dip,
509fcf3ce44SJohn Forte DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "scsi-binding-set",
510fcf3ce44SJohn Forte &scsi_binding_set) != DDI_PROP_SUCCESS) {
511fcf3ce44SJohn Forte scsi_binding_set = NULL;
512fcf3ce44SJohn Forte }
513fcf3ce44SJohn Forte
514fcf3ce44SJohn Forte /* generate compatible property */
515fcf3ce44SJohn Forte scsi_hba_nodename_compatible_get(inq, scsi_binding_set,
516fcf3ce44SJohn Forte inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible);
517fcf3ce44SJohn Forte if (scsi_binding_set)
518fcf3ce44SJohn Forte ddi_prop_free(scsi_binding_set);
519fcf3ce44SJohn Forte
520fcf3ce44SJohn Forte /* if nodename can't be determined then print a message and skip it */
521fcf3ce44SJohn Forte if (nodename == NULL) {
522fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver found no compatible driver "
523fcf3ce44SJohn Forte "for %s lun %d", isp->sess_name, lun_num);
524fcf3ce44SJohn Forte return (ISCSI_STATUS_INTERNAL_ERROR);
525fcf3ce44SJohn Forte }
526fcf3ce44SJohn Forte
527*3fe80ca4SDan Cross ndi_devi_enter(ihp->hba_dip);
528fcf3ce44SJohn Forte
529fcf3ce44SJohn Forte ndi_rtn = ndi_devi_alloc(ihp->hba_dip, nodename,
530fcf3ce44SJohn Forte DEVI_SID_NODEID, &lun_dip);
531fcf3ce44SJohn Forte
532fcf3ce44SJohn Forte /* if lun alloc success, set props */
533fcf3ce44SJohn Forte if (ndi_rtn == NDI_SUCCESS) {
534fcf3ce44SJohn Forte
535fcf3ce44SJohn Forte if (ndi_prop_update_int(DDI_DEV_T_NONE,
536fcf3ce44SJohn Forte lun_dip, TARGET_PROP, (int)isp->sess_oid) !=
537fcf3ce44SJohn Forte DDI_PROP_SUCCESS) {
538fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
539fcf3ce44SJohn Forte "property for %s lun %d (TARGET_PROP)",
540fcf3ce44SJohn Forte isp->sess_name, lun_num);
541fcf3ce44SJohn Forte ndi_rtn = NDI_FAILURE;
542fcf3ce44SJohn Forte goto phys_create_done;
543fcf3ce44SJohn Forte }
544fcf3ce44SJohn Forte
545fcf3ce44SJohn Forte if (ndi_prop_update_int(DDI_DEV_T_NONE,
546fcf3ce44SJohn Forte lun_dip, LUN_PROP, (int)ilp->lun_num) !=
547fcf3ce44SJohn Forte DDI_PROP_SUCCESS) {
548fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
549fcf3ce44SJohn Forte "property for %s lun %d (LUN_PROP)",
550fcf3ce44SJohn Forte isp->sess_name, lun_num);
551fcf3ce44SJohn Forte ndi_rtn = NDI_FAILURE;
552fcf3ce44SJohn Forte goto phys_create_done;
553fcf3ce44SJohn Forte }
554fcf3ce44SJohn Forte
555fcf3ce44SJohn Forte if (ndi_prop_update_string_array(DDI_DEV_T_NONE,
556fcf3ce44SJohn Forte lun_dip, "compatible", compatible, ncompatible)
557fcf3ce44SJohn Forte != DDI_PROP_SUCCESS) {
558fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to create "
559fcf3ce44SJohn Forte "property for %s lun %d (COMPATIBLE)",
560fcf3ce44SJohn Forte isp->sess_name, lun_num);
561fcf3ce44SJohn Forte ndi_rtn = NDI_FAILURE;
562fcf3ce44SJohn Forte goto phys_create_done;
563fcf3ce44SJohn Forte }
564fcf3ce44SJohn Forte
565fcf3ce44SJohn Forte phys_create_done:
566fcf3ce44SJohn Forte /* If props were setup ok, online the lun */
567fcf3ce44SJohn Forte if (ndi_rtn == NDI_SUCCESS) {
568fcf3ce44SJohn Forte /* Try to online the new node */
569fcf3ce44SJohn Forte ndi_rtn = ndi_devi_online(lun_dip, 0);
570fcf3ce44SJohn Forte }
571fcf3ce44SJohn Forte
572fcf3ce44SJohn Forte /* If success set rtn flag, else unwire alloc'd lun */
573fcf3ce44SJohn Forte if (ndi_rtn == NDI_SUCCESS) {
574fcf3ce44SJohn Forte rtn = ISCSI_STATUS_SUCCESS;
575fcf3ce44SJohn Forte /*
576fcf3ce44SJohn Forte * Assign the instance number for the dev_link
577fcf3ce44SJohn Forte * generator. This will ensure the link name is
578fcf3ce44SJohn Forte * unique and persistent across reboots.
579fcf3ce44SJohn Forte */
580fcf3ce44SJohn Forte (void) snprintf(instance, 32, "%d",
581fcf3ce44SJohn Forte ddi_get_instance(lun_dip));
582fcf3ce44SJohn Forte (void) ndi_prop_update_string(DDI_DEV_T_NONE,
583fcf3ce44SJohn Forte lun_dip, NDI_GUID, instance);
584fcf3ce44SJohn Forte } else {
585fcf3ce44SJohn Forte cmn_err(CE_WARN, "iscsi driver unable to online "
586fcf3ce44SJohn Forte "%s lun %d", isp->sess_name, lun_num);
587fcf3ce44SJohn Forte ndi_prop_remove_all(lun_dip);
588fcf3ce44SJohn Forte (void) ndi_devi_free(lun_dip);
589fcf3ce44SJohn Forte }
590fcf3ce44SJohn Forte
591fcf3ce44SJohn Forte }
592*3fe80ca4SDan Cross ndi_devi_exit(ihp->hba_dip);
593fcf3ce44SJohn Forte
594fcf3ce44SJohn Forte ilp->lun_dip = lun_dip;
595fcf3ce44SJohn Forte ilp->lun_pip = NULL;
596fcf3ce44SJohn Forte
597fcf3ce44SJohn Forte scsi_hba_nodename_compatible_free(nodename, compatible);
598fcf3ce44SJohn Forte
599fcf3ce44SJohn Forte return (rtn);
600fcf3ce44SJohn Forte }
601fcf3ce44SJohn Forte
602fcf3ce44SJohn Forte
603fcf3ce44SJohn Forte /*
604fcf3ce44SJohn Forte * iscsi_lun_online - _di_online logical unit
605fcf3ce44SJohn Forte *
606fcf3ce44SJohn Forte * This is called after a path has recovered it will cause
607fcf3ce44SJohn Forte * an offline path to become online/active again.
608fcf3ce44SJohn Forte */
609fcf3ce44SJohn Forte void
iscsi_lun_online(iscsi_hba_t * ihp,iscsi_lun_t * ilp)610fcf3ce44SJohn Forte iscsi_lun_online(iscsi_hba_t *ihp, iscsi_lun_t *ilp)
611fcf3ce44SJohn Forte {
6126cefaae1SJack Meng int rval = 0;
6136cefaae1SJack Meng uint64_t *lun_num_ptr = NULL;
6146cefaae1SJack Meng uint16_t boot_lun_num = 0;
6156cefaae1SJack Meng iscsi_sess_t *isp = NULL;
616c60a6da3Sbing zhao - Sun Microsystems - Beijing China boolean_t online = B_FALSE;
617c60a6da3Sbing zhao - Sun Microsystems - Beijing China nvlist_t *attr_list = NULL;
618c60a6da3Sbing zhao - Sun Microsystems - Beijing China char *pathname = NULL;
619c60a6da3Sbing zhao - Sun Microsystems - Beijing China dev_info_t *lun_dip = NULL;
620fcf3ce44SJohn Forte
621fcf3ce44SJohn Forte ASSERT(ilp != NULL);
622fcf3ce44SJohn Forte ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
623fcf3ce44SJohn Forte
624fcf3ce44SJohn Forte if (ilp->lun_pip != NULL) {
625*3fe80ca4SDan Cross ndi_devi_enter(scsi_vhci_dip);
626fcf3ce44SJohn Forte rval = mdi_pi_online(ilp->lun_pip, 0);
627*3fe80ca4SDan Cross ndi_devi_exit(scsi_vhci_dip);
628fcf3ce44SJohn Forte if (rval == MDI_SUCCESS) {
62991dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
63091dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
631fcf3ce44SJohn Forte ilp->lun_time_online = ddi_get_time();
632c60a6da3Sbing zhao - Sun Microsystems - Beijing China online = B_TRUE;
633fcf3ce44SJohn Forte }
634fcf3ce44SJohn Forte
635fcf3ce44SJohn Forte } else if (ilp->lun_dip != NULL) {
636*3fe80ca4SDan Cross ndi_devi_enter(ihp->hba_dip);
637fcf3ce44SJohn Forte rval = ndi_devi_online(ilp->lun_dip, 0);
638*3fe80ca4SDan Cross ndi_devi_exit(ihp->hba_dip);
639fcf3ce44SJohn Forte if (rval == NDI_SUCCESS) {
64091dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
64191dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_ONLINE;
642fcf3ce44SJohn Forte ilp->lun_time_online = ddi_get_time();
643c60a6da3Sbing zhao - Sun Microsystems - Beijing China online = B_TRUE;
644fcf3ce44SJohn Forte }
645fcf3ce44SJohn Forte }
6466cefaae1SJack Meng
6476cefaae1SJack Meng /* Check whether this is the required LUN for iscsi boot */
6486cefaae1SJack Meng if (iscsiboot_prop != NULL &&
6496cefaae1SJack Meng iscsiboot_prop->boot_tgt.lun_online == 0) {
6506cefaae1SJack Meng isp = ilp->lun_sess;
6516cefaae1SJack Meng if (isp->sess_boot == B_TRUE) {
6526cefaae1SJack Meng lun_num_ptr =
6536cefaae1SJack Meng (uint64_t *)iscsiboot_prop->boot_tgt.tgt_boot_lun;
6546cefaae1SJack Meng boot_lun_num = (uint16_t)(*lun_num_ptr);
6556cefaae1SJack Meng if (boot_lun_num == ilp->lun_num) {
6566cefaae1SJack Meng /*
6576cefaae1SJack Meng * During iscsi boot, the boot lun has been
6586cefaae1SJack Meng * online, we should set the "online flag".
6596cefaae1SJack Meng */
6606cefaae1SJack Meng iscsiboot_prop->boot_tgt.lun_online = 1;
6616cefaae1SJack Meng }
6626cefaae1SJack Meng }
6636cefaae1SJack Meng }
664c60a6da3Sbing zhao - Sun Microsystems - Beijing China
665c60a6da3Sbing zhao - Sun Microsystems - Beijing China /*
666c60a6da3Sbing zhao - Sun Microsystems - Beijing China * If the LUN has been online and it is a disk,
667c60a6da3Sbing zhao - Sun Microsystems - Beijing China * send out a system event.
668c60a6da3Sbing zhao - Sun Microsystems - Beijing China */
669c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (online == B_TRUE && ilp->lun_type == DTYPE_DIRECT) {
670c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
671c60a6da3Sbing zhao - Sun Microsystems - Beijing China DDI_SUCCESS) {
672c60a6da3Sbing zhao - Sun Microsystems - Beijing China return;
673c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
674c60a6da3Sbing zhao - Sun Microsystems - Beijing China
675c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (ilp->lun_pip != NULL) {
676c60a6da3Sbing zhao - Sun Microsystems - Beijing China lun_dip = mdi_pi_get_client(ilp->lun_pip);
677c60a6da3Sbing zhao - Sun Microsystems - Beijing China } else {
678c60a6da3Sbing zhao - Sun Microsystems - Beijing China lun_dip = ilp->lun_dip;
679c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
680c60a6da3Sbing zhao - Sun Microsystems - Beijing China
681c60a6da3Sbing zhao - Sun Microsystems - Beijing China pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
682c60a6da3Sbing zhao - Sun Microsystems - Beijing China (void) ddi_pathname(lun_dip, pathname);
683c60a6da3Sbing zhao - Sun Microsystems - Beijing China
684c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (nvlist_add_string(attr_list, DEV_PHYS_PATH, pathname) !=
685c60a6da3Sbing zhao - Sun Microsystems - Beijing China DDI_SUCCESS) {
686c60a6da3Sbing zhao - Sun Microsystems - Beijing China nvlist_free(attr_list);
687c60a6da3Sbing zhao - Sun Microsystems - Beijing China kmem_free(pathname, MAXNAMELEN + 1);
688c60a6da3Sbing zhao - Sun Microsystems - Beijing China return;
689c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
690c60a6da3Sbing zhao - Sun Microsystems - Beijing China iscsi_send_sysevent(ihp, EC_DEV_ADD, ESC_DISK, attr_list);
691c60a6da3Sbing zhao - Sun Microsystems - Beijing China kmem_free(pathname, MAXNAMELEN + 1);
692c60a6da3Sbing zhao - Sun Microsystems - Beijing China nvlist_free(attr_list);
693c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
694fcf3ce44SJohn Forte }
695fcf3ce44SJohn Forte
696fcf3ce44SJohn Forte /*
697fcf3ce44SJohn Forte * iscsi_lun_offline - attempt _di_offline [and optional _di_free]
698fcf3ce44SJohn Forte *
699fcf3ce44SJohn Forte * This function is called via two paths. When a transport
700fcf3ce44SJohn Forte * path has failed it will be called to offline the logical
701fcf3ce44SJohn Forte * unit. When nameservice access has been removed it will
702fcf3ce44SJohn Forte * be called to both offline and free the logical unit.
703fcf3ce44SJohn Forte * (This operates soley on the solaris node states.
704fcf3ce44SJohn Forte * iscsi_lun_destroy() should be called when attempting
705fcf3ce44SJohn Forte * to free all iscsi lun resources.)
706fcf3ce44SJohn Forte *
707fcf3ce44SJohn Forte * This function can fail with ISCSI_STATUS_BUSY if the
708fcf3ce44SJohn Forte * logical unit is in use. The user should unmount or
709fcf3ce44SJohn Forte * close the device and perform the nameservice operation
710fcf3ce44SJohn Forte * again if this occurs.
71191dae09cSbing zhao - Sun Microsystems - Beijing China *
71291dae09cSbing zhao - Sun Microsystems - Beijing China * If we fail to offline a LUN that we don't want to destroy,
71391dae09cSbing zhao - Sun Microsystems - Beijing China * we will mark it with invalid state. If this LUN still
71491dae09cSbing zhao - Sun Microsystems - Beijing China * exists on the target, we can have another chance to online
71591dae09cSbing zhao - Sun Microsystems - Beijing China * it again when we do the LUN enumeration.
716fcf3ce44SJohn Forte */
717fcf3ce44SJohn Forte iscsi_status_t
iscsi_lun_offline(iscsi_hba_t * ihp,iscsi_lun_t * ilp,boolean_t lun_free)718fcf3ce44SJohn Forte iscsi_lun_offline(iscsi_hba_t *ihp, iscsi_lun_t *ilp, boolean_t lun_free)
719fcf3ce44SJohn Forte {
720c60a6da3Sbing zhao - Sun Microsystems - Beijing China iscsi_status_t status = ISCSI_STATUS_SUCCESS;
72161dfa509SRick McNeal dev_info_t *cdip;
722c60a6da3Sbing zhao - Sun Microsystems - Beijing China char *pathname = NULL;
723c60a6da3Sbing zhao - Sun Microsystems - Beijing China boolean_t offline = B_FALSE;
724c60a6da3Sbing zhao - Sun Microsystems - Beijing China nvlist_t *attr_list = NULL;
725fcf3ce44SJohn Forte
726fcf3ce44SJohn Forte ASSERT(ilp != NULL);
727fcf3ce44SJohn Forte ASSERT((ilp->lun_pip != NULL) || (ilp->lun_dip != NULL));
728fcf3ce44SJohn Forte
72961dfa509SRick McNeal if (ilp->lun_pip == NULL)
730fcf3ce44SJohn Forte cdip = ilp->lun_dip;
73161dfa509SRick McNeal else
732fcf3ce44SJohn Forte cdip = mdi_pi_get_client(ilp->lun_pip);
733fcf3ce44SJohn Forte
734c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (cdip != NULL && ilp->lun_type == DTYPE_DIRECT) {
735c60a6da3Sbing zhao - Sun Microsystems - Beijing China pathname = kmem_zalloc(MAXNAMELEN + 1, KM_SLEEP);
736c60a6da3Sbing zhao - Sun Microsystems - Beijing China (void) ddi_pathname(cdip, pathname);
737c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
738c60a6da3Sbing zhao - Sun Microsystems - Beijing China
739fcf3ce44SJohn Forte /* Attempt to offline the logical units */
740fcf3ce44SJohn Forte if (ilp->lun_pip != NULL) {
741fcf3ce44SJohn Forte /* virt/mdi */
742*3fe80ca4SDan Cross ndi_devi_enter(scsi_vhci_dip);
74361dfa509SRick McNeal if (mdi_pi_offline(ilp->lun_pip, 0) == MDI_SUCCESS) {
74491dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
74591dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
746fcf3ce44SJohn Forte if (lun_free == B_TRUE) {
747fcf3ce44SJohn Forte (void) mdi_prop_remove(ilp->lun_pip, NULL);
748fcf3ce44SJohn Forte (void) mdi_pi_free(ilp->lun_pip, 0);
749fcf3ce44SJohn Forte }
750c60a6da3Sbing zhao - Sun Microsystems - Beijing China offline = B_TRUE;
751fcf3ce44SJohn Forte } else {
7525295a27aSJack Meng status = ISCSI_STATUS_BUSY;
75391dae09cSbing zhao - Sun Microsystems - Beijing China if (lun_free == B_FALSE) {
75491dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
755c60a6da3Sbing zhao - Sun Microsystems - Beijing China offline = B_TRUE;
75691dae09cSbing zhao - Sun Microsystems - Beijing China }
757fcf3ce44SJohn Forte }
758*3fe80ca4SDan Cross ndi_devi_exit(scsi_vhci_dip);
759fcf3ce44SJohn Forte
760fcf3ce44SJohn Forte } else {
761fcf3ce44SJohn Forte /* phys/ndi */
76261dfa509SRick McNeal int flags = NDI_DEVFS_CLEAN;
76361dfa509SRick McNeal
764*3fe80ca4SDan Cross ndi_devi_enter(ihp->hba_dip);
76561dfa509SRick McNeal if (lun_free == B_TRUE &&
76661dfa509SRick McNeal (ilp->lun_state & ISCSI_LUN_STATE_ONLINE))
76761dfa509SRick McNeal flags |= NDI_DEVI_REMOVE;
76861dfa509SRick McNeal if (ndi_devi_offline(ilp->lun_dip, flags) != NDI_SUCCESS) {
7695295a27aSJack Meng status = ISCSI_STATUS_BUSY;
77091dae09cSbing zhao - Sun Microsystems - Beijing China if (lun_free == B_FALSE) {
77191dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_INVALID;
772c60a6da3Sbing zhao - Sun Microsystems - Beijing China offline = B_TRUE;
77391dae09cSbing zhao - Sun Microsystems - Beijing China }
774fcf3ce44SJohn Forte } else {
77591dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state &= ISCSI_LUN_STATE_CLEAR;
77691dae09cSbing zhao - Sun Microsystems - Beijing China ilp->lun_state |= ISCSI_LUN_STATE_OFFLINE;
777c60a6da3Sbing zhao - Sun Microsystems - Beijing China offline = B_TRUE;
778fcf3ce44SJohn Forte }
779*3fe80ca4SDan Cross ndi_devi_exit(ihp->hba_dip);
780c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
781c60a6da3Sbing zhao - Sun Microsystems - Beijing China
782c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (offline == B_TRUE && pathname != NULL &&
783c60a6da3Sbing zhao - Sun Microsystems - Beijing China ilp->lun_type == DTYPE_DIRECT) {
784c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (nvlist_alloc(&attr_list, NV_UNIQUE_NAME_TYPE, KM_SLEEP) !=
785c60a6da3Sbing zhao - Sun Microsystems - Beijing China DDI_SUCCESS) {
786c60a6da3Sbing zhao - Sun Microsystems - Beijing China kmem_free(pathname, MAXNAMELEN + 1);
787c60a6da3Sbing zhao - Sun Microsystems - Beijing China return (status);
788c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
789c60a6da3Sbing zhao - Sun Microsystems - Beijing China
790c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (nvlist_add_string(attr_list, DEV_PHYS_PATH, pathname) !=
791c60a6da3Sbing zhao - Sun Microsystems - Beijing China DDI_SUCCESS) {
792c60a6da3Sbing zhao - Sun Microsystems - Beijing China nvlist_free(attr_list);
793c60a6da3Sbing zhao - Sun Microsystems - Beijing China kmem_free(pathname, MAXNAMELEN + 1);
794c60a6da3Sbing zhao - Sun Microsystems - Beijing China return (status);
795c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
796fcf3ce44SJohn Forte
797c60a6da3Sbing zhao - Sun Microsystems - Beijing China iscsi_send_sysevent(ihp, EC_DEV_REMOVE, ESC_DISK, attr_list);
798c60a6da3Sbing zhao - Sun Microsystems - Beijing China nvlist_free(attr_list);
799fcf3ce44SJohn Forte }
800c60a6da3Sbing zhao - Sun Microsystems - Beijing China
801c60a6da3Sbing zhao - Sun Microsystems - Beijing China if (pathname != NULL) {
802c60a6da3Sbing zhao - Sun Microsystems - Beijing China kmem_free(pathname, MAXNAMELEN + 1);
803c60a6da3Sbing zhao - Sun Microsystems - Beijing China }
804c60a6da3Sbing zhao - Sun Microsystems - Beijing China
805fcf3ce44SJohn Forte return (status);
806fcf3ce44SJohn Forte }
807