1a6d42e7dSPeter Dunlap /*
2a6d42e7dSPeter Dunlap  * CDDL HEADER START
3a6d42e7dSPeter Dunlap  *
4a6d42e7dSPeter Dunlap  * The contents of this file are subject to the terms of the
5a6d42e7dSPeter Dunlap  * Common Development and Distribution License (the "License").
6a6d42e7dSPeter Dunlap  * You may not use this file except in compliance with the License.
7a6d42e7dSPeter Dunlap  *
8a6d42e7dSPeter Dunlap  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9a6d42e7dSPeter Dunlap  * or http://www.opensolaris.org/os/licensing.
10a6d42e7dSPeter Dunlap  * See the License for the specific language governing permissions
11a6d42e7dSPeter Dunlap  * and limitations under the License.
12a6d42e7dSPeter Dunlap  *
13a6d42e7dSPeter Dunlap  * When distributing Covered Code, include this CDDL HEADER in each
14a6d42e7dSPeter Dunlap  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15a6d42e7dSPeter Dunlap  * If applicable, add the following below this CDDL HEADER, with the
16a6d42e7dSPeter Dunlap  * fields enclosed by brackets "[]" replaced with your own identifying
17a6d42e7dSPeter Dunlap  * information: Portions Copyright [yyyy] [name of copyright owner]
18a6d42e7dSPeter Dunlap  *
19a6d42e7dSPeter Dunlap  * CDDL HEADER END
20a6d42e7dSPeter Dunlap  */
21a6d42e7dSPeter Dunlap /*
2242bf653bSPeter Gill  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23a481fa48SRick McNeal  * Copyright 2011, 2015 Nexenta Systems, Inc. All rights reserved.
24a6d42e7dSPeter Dunlap  */
25a6d42e7dSPeter Dunlap 
26a6d42e7dSPeter Dunlap #include <sys/cpuvar.h>
27a6d42e7dSPeter Dunlap #include <sys/types.h>
28a6d42e7dSPeter Dunlap #include <sys/conf.h>
29a6d42e7dSPeter Dunlap #include <sys/file.h>
30a6d42e7dSPeter Dunlap #include <sys/ddi.h>
31a6d42e7dSPeter Dunlap #include <sys/sunddi.h>
32a6d42e7dSPeter Dunlap #include <sys/modctl.h>
33a6d42e7dSPeter Dunlap #include <sys/sysmacros.h>
34a6d42e7dSPeter Dunlap #include <sys/sdt.h>
35a6d42e7dSPeter Dunlap 
36a6d42e7dSPeter Dunlap #include <sys/socket.h>
37a6d42e7dSPeter Dunlap #include <sys/strsubr.h>
38a6d42e7dSPeter Dunlap 
39a6d42e7dSPeter Dunlap #include <sys/stmf.h>
40a6d42e7dSPeter Dunlap #include <sys/stmf_ioctl.h>
41a6d42e7dSPeter Dunlap #include <sys/portif.h>
42a6d42e7dSPeter Dunlap #include <sys/idm/idm.h>
43a6d42e7dSPeter Dunlap 
44a6d42e7dSPeter Dunlap #define	ISCSIT_TGT_SM_STRINGS
454558d122SViswanathan Kannappan #include "iscsit.h"
464558d122SViswanathan Kannappan #include "iscsit_isns.h"
47a6d42e7dSPeter Dunlap 
48a6d42e7dSPeter Dunlap typedef struct {
49a6d42e7dSPeter Dunlap 	list_node_t		te_ctx_node;
50a6d42e7dSPeter Dunlap 	iscsit_tgt_event_t	te_ctx_event;
51a6d42e7dSPeter Dunlap } tgt_event_ctx_t;
52a6d42e7dSPeter Dunlap 
53a6d42e7dSPeter Dunlap static void
54a6d42e7dSPeter Dunlap tgt_sm_event_dispatch(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
55a6d42e7dSPeter Dunlap 
56a6d42e7dSPeter Dunlap static void
57a6d42e7dSPeter Dunlap tgt_sm_created(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
58a6d42e7dSPeter Dunlap 
59a6d42e7dSPeter Dunlap static void
60a6d42e7dSPeter Dunlap tgt_sm_onlining(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
61a6d42e7dSPeter Dunlap 
62a6d42e7dSPeter Dunlap static void
63a6d42e7dSPeter Dunlap tgt_sm_online(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
64a6d42e7dSPeter Dunlap 
65a6d42e7dSPeter Dunlap static void
66a6d42e7dSPeter Dunlap tgt_sm_stmf_online(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
67a6d42e7dSPeter Dunlap 
68a6d42e7dSPeter Dunlap static void
69a6d42e7dSPeter Dunlap tgt_sm_deleting_need_offline(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
70a6d42e7dSPeter Dunlap 
71a6d42e7dSPeter Dunlap static void
72a6d42e7dSPeter Dunlap tgt_sm_offlining(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
73a6d42e7dSPeter Dunlap 
74a6d42e7dSPeter Dunlap static void
75a6d42e7dSPeter Dunlap tgt_sm_offline(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
76a6d42e7dSPeter Dunlap 
77a6d42e7dSPeter Dunlap static void
78a6d42e7dSPeter Dunlap tgt_sm_stmf_offline(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
79a6d42e7dSPeter Dunlap 
80a6d42e7dSPeter Dunlap static void
81a6d42e7dSPeter Dunlap tgt_sm_deleting_stmf_dereg(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
82a6d42e7dSPeter Dunlap 
83a6d42e7dSPeter Dunlap static void
84a6d42e7dSPeter Dunlap tgt_sm_deleting_stmf_dereg_fail(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
85a6d42e7dSPeter Dunlap 
86a6d42e7dSPeter Dunlap static void
87a6d42e7dSPeter Dunlap tgt_sm_deleting(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx);
88a6d42e7dSPeter Dunlap 
89a6d42e7dSPeter Dunlap static void
90a6d42e7dSPeter Dunlap iscsit_tgt_dereg_retry(void *arg);
91a6d42e7dSPeter Dunlap 
92a6d42e7dSPeter Dunlap static void
93a6d42e7dSPeter Dunlap iscsit_tgt_dereg_task(void *arg);
94a6d42e7dSPeter Dunlap 
95a6d42e7dSPeter Dunlap static void
96a6d42e7dSPeter Dunlap tgt_sm_new_state(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx,
97a6d42e7dSPeter Dunlap     iscsit_tgt_state_t new_state);
98a6d42e7dSPeter Dunlap 
99a6d42e7dSPeter Dunlap 
100a6d42e7dSPeter Dunlap static iscsit_tgt_t *
101a6d42e7dSPeter Dunlap iscsit_tgt_create(it_tgt_t *cfg_tgt);
102a6d42e7dSPeter Dunlap 
103a6d42e7dSPeter Dunlap static void
104a6d42e7dSPeter Dunlap iscsit_tgt_unref(void *tgt);
105a6d42e7dSPeter Dunlap 
106a6d42e7dSPeter Dunlap static void
107a6d42e7dSPeter Dunlap iscsit_tgt_async_wait_ref(iscsit_tgt_t *tgt, idm_refcnt_cb_t *cb_func);
108a6d42e7dSPeter Dunlap 
109a6d42e7dSPeter Dunlap static void
110a6d42e7dSPeter Dunlap iscsit_tgt_destroy(iscsit_tgt_t *tgt);
111a6d42e7dSPeter Dunlap 
112a6d42e7dSPeter Dunlap static iscsit_tpgt_t *
113a6d42e7dSPeter Dunlap iscsit_tgt_lookup_tpgt_locked(iscsit_tgt_t *tgt, uint16_t tag);
114a6d42e7dSPeter Dunlap 
115a6d42e7dSPeter Dunlap static iscsit_tpg_t *
116a6d42e7dSPeter Dunlap iscsit_tpg_lookup_locked(char *tpg_name);
117a6d42e7dSPeter Dunlap 
118a6d42e7dSPeter Dunlap static iscsit_portal_t *
119a6d42e7dSPeter Dunlap iscsit_tpg_portal_lookup_locked(iscsit_tpg_t *tpg,
120a6d42e7dSPeter Dunlap     struct sockaddr_storage *sa);
121a6d42e7dSPeter Dunlap 
122a6d42e7dSPeter Dunlap static idm_status_t
123a6d42e7dSPeter Dunlap iscsit_tgt_online(iscsit_tgt_t *tgt);
124a6d42e7dSPeter Dunlap 
125a6d42e7dSPeter Dunlap static void
126a6d42e7dSPeter Dunlap iscsit_tgt_offline(iscsit_tgt_t *tgt);
127a6d42e7dSPeter Dunlap 
128a6d42e7dSPeter Dunlap static idm_status_t
129a6d42e7dSPeter Dunlap iscsit_tgt_modify(iscsit_tgt_t *tgt, it_tgt_t *cfg_tgt);
130a6d42e7dSPeter Dunlap 
131a6d42e7dSPeter Dunlap static idm_status_t
132a6d42e7dSPeter Dunlap iscsit_tgt_merge_tpgt(iscsit_tgt_t *tgt, it_tgt_t *cfg_tgt,
133a6d42e7dSPeter Dunlap     list_t *tpgt_del_list);
134a6d42e7dSPeter Dunlap 
135a6d42e7dSPeter Dunlap static iscsit_tpgt_t *
136a6d42e7dSPeter Dunlap iscsit_tpgt_create(it_tpgt_t *cfg_tpgt);
137a6d42e7dSPeter Dunlap 
138a6d42e7dSPeter Dunlap static iscsit_tpgt_t *
139a6d42e7dSPeter Dunlap iscsit_tpgt_create_default();
140a6d42e7dSPeter Dunlap 
141a6d42e7dSPeter Dunlap static void
142a6d42e7dSPeter Dunlap iscsit_tpgt_destroy(iscsit_tpgt_t *tpgt);
143a6d42e7dSPeter Dunlap 
144a6d42e7dSPeter Dunlap static iscsit_tpg_t *
145a6d42e7dSPeter Dunlap iscsit_tpg_create(it_tpg_t *tpg);
146a6d42e7dSPeter Dunlap 
147a6d42e7dSPeter Dunlap static void
148a6d42e7dSPeter Dunlap iscsit_tpg_modify(iscsit_tpg_t *tpg, it_tpg_t *cfg_tpg);
149a6d42e7dSPeter Dunlap 
150a6d42e7dSPeter Dunlap static void
151a6d42e7dSPeter Dunlap iscsit_tpg_destroy(iscsit_tpg_t *tpg);
152a6d42e7dSPeter Dunlap 
153a6d42e7dSPeter Dunlap static iscsit_portal_t *
154a6d42e7dSPeter Dunlap iscsit_portal_create(iscsit_tpg_t *tpg, struct sockaddr_storage *sa);
155a6d42e7dSPeter Dunlap 
156a6d42e7dSPeter Dunlap static void
157d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States iscsit_portal_delete(iscsit_portal_t *portal);
158a6d42e7dSPeter Dunlap 
159a6d42e7dSPeter Dunlap static idm_status_t
160a6d42e7dSPeter Dunlap iscsit_portal_online(iscsit_portal_t *portal);
161a6d42e7dSPeter Dunlap 
162a6d42e7dSPeter Dunlap static void
163a6d42e7dSPeter Dunlap iscsit_portal_offline(iscsit_portal_t *portal);
164a6d42e7dSPeter Dunlap 
165a6d42e7dSPeter Dunlap 
166a6d42e7dSPeter Dunlap 
167a6d42e7dSPeter Dunlap /*
168a6d42e7dSPeter Dunlap  * Target state machine
169a6d42e7dSPeter Dunlap  */
170a6d42e7dSPeter Dunlap 
171a6d42e7dSPeter Dunlap void
iscsit_tgt_sm_event(iscsit_tgt_t * tgt,iscsit_tgt_event_t event)172a6d42e7dSPeter Dunlap iscsit_tgt_sm_event(iscsit_tgt_t *tgt, iscsit_tgt_event_t event)
173a6d42e7dSPeter Dunlap {
174a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
175a6d42e7dSPeter Dunlap 	tgt_sm_event_locked(tgt, event);
176a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
177a6d42e7dSPeter Dunlap }
178a6d42e7dSPeter Dunlap 
179a6d42e7dSPeter Dunlap void
tgt_sm_event_locked(iscsit_tgt_t * tgt,iscsit_tgt_event_t event)180a6d42e7dSPeter Dunlap tgt_sm_event_locked(iscsit_tgt_t *tgt, iscsit_tgt_event_t event)
181a6d42e7dSPeter Dunlap {
182a6d42e7dSPeter Dunlap 	tgt_event_ctx_t *ctx;
183a6d42e7dSPeter Dunlap 
184a6d42e7dSPeter Dunlap 	iscsit_tgt_hold(tgt);
185a6d42e7dSPeter Dunlap 
186a6d42e7dSPeter Dunlap 	ctx = kmem_zalloc(sizeof (*ctx), KM_SLEEP);
187a6d42e7dSPeter Dunlap 
188a6d42e7dSPeter Dunlap 	ctx->te_ctx_event = event;
189a6d42e7dSPeter Dunlap 
190a6d42e7dSPeter Dunlap 	list_insert_tail(&tgt->target_events, ctx);
191a6d42e7dSPeter Dunlap 	/*
19230e7468fSPeter Dunlap 	 * Use the target_sm_busy flag to keep the state machine single
19330e7468fSPeter Dunlap 	 * threaded.  This also serves as recursion avoidance since this
19430e7468fSPeter Dunlap 	 * flag will always be set if we call iscsit_tgt_sm_event from
19530e7468fSPeter Dunlap 	 * within the state machine code.
196a6d42e7dSPeter Dunlap 	 */
197a6d42e7dSPeter Dunlap 	if (!tgt->target_sm_busy) {
198a6d42e7dSPeter Dunlap 		tgt->target_sm_busy = B_TRUE;
199a6d42e7dSPeter Dunlap 		while (!list_is_empty(&tgt->target_events)) {
200a6d42e7dSPeter Dunlap 			ctx = list_head(&tgt->target_events);
201a6d42e7dSPeter Dunlap 			list_remove(&tgt->target_events, ctx);
202a6d42e7dSPeter Dunlap 			idm_sm_audit_event(&tgt->target_state_audit,
203a6d42e7dSPeter Dunlap 			    SAS_ISCSIT_TGT, (int)tgt->target_state,
204a6d42e7dSPeter Dunlap 			    (int)ctx->te_ctx_event, 0);
205a6d42e7dSPeter Dunlap 			mutex_exit(&tgt->target_mutex);
206a6d42e7dSPeter Dunlap 			tgt_sm_event_dispatch(tgt, ctx);
207a6d42e7dSPeter Dunlap 			mutex_enter(&tgt->target_mutex);
208a6d42e7dSPeter Dunlap 		}
209a6d42e7dSPeter Dunlap 		tgt->target_sm_busy = B_FALSE;
210a6d42e7dSPeter Dunlap 
211a6d42e7dSPeter Dunlap 	}
212a6d42e7dSPeter Dunlap 
213a6d42e7dSPeter Dunlap 	iscsit_tgt_rele(tgt);
214a6d42e7dSPeter Dunlap }
215a6d42e7dSPeter Dunlap 
216a6d42e7dSPeter Dunlap static void
tgt_sm_event_dispatch(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)217a6d42e7dSPeter Dunlap tgt_sm_event_dispatch(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
218a6d42e7dSPeter Dunlap {
219a6d42e7dSPeter Dunlap 	DTRACE_PROBE2(tgt__event, iscsit_tgt_t *, tgt,
220a6d42e7dSPeter Dunlap 	    tgt_event_ctx_t *, ctx);
221a6d42e7dSPeter Dunlap 
222a6d42e7dSPeter Dunlap 	IDM_SM_LOG(CE_NOTE, "tgt_sm_event_dispatch: tgt %p event %s(%d)",
223a6d42e7dSPeter Dunlap 	    (void *)tgt, iscsit_te_name[ctx->te_ctx_event], ctx->te_ctx_event);
224a6d42e7dSPeter Dunlap 
225a6d42e7dSPeter Dunlap 	/* State independent actions */
226a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
227a6d42e7dSPeter Dunlap 	case TE_DELETE:
228a6d42e7dSPeter Dunlap 		tgt->target_deleting = B_TRUE;
229a6d42e7dSPeter Dunlap 		break;
230a6d42e7dSPeter Dunlap 	}
231a6d42e7dSPeter Dunlap 
232a6d42e7dSPeter Dunlap 	/* State dependent actions */
233a6d42e7dSPeter Dunlap 	switch (tgt->target_state) {
234a6d42e7dSPeter Dunlap 	case TS_CREATED:
235a6d42e7dSPeter Dunlap 		tgt_sm_created(tgt, ctx);
236a6d42e7dSPeter Dunlap 		break;
237a6d42e7dSPeter Dunlap 	case TS_ONLINING:
238a6d42e7dSPeter Dunlap 		tgt_sm_onlining(tgt, ctx);
239a6d42e7dSPeter Dunlap 		break;
240a6d42e7dSPeter Dunlap 	case TS_ONLINE:
241a6d42e7dSPeter Dunlap 		tgt_sm_online(tgt, ctx);
242a6d42e7dSPeter Dunlap 		break;
243a6d42e7dSPeter Dunlap 	case TS_STMF_ONLINE:
244a6d42e7dSPeter Dunlap 		tgt_sm_stmf_online(tgt, ctx);
245a6d42e7dSPeter Dunlap 		break;
246a6d42e7dSPeter Dunlap 	case TS_DELETING_NEED_OFFLINE:
247a6d42e7dSPeter Dunlap 		tgt_sm_deleting_need_offline(tgt, ctx);
248a6d42e7dSPeter Dunlap 		break;
249a6d42e7dSPeter Dunlap 	case TS_OFFLINING:
250a6d42e7dSPeter Dunlap 		tgt_sm_offlining(tgt, ctx);
251a6d42e7dSPeter Dunlap 		break;
252a6d42e7dSPeter Dunlap 	case TS_OFFLINE:
253a6d42e7dSPeter Dunlap 		tgt_sm_offline(tgt, ctx);
254a6d42e7dSPeter Dunlap 		break;
255a6d42e7dSPeter Dunlap 	case TS_STMF_OFFLINE:
256a6d42e7dSPeter Dunlap 		tgt_sm_stmf_offline(tgt, ctx);
257a6d42e7dSPeter Dunlap 		break;
258a6d42e7dSPeter Dunlap 	case TS_DELETING_STMF_DEREG:
259a6d42e7dSPeter Dunlap 		tgt_sm_deleting_stmf_dereg(tgt, ctx);
260a6d42e7dSPeter Dunlap 		break;
261a6d42e7dSPeter Dunlap 	case TS_DELETING_STMF_DEREG_FAIL:
262a6d42e7dSPeter Dunlap 		tgt_sm_deleting_stmf_dereg_fail(tgt, ctx);
263a6d42e7dSPeter Dunlap 		break;
264a6d42e7dSPeter Dunlap 	case TS_DELETING:
265a6d42e7dSPeter Dunlap 		tgt_sm_deleting(tgt, ctx);
266a6d42e7dSPeter Dunlap 		break;
267a6d42e7dSPeter Dunlap 	default:
268a6d42e7dSPeter Dunlap 		ASSERT(0);
269a6d42e7dSPeter Dunlap 	}
270a6d42e7dSPeter Dunlap 
271a6d42e7dSPeter Dunlap 	kmem_free(ctx, sizeof (*ctx));
272a6d42e7dSPeter Dunlap }
273a6d42e7dSPeter Dunlap 
274a6d42e7dSPeter Dunlap static void
tgt_sm_created(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)275a6d42e7dSPeter Dunlap tgt_sm_created(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
276a6d42e7dSPeter Dunlap {
277a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
278a6d42e7dSPeter Dunlap 
279a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
280a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
281a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_ONLINING);
282a6d42e7dSPeter Dunlap 		break;
283a6d42e7dSPeter Dunlap 	case TE_DELETE:
284a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
285a6d42e7dSPeter Dunlap 		break;
286a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
287a6d42e7dSPeter Dunlap 		/*
288a6d42e7dSPeter Dunlap 		 * We're already offline but update to an equivelant
289a6d42e7dSPeter Dunlap 		 * state just to note that STMF talked to us.
290a6d42e7dSPeter Dunlap 		 */
291a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_SUCCESS;
292a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
293a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_OFFLINE);
294a6d42e7dSPeter Dunlap 		(void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
295a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
296a6d42e7dSPeter Dunlap 		break;
297a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
298a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
299a6d42e7dSPeter Dunlap 		/* Ignore */
300a6d42e7dSPeter Dunlap 		break;
301a6d42e7dSPeter Dunlap 	default:
302a6d42e7dSPeter Dunlap 		ASSERT(0);
303a6d42e7dSPeter Dunlap 	}
304a6d42e7dSPeter Dunlap }
305a6d42e7dSPeter Dunlap 
306a6d42e7dSPeter Dunlap static void
tgt_sm_onlining(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)307a6d42e7dSPeter Dunlap tgt_sm_onlining(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
308a6d42e7dSPeter Dunlap {
309a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
310a6d42e7dSPeter Dunlap 
311a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
312a6d42e7dSPeter Dunlap 	case TE_ONLINE_SUCCESS:
313a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_ONLINE);
314a6d42e7dSPeter Dunlap 		break;
315a6d42e7dSPeter Dunlap 	case TE_ONLINE_FAIL:
316a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE);
317a6d42e7dSPeter Dunlap 		break;
318a6d42e7dSPeter Dunlap 	case TE_DELETE:
319a6d42e7dSPeter Dunlap 		/* TE_DELETE is handled in tgt_sm_event_dispatch() */
320a6d42e7dSPeter Dunlap 		break;
321a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
322a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
323a6d42e7dSPeter Dunlap 		/*
324a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are busy going
325a6d42e7dSPeter Dunlap 		 * online.
326a6d42e7dSPeter Dunlap 		 */
327a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
328a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
329a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
330a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
331a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
332a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
333a6d42e7dSPeter Dunlap 		break;
334a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
335a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
336a6d42e7dSPeter Dunlap 		/* Ignore */
337a6d42e7dSPeter Dunlap 		break;
338a6d42e7dSPeter Dunlap 	default:
339a6d42e7dSPeter Dunlap 		ASSERT(0);
340a6d42e7dSPeter Dunlap 	}
341a6d42e7dSPeter Dunlap }
342a6d42e7dSPeter Dunlap 
343a6d42e7dSPeter Dunlap static void
tgt_sm_online(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)344a6d42e7dSPeter Dunlap tgt_sm_online(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
345a6d42e7dSPeter Dunlap {
346a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
347a6d42e7dSPeter Dunlap 
348a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
349a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
350a6d42e7dSPeter Dunlap 		if (tgt->target_deleting) {
351a6d42e7dSPeter Dunlap 			tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE);
352a6d42e7dSPeter Dunlap 		} else {
353a6d42e7dSPeter Dunlap 			tgt_sm_new_state(tgt, ctx, TS_STMF_ONLINE);
354a6d42e7dSPeter Dunlap 		}
355a6d42e7dSPeter Dunlap 		break;
356a6d42e7dSPeter Dunlap 	case TE_DELETE:
357a6d42e7dSPeter Dunlap 		/* TE_DELETE is handled in tgt_sm_event_dispatch() */
358a6d42e7dSPeter Dunlap 		break;
359a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
360a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
361a6d42e7dSPeter Dunlap 		/*
362a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are busy going
363a6d42e7dSPeter Dunlap 		 * online (waiting for acknowlegement from STMF)
364a6d42e7dSPeter Dunlap 		 */
365a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
366a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
367a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
368a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
369a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
370a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
371a6d42e7dSPeter Dunlap 		break;
372a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
373a6d42e7dSPeter Dunlap 		/* Ignore */
374a6d42e7dSPeter Dunlap 		break;
375a6d42e7dSPeter Dunlap 	default:
376a6d42e7dSPeter Dunlap 		ASSERT(0);
377a6d42e7dSPeter Dunlap 	}
378a6d42e7dSPeter Dunlap }
379a6d42e7dSPeter Dunlap 
380a6d42e7dSPeter Dunlap 
381a6d42e7dSPeter Dunlap static void
tgt_sm_stmf_online(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)382a6d42e7dSPeter Dunlap tgt_sm_stmf_online(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
383a6d42e7dSPeter Dunlap {
384a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
385a6d42e7dSPeter Dunlap 
386a6d42e7dSPeter Dunlap 	/* Deregister target with iSNS whenever we leave this state */
387a6d42e7dSPeter Dunlap 
388a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
389a6d42e7dSPeter Dunlap 	case TE_DELETE:
390a6d42e7dSPeter Dunlap 		(void) iscsit_isns_deregister(tgt);
391a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_DELETING_NEED_OFFLINE);
392a6d42e7dSPeter Dunlap 		break;
393a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
394a6d42e7dSPeter Dunlap 		(void) iscsit_isns_deregister(tgt);
395a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_OFFLINING);
396a6d42e7dSPeter Dunlap 		break;
397a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
398a6d42e7dSPeter Dunlap 		/* Already online */
399a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_ALREADY;
400a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
401a6d42e7dSPeter Dunlap 		(void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE,
402a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
403a6d42e7dSPeter Dunlap 		break;
404a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
405a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
406a6d42e7dSPeter Dunlap 		/* Ignore */
407a6d42e7dSPeter Dunlap 		break;
408a6d42e7dSPeter Dunlap 	default:
409a6d42e7dSPeter Dunlap 		ASSERT(0);
410a6d42e7dSPeter Dunlap 	}
411a6d42e7dSPeter Dunlap }
412a6d42e7dSPeter Dunlap 
413a6d42e7dSPeter Dunlap 
414a6d42e7dSPeter Dunlap static void
tgt_sm_deleting_need_offline(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)415a6d42e7dSPeter Dunlap tgt_sm_deleting_need_offline(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
416a6d42e7dSPeter Dunlap {
417a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
418a6d42e7dSPeter Dunlap 
419a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
420a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
421a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_OFFLINING);
422a6d42e7dSPeter Dunlap 		break;
423a6d42e7dSPeter Dunlap 	case TE_DELETE:
424a6d42e7dSPeter Dunlap 		/* TE_DELETE is handled in tgt_sm_event_dispatch() */
425a6d42e7dSPeter Dunlap 		break;
426a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
427a6d42e7dSPeter Dunlap 		/*
428a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we need to be offlined
429a6d42e7dSPeter Dunlap 		 */
430a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
431a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
432a6d42e7dSPeter Dunlap 		(void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE,
433a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
434a6d42e7dSPeter Dunlap 		break;
435a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
436a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
437a6d42e7dSPeter Dunlap 		/* Ignore */
438a6d42e7dSPeter Dunlap 		break;
439a6d42e7dSPeter Dunlap 	default:
440a6d42e7dSPeter Dunlap 		ASSERT(0);
441a6d42e7dSPeter Dunlap 	}
442a6d42e7dSPeter Dunlap }
443a6d42e7dSPeter Dunlap 
444a6d42e7dSPeter Dunlap 
445a6d42e7dSPeter Dunlap static void
tgt_sm_offlining(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)446a6d42e7dSPeter Dunlap tgt_sm_offlining(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
447a6d42e7dSPeter Dunlap {
448a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
449a6d42e7dSPeter Dunlap 
450a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
451a6d42e7dSPeter Dunlap 	case TE_OFFLINE_COMPLETE:
452a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_OFFLINE);
453a6d42e7dSPeter Dunlap 		break;
454a6d42e7dSPeter Dunlap 	case TE_DELETE:
455a6d42e7dSPeter Dunlap 		/* TE_DELETE is handled in tgt_sm_event_dispatch() */
456a6d42e7dSPeter Dunlap 		break;
457a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
458a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
459a6d42e7dSPeter Dunlap 		/*
460a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are busy going
461a6d42e7dSPeter Dunlap 		 * offline.
462a6d42e7dSPeter Dunlap 		 */
463a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
464a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
465a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
466a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
467a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
468a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
469a6d42e7dSPeter Dunlap 		break;
470a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
471a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
472a6d42e7dSPeter Dunlap 		/* Ignore */
473a6d42e7dSPeter Dunlap 		break;
474a6d42e7dSPeter Dunlap 	default:
475a6d42e7dSPeter Dunlap 		ASSERT(0);
476a6d42e7dSPeter Dunlap 	}
477a6d42e7dSPeter Dunlap }
478a6d42e7dSPeter Dunlap 
479a6d42e7dSPeter Dunlap 
480a6d42e7dSPeter Dunlap static void
tgt_sm_offline(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)481a6d42e7dSPeter Dunlap tgt_sm_offline(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
482a6d42e7dSPeter Dunlap {
483a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
484a6d42e7dSPeter Dunlap 
485a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
486a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
487a6d42e7dSPeter Dunlap 		if (tgt->target_deleting) {
488a6d42e7dSPeter Dunlap 			tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
489a6d42e7dSPeter Dunlap 		} else {
490a6d42e7dSPeter Dunlap 			tgt_sm_new_state(tgt, ctx, TS_STMF_OFFLINE);
491a6d42e7dSPeter Dunlap 		}
492a6d42e7dSPeter Dunlap 		break;
493a6d42e7dSPeter Dunlap 	case TE_DELETE:
494a6d42e7dSPeter Dunlap 		/* TE_DELETE is handled in tgt_sm_event_dispatch() */
495a6d42e7dSPeter Dunlap 		break;
496a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
497a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
498a6d42e7dSPeter Dunlap 		/*
499a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are busy going
500a6d42e7dSPeter Dunlap 		 * offline.
501a6d42e7dSPeter Dunlap 		 */
502a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
503a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
504a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
505a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
506a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
507a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
508a6d42e7dSPeter Dunlap 		break;
509a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
510a6d42e7dSPeter Dunlap 		/* Ignore */
511a6d42e7dSPeter Dunlap 		break;
512a6d42e7dSPeter Dunlap 	default:
513a6d42e7dSPeter Dunlap 		ASSERT(0);
514a6d42e7dSPeter Dunlap 	}
515a6d42e7dSPeter Dunlap }
516a6d42e7dSPeter Dunlap 
517a6d42e7dSPeter Dunlap 
518a6d42e7dSPeter Dunlap static void
tgt_sm_stmf_offline(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)519a6d42e7dSPeter Dunlap tgt_sm_stmf_offline(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
520a6d42e7dSPeter Dunlap {
521a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
522a6d42e7dSPeter Dunlap 
523a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
524a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
525a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_ONLINING);
526a6d42e7dSPeter Dunlap 		break;
527a6d42e7dSPeter Dunlap 	case TE_DELETE:
528a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
529a6d42e7dSPeter Dunlap 		break;
530a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
531a6d42e7dSPeter Dunlap 		/* Already offline */
532a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_ALREADY;
533a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
534a6d42e7dSPeter Dunlap 		(void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
535a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
536a6d42e7dSPeter Dunlap 		break;
537a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
538a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
539a6d42e7dSPeter Dunlap 		/* Ignore */
540a6d42e7dSPeter Dunlap 		break;
541a6d42e7dSPeter Dunlap 	default:
542a6d42e7dSPeter Dunlap 		ASSERT(0);
543a6d42e7dSPeter Dunlap 	}
544a6d42e7dSPeter Dunlap }
545a6d42e7dSPeter Dunlap 
546a6d42e7dSPeter Dunlap 
547a6d42e7dSPeter Dunlap static void
tgt_sm_deleting_stmf_dereg(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)548a6d42e7dSPeter Dunlap tgt_sm_deleting_stmf_dereg(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
549a6d42e7dSPeter Dunlap {
550a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
551a6d42e7dSPeter Dunlap 
552a6d42e7dSPeter Dunlap 	/* Terminal state, no events */
553a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
554a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
555a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
556a6d42e7dSPeter Dunlap 		/*
557a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are being deleted
558a6d42e7dSPeter Dunlap 		 */
559a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
560a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
561a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
562a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
563a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
564a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
565a6d42e7dSPeter Dunlap 		break;
566a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
567a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
568a6d42e7dSPeter Dunlap 		/* Ignore */
569a6d42e7dSPeter Dunlap 		break;
570a6d42e7dSPeter Dunlap 	case TE_STMF_DEREG_SUCCESS:
571a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_DELETING);
572a6d42e7dSPeter Dunlap 		break;
573a6d42e7dSPeter Dunlap 	case TE_STMF_DEREG_FAIL:
574a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG_FAIL);
575a6d42e7dSPeter Dunlap 		break;
576a6d42e7dSPeter Dunlap 	default:
577a6d42e7dSPeter Dunlap 		ASSERT(0);
578a6d42e7dSPeter Dunlap 	}
579a6d42e7dSPeter Dunlap }
580a6d42e7dSPeter Dunlap 
581a6d42e7dSPeter Dunlap static void
tgt_sm_deleting_stmf_dereg_fail(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)582a6d42e7dSPeter Dunlap tgt_sm_deleting_stmf_dereg_fail(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
583a6d42e7dSPeter Dunlap {
584a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
585a6d42e7dSPeter Dunlap 
586a6d42e7dSPeter Dunlap 	/* Terminal state, no events */
587a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
588a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
589a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
590a6d42e7dSPeter Dunlap 		/*
591a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are being deleted
592a6d42e7dSPeter Dunlap 		 */
593a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
594a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
595a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
596a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
597a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
598a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
599a6d42e7dSPeter Dunlap 		break;
600a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
601a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
602a6d42e7dSPeter Dunlap 		/* Ignore */
603a6d42e7dSPeter Dunlap 		break;
604a6d42e7dSPeter Dunlap 	case TE_STMF_DEREG_RETRY:
605a6d42e7dSPeter Dunlap 		tgt_sm_new_state(tgt, ctx, TS_DELETING_STMF_DEREG);
606a6d42e7dSPeter Dunlap 		break;
607a6d42e7dSPeter Dunlap 	default:
608a6d42e7dSPeter Dunlap 		ASSERT(0);
609a6d42e7dSPeter Dunlap 	}
610a6d42e7dSPeter Dunlap }
611a6d42e7dSPeter Dunlap 
612a6d42e7dSPeter Dunlap static void
tgt_sm_deleting(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx)613a6d42e7dSPeter Dunlap tgt_sm_deleting(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx)
614a6d42e7dSPeter Dunlap {
615a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
616a6d42e7dSPeter Dunlap 
617a6d42e7dSPeter Dunlap 	/* Terminal state, no events */
618a6d42e7dSPeter Dunlap 	switch (ctx->te_ctx_event) {
619a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_REQ:
620a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_REQ:
621a6d42e7dSPeter Dunlap 		/*
622a6d42e7dSPeter Dunlap 		 * We can't complete STMF's request since we are being deleted
623a6d42e7dSPeter Dunlap 		 */
624a6d42e7dSPeter Dunlap 		scs.st_completion_status = STMF_INVALID_ARG;
625a6d42e7dSPeter Dunlap 		scs.st_additional_info = NULL;
626a6d42e7dSPeter Dunlap 		(void) stmf_ctl((ctx->te_ctx_event == TE_STMF_ONLINE_REQ) ?
627a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_ONLINE_COMPLETE :
628a6d42e7dSPeter Dunlap 		    STMF_CMD_LPORT_OFFLINE_COMPLETE,
629a6d42e7dSPeter Dunlap 		    tgt->target_stmf_lport, &scs);
630a6d42e7dSPeter Dunlap 		break;
631a6d42e7dSPeter Dunlap 	case TE_STMF_ONLINE_COMPLETE_ACK:
632a6d42e7dSPeter Dunlap 	case TE_STMF_OFFLINE_COMPLETE_ACK:
633a6d42e7dSPeter Dunlap 		/* Ignore */
634a6d42e7dSPeter Dunlap 		break;
635a6d42e7dSPeter Dunlap 	default:
636a6d42e7dSPeter Dunlap 		ASSERT(0);
637a6d42e7dSPeter Dunlap 	}
638a6d42e7dSPeter Dunlap }
639a6d42e7dSPeter Dunlap 
640a6d42e7dSPeter Dunlap 
641a6d42e7dSPeter Dunlap static void
iscsit_tgt_dereg_retry(void * arg)642a6d42e7dSPeter Dunlap iscsit_tgt_dereg_retry(void *arg)
643a6d42e7dSPeter Dunlap {
644a6d42e7dSPeter Dunlap 	iscsit_tgt_t *tgt = arg;
645a6d42e7dSPeter Dunlap 
646a6d42e7dSPeter Dunlap 	/*
647a6d42e7dSPeter Dunlap 	 * Rather than guaranteeing the target state machine code will not
648a6d42e7dSPeter Dunlap 	 * block for long periods of time (tying up this callout thread)
649a6d42e7dSPeter Dunlap 	 * we will queue a task on the taskq to send the retry event.
650a6d42e7dSPeter Dunlap 	 * If it fails we'll setup another timeout and try again later.
651a6d42e7dSPeter Dunlap 	 */
652a6d42e7dSPeter Dunlap 	if (taskq_dispatch(iscsit_global.global_dispatch_taskq,
653fc8ae2ecSToomas Soome 	    iscsit_tgt_dereg_task, tgt, DDI_NOSLEEP) == TASKQID_INVALID) {
654a6d42e7dSPeter Dunlap 		/* Dispatch failed, try again later */
655a6d42e7dSPeter Dunlap 		(void) timeout(iscsit_tgt_dereg_retry, tgt,
656a6d42e7dSPeter Dunlap 		    drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000));
657a6d42e7dSPeter Dunlap 	}
658a6d42e7dSPeter Dunlap }
659a6d42e7dSPeter Dunlap 
660a6d42e7dSPeter Dunlap static void
iscsit_tgt_dereg_task(void * arg)661a6d42e7dSPeter Dunlap iscsit_tgt_dereg_task(void *arg)
662a6d42e7dSPeter Dunlap {
663a6d42e7dSPeter Dunlap 	iscsit_tgt_t *tgt = arg;
664a6d42e7dSPeter Dunlap 
665a6d42e7dSPeter Dunlap 	iscsit_tgt_sm_event(tgt, TE_STMF_DEREG_RETRY);
666a6d42e7dSPeter Dunlap }
667a6d42e7dSPeter Dunlap 
668a6d42e7dSPeter Dunlap static void
tgt_sm_new_state(iscsit_tgt_t * tgt,tgt_event_ctx_t * ctx,iscsit_tgt_state_t new_state)669a6d42e7dSPeter Dunlap tgt_sm_new_state(iscsit_tgt_t *tgt, tgt_event_ctx_t *ctx,
670a6d42e7dSPeter Dunlap     iscsit_tgt_state_t new_state)
671a6d42e7dSPeter Dunlap {
672a6d42e7dSPeter Dunlap 	stmf_local_port_t		*lport = tgt->target_stmf_lport;
673a6d42e7dSPeter Dunlap 	stmf_change_status_t		scs;
674a6d42e7dSPeter Dunlap 	stmf_state_change_info_t	sci;
675a6d42e7dSPeter Dunlap 	idm_status_t			idmrc;
676a6d42e7dSPeter Dunlap 	stmf_status_t			stmfrc;
677a6d42e7dSPeter Dunlap 
678a6d42e7dSPeter Dunlap 	scs.st_completion_status = STMF_SUCCESS;
679a6d42e7dSPeter Dunlap 	scs.st_additional_info = NULL;
680a6d42e7dSPeter Dunlap 
681a6d42e7dSPeter Dunlap 	/*
682a6d42e7dSPeter Dunlap 	 * Validate new state
683a6d42e7dSPeter Dunlap 	 */
684a6d42e7dSPeter Dunlap 	ASSERT(new_state != TS_UNDEFINED);
685a6d42e7dSPeter Dunlap 	ASSERT3U(new_state, <, TS_MAX_STATE);
686a6d42e7dSPeter Dunlap 
687a6d42e7dSPeter Dunlap 	new_state = (new_state < TS_MAX_STATE) ?
688a6d42e7dSPeter Dunlap 	    new_state : TS_UNDEFINED;
689a6d42e7dSPeter Dunlap 
690a6d42e7dSPeter Dunlap 	IDM_SM_LOG(CE_NOTE, "tgt_sm_new_state: tgt %p, %s(%d) --> %s(%d)\n",
691a6d42e7dSPeter Dunlap 	    (void *) tgt, iscsit_ts_name[tgt->target_state], tgt->target_state,
692a6d42e7dSPeter Dunlap 	    iscsit_ts_name[new_state], new_state);
693a6d42e7dSPeter Dunlap 	DTRACE_PROBE3(target__state__change,
694a6d42e7dSPeter Dunlap 	    iscsit_tgt_t *, tgt, tgt_event_ctx_t *, ctx,
695a6d42e7dSPeter Dunlap 	    iscsit_tgt_state_t, new_state);
696a6d42e7dSPeter Dunlap 
697a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
698a6d42e7dSPeter Dunlap 	idm_sm_audit_state_change(&tgt->target_state_audit, SAS_ISCSIT_TGT,
699a6d42e7dSPeter Dunlap 	    (int)tgt->target_state, (int)new_state);
700a6d42e7dSPeter Dunlap 	tgt->target_last_state = tgt->target_state;
701a6d42e7dSPeter Dunlap 	tgt->target_state = new_state;
702a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
703a6d42e7dSPeter Dunlap 
704a6d42e7dSPeter Dunlap 	switch (tgt->target_state) {
705a6d42e7dSPeter Dunlap 	case TS_ONLINING:
706a6d42e7dSPeter Dunlap 		idmrc = iscsit_tgt_online(tgt);
707a6d42e7dSPeter Dunlap 		if (idmrc != IDM_STATUS_SUCCESS) {
708a6d42e7dSPeter Dunlap 			scs.st_completion_status = STMF_TARGET_FAILURE;
709a6d42e7dSPeter Dunlap 			iscsit_tgt_sm_event(tgt, TE_ONLINE_FAIL);
710a6d42e7dSPeter Dunlap 		} else {
711a6d42e7dSPeter Dunlap 			iscsit_tgt_sm_event(tgt, TE_ONLINE_SUCCESS);
712a6d42e7dSPeter Dunlap 		}
713a6d42e7dSPeter Dunlap 		/*
714a6d42e7dSPeter Dunlap 		 * Let STMF know the how the online operation completed.
715a6d42e7dSPeter Dunlap 		 * STMF will respond with an acknowlege later
716a6d42e7dSPeter Dunlap 		 */
717a6d42e7dSPeter Dunlap 		(void) stmf_ctl(STMF_CMD_LPORT_ONLINE_COMPLETE, lport, &scs);
718a6d42e7dSPeter Dunlap 		break;
719a6d42e7dSPeter Dunlap 	case TS_ONLINE:
720a6d42e7dSPeter Dunlap 		break;
721a6d42e7dSPeter Dunlap 	case TS_STMF_ONLINE:
722a6d42e7dSPeter Dunlap 		(void) iscsit_isns_register(tgt);
723a6d42e7dSPeter Dunlap 		break;
724a6d42e7dSPeter Dunlap 	case TS_DELETING_NEED_OFFLINE:
725a6d42e7dSPeter Dunlap 		sci.st_rflags = STMF_RFLAG_STAY_OFFLINED;
726a6d42e7dSPeter Dunlap 		sci.st_additional_info = "Offline for delete";
727a6d42e7dSPeter Dunlap 		(void) stmf_ctl(STMF_CMD_LPORT_OFFLINE, lport, &sci);
728a6d42e7dSPeter Dunlap 		break;
729a6d42e7dSPeter Dunlap 	case TS_OFFLINING:
730a6d42e7dSPeter Dunlap 		/* Async callback generates completion event */
731a6d42e7dSPeter Dunlap 		iscsit_tgt_offline(tgt);
732a6d42e7dSPeter Dunlap 		break;
733a6d42e7dSPeter Dunlap 	case TS_OFFLINE:
734a6d42e7dSPeter Dunlap 		break;
735a6d42e7dSPeter Dunlap 	case TS_STMF_OFFLINE:
736a6d42e7dSPeter Dunlap 		break;
737a6d42e7dSPeter Dunlap 	case TS_DELETING_STMF_DEREG:
738a6d42e7dSPeter Dunlap 		stmfrc = stmf_deregister_local_port(tgt->target_stmf_lport);
739a6d42e7dSPeter Dunlap 		if (stmfrc == STMF_SUCCESS) {
740a6d42e7dSPeter Dunlap 			iscsit_tgt_sm_event(tgt, TE_STMF_DEREG_SUCCESS);
741a6d42e7dSPeter Dunlap 		} else {
742a6d42e7dSPeter Dunlap 			iscsit_tgt_sm_event(tgt, TE_STMF_DEREG_FAIL);
743a6d42e7dSPeter Dunlap 		}
744a6d42e7dSPeter Dunlap 		break;
745a6d42e7dSPeter Dunlap 	case TS_DELETING_STMF_DEREG_FAIL:
746a6d42e7dSPeter Dunlap 		/* Retry dereg in 1 second */
747a6d42e7dSPeter Dunlap 		(void) timeout(iscsit_tgt_dereg_retry, tgt,
748a6d42e7dSPeter Dunlap 		    drv_usectohz(TGT_DEREG_RETRY_SECONDS * 1000000));
749a6d42e7dSPeter Dunlap 		break;
750a6d42e7dSPeter Dunlap 	case TS_DELETING:
751a6d42e7dSPeter Dunlap 		iscsit_tgt_async_wait_ref(tgt, iscsit_tgt_unref);
752a6d42e7dSPeter Dunlap 		break;
753a6d42e7dSPeter Dunlap 	default:
754a6d42e7dSPeter Dunlap 		ASSERT(0);
755a6d42e7dSPeter Dunlap 	}
756a6d42e7dSPeter Dunlap }
757a6d42e7dSPeter Dunlap 
758a6d42e7dSPeter Dunlap 
759a6d42e7dSPeter Dunlap /*
760a6d42e7dSPeter Dunlap  * Target, TPGT, TPG utility functions
761a6d42e7dSPeter Dunlap  */
762a6d42e7dSPeter Dunlap 
763a6d42e7dSPeter Dunlap it_cfg_status_t
iscsit_config_merge_tgt(it_config_t * cfg)764a6d42e7dSPeter Dunlap iscsit_config_merge_tgt(it_config_t *cfg)
765a6d42e7dSPeter Dunlap {
766a6d42e7dSPeter Dunlap 	it_tgt_t	*cfg_tgt;
767a6d42e7dSPeter Dunlap 	iscsit_tgt_t	*tgt, *next_tgt;
768031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	it_cfg_status_t	itrc = ITCFG_SUCCESS;
769a6d42e7dSPeter Dunlap 
770a6d42e7dSPeter Dunlap 
771a6d42e7dSPeter Dunlap 	/*
772a6d42e7dSPeter Dunlap 	 * 1. >> Lock <<
773a6d42e7dSPeter Dunlap 	 * 2. Removing deleted objects
774a6d42e7dSPeter Dunlap 	 * 3. Add deleted targets to global delete list
775a6d42e7dSPeter Dunlap 	 * 4. "delete" event to target state machine
776a6d42e7dSPeter Dunlap 	 * 5. >> Unlock <<
777a6d42e7dSPeter Dunlap 	 * 6. Create new targets, update modified targets
778a6d42e7dSPeter Dunlap 	 */
779a6d42e7dSPeter Dunlap 	for (tgt = avl_first(&iscsit_global.global_target_list);
780a6d42e7dSPeter Dunlap 	    tgt != NULL;
781a6d42e7dSPeter Dunlap 	    tgt = next_tgt) {
782a6d42e7dSPeter Dunlap 		next_tgt = AVL_NEXT(&iscsit_global.global_target_list, tgt);
783a6d42e7dSPeter Dunlap 
784a6d42e7dSPeter Dunlap 		if (it_tgt_lookup(cfg, tgt->target_name) == NULL) {
785a6d42e7dSPeter Dunlap 			avl_remove(&iscsit_global.global_target_list, tgt);
786a6d42e7dSPeter Dunlap 			list_insert_tail(
787a6d42e7dSPeter Dunlap 			    &iscsit_global.global_deleted_target_list, tgt);
788a6d42e7dSPeter Dunlap 			iscsit_tgt_sm_event(tgt, TE_DELETE);
789a6d42e7dSPeter Dunlap 		}
790a6d42e7dSPeter Dunlap 	}
791a6d42e7dSPeter Dunlap 
792a6d42e7dSPeter Dunlap 	/* Now walk through the list of configured targets */
793a6d42e7dSPeter Dunlap 	for (cfg_tgt = cfg->config_tgt_list;
794a6d42e7dSPeter Dunlap 	    cfg_tgt != NULL;
795a6d42e7dSPeter Dunlap 	    cfg_tgt = cfg_tgt->tgt_next) {
796a6d42e7dSPeter Dunlap 		/* See if we have an existing target */
797a6d42e7dSPeter Dunlap 		tgt = iscsit_tgt_lookup_locked(cfg_tgt->tgt_name);
798a6d42e7dSPeter Dunlap 
799a6d42e7dSPeter Dunlap 		if (tgt == NULL) {
800a6d42e7dSPeter Dunlap 			tgt = iscsit_tgt_create(cfg_tgt);
801a6d42e7dSPeter Dunlap 			if (tgt == NULL)
802a6d42e7dSPeter Dunlap 				return (ITCFG_TGT_CREATE_ERR);
803a6d42e7dSPeter Dunlap 			avl_add(&iscsit_global.global_target_list, tgt);
804a6d42e7dSPeter Dunlap 		} else {
805031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 			if (iscsit_tgt_modify(tgt, cfg_tgt) !=
806031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 			    IDM_STATUS_SUCCESS)
807031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				itrc = ITCFG_MISC_ERR;
808a6d42e7dSPeter Dunlap 			iscsit_tgt_rele(tgt);
809a6d42e7dSPeter Dunlap 		}
810a6d42e7dSPeter Dunlap 	}
811a6d42e7dSPeter Dunlap 
812a6d42e7dSPeter Dunlap 	/*
813a6d42e7dSPeter Dunlap 	 * Targets on the iscsit_global.global_deleted_target_list will remove
814a6d42e7dSPeter Dunlap 	 * and destroy themselves when their associated state machines reach
815a6d42e7dSPeter Dunlap 	 * the TS_DELETED state and all references are released.
816a6d42e7dSPeter Dunlap 	 */
817031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	return (itrc);
818a6d42e7dSPeter Dunlap }
819a6d42e7dSPeter Dunlap 
820a6d42e7dSPeter Dunlap iscsit_tgt_t *
iscsit_tgt_lookup(char * target_name)821a6d42e7dSPeter Dunlap iscsit_tgt_lookup(char *target_name)
822a6d42e7dSPeter Dunlap {
823a6d42e7dSPeter Dunlap 	iscsit_tgt_t	*result;
824a6d42e7dSPeter Dunlap 
825a6d42e7dSPeter Dunlap 	ISCSIT_GLOBAL_LOCK(RW_READER);
826a6d42e7dSPeter Dunlap 	result = iscsit_tgt_lookup_locked(target_name);
827a6d42e7dSPeter Dunlap 	ISCSIT_GLOBAL_UNLOCK();
828a6d42e7dSPeter Dunlap 
829a6d42e7dSPeter Dunlap 	return (result);
830a6d42e7dSPeter Dunlap }
831a6d42e7dSPeter Dunlap 
832a6d42e7dSPeter Dunlap iscsit_tgt_t *
iscsit_tgt_lookup_locked(char * target_name)833a6d42e7dSPeter Dunlap iscsit_tgt_lookup_locked(char *target_name)
834a6d42e7dSPeter Dunlap {
835a6d42e7dSPeter Dunlap 	iscsit_tgt_t	tmp_tgt;
836a6d42e7dSPeter Dunlap 	iscsit_tgt_t	*result;
837a6d42e7dSPeter Dunlap 
838a6d42e7dSPeter Dunlap 	/*
839a6d42e7dSPeter Dunlap 	 * Use a dummy target for lookup, filling in all fields used in AVL
840a6d42e7dSPeter Dunlap 	 * comparison.
841a6d42e7dSPeter Dunlap 	 */
842a6d42e7dSPeter Dunlap 	tmp_tgt.target_name = target_name;
843a6d42e7dSPeter Dunlap 	if ((result = avl_find(&iscsit_global.global_target_list,
844a6d42e7dSPeter Dunlap 	    &tmp_tgt, NULL)) != NULL) {
845a6d42e7dSPeter Dunlap 		iscsit_tgt_hold(result);
846a6d42e7dSPeter Dunlap 	}
847a6d42e7dSPeter Dunlap 
848a6d42e7dSPeter Dunlap 	return (result);
849a6d42e7dSPeter Dunlap }
850a6d42e7dSPeter Dunlap 
851a6d42e7dSPeter Dunlap iscsit_tgt_t *
iscsit_tgt_create(it_tgt_t * cfg_tgt)852a6d42e7dSPeter Dunlap iscsit_tgt_create(it_tgt_t *cfg_tgt)
853a6d42e7dSPeter Dunlap {
854a6d42e7dSPeter Dunlap 	iscsit_tgt_t		*result;
855a6d42e7dSPeter Dunlap 	stmf_local_port_t	*lport;
856ca3b8945SYuri Pankov 	char			*alias;
857a6d42e7dSPeter Dunlap 
858a6d42e7dSPeter Dunlap 	/*
859a6d42e7dSPeter Dunlap 	 * Each target is an STMF local port.
860a6d42e7dSPeter Dunlap 	 */
861a6d42e7dSPeter Dunlap 	lport = stmf_alloc(STMF_STRUCT_STMF_LOCAL_PORT,
862a6d42e7dSPeter Dunlap 	    sizeof (iscsit_tgt_t) + sizeof (scsi_devid_desc_t) +
863a6d42e7dSPeter Dunlap 	    strnlen(cfg_tgt->tgt_name, MAX_ISCSI_NODENAMELEN) + 1, 0);
864a6d42e7dSPeter Dunlap 	if (lport == NULL) {
865a6d42e7dSPeter Dunlap 		return (NULL);
866a6d42e7dSPeter Dunlap 	}
867a6d42e7dSPeter Dunlap 
868a6d42e7dSPeter Dunlap 	result = lport->lport_port_private;
869a6d42e7dSPeter Dunlap 	result->target_state = TS_CREATED;
870a6d42e7dSPeter Dunlap 	result->target_stmf_lport_registered = 0;
871a6d42e7dSPeter Dunlap 	/* Use pointer arithmetic to find scsi_devid_desc_t */
872a6d42e7dSPeter Dunlap 	result->target_devid = (scsi_devid_desc_t *)(result + 1);
873a6d42e7dSPeter Dunlap 	(void) strcpy((char *)result->target_devid->ident, cfg_tgt->tgt_name);
874a6d42e7dSPeter Dunlap 	result->target_devid->ident_length =
875a6d42e7dSPeter Dunlap 	    strnlen(cfg_tgt->tgt_name, MAX_ISCSI_NODENAMELEN);
876a6d42e7dSPeter Dunlap 	result->target_devid->protocol_id = PROTOCOL_iSCSI;
877a6d42e7dSPeter Dunlap 	result->target_devid->piv = 1;
878a6d42e7dSPeter Dunlap 	result->target_devid->code_set = CODE_SET_ASCII;
879a6d42e7dSPeter Dunlap 	result->target_devid->association = ID_IS_TARGET_PORT;
880a6d42e7dSPeter Dunlap 
881a6d42e7dSPeter Dunlap 	/* Store a shortcut to the target name */
882a6d42e7dSPeter Dunlap 	result->target_name = (char *)result->target_devid->ident;
883a6d42e7dSPeter Dunlap 	idm_sm_audit_init(&result->target_state_audit);
884a6d42e7dSPeter Dunlap 	mutex_init(&result->target_mutex, NULL, MUTEX_DEFAULT, NULL);
885a6d42e7dSPeter Dunlap 	avl_create(&result->target_sess_list, iscsit_sess_avl_compare,
886a6d42e7dSPeter Dunlap 	    sizeof (iscsit_sess_t), offsetof(iscsit_sess_t, ist_tgt_ln));
887a6d42e7dSPeter Dunlap 	avl_create(&result->target_tpgt_list, iscsit_tpgt_avl_compare,
888a6d42e7dSPeter Dunlap 	    sizeof (iscsit_tpgt_t), offsetof(iscsit_tpgt_t, tpgt_tgt_ln));
889a6d42e7dSPeter Dunlap 	list_create(&result->target_events, sizeof (tgt_event_ctx_t),
890a6d42e7dSPeter Dunlap 	    offsetof(tgt_event_ctx_t, te_ctx_node));
891a6d42e7dSPeter Dunlap 	idm_refcnt_init(&result->target_refcnt, result);
892a6d42e7dSPeter Dunlap 	idm_refcnt_init(&result->target_sess_refcnt, result);
893a6d42e7dSPeter Dunlap 
894ca3b8945SYuri Pankov 	/* Set target alias */
895ca3b8945SYuri Pankov 	if (nvlist_lookup_string(cfg_tgt->tgt_properties, "alias", &alias) == 0)
896ca3b8945SYuri Pankov 		lport->lport_alias = strdup(alias);
897ca3b8945SYuri Pankov 
898a6d42e7dSPeter Dunlap 	/* Finish initializing local port */
89930e7468fSPeter Dunlap 	/*
90030e7468fSPeter Dunlap 	 * Would like infinite timeout, but this is about as long as can
90130e7468fSPeter Dunlap 	 * be specified to stmf on a 32 bit kernel.
90230e7468fSPeter Dunlap 	 */
90330e7468fSPeter Dunlap 	lport->lport_abort_timeout = 2000; /* seconds */
904a6d42e7dSPeter Dunlap 	lport->lport_id = result->target_devid;
905a6d42e7dSPeter Dunlap 	lport->lport_pp = iscsit_global.global_pp;
906a6d42e7dSPeter Dunlap 	lport->lport_ds = iscsit_global.global_dbuf_store;
907a6d42e7dSPeter Dunlap 	lport->lport_xfer_data = &iscsit_xfer_scsi_data;
908a6d42e7dSPeter Dunlap 	lport->lport_send_status = &iscsit_send_scsi_status;
909a6d42e7dSPeter Dunlap 	lport->lport_task_free = &iscsit_lport_task_free;
910a6d42e7dSPeter Dunlap 	lport->lport_abort = &iscsit_abort;
911a6d42e7dSPeter Dunlap 	lport->lport_ctl = &iscsit_ctl;
912a6d42e7dSPeter Dunlap 	result->target_stmf_lport = lport;
913a6d42e7dSPeter Dunlap 
91407a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	/*
91507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * We need a global hold until the STMF-ONLINE state machine
91607a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * completes.  Acquire that hold now, in case we need to call
91707a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 * iscsit_tgt_destroy, which will also release the hold.
91807a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	 */
91907a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	iscsit_global_hold();
92007a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
921a6d42e7dSPeter Dunlap 	/*
922a6d42e7dSPeter Dunlap 	 * Additional target modifications from config
923a6d42e7dSPeter Dunlap 	 */
924a6d42e7dSPeter Dunlap 	if (iscsit_tgt_modify(result, cfg_tgt) != IDM_STATUS_SUCCESS) {
925a6d42e7dSPeter Dunlap 		iscsit_tgt_destroy(result);
926a6d42e7dSPeter Dunlap 		return (NULL);
927a6d42e7dSPeter Dunlap 	}
928a6d42e7dSPeter Dunlap 
929a6d42e7dSPeter Dunlap 	/*
930a6d42e7dSPeter Dunlap 	 * Register the target with STMF but not until we have all the
931a6d42e7dSPeter Dunlap 	 * TPGT bindings and any other additional config setup.  STMF
932a6d42e7dSPeter Dunlap 	 * may immediately ask us to go online.
933a6d42e7dSPeter Dunlap 	 */
934a6d42e7dSPeter Dunlap 	if (stmf_register_local_port(lport) != STMF_SUCCESS) {
935a6d42e7dSPeter Dunlap 		iscsit_tgt_destroy(result);
936a6d42e7dSPeter Dunlap 		return (NULL);
937a6d42e7dSPeter Dunlap 	}
938a6d42e7dSPeter Dunlap 	result->target_stmf_lport_registered = 1;
939a6d42e7dSPeter Dunlap 
940a6d42e7dSPeter Dunlap 	return (result);
941a6d42e7dSPeter Dunlap }
942a6d42e7dSPeter Dunlap 
943a6d42e7dSPeter Dunlap static idm_status_t
iscsit_tgt_modify(iscsit_tgt_t * tgt,it_tgt_t * cfg_tgt)944a6d42e7dSPeter Dunlap iscsit_tgt_modify(iscsit_tgt_t *tgt, it_tgt_t *cfg_tgt)
945a6d42e7dSPeter Dunlap {
946a6d42e7dSPeter Dunlap 	idm_status_t	idmrc = IDM_STATUS_SUCCESS;
947a6d42e7dSPeter Dunlap 	list_t		tpgt_del_list;
948ca3b8945SYuri Pankov 	char		*alias;
949a6d42e7dSPeter Dunlap 
950a6d42e7dSPeter Dunlap 	/* Merge TPGT */
951a6d42e7dSPeter Dunlap 	list_create(&tpgt_del_list, sizeof (iscsit_tpgt_t),
952a6d42e7dSPeter Dunlap 	    offsetof(iscsit_tpgt_t, tpgt_delete_ln));
953a6d42e7dSPeter Dunlap 
954a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
955a6d42e7dSPeter Dunlap 	if (tgt->target_props) {
956a6d42e7dSPeter Dunlap 		nvlist_free(tgt->target_props);
957a6d42e7dSPeter Dunlap 		tgt->target_props = NULL;
958a6d42e7dSPeter Dunlap 	}
959a6d42e7dSPeter Dunlap 	(void) nvlist_dup(cfg_tgt->tgt_properties, &tgt->target_props,
960a6d42e7dSPeter Dunlap 	    KM_SLEEP);
961a6d42e7dSPeter Dunlap 
962ca3b8945SYuri Pankov 	/* Update alias */
963ca3b8945SYuri Pankov 	if (tgt->target_stmf_lport->lport_alias) {
964ca3b8945SYuri Pankov 		strfree(tgt->target_stmf_lport->lport_alias);
965ca3b8945SYuri Pankov 		tgt->target_stmf_lport->lport_alias = NULL;
966ca3b8945SYuri Pankov 	}
967ca3b8945SYuri Pankov 	if (nvlist_lookup_string(tgt->target_props, "alias", &alias) == 0)
968ca3b8945SYuri Pankov 		tgt->target_stmf_lport->lport_alias = strdup(alias);
969ca3b8945SYuri Pankov 
970a6d42e7dSPeter Dunlap 	if ((idmrc = iscsit_tgt_merge_tpgt(tgt, cfg_tgt, &tpgt_del_list)) !=
971a6d42e7dSPeter Dunlap 	    IDM_STATUS_SUCCESS) {
972a6d42e7dSPeter Dunlap 		/* This should never happen */
973a6d42e7dSPeter Dunlap 		cmn_err(CE_WARN, "Fail to configure TPGTs for "
974a6d42e7dSPeter Dunlap 		    "target %s, the target modification could not be "
975a6d42e7dSPeter Dunlap 		    "completed.", tgt->target_name);
976a6d42e7dSPeter Dunlap 	}
977a6d42e7dSPeter Dunlap 
978a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
979a6d42e7dSPeter Dunlap 
980a6d42e7dSPeter Dunlap 	iscsit_config_destroy_tpgts(&tpgt_del_list);
981a6d42e7dSPeter Dunlap 
982a6d42e7dSPeter Dunlap 	/*
983a6d42e7dSPeter Dunlap 	 * If the target is truly modified (not newly created),
984a6d42e7dSPeter Dunlap 	 * inform iSNS to update the target registration.
985a6d42e7dSPeter Dunlap 	 */
986a6d42e7dSPeter Dunlap 	if ((tgt->target_generation > 0) &&
987a6d42e7dSPeter Dunlap 	    (cfg_tgt->tgt_generation > tgt->target_generation)) {
988a6d42e7dSPeter Dunlap 		iscsit_isns_target_update(tgt);
989a6d42e7dSPeter Dunlap 	}
990a6d42e7dSPeter Dunlap 
991a6d42e7dSPeter Dunlap 	tgt->target_generation = cfg_tgt->tgt_generation;
992a6d42e7dSPeter Dunlap 
993a6d42e7dSPeter Dunlap 	return (idmrc);
994a6d42e7dSPeter Dunlap }
995a6d42e7dSPeter Dunlap 
996a6d42e7dSPeter Dunlap void
iscsit_config_destroy_tpgts(list_t * tpgt_del_list)997a6d42e7dSPeter Dunlap iscsit_config_destroy_tpgts(list_t *tpgt_del_list)
998a6d42e7dSPeter Dunlap {
999a6d42e7dSPeter Dunlap 	iscsit_tpgt_t	*tpgt, *next_tpgt;
1000a6d42e7dSPeter Dunlap 
1001a6d42e7dSPeter Dunlap 	for (tpgt = list_head(tpgt_del_list);
1002a6d42e7dSPeter Dunlap 	    tpgt != NULL;
1003a6d42e7dSPeter Dunlap 	    tpgt = next_tpgt) {
1004a6d42e7dSPeter Dunlap 		next_tpgt = list_next(tpgt_del_list, tpgt);
1005a6d42e7dSPeter Dunlap 
1006a6d42e7dSPeter Dunlap 		list_remove(tpgt_del_list, tpgt);
1007a6d42e7dSPeter Dunlap 		idm_refcnt_wait_ref(&tpgt->tpgt_refcnt);
1008a6d42e7dSPeter Dunlap 		iscsit_tpgt_destroy(tpgt);
1009a6d42e7dSPeter Dunlap 	}
1010a6d42e7dSPeter Dunlap }
1011a6d42e7dSPeter Dunlap 
1012a6d42e7dSPeter Dunlap void
iscsit_tgt_unref(void * tgt_void)1013a6d42e7dSPeter Dunlap iscsit_tgt_unref(void *tgt_void)
1014a6d42e7dSPeter Dunlap {
1015a6d42e7dSPeter Dunlap 	iscsit_tgt_t	*tgt = tgt_void;
1016a6d42e7dSPeter Dunlap 
1017a6d42e7dSPeter Dunlap 	ISCSIT_GLOBAL_LOCK(RW_WRITER);
1018a6d42e7dSPeter Dunlap 	list_remove(&iscsit_global.global_deleted_target_list, tgt);
1019a6d42e7dSPeter Dunlap 	ISCSIT_GLOBAL_UNLOCK();
1020a6d42e7dSPeter Dunlap 	iscsit_tgt_destroy(tgt);
1021a6d42e7dSPeter Dunlap }
1022a6d42e7dSPeter Dunlap 
1023a6d42e7dSPeter Dunlap void
iscsit_tgt_async_wait_ref(iscsit_tgt_t * tgt,idm_refcnt_cb_t * cb_func)1024a6d42e7dSPeter Dunlap iscsit_tgt_async_wait_ref(iscsit_tgt_t *tgt, idm_refcnt_cb_t *cb_func)
1025a6d42e7dSPeter Dunlap {
1026a6d42e7dSPeter Dunlap 	idm_refcnt_async_wait_ref(&tgt->target_refcnt, cb_func);
1027a6d42e7dSPeter Dunlap }
1028a6d42e7dSPeter Dunlap 
1029a6d42e7dSPeter Dunlap static void
iscsit_tgt_destroy(iscsit_tgt_t * tgt)1030a6d42e7dSPeter Dunlap iscsit_tgt_destroy(iscsit_tgt_t *tgt)
1031a6d42e7dSPeter Dunlap {
1032a6d42e7dSPeter Dunlap 	iscsit_tpgt_t *tpgt, *next_tpgt;
1033a6d42e7dSPeter Dunlap 
103407a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	ASSERT(tgt->target_state == TS_DELETING ||
103507a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	    (tgt->target_state == TS_CREATED &&
103607a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	    tgt->target_stmf_lport_registered == 0));
1037a6d42e7dSPeter Dunlap 
1038a6d42e7dSPeter Dunlap 	/*
1039a6d42e7dSPeter Dunlap 	 * Destroy all target portal group tags
1040a6d42e7dSPeter Dunlap 	 */
1041a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
1042a6d42e7dSPeter Dunlap 	for (tpgt = avl_first(&tgt->target_tpgt_list);
1043a6d42e7dSPeter Dunlap 	    tpgt != NULL;
1044a6d42e7dSPeter Dunlap 	    tpgt = next_tpgt) {
1045a6d42e7dSPeter Dunlap 		next_tpgt = AVL_NEXT(&tgt->target_tpgt_list, tpgt);
1046a6d42e7dSPeter Dunlap 		avl_remove(&tgt->target_tpgt_list, tpgt);
1047a6d42e7dSPeter Dunlap 		iscsit_tpgt_destroy(tpgt);
1048a6d42e7dSPeter Dunlap 	}
1049a6d42e7dSPeter Dunlap 
1050a6d42e7dSPeter Dunlap 	if (tgt->target_props) {
1051a6d42e7dSPeter Dunlap 		nvlist_free(tgt->target_props);
1052a6d42e7dSPeter Dunlap 	}
1053a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
1054a6d42e7dSPeter Dunlap 
1055a6d42e7dSPeter Dunlap 	/*
1056a6d42e7dSPeter Dunlap 	 * Destroy target
1057a6d42e7dSPeter Dunlap 	 */
1058a6d42e7dSPeter Dunlap 	idm_refcnt_destroy(&tgt->target_sess_refcnt);
1059a6d42e7dSPeter Dunlap 	idm_refcnt_destroy(&tgt->target_refcnt);
1060a6d42e7dSPeter Dunlap 	list_destroy(&tgt->target_events);
1061a6d42e7dSPeter Dunlap 	avl_destroy(&tgt->target_tpgt_list);
1062a6d42e7dSPeter Dunlap 	avl_destroy(&tgt->target_sess_list);
1063a6d42e7dSPeter Dunlap 	mutex_destroy(&tgt->target_mutex);
1064ca3b8945SYuri Pankov 	if (tgt->target_stmf_lport->lport_alias)
1065ca3b8945SYuri Pankov 		strfree(tgt->target_stmf_lport->lport_alias);
1066a6d42e7dSPeter Dunlap 	stmf_free(tgt->target_stmf_lport); /* Also frees "tgt' */
1067a6d42e7dSPeter Dunlap 	iscsit_global_rele();
1068a6d42e7dSPeter Dunlap }
1069a6d42e7dSPeter Dunlap 
1070a6d42e7dSPeter Dunlap void
iscsit_tgt_hold(iscsit_tgt_t * tgt)1071a6d42e7dSPeter Dunlap iscsit_tgt_hold(iscsit_tgt_t *tgt)
1072a6d42e7dSPeter Dunlap {
1073a6d42e7dSPeter Dunlap 	idm_refcnt_hold(&tgt->target_refcnt);
1074a6d42e7dSPeter Dunlap }
1075a6d42e7dSPeter Dunlap 
1076a6d42e7dSPeter Dunlap void
iscsit_tgt_rele(iscsit_tgt_t * tgt)1077a6d42e7dSPeter Dunlap iscsit_tgt_rele(iscsit_tgt_t *tgt)
1078a6d42e7dSPeter Dunlap {
1079a6d42e7dSPeter Dunlap 	idm_refcnt_rele(&tgt->target_refcnt);
1080a6d42e7dSPeter Dunlap }
1081a6d42e7dSPeter Dunlap 
1082a6d42e7dSPeter Dunlap int
iscsit_tgt_avl_compare(const void * void_tgt1,const void * void_tgt2)1083a6d42e7dSPeter Dunlap iscsit_tgt_avl_compare(const void *void_tgt1, const void *void_tgt2)
1084a6d42e7dSPeter Dunlap {
1085a6d42e7dSPeter Dunlap 	const iscsit_tgt_t	*tgt1 = void_tgt1;
1086a6d42e7dSPeter Dunlap 	const iscsit_tgt_t	*tgt2 = void_tgt2;
1087*1f99504aSToomas Soome 	int			result;
1088a6d42e7dSPeter Dunlap 
1089a6d42e7dSPeter Dunlap 	/*
1090a6d42e7dSPeter Dunlap 	 * Sort by ISID first then TSIH
1091a6d42e7dSPeter Dunlap 	 */
1092a6d42e7dSPeter Dunlap 	result = strcmp(tgt1->target_name, tgt2->target_name);
1093a6d42e7dSPeter Dunlap 	if (result < 0) {
1094a6d42e7dSPeter Dunlap 		return (-1);
1095a6d42e7dSPeter Dunlap 	} else if (result > 0) {
1096a6d42e7dSPeter Dunlap 		return (1);
1097a6d42e7dSPeter Dunlap 	}
1098a6d42e7dSPeter Dunlap 
1099a6d42e7dSPeter Dunlap 	return (0);
1100a6d42e7dSPeter Dunlap }
1101a6d42e7dSPeter Dunlap 
1102a6d42e7dSPeter Dunlap 
1103a6d42e7dSPeter Dunlap iscsit_tpgt_t *
iscsit_tgt_lookup_tpgt(iscsit_tgt_t * tgt,uint16_t tag)1104a6d42e7dSPeter Dunlap iscsit_tgt_lookup_tpgt(iscsit_tgt_t *tgt, uint16_t tag)
1105a6d42e7dSPeter Dunlap {
1106a6d42e7dSPeter Dunlap 	iscsit_tpgt_t *result;
1107a6d42e7dSPeter Dunlap 
1108a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
1109a6d42e7dSPeter Dunlap 	result = iscsit_tgt_lookup_tpgt_locked(tgt, tag);
1110a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
1111a6d42e7dSPeter Dunlap 
1112a6d42e7dSPeter Dunlap 	return (result);
1113a6d42e7dSPeter Dunlap }
1114a6d42e7dSPeter Dunlap 
1115a6d42e7dSPeter Dunlap static iscsit_tpgt_t *
iscsit_tgt_lookup_tpgt_locked(iscsit_tgt_t * tgt,uint16_t tag)1116a6d42e7dSPeter Dunlap iscsit_tgt_lookup_tpgt_locked(iscsit_tgt_t *tgt, uint16_t tag)
1117a6d42e7dSPeter Dunlap {
1118a6d42e7dSPeter Dunlap 	iscsit_tpgt_t	tmp_tpgt;
1119a6d42e7dSPeter Dunlap 	iscsit_tpgt_t	*result;
1120a6d42e7dSPeter Dunlap 
1121a6d42e7dSPeter Dunlap 	/* Caller holds tgt->target_mutex */
1122a6d42e7dSPeter Dunlap 	tmp_tpgt.tpgt_tag = tag;
1123a6d42e7dSPeter Dunlap 	if ((result = avl_find(&tgt->target_tpgt_list, &tmp_tpgt, NULL)) !=
1124a6d42e7dSPeter Dunlap 	    NULL) {
1125a6d42e7dSPeter Dunlap 		iscsit_tpgt_hold(result);
1126a6d42e7dSPeter Dunlap 	}
1127a6d42e7dSPeter Dunlap 
1128a6d42e7dSPeter Dunlap 	return (result);
1129a6d42e7dSPeter Dunlap }
1130a6d42e7dSPeter Dunlap 
1131a6d42e7dSPeter Dunlap iscsit_portal_t *
iscsit_tgt_lookup_portal(iscsit_tgt_t * tgt,struct sockaddr_storage * sa,iscsit_tpgt_t ** output_tpgt)1132a6d42e7dSPeter Dunlap iscsit_tgt_lookup_portal(iscsit_tgt_t *tgt, struct sockaddr_storage *sa,
1133a6d42e7dSPeter Dunlap     iscsit_tpgt_t **output_tpgt)
1134a6d42e7dSPeter Dunlap {
1135*1f99504aSToomas Soome 	iscsit_tpgt_t	*tpgt;
1136a6d42e7dSPeter Dunlap 	iscsit_portal_t	*portal;
1137a6d42e7dSPeter Dunlap 
1138a6d42e7dSPeter Dunlap 	/* Caller holds tgt->target_mutex */
1139a6d42e7dSPeter Dunlap 	ASSERT(mutex_owned(&tgt->target_mutex));
1140a6d42e7dSPeter Dunlap 	for (tpgt = avl_first(&tgt->target_tpgt_list);
1141a6d42e7dSPeter Dunlap 	    tpgt != NULL;
1142a6d42e7dSPeter Dunlap 	    tpgt = AVL_NEXT(&tgt->target_tpgt_list, tpgt)) {
1143a6d42e7dSPeter Dunlap 		portal = iscsit_tpg_portal_lookup(tpgt->tpgt_tpg, sa);
1144a6d42e7dSPeter Dunlap 		if (portal) {
1145a6d42e7dSPeter Dunlap 			iscsit_tpgt_hold(tpgt);
1146a6d42e7dSPeter Dunlap 			*output_tpgt = tpgt;
1147a6d42e7dSPeter Dunlap 			return (portal);
1148a6d42e7dSPeter Dunlap 		}
1149a6d42e7dSPeter Dunlap 	}
1150a6d42e7dSPeter Dunlap 
1151a6d42e7dSPeter Dunlap 	return (NULL);
1152a6d42e7dSPeter Dunlap }
1153a6d42e7dSPeter Dunlap 
1154a6d42e7dSPeter Dunlap 
1155a6d42e7dSPeter Dunlap void
iscsit_tgt_bind_sess(iscsit_tgt_t * tgt,iscsit_sess_t * sess)1156a6d42e7dSPeter Dunlap iscsit_tgt_bind_sess(iscsit_tgt_t *tgt, iscsit_sess_t *sess)
1157a6d42e7dSPeter Dunlap {
1158a6d42e7dSPeter Dunlap 	if (tgt) {
1159a6d42e7dSPeter Dunlap 		sess->ist_lport = tgt->target_stmf_lport;
1160a6d42e7dSPeter Dunlap 		iscsit_tgt_hold(tgt);
1161a6d42e7dSPeter Dunlap 		idm_refcnt_hold(&tgt->target_sess_refcnt);
1162a6d42e7dSPeter Dunlap 		mutex_enter(&tgt->target_mutex);
1163a6d42e7dSPeter Dunlap 		avl_add(&tgt->target_sess_list, sess);
1164a6d42e7dSPeter Dunlap 		mutex_exit(&tgt->target_mutex);
1165a6d42e7dSPeter Dunlap 	} else {
1166a6d42e7dSPeter Dunlap 		/* Discovery session */
1167a6d42e7dSPeter Dunlap 		sess->ist_lport = NULL;
1168a6d42e7dSPeter Dunlap 		ISCSIT_GLOBAL_LOCK(RW_WRITER);
1169a6d42e7dSPeter Dunlap 		avl_add(&iscsit_global.global_discovery_sessions, sess);
1170a6d42e7dSPeter Dunlap 		ISCSIT_GLOBAL_UNLOCK();
1171a6d42e7dSPeter Dunlap 	}
1172a6d42e7dSPeter Dunlap }
1173a6d42e7dSPeter Dunlap 
1174a6d42e7dSPeter Dunlap void
iscsit_tgt_unbind_sess(iscsit_tgt_t * tgt,iscsit_sess_t * sess)1175a6d42e7dSPeter Dunlap iscsit_tgt_unbind_sess(iscsit_tgt_t *tgt, iscsit_sess_t *sess)
1176a6d42e7dSPeter Dunlap {
1177a6d42e7dSPeter Dunlap 	if (tgt) {
1178a6d42e7dSPeter Dunlap 		mutex_enter(&tgt->target_mutex);
1179a6d42e7dSPeter Dunlap 		avl_remove(&tgt->target_sess_list, sess);
1180a6d42e7dSPeter Dunlap 		mutex_exit(&tgt->target_mutex);
1181a6d42e7dSPeter Dunlap 		sess->ist_tgt = (iscsit_tgt_t *)SESS_UNBOUND_FROM_TGT;
1182a6d42e7dSPeter Dunlap 		idm_refcnt_rele(&tgt->target_sess_refcnt);
1183a6d42e7dSPeter Dunlap 		iscsit_tgt_rele(tgt);
1184a6d42e7dSPeter Dunlap 	} else {
1185a6d42e7dSPeter Dunlap 		/* Discovery session */
1186a6d42e7dSPeter Dunlap 		ISCSIT_GLOBAL_LOCK(RW_WRITER);
1187a6d42e7dSPeter Dunlap 		avl_remove(&iscsit_global.global_discovery_sessions, sess);
1188a6d42e7dSPeter Dunlap 		ISCSIT_GLOBAL_UNLOCK();
1189a6d42e7dSPeter Dunlap 	}
1190a6d42e7dSPeter Dunlap }
1191a6d42e7dSPeter Dunlap 
1192*1f99504aSToomas Soome #define	LOCK_FOR_SESS_LOOKUP(lookup_tgt) {			\
1193a6d42e7dSPeter Dunlap 	if ((lookup_tgt) == NULL) {				\
1194a6d42e7dSPeter Dunlap 		ISCSIT_GLOBAL_LOCK(RW_READER);			\
1195a6d42e7dSPeter Dunlap 	} else {						\
1196a6d42e7dSPeter Dunlap 		mutex_enter(&(lookup_tgt)->target_mutex);	\
1197a6d42e7dSPeter Dunlap 	}							\
1198a6d42e7dSPeter Dunlap }
1199a6d42e7dSPeter Dunlap 
1200*1f99504aSToomas Soome #define	UNLOCK_FOR_SESS_LOOKUP(lookup_tgt) {			\
1201a6d42e7dSPeter Dunlap 	if ((lookup_tgt) == NULL) {				\
1202a6d42e7dSPeter Dunlap 		ISCSIT_GLOBAL_UNLOCK();				\
1203*1f99504aSToomas Soome 	} else {						\
1204*1f99504aSToomas Soome 		mutex_exit(&(lookup_tgt)->target_mutex);	\
1205a6d42e7dSPeter Dunlap 	}							\
1206a6d42e7dSPeter Dunlap }
1207a6d42e7dSPeter Dunlap 
1208a6d42e7dSPeter Dunlap iscsit_sess_t *
iscsit_tgt_lookup_sess(iscsit_tgt_t * tgt,char * initiator_name,uint8_t * isid,uint16_t tsih,uint16_t tag)1209a6d42e7dSPeter Dunlap iscsit_tgt_lookup_sess(iscsit_tgt_t *tgt, char *initiator_name,
1210a6d42e7dSPeter Dunlap     uint8_t *isid, uint16_t tsih, uint16_t tag)
1211a6d42e7dSPeter Dunlap {
1212a6d42e7dSPeter Dunlap 	iscsit_sess_t	tmp_sess;
1213a6d42e7dSPeter Dunlap 	avl_tree_t	*sess_avl;
1214a6d42e7dSPeter Dunlap 	avl_index_t	where;
1215a6d42e7dSPeter Dunlap 	iscsit_sess_t	*result;
1216a6d42e7dSPeter Dunlap 
1217a6d42e7dSPeter Dunlap 	/*
1218a6d42e7dSPeter Dunlap 	 * If tgt is NULL then we are looking for a discovery session
1219a6d42e7dSPeter Dunlap 	 */
1220a6d42e7dSPeter Dunlap 	if (tgt == NULL) {
1221a6d42e7dSPeter Dunlap 		sess_avl = &iscsit_global.global_discovery_sessions;
1222a6d42e7dSPeter Dunlap 	} else {
1223a6d42e7dSPeter Dunlap 		sess_avl = &tgt->target_sess_list;
1224a6d42e7dSPeter Dunlap 	}
1225a6d42e7dSPeter Dunlap 
1226a6d42e7dSPeter Dunlap 	LOCK_FOR_SESS_LOOKUP(tgt);
1227*1f99504aSToomas Soome 	if (avl_numnodes(sess_avl) == 0) {
1228a6d42e7dSPeter Dunlap 		UNLOCK_FOR_SESS_LOOKUP(tgt);
1229a6d42e7dSPeter Dunlap 		return (NULL);
1230a6d42e7dSPeter Dunlap 	}
1231a6d42e7dSPeter Dunlap 
1232a6d42e7dSPeter Dunlap 	/*
1233a6d42e7dSPeter Dunlap 	 * We'll try to find a session matching ISID + TSIH first.  If we
1234a6d42e7dSPeter Dunlap 	 * can't find one then we will return the closest match.  If the
1235a6d42e7dSPeter Dunlap 	 * caller needs an exact match it must compare the TSIH after
1236a6d42e7dSPeter Dunlap 	 * the session is returned.
1237a6d42e7dSPeter Dunlap 	 *
1238a6d42e7dSPeter Dunlap 	 * The reason we do this "fuzzy matching" is to allow matching
1239a6d42e7dSPeter Dunlap 	 * sessions with different TSIH values on the same AVL list.  This
1240a6d42e7dSPeter Dunlap 	 * makes session reinstatement much easier since the new session can
1241a6d42e7dSPeter Dunlap 	 * live on the list at the same time as the old session is cleaning up.
1242a6d42e7dSPeter Dunlap 	 */
1243a6d42e7dSPeter Dunlap 	bcopy(isid, tmp_sess.ist_isid, ISCSI_ISID_LEN);
1244a6d42e7dSPeter Dunlap 	tmp_sess.ist_initiator_name = initiator_name;
1245a6d42e7dSPeter Dunlap 	tmp_sess.ist_tsih = tsih;
1246a6d42e7dSPeter Dunlap 	tmp_sess.ist_tpgt_tag = tag;
1247a6d42e7dSPeter Dunlap 
1248a6d42e7dSPeter Dunlap 	result = avl_find(sess_avl, &tmp_sess, &where);
1249a6d42e7dSPeter Dunlap 	if (result != NULL) {
125047715e7fSPriya Krishnan 		goto found_result;
1251a6d42e7dSPeter Dunlap 	}
1252a6d42e7dSPeter Dunlap 
1253a6d42e7dSPeter Dunlap 	/*
1254a6d42e7dSPeter Dunlap 	 * avl_find_nearest() may return a result with a different ISID so
1255a6d42e7dSPeter Dunlap 	 * we should only return a result if the name and ISID match
1256a6d42e7dSPeter Dunlap 	 */
1257a6d42e7dSPeter Dunlap 	result = avl_nearest(sess_avl, where, AVL_BEFORE);
1258a6d42e7dSPeter Dunlap 	if ((result != NULL) &&
1259a6d42e7dSPeter Dunlap 	    (strcmp(result->ist_initiator_name, initiator_name) == 0) &&
1260a6d42e7dSPeter Dunlap 	    (memcmp(result->ist_isid, isid, ISCSI_ISID_LEN) == 0) &&
1261a6d42e7dSPeter Dunlap 	    (result->ist_tpgt_tag == tag)) {
126247715e7fSPriya Krishnan 		goto found_result;
1263a6d42e7dSPeter Dunlap 	}
1264a6d42e7dSPeter Dunlap 
1265a6d42e7dSPeter Dunlap 	result = avl_nearest(sess_avl, where, AVL_AFTER);
1266a6d42e7dSPeter Dunlap 	if ((result != NULL) &&
1267a6d42e7dSPeter Dunlap 	    (strcmp(result->ist_initiator_name, initiator_name) == 0) &&
1268a6d42e7dSPeter Dunlap 	    (memcmp(result->ist_isid, isid, ISCSI_ISID_LEN) == 0) &&
1269a6d42e7dSPeter Dunlap 	    (result->ist_tpgt_tag == tag)) {
127047715e7fSPriya Krishnan 		goto found_result;
1271a6d42e7dSPeter Dunlap 	}
1272a6d42e7dSPeter Dunlap 
127347715e7fSPriya Krishnan 	result = NULL;
1274a6d42e7dSPeter Dunlap 
127547715e7fSPriya Krishnan found_result:
127647715e7fSPriya Krishnan 	if ((result != NULL) &&
127747715e7fSPriya Krishnan 	    (iscsit_sess_check_hold(result) != IDM_STATUS_SUCCESS)) {
127847715e7fSPriya Krishnan 		result = NULL;
127947715e7fSPriya Krishnan 	}
128047715e7fSPriya Krishnan 	UNLOCK_FOR_SESS_LOOKUP(tgt);
128147715e7fSPriya Krishnan 	return (result);
1282a6d42e7dSPeter Dunlap }
1283a6d42e7dSPeter Dunlap 
1284a6d42e7dSPeter Dunlap static idm_status_t
iscsit_tgt_merge_tpgt(iscsit_tgt_t * tgt,it_tgt_t * cfg_tgt,list_t * tpgt_del_list)1285a6d42e7dSPeter Dunlap iscsit_tgt_merge_tpgt(iscsit_tgt_t *tgt, it_tgt_t *cfg_tgt,
1286a6d42e7dSPeter Dunlap     list_t *tpgt_del_list)
1287a6d42e7dSPeter Dunlap {
1288a6d42e7dSPeter Dunlap 	iscsit_tpgt_t	*tpgt, *next_tpgt;
1289a6d42e7dSPeter Dunlap 	it_tpgt_t	*cfg_tpgt;
1290031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	idm_status_t	status = IDM_STATUS_SUCCESS;
1291a6d42e7dSPeter Dunlap 
1292a6d42e7dSPeter Dunlap 	/*
1293a6d42e7dSPeter Dunlap 	 * 1. >> Lock <<
1294a6d42e7dSPeter Dunlap 	 * 2. Removing all objects and place on a temp list
1295a6d42e7dSPeter Dunlap 	 * 3. Add new objects
1296a6d42e7dSPeter Dunlap 	 * 4. >> Unlock <<
1297a6d42e7dSPeter Dunlap 	 * 5. tpgt_del_list contains deleted objects
1298a6d42e7dSPeter Dunlap 	 */
1299a6d42e7dSPeter Dunlap 	ASSERT(avl_is_empty(&tgt->target_tpgt_list) ||
1300a6d42e7dSPeter Dunlap 	    (tpgt_del_list != NULL));
1301a6d42e7dSPeter Dunlap 
1302a6d42e7dSPeter Dunlap 	if (tpgt_del_list) {
1303a6d42e7dSPeter Dunlap 		for (tpgt = avl_first(&tgt->target_tpgt_list);
1304a6d42e7dSPeter Dunlap 		    tpgt != NULL; tpgt = next_tpgt) {
1305a6d42e7dSPeter Dunlap 			next_tpgt = AVL_NEXT(&tgt->target_tpgt_list, tpgt);
1306a6d42e7dSPeter Dunlap 			avl_remove(&tgt->target_tpgt_list, tpgt);
1307a6d42e7dSPeter Dunlap 			if (tgt->target_state == TS_STMF_ONLINE) {
1308a6d42e7dSPeter Dunlap 				tpgt->tpgt_needs_tpg_offline = B_TRUE;
1309a6d42e7dSPeter Dunlap 			}
1310a6d42e7dSPeter Dunlap 			list_insert_tail(tpgt_del_list, tpgt);
1311a6d42e7dSPeter Dunlap 		}
1312a6d42e7dSPeter Dunlap 	}
1313a6d42e7dSPeter Dunlap 
1314031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	if (cfg_tgt->tgt_tpgt_list != NULL) {
1315a6d42e7dSPeter Dunlap 		/* Add currently defined TPGTs */
1316a6d42e7dSPeter Dunlap 		for (cfg_tpgt = cfg_tgt->tgt_tpgt_list;
1317a6d42e7dSPeter Dunlap 		    cfg_tpgt != NULL;
1318a6d42e7dSPeter Dunlap 		    cfg_tpgt = cfg_tpgt->tpgt_next) {
1319a6d42e7dSPeter Dunlap 			tpgt = iscsit_tpgt_create(cfg_tpgt);
1320031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 			if (tpgt == NULL) {
1321031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				/*
1322031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				 * There is a problem in the configuration we
1323031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				 * received from the ioctl -- a missing tpg.
1324031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				 * All the unbind operations have already
1325031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				 * taken place.  To leave the system in a
1326031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				 * non-panic'd state, use the default tpgt.
1327031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				 */
1328031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				status = IDM_STATUS_FAIL;
1329031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 				continue;
1330031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 			}
1331a6d42e7dSPeter Dunlap 			if (tgt->target_state == TS_STMF_ONLINE) {
1332a6d42e7dSPeter Dunlap 				(void) iscsit_tpg_online(tpgt->tpgt_tpg);
1333a6d42e7dSPeter Dunlap 			}
1334a6d42e7dSPeter Dunlap 			avl_add(&tgt->target_tpgt_list, tpgt);
1335a6d42e7dSPeter Dunlap 		}
1336a6d42e7dSPeter Dunlap 	}
1337a6d42e7dSPeter Dunlap 
1338031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	/* If no TPGTs defined, add the default TPGT */
1339031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	if (avl_numnodes(&tgt->target_tpgt_list) == 0) {
1340031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 		tpgt = iscsit_tpgt_create_default();
1341031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 		if (tgt->target_state == TS_STMF_ONLINE) {
1342031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 			(void) iscsit_tpg_online(tpgt->tpgt_tpg);
1343031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 		}
1344031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 		avl_add(&tgt->target_tpgt_list, tpgt);
1345031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	}
1346a6d42e7dSPeter Dunlap 
1347031f730cSPeter Cudhea - Sun Microsystems - Burlington, MA United States 	return (status);
1348a6d42e7dSPeter Dunlap }
1349a6d42e7dSPeter Dunlap 
1350a6d42e7dSPeter Dunlap static iscsit_tpgt_t *
iscsit_tpgt_create(it_tpgt_t * cfg_tpgt)1351a6d42e7dSPeter Dunlap iscsit_tpgt_create(it_tpgt_t *cfg_tpgt)
1352a6d42e7dSPeter Dunlap {
1353a6d42e7dSPeter Dunlap 	iscsit_tpg_t	*tpg;
1354a6d42e7dSPeter Dunlap 	iscsit_tpgt_t	*result;
1355a6d42e7dSPeter Dunlap 
1356a6d42e7dSPeter Dunlap 	/* This takes a reference on the TPG */
1357a6d42e7dSPeter Dunlap 	tpg = iscsit_tpg_lookup_locked(cfg_tpgt->tpgt_tpg_name);
1358a6d42e7dSPeter Dunlap 	if (tpg == NULL)
1359a6d42e7dSPeter Dunlap 		return (NULL);
1360a6d42e7dSPeter Dunlap 
1361a6d42e7dSPeter Dunlap 	result = kmem_zalloc(sizeof (*result), KM_SLEEP);
1362a6d42e7dSPeter Dunlap 
1363a6d42e7dSPeter Dunlap 	result->tpgt_tpg = tpg;
1364a6d42e7dSPeter Dunlap 	result->tpgt_tag = cfg_tpgt->tpgt_tag;
1365a6d42e7dSPeter Dunlap 
1366a6d42e7dSPeter Dunlap 	return (result);
1367a6d42e7dSPeter Dunlap }
1368a6d42e7dSPeter Dunlap 
1369a6d42e7dSPeter Dunlap iscsit_tpgt_t *
iscsit_tpgt_create_default()1370a6d42e7dSPeter Dunlap iscsit_tpgt_create_default()
1371a6d42e7dSPeter Dunlap {
1372a6d42e7dSPeter Dunlap 	iscsit_tpgt_t	*result;
1373a6d42e7dSPeter Dunlap 
1374a6d42e7dSPeter Dunlap 	result = kmem_zalloc(sizeof (*result), KM_SLEEP);
1375a6d42e7dSPeter Dunlap 
1376a6d42e7dSPeter Dunlap 	result->tpgt_tpg = iscsit_global.global_default_tpg;
1377a6d42e7dSPeter Dunlap 	iscsit_tpg_hold(result->tpgt_tpg);
1378a6d42e7dSPeter Dunlap 	result->tpgt_tag = ISCSIT_DEFAULT_TPGT;
1379a6d42e7dSPeter Dunlap 
1380a6d42e7dSPeter Dunlap 	return (result);
1381a6d42e7dSPeter Dunlap }
1382a6d42e7dSPeter Dunlap 
1383a6d42e7dSPeter Dunlap void
iscsit_tpgt_destroy(iscsit_tpgt_t * tpgt)1384a6d42e7dSPeter Dunlap iscsit_tpgt_destroy(iscsit_tpgt_t *tpgt)
1385a6d42e7dSPeter Dunlap {
1386a6d42e7dSPeter Dunlap 	if (tpgt->tpgt_needs_tpg_offline) {
1387a6d42e7dSPeter Dunlap 		iscsit_tpg_offline(tpgt->tpgt_tpg);
1388a6d42e7dSPeter Dunlap 	}
1389a6d42e7dSPeter Dunlap 	iscsit_tpg_rele(tpgt->tpgt_tpg);
1390a6d42e7dSPeter Dunlap 	kmem_free(tpgt, sizeof (*tpgt));
1391a6d42e7dSPeter Dunlap }
1392a6d42e7dSPeter Dunlap 
1393a6d42e7dSPeter Dunlap void
iscsit_tpgt_hold(iscsit_tpgt_t * tpgt)1394a6d42e7dSPeter Dunlap iscsit_tpgt_hold(iscsit_tpgt_t *tpgt)
1395a6d42e7dSPeter Dunlap {
1396a6d42e7dSPeter Dunlap 	idm_refcnt_hold(&tpgt->tpgt_refcnt);
1397a6d42e7dSPeter Dunlap }
1398a6d42e7dSPeter Dunlap 
1399a6d42e7dSPeter Dunlap void
iscsit_tpgt_rele(iscsit_tpgt_t * tpgt)1400a6d42e7dSPeter Dunlap iscsit_tpgt_rele(iscsit_tpgt_t *tpgt)
1401a6d42e7dSPeter Dunlap {
1402a6d42e7dSPeter Dunlap 	idm_refcnt_rele(&tpgt->tpgt_refcnt);
1403a6d42e7dSPeter Dunlap }
1404a6d42e7dSPeter Dunlap 
1405a6d42e7dSPeter Dunlap int
iscsit_tpgt_avl_compare(const void * void_tpgt1,const void * void_tpgt2)1406a6d42e7dSPeter Dunlap iscsit_tpgt_avl_compare(const void *void_tpgt1, const void *void_tpgt2)
1407a6d42e7dSPeter Dunlap {
1408a6d42e7dSPeter Dunlap 	const iscsit_tpgt_t	*tpgt1 = void_tpgt1;
1409a6d42e7dSPeter Dunlap 	const iscsit_tpgt_t	*tpgt2 = void_tpgt2;
1410a6d42e7dSPeter Dunlap 
1411a6d42e7dSPeter Dunlap 	if (tpgt1->tpgt_tag < tpgt2->tpgt_tag)
1412a6d42e7dSPeter Dunlap 		return (-1);
1413a6d42e7dSPeter Dunlap 	else if (tpgt1->tpgt_tag > tpgt2->tpgt_tag)
1414a6d42e7dSPeter Dunlap 		return (1);
1415a6d42e7dSPeter Dunlap 
1416a6d42e7dSPeter Dunlap 	return (0);
1417a6d42e7dSPeter Dunlap }
1418a6d42e7dSPeter Dunlap 
1419a6d42e7dSPeter Dunlap static idm_status_t
iscsit_tgt_online(iscsit_tgt_t * tgt)1420a6d42e7dSPeter Dunlap iscsit_tgt_online(iscsit_tgt_t *tgt)
1421a6d42e7dSPeter Dunlap {
1422*1f99504aSToomas Soome 	iscsit_tpgt_t		*tpgt, *tpgt_fail;
1423a6d42e7dSPeter Dunlap 	idm_status_t		rc;
1424a6d42e7dSPeter Dunlap 
1425a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
1426a6d42e7dSPeter Dunlap 
1427a6d42e7dSPeter Dunlap 	ASSERT(tgt->target_sess_list.avl_numnodes == 0);
1428a6d42e7dSPeter Dunlap 	idm_refcnt_reset(&tgt->target_sess_refcnt);
1429a6d42e7dSPeter Dunlap 	for (tpgt = avl_first(&tgt->target_tpgt_list);
1430a6d42e7dSPeter Dunlap 	    tpgt != NULL;
1431a6d42e7dSPeter Dunlap 	    tpgt = AVL_NEXT(&tgt->target_tpgt_list, tpgt)) {
1432a6d42e7dSPeter Dunlap 		rc = iscsit_tpg_online(tpgt->tpgt_tpg);
1433a6d42e7dSPeter Dunlap 		if (rc != IDM_STATUS_SUCCESS) {
1434a6d42e7dSPeter Dunlap 			tpgt_fail = tpgt;
1435a6d42e7dSPeter Dunlap 			goto tgt_online_fail;
1436a6d42e7dSPeter Dunlap 		}
1437a6d42e7dSPeter Dunlap 	}
1438a6d42e7dSPeter Dunlap 
1439a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
1440a6d42e7dSPeter Dunlap 
1441a6d42e7dSPeter Dunlap 	return (IDM_STATUS_SUCCESS);
1442a6d42e7dSPeter Dunlap 
1443a6d42e7dSPeter Dunlap tgt_online_fail:
1444a6d42e7dSPeter Dunlap 	/* Offline all the tpgs we successfully onlined up to the failure */
1445a6d42e7dSPeter Dunlap 	for (tpgt = avl_first(&tgt->target_tpgt_list);
1446a6d42e7dSPeter Dunlap 	    tpgt != tpgt_fail;
1447a6d42e7dSPeter Dunlap 	    tpgt = AVL_NEXT(&tgt->target_tpgt_list, tpgt)) {
1448a6d42e7dSPeter Dunlap 		iscsit_tpg_offline(tpgt->tpgt_tpg);
1449a6d42e7dSPeter Dunlap 	}
1450a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
1451a6d42e7dSPeter Dunlap 	return (rc);
1452a6d42e7dSPeter Dunlap }
1453a6d42e7dSPeter Dunlap 
1454a6d42e7dSPeter Dunlap static void
iscsit_tgt_offline_cb(void * tgt_void)1455a6d42e7dSPeter Dunlap iscsit_tgt_offline_cb(void *tgt_void)
1456a6d42e7dSPeter Dunlap {
1457a6d42e7dSPeter Dunlap 	iscsit_tgt_t *tgt = tgt_void;
1458a6d42e7dSPeter Dunlap 	stmf_change_status_t	scs;
1459a6d42e7dSPeter Dunlap 
1460a6d42e7dSPeter Dunlap 	iscsit_tgt_sm_event(tgt, TE_OFFLINE_COMPLETE);
1461a6d42e7dSPeter Dunlap 
1462a6d42e7dSPeter Dunlap 	scs.st_completion_status = STMF_SUCCESS;
1463a6d42e7dSPeter Dunlap 	scs.st_additional_info = NULL;
1464a6d42e7dSPeter Dunlap 	(void) stmf_ctl(STMF_CMD_LPORT_OFFLINE_COMPLETE,
1465a6d42e7dSPeter Dunlap 	    tgt->target_stmf_lport, &scs);
1466a6d42e7dSPeter Dunlap }
1467a6d42e7dSPeter Dunlap 
1468a6d42e7dSPeter Dunlap static void
iscsit_tgt_offline(iscsit_tgt_t * tgt)1469a6d42e7dSPeter Dunlap iscsit_tgt_offline(iscsit_tgt_t *tgt)
1470a6d42e7dSPeter Dunlap {
1471*1f99504aSToomas Soome 	iscsit_tpgt_t		*tpgt;
1472a6d42e7dSPeter Dunlap 	iscsit_sess_t		*ist;
1473a6d42e7dSPeter Dunlap 
1474a6d42e7dSPeter Dunlap 	mutex_enter(&tgt->target_mutex);
1475a6d42e7dSPeter Dunlap 
1476a6d42e7dSPeter Dunlap 	/* Offline target portal groups */
1477a6d42e7dSPeter Dunlap 	for (tpgt = avl_first(&tgt->target_tpgt_list);
1478a6d42e7dSPeter Dunlap 	    tpgt != NULL;
1479a6d42e7dSPeter Dunlap 	    tpgt = AVL_NEXT(&tgt->target_tpgt_list, tpgt)) {
1480a6d42e7dSPeter Dunlap 		iscsit_tpg_offline(tpgt->tpgt_tpg);
1481a6d42e7dSPeter Dunlap 	}
1482a6d42e7dSPeter Dunlap 
1483a6d42e7dSPeter Dunlap 	/* Close any active sessions */
1484a6d42e7dSPeter Dunlap 	for (ist = avl_first(&tgt->target_sess_list);
1485a6d42e7dSPeter Dunlap 	    ist != NULL;
1486a6d42e7dSPeter Dunlap 	    ist = AVL_NEXT(&tgt->target_sess_list, ist)) {
1487a6d42e7dSPeter Dunlap 		/*
1488a6d42e7dSPeter Dunlap 		 * This is not a synchronous operation but after all
1489a6d42e7dSPeter Dunlap 		 * sessions have been cleaned up there will be no
1490a6d42e7dSPeter Dunlap 		 * more session-related holds on the target.
1491a6d42e7dSPeter Dunlap 		 */
1492a6d42e7dSPeter Dunlap 		iscsit_sess_close(ist);
1493a6d42e7dSPeter Dunlap 	}
1494a6d42e7dSPeter Dunlap 
1495a6d42e7dSPeter Dunlap 	mutex_exit(&tgt->target_mutex);
1496a6d42e7dSPeter Dunlap 
1497a6d42e7dSPeter Dunlap 	/*
1498a6d42e7dSPeter Dunlap 	 * Wait for all the sessions to quiesce.
1499a6d42e7dSPeter Dunlap 	 */
1500a6d42e7dSPeter Dunlap 	idm_refcnt_async_wait_ref(&tgt->target_sess_refcnt,
1501a6d42e7dSPeter Dunlap 	    &iscsit_tgt_offline_cb);
1502a6d42e7dSPeter Dunlap }
1503a6d42e7dSPeter Dunlap 
1504a6d42e7dSPeter Dunlap it_cfg_status_t
iscsit_config_merge_tpg(it_config_t * cfg,list_t * tpg_del_list)1505a6d42e7dSPeter Dunlap iscsit_config_merge_tpg(it_config_t *cfg, list_t *tpg_del_list)
1506a6d42e7dSPeter Dunlap {
1507a6d42e7dSPeter Dunlap 	it_tpg_t	*cfg_tpg;
1508a6d42e7dSPeter Dunlap 	iscsit_tpg_t	*tpg, *next_tpg;
1509a6d42e7dSPeter Dunlap 
1510a6d42e7dSPeter Dunlap 	/*
1511a6d42e7dSPeter Dunlap 	 * 1. >> Lock <<
1512a6d42e7dSPeter Dunlap 	 * 2. Removing deleted objects and place on a temp list
1513a6d42e7dSPeter Dunlap 	 * 3. Add new objects
1514a6d42e7dSPeter Dunlap 	 * 4. >> Unlock <<
1515a6d42e7dSPeter Dunlap 	 * 5. tpg_del_list contains objects to destroy
1516a6d42e7dSPeter Dunlap 	 */
1517a6d42e7dSPeter Dunlap 	for (tpg = avl_first(&iscsit_global.global_tpg_list);
1518a6d42e7dSPeter Dunlap 	    tpg != NULL;
1519a6d42e7dSPeter Dunlap 	    tpg = next_tpg) {
1520a6d42e7dSPeter Dunlap 		next_tpg = AVL_NEXT(&iscsit_global.global_tpg_list, tpg);
1521a6d42e7dSPeter Dunlap 
1522a6d42e7dSPeter Dunlap 		if (it_tpg_lookup(cfg, tpg->tpg_name) == NULL) {
1523a6d42e7dSPeter Dunlap 			/*
1524a6d42e7dSPeter Dunlap 			 * The policy around when to allow a target portal
1525a6d42e7dSPeter Dunlap 			 * group to be deleted is implemented in libiscsit.
1526a6d42e7dSPeter Dunlap 			 * By the time the request gets to the kernel module
1527a6d42e7dSPeter Dunlap 			 * we expect that it conforms to policy so we will
1528a6d42e7dSPeter Dunlap 			 * cleanup all references to TPG and destroy it if it
1529a6d42e7dSPeter Dunlap 			 * is possible to do so.
1530a6d42e7dSPeter Dunlap 			 *
1531a6d42e7dSPeter Dunlap 			 */
1532a6d42e7dSPeter Dunlap 			avl_remove(&iscsit_global.global_tpg_list, tpg);
1533a6d42e7dSPeter Dunlap 			list_insert_tail(tpg_del_list, tpg);
1534a6d42e7dSPeter Dunlap 		}
1535a6d42e7dSPeter Dunlap 	}
1536a6d42e7dSPeter Dunlap 
1537a6d42e7dSPeter Dunlap 	/* Now walk through the list of configured target portal groups */
1538a6d42e7dSPeter Dunlap 	for (cfg_tpg = cfg->config_tpg_list;
1539a6d42e7dSPeter Dunlap 	    cfg_tpg != NULL;
1540a6d42e7dSPeter Dunlap 	    cfg_tpg = cfg_tpg->tpg_next) {
1541a6d42e7dSPeter Dunlap 		/* See if we have an existing target portal group */
1542a6d42e7dSPeter Dunlap 		tpg = iscsit_tpg_lookup_locked(cfg_tpg->tpg_name);
1543a6d42e7dSPeter Dunlap 
1544a6d42e7dSPeter Dunlap 		if (tpg == NULL) {
1545a6d42e7dSPeter Dunlap 			tpg = iscsit_tpg_create(cfg_tpg);
1546a6d42e7dSPeter Dunlap 			ASSERT(tpg != NULL);
1547a6d42e7dSPeter Dunlap 			avl_add(&iscsit_global.global_tpg_list, tpg);
1548a6d42e7dSPeter Dunlap 		} else {
1549a6d42e7dSPeter Dunlap 			mutex_enter(&tpg->tpg_mutex);
1550a6d42e7dSPeter Dunlap 			iscsit_tpg_modify(tpg, cfg_tpg);
1551a6d42e7dSPeter Dunlap 			mutex_exit(&tpg->tpg_mutex);
1552a6d42e7dSPeter Dunlap 			iscsit_tpg_rele(tpg);
1553a6d42e7dSPeter Dunlap 		}
1554a6d42e7dSPeter Dunlap 	}
1555a6d42e7dSPeter Dunlap 
1556a6d42e7dSPeter Dunlap 	return (ITCFG_SUCCESS);
1557a6d42e7dSPeter Dunlap }
1558a6d42e7dSPeter Dunlap 
1559a6d42e7dSPeter Dunlap 
1560a6d42e7dSPeter Dunlap void
iscsit_config_destroy_tpgs(list_t * tpg_del_list)1561a6d42e7dSPeter Dunlap iscsit_config_destroy_tpgs(list_t *tpg_del_list)
1562a6d42e7dSPeter Dunlap {
1563a6d42e7dSPeter Dunlap 	iscsit_tpg_t	*tpg, *next_tpg;
1564a6d42e7dSPeter Dunlap 
1565a6d42e7dSPeter Dunlap 	/* Now finish destroying the target portal groups */
1566a6d42e7dSPeter Dunlap 	for (tpg = list_head(tpg_del_list);
1567a6d42e7dSPeter Dunlap 	    tpg != NULL;
1568a6d42e7dSPeter Dunlap 	    tpg = next_tpg) {
1569a6d42e7dSPeter Dunlap 		next_tpg = list_next(tpg_del_list, tpg);
1570a6d42e7dSPeter Dunlap 		list_remove(tpg_del_list, tpg);
1571a6d42e7dSPeter Dunlap 		idm_refcnt_wait_ref(&tpg->tpg_refcnt);
1572a6d42e7dSPeter Dunlap 
1573a6d42e7dSPeter Dunlap 		/* Kill it */
1574a6d42e7dSPeter Dunlap 		iscsit_tpg_destroy(tpg);
1575a6d42e7dSPeter Dunlap 	}
1576a6d42e7dSPeter Dunlap }
1577a6d42e7dSPeter Dunlap 
1578a6d42e7dSPeter Dunlap iscsit_tpg_t *
iscsit_tpg_lookup(char * tpg_name)1579a6d42e7dSPeter Dunlap iscsit_tpg_lookup(char *tpg_name)
1580a6d42e7dSPeter Dunlap {
1581a6d42e7dSPeter Dunlap 	iscsit_tpg_t *result;
1582a6d42e7dSPeter Dunlap 
1583a6d42e7dSPeter Dunlap 	ISCSIT_GLOBAL_LOCK(RW_READER);
1584a6d42e7dSPeter Dunlap 	result = iscsit_tpg_lookup_locked(tpg_name);
1585a6d42e7dSPeter Dunlap 	ISCSIT_GLOBAL_UNLOCK();
1586a6d42e7dSPeter Dunlap 
1587a6d42e7dSPeter Dunlap 	return (result);
1588a6d42e7dSPeter Dunlap }
1589a6d42e7dSPeter Dunlap 
1590a6d42e7dSPeter Dunlap static iscsit_tpg_t *
iscsit_tpg_lookup_locked(char * tpg_name)1591a6d42e7dSPeter Dunlap iscsit_tpg_lookup_locked(char *tpg_name)
1592a6d42e7dSPeter Dunlap {
1593a6d42e7dSPeter Dunlap 	iscsit_tpg_t	tmp_tpg;
1594a6d42e7dSPeter Dunlap 	iscsit_tpg_t	*result;
1595a6d42e7dSPeter Dunlap 
1596a6d42e7dSPeter Dunlap 	(void) strlcpy(tmp_tpg.tpg_name, tpg_name, MAX_ISCSI_NODENAMELEN);
1597a6d42e7dSPeter Dunlap 	if ((result = avl_find(&iscsit_global.global_tpg_list,
1598a6d42e7dSPeter Dunlap 	    &tmp_tpg, NULL)) != NULL) {
1599a6d42e7dSPeter Dunlap 		iscsit_tpg_hold(result);
1600a6d42e7dSPeter Dunlap 	}
1601a6d42e7dSPeter Dunlap 
1602a6d42e7dSPeter Dunlap 	return (result);
1603a6d42e7dSPeter Dunlap }
1604a6d42e7dSPeter Dunlap 
1605a6d42e7dSPeter Dunlap iscsit_tpg_t *
iscsit_tpg_create(it_tpg_t * cfg_tpg)1606a6d42e7dSPeter Dunlap iscsit_tpg_create(it_tpg_t *cfg_tpg)
1607a6d42e7dSPeter Dunlap {
1608a6d42e7dSPeter Dunlap 	iscsit_tpg_t *tpg;
1609a6d42e7dSPeter Dunlap 
1610a6d42e7dSPeter Dunlap 	tpg = kmem_zalloc(sizeof (*tpg), KM_SLEEP);
1611a6d42e7dSPeter Dunlap 
1612a6d42e7dSPeter Dunlap 	mutex_init(&tpg->tpg_mutex, NULL, MUTEX_DEFAULT, NULL);
1613a6d42e7dSPeter Dunlap 	(void) strlcpy(tpg->tpg_name, cfg_tpg->tpg_name, MAX_TPG_NAMELEN);
1614a6d42e7dSPeter Dunlap 	avl_create(&tpg->tpg_portal_list, iscsit_portal_avl_compare,
1615a6d42e7dSPeter Dunlap 	    sizeof (iscsit_portal_t), offsetof(iscsit_portal_t, portal_tpg_ln));
1616a6d42e7dSPeter Dunlap 	idm_refcnt_init(&tpg->tpg_refcnt, tpg);
1617a6d42e7dSPeter Dunlap 
1618a6d42e7dSPeter Dunlap 	mutex_enter(&tpg->tpg_mutex);
1619a6d42e7dSPeter Dunlap 	iscsit_tpg_modify(tpg, cfg_tpg);
1620a6d42e7dSPeter Dunlap 	mutex_exit(&tpg->tpg_mutex);
1621a6d42e7dSPeter Dunlap 	iscsit_global_hold();
1622a6d42e7dSPeter Dunlap 
1623a6d42e7dSPeter Dunlap 	return (tpg);
1624a6d42e7dSPeter Dunlap }
1625a6d42e7dSPeter Dunlap 
1626a6d42e7dSPeter Dunlap static void
iscsit_tpg_modify(iscsit_tpg_t * tpg,it_tpg_t * cfg_tpg)1627a6d42e7dSPeter Dunlap iscsit_tpg_modify(iscsit_tpg_t *tpg, it_tpg_t *cfg_tpg)
1628a6d42e7dSPeter Dunlap {
1629a6d42e7dSPeter Dunlap 	iscsit_portal_t		*portal, *next_portal;
1630a6d42e7dSPeter Dunlap 	it_portal_t		*cfg_portal;
1631a6d42e7dSPeter Dunlap 
1632a6d42e7dSPeter Dunlap 	/* Update portals */
1633a6d42e7dSPeter Dunlap 	for (portal = avl_first(&tpg->tpg_portal_list);
1634a6d42e7dSPeter Dunlap 	    portal != NULL;
1635a6d42e7dSPeter Dunlap 	    portal = next_portal) {
1636a6d42e7dSPeter Dunlap 		next_portal = AVL_NEXT(&tpg->tpg_portal_list, portal);
1637a6d42e7dSPeter Dunlap 		if (it_portal_lookup(cfg_tpg, &portal->portal_addr) == NULL) {
1638a6d42e7dSPeter Dunlap 			avl_remove(&tpg->tpg_portal_list, portal);
1639d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 			iscsit_portal_delete(portal);
16404f1d4f27SPriya Krishnan 			/*
16414f1d4f27SPriya Krishnan 			 * If the last portal is deleted from the target
16424f1d4f27SPriya Krishnan 			 * portal group, then the tpg->tpg_online count
16434f1d4f27SPriya Krishnan 			 * must be decremented. The other two callers of
16444f1d4f27SPriya Krishnan 			 * iscsit_portal_delete() destroy the target portal
16454f1d4f27SPriya Krishnan 			 * after deleting the portal so it is not necessary
16464f1d4f27SPriya Krishnan 			 * to decrement the tpg->tpg_online count.
16474f1d4f27SPriya Krishnan 			 */
16484f1d4f27SPriya Krishnan 			if (avl_is_empty(&tpg->tpg_portal_list)) {
16494f1d4f27SPriya Krishnan 				tpg->tpg_online--;
16504f1d4f27SPriya Krishnan 			}
1651a6d42e7dSPeter Dunlap 		}
1652a6d42e7dSPeter Dunlap 	}
1653a6d42e7dSPeter Dunlap 
1654a6d42e7dSPeter Dunlap 	for (cfg_portal = cfg_tpg->tpg_portal_list;
1655a6d42e7dSPeter Dunlap 	    cfg_portal != NULL;
165642bf653bSPeter Gill 	    cfg_portal = cfg_portal->portal_next) {
1657a6d42e7dSPeter Dunlap 		if ((portal = iscsit_tpg_portal_lookup_locked(tpg,
1658a6d42e7dSPeter Dunlap 		    &cfg_portal->portal_addr)) == NULL) {
1659a6d42e7dSPeter Dunlap 			(void) iscsit_portal_create(tpg,
1660a6d42e7dSPeter Dunlap 			    &cfg_portal->portal_addr);
1661a6d42e7dSPeter Dunlap 		} else {
1662a6d42e7dSPeter Dunlap 			iscsit_portal_rele(portal);
1663a6d42e7dSPeter Dunlap 		}
1664a6d42e7dSPeter Dunlap 	}
1665a6d42e7dSPeter Dunlap }
1666a6d42e7dSPeter Dunlap 
1667a6d42e7dSPeter Dunlap void
iscsit_tpg_destroy(iscsit_tpg_t * tpg)1668a6d42e7dSPeter Dunlap iscsit_tpg_destroy(iscsit_tpg_t *tpg)
1669a6d42e7dSPeter Dunlap {
1670a6d42e7dSPeter Dunlap 	iscsit_portal_t *portal, *next_portal;
1671a6d42e7dSPeter Dunlap 
1672a6d42e7dSPeter Dunlap 	for (portal = avl_first(&tpg->tpg_portal_list);
1673a6d42e7dSPeter Dunlap 	    portal != NULL;
1674a6d42e7dSPeter Dunlap 	    portal = next_portal) {
1675a6d42e7dSPeter Dunlap 		next_portal = AVL_NEXT(&tpg->tpg_portal_list, portal);
1676a6d42e7dSPeter Dunlap 		avl_remove(&tpg->tpg_portal_list, portal);
1677d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		iscsit_portal_delete(portal);
1678a6d42e7dSPeter Dunlap 	}
1679a6d42e7dSPeter Dunlap 
1680a6d42e7dSPeter Dunlap 	idm_refcnt_wait_ref(&tpg->tpg_refcnt);
1681a6d42e7dSPeter Dunlap 	idm_refcnt_destroy(&tpg->tpg_refcnt);
1682a6d42e7dSPeter Dunlap 	avl_destroy(&tpg->tpg_portal_list);
1683a6d42e7dSPeter Dunlap 	mutex_destroy(&tpg->tpg_mutex);
1684a6d42e7dSPeter Dunlap 	kmem_free(tpg, sizeof (*tpg));
1685a6d42e7dSPeter Dunlap 	iscsit_global_rele();
1686a6d42e7dSPeter Dunlap }
1687a6d42e7dSPeter Dunlap 
1688a6d42e7dSPeter Dunlap void
iscsit_tpg_hold(iscsit_tpg_t * tpg)1689a6d42e7dSPeter Dunlap iscsit_tpg_hold(iscsit_tpg_t *tpg)
1690a6d42e7dSPeter Dunlap {
1691a6d42e7dSPeter Dunlap 	idm_refcnt_hold(&tpg->tpg_refcnt);
1692a6d42e7dSPeter Dunlap }
1693a6d42e7dSPeter Dunlap 
1694a6d42e7dSPeter Dunlap void
iscsit_tpg_rele(iscsit_tpg_t * tpg)1695a6d42e7dSPeter Dunlap iscsit_tpg_rele(iscsit_tpg_t *tpg)
1696a6d42e7dSPeter Dunlap {
1697a6d42e7dSPeter Dunlap 	idm_refcnt_rele(&tpg->tpg_refcnt);
1698a6d42e7dSPeter Dunlap }
1699a6d42e7dSPeter Dunlap 
1700a6d42e7dSPeter Dunlap iscsit_tpg_t *
iscsit_tpg_createdefault()1701a6d42e7dSPeter Dunlap iscsit_tpg_createdefault()
1702a6d42e7dSPeter Dunlap {
1703a6d42e7dSPeter Dunlap 	iscsit_tpg_t *tpg;
1704a6d42e7dSPeter Dunlap 
1705a6d42e7dSPeter Dunlap 	tpg = kmem_zalloc(sizeof (*tpg), KM_SLEEP);
1706a6d42e7dSPeter Dunlap 
1707a6d42e7dSPeter Dunlap 	mutex_init(&tpg->tpg_mutex, NULL, MUTEX_DEFAULT, NULL);
1708a6d42e7dSPeter Dunlap 	(void) strlcpy(tpg->tpg_name, ISCSIT_DEFAULT_TPG, MAX_TPG_NAMELEN);
1709a6d42e7dSPeter Dunlap 	avl_create(&tpg->tpg_portal_list, iscsit_portal_avl_compare,
1710a6d42e7dSPeter Dunlap 	    sizeof (iscsit_portal_t), offsetof(iscsit_portal_t, portal_tpg_ln));
1711a6d42e7dSPeter Dunlap 	idm_refcnt_init(&tpg->tpg_refcnt, tpg);
1712a6d42e7dSPeter Dunlap 
1713a6d42e7dSPeter Dunlap 	/* Now create default portal */
1714a6d42e7dSPeter Dunlap 	if (iscsit_portal_create(tpg, NULL) == NULL) {
1715a6d42e7dSPeter Dunlap 		iscsit_tpg_destroy(tpg);
1716a6d42e7dSPeter Dunlap 		return (NULL);
1717a6d42e7dSPeter Dunlap 	}
1718a6d42e7dSPeter Dunlap 
1719a6d42e7dSPeter Dunlap 	return (tpg);
1720a6d42e7dSPeter Dunlap }
1721a6d42e7dSPeter Dunlap 
1722a6d42e7dSPeter Dunlap void
iscsit_tpg_destroydefault(iscsit_tpg_t * tpg)1723a6d42e7dSPeter Dunlap iscsit_tpg_destroydefault(iscsit_tpg_t *tpg)
1724a6d42e7dSPeter Dunlap {
1725a6d42e7dSPeter Dunlap 	iscsit_portal_t *portal;
1726a6d42e7dSPeter Dunlap 
1727a6d42e7dSPeter Dunlap 	portal = avl_first(&tpg->tpg_portal_list);
1728a6d42e7dSPeter Dunlap 	ASSERT(portal != NULL);
1729a6d42e7dSPeter Dunlap 	avl_remove(&tpg->tpg_portal_list, portal);
1730d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	iscsit_portal_delete(portal);
1731a6d42e7dSPeter Dunlap 
1732a6d42e7dSPeter Dunlap 	idm_refcnt_wait_ref(&tpg->tpg_refcnt);
1733a6d42e7dSPeter Dunlap 	idm_refcnt_destroy(&tpg->tpg_refcnt);
1734a6d42e7dSPeter Dunlap 	avl_destroy(&tpg->tpg_portal_list);
1735a6d42e7dSPeter Dunlap 	mutex_destroy(&tpg->tpg_mutex);
1736a6d42e7dSPeter Dunlap 	kmem_free(tpg, sizeof (*tpg));
1737a6d42e7dSPeter Dunlap }
1738a6d42e7dSPeter Dunlap 
1739a6d42e7dSPeter Dunlap int
iscsit_tpg_avl_compare(const void * void_tpg1,const void * void_tpg2)1740a6d42e7dSPeter Dunlap iscsit_tpg_avl_compare(const void *void_tpg1, const void *void_tpg2)
1741a6d42e7dSPeter Dunlap {
1742a6d42e7dSPeter Dunlap 	const iscsit_tpg_t	*tpg1 = void_tpg1;
1743a6d42e7dSPeter Dunlap 	const iscsit_tpg_t	*tpg2 = void_tpg2;
1744*1f99504aSToomas Soome 	int			result;
1745a6d42e7dSPeter Dunlap 
1746a6d42e7dSPeter Dunlap 	/*
1747a6d42e7dSPeter Dunlap 	 * Sort by ISID first then TSIH
1748a6d42e7dSPeter Dunlap 	 */
1749a6d42e7dSPeter Dunlap 	result = strcmp(tpg1->tpg_name, tpg2->tpg_name);
1750a6d42e7dSPeter Dunlap 	if (result < 0) {
1751a6d42e7dSPeter Dunlap 		return (-1);
1752a6d42e7dSPeter Dunlap 	} else if (result > 0) {
1753a6d42e7dSPeter Dunlap 		return (1);
1754a6d42e7dSPeter Dunlap 	}
1755a6d42e7dSPeter Dunlap 
1756a6d42e7dSPeter Dunlap 	return (0);
1757a6d42e7dSPeter Dunlap }
1758a6d42e7dSPeter Dunlap 
1759a6d42e7dSPeter Dunlap idm_status_t
iscsit_tpg_online(iscsit_tpg_t * tpg)1760a6d42e7dSPeter Dunlap iscsit_tpg_online(iscsit_tpg_t *tpg)
1761a6d42e7dSPeter Dunlap {
1762a6d42e7dSPeter Dunlap 	iscsit_portal_t *portal, *portal_fail;
1763a6d42e7dSPeter Dunlap 	idm_status_t	rc;
1764a6d42e7dSPeter Dunlap 
1765a6d42e7dSPeter Dunlap 	mutex_enter(&tpg->tpg_mutex);
1766a6d42e7dSPeter Dunlap 	if (tpg->tpg_online == 0) {
1767a6d42e7dSPeter Dunlap 		for (portal = avl_first(&tpg->tpg_portal_list);
1768a6d42e7dSPeter Dunlap 		    portal != NULL;
1769a6d42e7dSPeter Dunlap 		    portal = AVL_NEXT(&tpg->tpg_portal_list, portal)) {
1770a6d42e7dSPeter Dunlap 			rc = iscsit_portal_online(portal);
1771a6d42e7dSPeter Dunlap 			if (rc != IDM_STATUS_SUCCESS) {
1772a6d42e7dSPeter Dunlap 				portal_fail = portal;
1773a6d42e7dSPeter Dunlap 				goto tpg_online_fail;
1774a6d42e7dSPeter Dunlap 			}
1775a6d42e7dSPeter Dunlap 		}
1776a6d42e7dSPeter Dunlap 	}
1777a6d42e7dSPeter Dunlap 	tpg->tpg_online++;
1778a6d42e7dSPeter Dunlap 
1779a6d42e7dSPeter Dunlap 	mutex_exit(&tpg->tpg_mutex);
1780a6d42e7dSPeter Dunlap 	return (IDM_STATUS_SUCCESS);
1781a6d42e7dSPeter Dunlap 
1782a6d42e7dSPeter Dunlap tpg_online_fail:
1783a6d42e7dSPeter Dunlap 	/* Offline all the portals we successfully onlined up to the failure */
1784a6d42e7dSPeter Dunlap 	for (portal = avl_first(&tpg->tpg_portal_list);
1785a6d42e7dSPeter Dunlap 	    portal != portal_fail;
1786a6d42e7dSPeter Dunlap 	    portal = AVL_NEXT(&tpg->tpg_portal_list, portal)) {
1787a6d42e7dSPeter Dunlap 		iscsit_portal_offline(portal);
1788a6d42e7dSPeter Dunlap 	}
1789a6d42e7dSPeter Dunlap 	mutex_exit(&tpg->tpg_mutex);
1790a6d42e7dSPeter Dunlap 	return (rc);
1791a6d42e7dSPeter Dunlap }
1792a6d42e7dSPeter Dunlap 
1793a6d42e7dSPeter Dunlap void
iscsit_tpg_offline(iscsit_tpg_t * tpg)1794a6d42e7dSPeter Dunlap iscsit_tpg_offline(iscsit_tpg_t *tpg)
1795a6d42e7dSPeter Dunlap {
1796a6d42e7dSPeter Dunlap 	iscsit_portal_t *portal;
1797a6d42e7dSPeter Dunlap 
1798a6d42e7dSPeter Dunlap 	mutex_enter(&tpg->tpg_mutex);
1799a6d42e7dSPeter Dunlap 	tpg->tpg_online--;
1800a6d42e7dSPeter Dunlap 	if (tpg->tpg_online == 0) {
1801a6d42e7dSPeter Dunlap 		for (portal = avl_first(&tpg->tpg_portal_list);
1802a6d42e7dSPeter Dunlap 		    portal != NULL;
1803a6d42e7dSPeter Dunlap 		    portal = AVL_NEXT(&tpg->tpg_portal_list, portal)) {
1804a6d42e7dSPeter Dunlap 			iscsit_portal_offline(portal);
1805a6d42e7dSPeter Dunlap 		}
1806a6d42e7dSPeter Dunlap 	}
1807a6d42e7dSPeter Dunlap 	mutex_exit(&tpg->tpg_mutex);
1808a6d42e7dSPeter Dunlap }
1809a6d42e7dSPeter Dunlap 
1810a6d42e7dSPeter Dunlap iscsit_portal_t *
iscsit_tpg_portal_lookup(iscsit_tpg_t * tpg,struct sockaddr_storage * sa)1811a6d42e7dSPeter Dunlap iscsit_tpg_portal_lookup(iscsit_tpg_t *tpg, struct sockaddr_storage *sa)
1812a6d42e7dSPeter Dunlap {
1813a6d42e7dSPeter Dunlap 	iscsit_portal_t	*result;
1814a6d42e7dSPeter Dunlap 
1815a6d42e7dSPeter Dunlap 	mutex_enter(&tpg->tpg_mutex);
1816a6d42e7dSPeter Dunlap 	result = iscsit_tpg_portal_lookup_locked(tpg, sa);
1817a6d42e7dSPeter Dunlap 	mutex_exit(&tpg->tpg_mutex);
1818a6d42e7dSPeter Dunlap 
1819a6d42e7dSPeter Dunlap 	return (result);
1820a6d42e7dSPeter Dunlap }
1821a6d42e7dSPeter Dunlap 
1822a6d42e7dSPeter Dunlap static iscsit_portal_t *
iscsit_tpg_portal_lookup_locked(iscsit_tpg_t * tpg,struct sockaddr_storage * sa)1823a6d42e7dSPeter Dunlap iscsit_tpg_portal_lookup_locked(iscsit_tpg_t *tpg,
1824a6d42e7dSPeter Dunlap     struct sockaddr_storage *sa)
1825a6d42e7dSPeter Dunlap {
1826a6d42e7dSPeter Dunlap 	iscsit_portal_t	tmp_portal;
1827a6d42e7dSPeter Dunlap 	iscsit_portal_t	*result;
1828a6d42e7dSPeter Dunlap 
1829a6d42e7dSPeter Dunlap 	/* Caller holds tpg->tpg_mutex */
1830a6d42e7dSPeter Dunlap 	bcopy(sa, &tmp_portal.portal_addr, sizeof (*sa));
1831a6d42e7dSPeter Dunlap 	if ((result = avl_find(&tpg->tpg_portal_list, &tmp_portal, NULL)) !=
1832a6d42e7dSPeter Dunlap 	    NULL) {
1833a6d42e7dSPeter Dunlap 		iscsit_portal_hold(result);
1834a6d42e7dSPeter Dunlap 	}
1835a6d42e7dSPeter Dunlap 
1836a6d42e7dSPeter Dunlap 	return (result);
1837a6d42e7dSPeter Dunlap }
1838a6d42e7dSPeter Dunlap 
1839a6d42e7dSPeter Dunlap iscsit_portal_t *
iscsit_portal_create(iscsit_tpg_t * tpg,struct sockaddr_storage * sa)1840a6d42e7dSPeter Dunlap iscsit_portal_create(iscsit_tpg_t *tpg, struct sockaddr_storage *sa)
1841a6d42e7dSPeter Dunlap {
1842a6d42e7dSPeter Dunlap 	iscsit_portal_t *portal;
1843a6d42e7dSPeter Dunlap 
1844a6d42e7dSPeter Dunlap 	portal = kmem_zalloc(sizeof (*portal), KM_SLEEP);
1845a6d42e7dSPeter Dunlap 	/*
1846a6d42e7dSPeter Dunlap 	 * If (sa == NULL) then we are being asked to create the default
1847a6d42e7dSPeter Dunlap 	 * portal -- targets will use this portal when no portals are
1848a6d42e7dSPeter Dunlap 	 * explicitly configured.
1849a6d42e7dSPeter Dunlap 	 */
1850e42a0851Speter dunlap 	if (sa == NULL) {
1851e42a0851Speter dunlap 		portal->portal_default = B_TRUE;
1852e42a0851Speter dunlap 	} else {
1853e42a0851Speter dunlap 		portal->portal_default = B_FALSE;
1854a6d42e7dSPeter Dunlap 		bcopy(sa, &portal->portal_addr, sizeof (*sa));
1855a6d42e7dSPeter Dunlap 	}
1856a6d42e7dSPeter Dunlap 
1857a6d42e7dSPeter Dunlap 	idm_refcnt_init(&portal->portal_refcnt, portal);
1858a6d42e7dSPeter Dunlap 
1859a6d42e7dSPeter Dunlap 	/*
1860a6d42e7dSPeter Dunlap 	 * Add this portal to the list
1861a6d42e7dSPeter Dunlap 	 */
1862a6d42e7dSPeter Dunlap 	avl_add(&tpg->tpg_portal_list, portal);
1863a6d42e7dSPeter Dunlap 
1864a6d42e7dSPeter Dunlap 	return (portal);
1865a6d42e7dSPeter Dunlap }
1866a6d42e7dSPeter Dunlap 
1867a6d42e7dSPeter Dunlap void
iscsit_portal_delete(iscsit_portal_t * portal)1868d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States iscsit_portal_delete(iscsit_portal_t *portal)
1869a6d42e7dSPeter Dunlap {
1870d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	if (portal->portal_online > 0) {
1871d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		iscsit_portal_offline(portal);
1872d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	}
1873d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 
1874d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	if (portal->portal_online == 0) {
1875d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		ASSERT(portal->portal_svc == NULL);
1876d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		idm_refcnt_destroy(&portal->portal_refcnt);
1877d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 		kmem_free(portal, sizeof (*portal));
1878d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	}
1879a6d42e7dSPeter Dunlap }
1880a6d42e7dSPeter Dunlap 
1881a6d42e7dSPeter Dunlap void
iscsit_portal_hold(iscsit_portal_t * portal)1882a6d42e7dSPeter Dunlap iscsit_portal_hold(iscsit_portal_t *portal)
1883a6d42e7dSPeter Dunlap {
1884a6d42e7dSPeter Dunlap 	idm_refcnt_hold(&portal->portal_refcnt);
1885a6d42e7dSPeter Dunlap }
1886a6d42e7dSPeter Dunlap 
1887a6d42e7dSPeter Dunlap void
iscsit_portal_rele(iscsit_portal_t * portal)1888a6d42e7dSPeter Dunlap iscsit_portal_rele(iscsit_portal_t *portal)
1889a6d42e7dSPeter Dunlap {
1890a6d42e7dSPeter Dunlap 	idm_refcnt_rele(&portal->portal_refcnt);
1891a6d42e7dSPeter Dunlap }
1892a6d42e7dSPeter Dunlap 
1893a6d42e7dSPeter Dunlap int
iscsit_portal_avl_compare(const void * void_portal1,const void * void_portal2)1894a6d42e7dSPeter Dunlap iscsit_portal_avl_compare(const void *void_portal1, const void *void_portal2)
1895a6d42e7dSPeter Dunlap {
1896a6d42e7dSPeter Dunlap 	const iscsit_portal_t			*portal1 = void_portal1;
1897a6d42e7dSPeter Dunlap 	const iscsit_portal_t			*portal2 = void_portal2;
1898a6d42e7dSPeter Dunlap 	const struct sockaddr_storage		*ss1, *ss2;
1899a6d42e7dSPeter Dunlap 	const struct in_addr			*in1, *in2;
1900a6d42e7dSPeter Dunlap 	const struct in6_addr			*in61, *in62;
1901a6d42e7dSPeter Dunlap 	int i;
1902a6d42e7dSPeter Dunlap 
1903a6d42e7dSPeter Dunlap 	/*
1904a6d42e7dSPeter Dunlap 	 * Compare ports, then address family, then ip address
1905a6d42e7dSPeter Dunlap 	 */
1906a6d42e7dSPeter Dunlap 	ss1 = &portal1->portal_addr;
1907a6d42e7dSPeter Dunlap 	ss2 = &portal2->portal_addr;
1908a6d42e7dSPeter Dunlap 	if (((struct sockaddr_in *)ss1)->sin_port !=
1909a6d42e7dSPeter Dunlap 	    ((struct sockaddr_in *)ss2)->sin_port) {
1910a6d42e7dSPeter Dunlap 		if (((struct sockaddr_in *)ss1)->sin_port >
1911a6d42e7dSPeter Dunlap 		    ((struct sockaddr_in *)ss2)->sin_port)
1912a6d42e7dSPeter Dunlap 			return (1);
1913a6d42e7dSPeter Dunlap 		else
1914a6d42e7dSPeter Dunlap 			return (-1);
1915a6d42e7dSPeter Dunlap 	}
1916a6d42e7dSPeter Dunlap 
1917a6d42e7dSPeter Dunlap 	/*
1918a6d42e7dSPeter Dunlap 	 * ports are the same
1919a6d42e7dSPeter Dunlap 	 */
1920a6d42e7dSPeter Dunlap 	if (ss1->ss_family != ss2->ss_family) {
1921a6d42e7dSPeter Dunlap 		if (ss1->ss_family == AF_INET)
1922a6d42e7dSPeter Dunlap 			return (1);
1923a6d42e7dSPeter Dunlap 		else
1924a6d42e7dSPeter Dunlap 			return (-1);
1925a6d42e7dSPeter Dunlap 	}
1926a6d42e7dSPeter Dunlap 	/*
1927a6d42e7dSPeter Dunlap 	 * address families are the same
1928a6d42e7dSPeter Dunlap 	 */
1929a6d42e7dSPeter Dunlap 	if (ss1->ss_family == AF_INET) {
1930a6d42e7dSPeter Dunlap 		in1 = &((struct sockaddr_in *)ss1)->sin_addr;
1931a6d42e7dSPeter Dunlap 		in2 = &((struct sockaddr_in *)ss2)->sin_addr;
1932a6d42e7dSPeter Dunlap 
1933a6d42e7dSPeter Dunlap 		if (in1->s_addr > in2->s_addr)
1934a6d42e7dSPeter Dunlap 			return (1);
1935a6d42e7dSPeter Dunlap 		else if (in1->s_addr < in2->s_addr)
1936a6d42e7dSPeter Dunlap 			return (-1);
1937a6d42e7dSPeter Dunlap 		else
1938a6d42e7dSPeter Dunlap 			return (0);
1939a6d42e7dSPeter Dunlap 	} else if (ss1->ss_family == AF_INET6) {
1940a6d42e7dSPeter Dunlap 		in61 = &((struct sockaddr_in6 *)ss1)->sin6_addr;
1941a6d42e7dSPeter Dunlap 		in62 = &((struct sockaddr_in6 *)ss2)->sin6_addr;
1942a6d42e7dSPeter Dunlap 
1943a6d42e7dSPeter Dunlap 		for (i = 0; i < 4; i++) {
1944a6d42e7dSPeter Dunlap 			if (in61->s6_addr32[i] > in62->s6_addr32[i])
1945a6d42e7dSPeter Dunlap 				return (1);
1946a6d42e7dSPeter Dunlap 			else if (in61->s6_addr32[i] < in62->s6_addr32[i])
1947a6d42e7dSPeter Dunlap 				return (-1);
1948a6d42e7dSPeter Dunlap 		}
1949a6d42e7dSPeter Dunlap 		return (0);
1950a6d42e7dSPeter Dunlap 	} else
1951a6d42e7dSPeter Dunlap 		cmn_err(CE_WARN,
1952a6d42e7dSPeter Dunlap 		    "iscsit_portal_avl_compare: unknown ss_family %d",
1953a6d42e7dSPeter Dunlap 		    ss1->ss_family);
1954a6d42e7dSPeter Dunlap 
1955a6d42e7dSPeter Dunlap 	return (1);
1956a6d42e7dSPeter Dunlap }
1957a6d42e7dSPeter Dunlap 
1958a6d42e7dSPeter Dunlap 
1959a6d42e7dSPeter Dunlap idm_status_t
iscsit_portal_online(iscsit_portal_t * portal)1960a6d42e7dSPeter Dunlap iscsit_portal_online(iscsit_portal_t *portal)
1961a6d42e7dSPeter Dunlap {
196207a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States 	idm_status_t rc = 0;
1963a6d42e7dSPeter Dunlap 	idm_svc_t	*svc;
1964a6d42e7dSPeter Dunlap 	idm_svc_req_t	sr;
1965a6d42e7dSPeter Dunlap 	uint16_t	port;
1966a6d42e7dSPeter Dunlap 	struct sockaddr_in *sin;
1967a6d42e7dSPeter Dunlap 
1968a6d42e7dSPeter Dunlap 	/* Caller holds parent TPG mutex */
1969a6d42e7dSPeter Dunlap 	if (portal->portal_online == 0) {
1970a6d42e7dSPeter Dunlap 		/*
1971a6d42e7dSPeter Dunlap 		 * If there is no existing IDM service instance for this port,
1972a6d42e7dSPeter Dunlap 		 * create one.  If the service exists, then the lookup,
1973a6d42e7dSPeter Dunlap 		 * creates a reference on the existing service.
1974a6d42e7dSPeter Dunlap 		 */
1975a6d42e7dSPeter Dunlap 		sin = (struct sockaddr_in *)&portal->portal_addr;
1976a6d42e7dSPeter Dunlap 		port = ntohs(sin->sin_port);
1977a6d42e7dSPeter Dunlap 		if (port == 0)
1978a6d42e7dSPeter Dunlap 			port = ISCSI_LISTEN_PORT;
1979a6d42e7dSPeter Dunlap 		ASSERT(portal->portal_svc == NULL);
1980a6d42e7dSPeter Dunlap 		if ((svc = idm_tgt_svc_lookup(port)) == NULL) {
1981a6d42e7dSPeter Dunlap 			sr.sr_port = port;
1982a6d42e7dSPeter Dunlap 			sr.sr_li = iscsit_global.global_li;
1983a6d42e7dSPeter Dunlap 			sr.sr_conn_ops.icb_rx_scsi_cmd = &iscsit_op_scsi_cmd;
1984a481fa48SRick McNeal 			sr.sr_conn_ops.icb_rx_scsi_rsp = &iscsit_rx_scsi_rsp;
1985a6d42e7dSPeter Dunlap 			sr.sr_conn_ops.icb_rx_misc = &iscsit_rx_pdu;
1986a6d42e7dSPeter Dunlap 			sr.sr_conn_ops.icb_rx_error = &iscsit_rx_pdu_error;
1987a6d42e7dSPeter Dunlap 			sr.sr_conn_ops.icb_task_aborted = &iscsit_task_aborted;
1988a6d42e7dSPeter Dunlap 			sr.sr_conn_ops.icb_client_notify =
1989a6d42e7dSPeter Dunlap 			    &iscsit_client_notify;
1990a6d42e7dSPeter Dunlap 			sr.sr_conn_ops.icb_build_hdr = &iscsit_build_hdr;
199160220f10SPriya Krishnan 			sr.sr_conn_ops.icb_update_statsn =
199260220f10SPriya Krishnan 			    &iscsit_update_statsn;
199372cf3143Speter dunlap 			sr.sr_conn_ops.icb_keepalive = &iscsit_keepalive;
1994a6d42e7dSPeter Dunlap 
1995a6d42e7dSPeter Dunlap 			if (idm_tgt_svc_create(&sr, &svc) !=
1996a6d42e7dSPeter Dunlap 			    IDM_STATUS_SUCCESS) {
1997a6d42e7dSPeter Dunlap 				return (IDM_STATUS_FAIL);
1998a6d42e7dSPeter Dunlap 			}
1999a6d42e7dSPeter Dunlap 
2000a6d42e7dSPeter Dunlap 			/* Get reference on the service we just created */
2001a6d42e7dSPeter Dunlap 			idm_tgt_svc_hold(svc);
2002a6d42e7dSPeter Dunlap 		}
2003a6d42e7dSPeter Dunlap 		if ((rc = idm_tgt_svc_online(svc)) != IDM_STATUS_SUCCESS) {
2004a6d42e7dSPeter Dunlap 			idm_tgt_svc_rele_and_destroy(svc);
2005a6d42e7dSPeter Dunlap 			return (IDM_STATUS_FAIL);
2006a6d42e7dSPeter Dunlap 		}
2007a6d42e7dSPeter Dunlap 		portal->portal_svc = svc;
2008a6d42e7dSPeter Dunlap 
2009a6d42e7dSPeter Dunlap 		/*
2010a6d42e7dSPeter Dunlap 		 * Only call iSNS for first online
2011a6d42e7dSPeter Dunlap 		 */
2012a6d42e7dSPeter Dunlap 		iscsit_isns_portal_online(portal);
2013a6d42e7dSPeter Dunlap 	}
2014a6d42e7dSPeter Dunlap 
2015a6d42e7dSPeter Dunlap 	portal->portal_online++;
2016a6d42e7dSPeter Dunlap 
2017a6d42e7dSPeter Dunlap 	return (rc);
2018a6d42e7dSPeter Dunlap }
2019a6d42e7dSPeter Dunlap 
2020a6d42e7dSPeter Dunlap void
iscsit_portal_offline(iscsit_portal_t * portal)2021a6d42e7dSPeter Dunlap iscsit_portal_offline(iscsit_portal_t *portal)
2022a6d42e7dSPeter Dunlap {
2023a6d42e7dSPeter Dunlap 	portal->portal_online--;
2024a6d42e7dSPeter Dunlap 
2025a6d42e7dSPeter Dunlap 	if (portal->portal_online == 0) {
2026a6d42e7dSPeter Dunlap 		/*
2027a6d42e7dSPeter Dunlap 		 * Only call iSNS for last offline
2028a6d42e7dSPeter Dunlap 		 */
2029a6d42e7dSPeter Dunlap 		iscsit_isns_portal_offline(portal);
2030a6d42e7dSPeter Dunlap 		idm_tgt_svc_offline(portal->portal_svc);
2031a6d42e7dSPeter Dunlap 		/* If service is unreferenced, destroy it too */
2032a6d42e7dSPeter Dunlap 		idm_tgt_svc_rele_and_destroy(portal->portal_svc);
2033a6d42e7dSPeter Dunlap 		portal->portal_svc = NULL;
2034a6d42e7dSPeter Dunlap 	}
2035a6d42e7dSPeter Dunlap 
2036a6d42e7dSPeter Dunlap }
2037a6d42e7dSPeter Dunlap 
2038a6d42e7dSPeter Dunlap it_cfg_status_t
iscsit_config_merge_ini(it_config_t * cfg)2039a6d42e7dSPeter Dunlap iscsit_config_merge_ini(it_config_t *cfg)
2040a6d42e7dSPeter Dunlap {
2041a6d42e7dSPeter Dunlap 	iscsit_ini_t	*ini, *next_ini;
2042a6d42e7dSPeter Dunlap 	it_ini_t	*cfg_ini;
2043a6d42e7dSPeter Dunlap 
2044a6d42e7dSPeter Dunlap 	/*
2045a6d42e7dSPeter Dunlap 	 * Initiator objects are so simple we will just destroy all the current
2046a6d42e7dSPeter Dunlap 	 * objects and build new ones.  Nothing should ever reference an
2047a6d42e7dSPeter Dunlap 	 * initator object.. instead just lookup the initiator object and
2048a6d42e7dSPeter Dunlap 	 * grab the properties while holding the global config lock.
2049a6d42e7dSPeter Dunlap 	 */
2050a6d42e7dSPeter Dunlap 	for (ini = avl_first(&iscsit_global.global_ini_list);
2051a6d42e7dSPeter Dunlap 	    ini != NULL;
2052a6d42e7dSPeter Dunlap 	    ini = next_ini) {
2053a6d42e7dSPeter Dunlap 		next_ini = AVL_NEXT(&iscsit_global.global_ini_list, ini);
2054a6d42e7dSPeter Dunlap 		avl_remove(&iscsit_global.global_ini_list, ini);
2055a6d42e7dSPeter Dunlap 		nvlist_free(ini->ini_props);
2056a6d42e7dSPeter Dunlap 		kmem_free(ini, sizeof (*ini));
2057a6d42e7dSPeter Dunlap 		iscsit_global_rele();
2058a6d42e7dSPeter Dunlap 	}
2059a6d42e7dSPeter Dunlap 
2060a6d42e7dSPeter Dunlap 	for (cfg_ini = cfg->config_ini_list;
2061a6d42e7dSPeter Dunlap 	    cfg_ini != NULL;
2062a6d42e7dSPeter Dunlap 	    cfg_ini = cfg_ini->ini_next) {
2063a6d42e7dSPeter Dunlap 		ini = kmem_zalloc(sizeof (iscsit_ini_t), KM_SLEEP);
2064a6d42e7dSPeter Dunlap 		(void) strlcpy(ini->ini_name, cfg_ini->ini_name,
2065a6d42e7dSPeter Dunlap 		    MAX_ISCSI_NODENAMELEN);
2066a6d42e7dSPeter Dunlap 		(void) nvlist_dup(cfg_ini->ini_properties, &ini->ini_props,
2067a6d42e7dSPeter Dunlap 		    KM_SLEEP);
2068a6d42e7dSPeter Dunlap 		avl_add(&iscsit_global.global_ini_list, ini);
2069a6d42e7dSPeter Dunlap 		iscsit_global_hold();
2070a6d42e7dSPeter Dunlap 	}
2071a6d42e7dSPeter Dunlap 
2072a6d42e7dSPeter Dunlap 	return (ITCFG_SUCCESS);
2073a6d42e7dSPeter Dunlap }
2074a6d42e7dSPeter Dunlap 
2075a6d42e7dSPeter Dunlap int
iscsit_ini_avl_compare(const void * void_ini1,const void * void_ini2)2076a6d42e7dSPeter Dunlap iscsit_ini_avl_compare(const void *void_ini1, const void *void_ini2)
2077a6d42e7dSPeter Dunlap {
2078a6d42e7dSPeter Dunlap 	const iscsit_ini_t	*ini1 = void_ini1;
2079a6d42e7dSPeter Dunlap 	const iscsit_ini_t	*ini2 = void_ini2;
2080*1f99504aSToomas Soome 	int			result;
2081a6d42e7dSPeter Dunlap 
2082a6d42e7dSPeter Dunlap 	/*
2083a6d42e7dSPeter Dunlap 	 * Sort by ISID first then TSIH
2084a6d42e7dSPeter Dunlap 	 */
2085a6d42e7dSPeter Dunlap 	result = strcmp(ini1->ini_name, ini2->ini_name);
2086a6d42e7dSPeter Dunlap 	if (result < 0) {
2087a6d42e7dSPeter Dunlap 		return (-1);
2088a6d42e7dSPeter Dunlap 	} else if (result > 0) {
2089a6d42e7dSPeter Dunlap 		return (1);
2090a6d42e7dSPeter Dunlap 	}
2091a6d42e7dSPeter Dunlap 
2092a6d42e7dSPeter Dunlap 	return (0);
2093a6d42e7dSPeter Dunlap }
2094a6d42e7dSPeter Dunlap 
2095a6d42e7dSPeter Dunlap iscsit_ini_t *
iscsit_ini_lookup_locked(char * ini_name)2096a6d42e7dSPeter Dunlap iscsit_ini_lookup_locked(char *ini_name)
2097a6d42e7dSPeter Dunlap {
2098a6d42e7dSPeter Dunlap 	iscsit_ini_t	tmp_ini;
2099a6d42e7dSPeter Dunlap 	iscsit_ini_t	*result;
2100a6d42e7dSPeter Dunlap 
2101a6d42e7dSPeter Dunlap 	/*
2102a6d42e7dSPeter Dunlap 	 * Use a dummy target for lookup, filling in all fields used in AVL
2103a6d42e7dSPeter Dunlap 	 * comparison.
2104a6d42e7dSPeter Dunlap 	 */
2105a6d42e7dSPeter Dunlap 	(void) strlcpy(tmp_ini.ini_name, ini_name, MAX_ISCSI_NODENAMELEN);
2106a6d42e7dSPeter Dunlap 	result = avl_find(&iscsit_global.global_ini_list, &tmp_ini, NULL);
2107a6d42e7dSPeter Dunlap 
2108a6d42e7dSPeter Dunlap 	return (result);
2109a6d42e7dSPeter Dunlap }
2110