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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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, 653*fc8ae2ecSToomas 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 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 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 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 * 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 * 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 * 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 914a6d42e7dSPeter Dunlap /* 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 92107a2bfd1SPeter Cudhea - Sun Microsystems - Burlington, MA United States /* 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 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 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 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 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 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 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 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 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; 1087a6d42e7dSPeter Dunlap 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 * 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 * 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 * 1132a6d42e7dSPeter Dunlap iscsit_tgt_lookup_portal(iscsit_tgt_t *tgt, struct sockaddr_storage *sa, 1133a6d42e7dSPeter Dunlap iscsit_tpgt_t **output_tpgt) 1134a6d42e7dSPeter Dunlap { 1135a6d42e7dSPeter Dunlap 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 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 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 1192a6d42e7dSPeter Dunlap #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 1200a6d42e7dSPeter Dunlap #define UNLOCK_FOR_SESS_LOOKUP(lookup_tgt) { \ 1201a6d42e7dSPeter Dunlap if ((lookup_tgt) == NULL) { \ 1202a6d42e7dSPeter Dunlap ISCSIT_GLOBAL_UNLOCK(); \ 1203a6d42e7dSPeter Dunlap } else { \ 1204a6d42e7dSPeter Dunlap mutex_exit(&(lookup_tgt)->target_mutex); \ 1205a6d42e7dSPeter Dunlap } \ 1206a6d42e7dSPeter Dunlap } 1207a6d42e7dSPeter Dunlap 1208a6d42e7dSPeter Dunlap iscsit_sess_t * 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); 1227a6d42e7dSPeter Dunlap if (avl_numnodes(sess_avl) == NULL) { 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 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 * 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 * 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 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 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 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 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 1420a6d42e7dSPeter Dunlap iscsit_tgt_online(iscsit_tgt_t *tgt) 1421a6d42e7dSPeter Dunlap { 1422a6d42e7dSPeter Dunlap 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 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 1469a6d42e7dSPeter Dunlap iscsit_tgt_offline(iscsit_tgt_t *tgt) 1470a6d42e7dSPeter Dunlap { 1471a6d42e7dSPeter Dunlap 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 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 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 * 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 * 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 * 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 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 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 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 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 * 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 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 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; 1744a6d42e7dSPeter Dunlap 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 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 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 * 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 * 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 * 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 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) { 1875a6d42e7dSPeter Dunlap ASSERT(portal->portal_svc == NULL); 1876a6d42e7dSPeter Dunlap idm_refcnt_destroy(&portal->portal_refcnt); 1877a6d42e7dSPeter Dunlap kmem_free(portal, sizeof (*portal)); 1878a6d42e7dSPeter Dunlap } 1879d0a3a998SPeter Cudhea - Sun Microsystems - Burlington, MA United States } 1880a6d42e7dSPeter Dunlap 1881a6d42e7dSPeter Dunlap void 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 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 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 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 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 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 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; 2080a6d42e7dSPeter Dunlap 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 * 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