LCOV - code coverage report
Current view: top level - lib/iscsi - conn.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 102 799 12.8 %
Date: 2024-12-09 07:15:33 Functions: 9 67 13.4 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
       3             :  *   Copyright (C) 2016 Intel Corporation.
       4             :  *   All rights reserved.
       5             :  */
       6             : 
       7             : #include "spdk/stdinc.h"
       8             : 
       9             : #include "spdk/endian.h"
      10             : #include "spdk/env.h"
      11             : #include "spdk/likely.h"
      12             : #include "spdk/thread.h"
      13             : #include "spdk/queue.h"
      14             : #include "spdk/trace.h"
      15             : #include "spdk/sock.h"
      16             : #include "spdk/string.h"
      17             : 
      18             : #include "spdk/log.h"
      19             : 
      20             : #include "iscsi/task.h"
      21             : #include "iscsi/conn.h"
      22             : #include "iscsi/tgt_node.h"
      23             : #include "iscsi/portal_grp.h"
      24             : 
      25             : #define MAKE_DIGEST_WORD(BUF, CRC32C) \
      26             :         (   ((*((uint8_t *)(BUF)+0)) = (uint8_t)((uint32_t)(CRC32C) >> 0)), \
      27             :             ((*((uint8_t *)(BUF)+1)) = (uint8_t)((uint32_t)(CRC32C) >> 8)), \
      28             :             ((*((uint8_t *)(BUF)+2)) = (uint8_t)((uint32_t)(CRC32C) >> 16)), \
      29             :             ((*((uint8_t *)(BUF)+3)) = (uint8_t)((uint32_t)(CRC32C) >> 24)))
      30             : 
      31             : #define SPDK_ISCSI_CONNECTION_MEMSET(conn)              \
      32             :         memset(&(conn)->portal, 0, sizeof(*(conn)) -     \
      33             :                 offsetof(struct spdk_iscsi_conn, portal));
      34             : 
      35             : #define SPDK_ISCSI_CONNECTION_STATUS(status, rnstr) case(status): return(rnstr)
      36             : 
      37             : static struct spdk_iscsi_conn *g_conns_array = NULL;
      38             : 
      39             : static TAILQ_HEAD(, spdk_iscsi_conn) g_free_conns = TAILQ_HEAD_INITIALIZER(g_free_conns);
      40             : static TAILQ_HEAD(, spdk_iscsi_conn) g_active_conns = TAILQ_HEAD_INITIALIZER(g_active_conns);
      41             : 
      42             : static pthread_mutex_t g_conns_mutex = PTHREAD_MUTEX_INITIALIZER;
      43             : 
      44             : static struct spdk_poller *g_shutdown_timer = NULL;
      45             : 
      46             : static void iscsi_conn_sock_cb(void *arg, struct spdk_sock_group *group,
      47             :                                struct spdk_sock *sock);
      48             : 
      49             : static struct spdk_iscsi_conn *
      50           0 : allocate_conn(void)
      51             : {
      52             :         struct spdk_iscsi_conn  *conn;
      53             : 
      54           0 :         pthread_mutex_lock(&g_conns_mutex);
      55           0 :         conn = TAILQ_FIRST(&g_free_conns);
      56           0 :         if (conn != NULL) {
      57           0 :                 assert(!conn->is_valid);
      58           0 :                 TAILQ_REMOVE(&g_free_conns, conn, conn_link);
      59           0 :                 SPDK_ISCSI_CONNECTION_MEMSET(conn);
      60           0 :                 conn->is_valid = 1;
      61             : 
      62           0 :                 TAILQ_INSERT_TAIL(&g_active_conns, conn, conn_link);
      63             :         }
      64           0 :         pthread_mutex_unlock(&g_conns_mutex);
      65             : 
      66           0 :         return conn;
      67             : }
      68             : 
      69             : static void
      70           0 : _free_conn(struct spdk_iscsi_conn *conn)
      71             : {
      72           0 :         TAILQ_REMOVE(&g_active_conns, conn, conn_link);
      73             : 
      74           0 :         memset(conn->portal_host, 0, sizeof(conn->portal_host));
      75           0 :         memset(conn->portal_port, 0, sizeof(conn->portal_port));
      76           0 :         conn->is_valid = 0;
      77             : 
      78           0 :         TAILQ_INSERT_TAIL(&g_free_conns, conn, conn_link);
      79           0 : }
      80             : 
      81             : static void
      82           0 : free_conn(struct spdk_iscsi_conn *conn)
      83             : {
      84           0 :         pthread_mutex_lock(&g_conns_mutex);
      85           0 :         _free_conn(conn);
      86           0 :         pthread_mutex_unlock(&g_conns_mutex);
      87           0 : }
      88             : 
      89             : static void
      90           0 : _iscsi_conns_cleanup(void)
      91             : {
      92           0 :         free(g_conns_array);
      93           0 : }
      94             : 
      95             : int
      96           0 : initialize_iscsi_conns(void)
      97             : {
      98             :         uint32_t i;
      99             : 
     100           0 :         SPDK_DEBUGLOG(iscsi, "spdk_iscsi_init\n");
     101             : 
     102           0 :         g_conns_array = calloc(MAX_ISCSI_CONNECTIONS, sizeof(struct spdk_iscsi_conn));
     103           0 :         if (g_conns_array == NULL) {
     104           0 :                 return -ENOMEM;
     105             :         }
     106             : 
     107           0 :         for (i = 0; i < MAX_ISCSI_CONNECTIONS; i++) {
     108           0 :                 g_conns_array[i].id = i;
     109           0 :                 TAILQ_INSERT_TAIL(&g_free_conns, &g_conns_array[i], conn_link);
     110             :         }
     111             : 
     112           0 :         return 0;
     113             : }
     114             : 
     115             : static void
     116           0 : iscsi_poll_group_add_conn(struct spdk_iscsi_poll_group *pg, struct spdk_iscsi_conn *conn)
     117             : {
     118             :         int rc;
     119             : 
     120           0 :         rc = spdk_sock_group_add_sock(pg->sock_group, conn->sock, iscsi_conn_sock_cb, conn);
     121           0 :         if (rc < 0) {
     122           0 :                 SPDK_ERRLOG("Failed to add sock=%p of conn=%p\n", conn->sock, conn);
     123           0 :                 return;
     124             :         }
     125             : 
     126           0 :         conn->is_stopped = false;
     127           0 :         STAILQ_INSERT_TAIL(&pg->connections, conn, pg_link);
     128             : }
     129             : 
     130             : static void
     131           0 : iscsi_poll_group_remove_conn(struct spdk_iscsi_poll_group *pg, struct spdk_iscsi_conn *conn)
     132             : {
     133             :         int rc;
     134             : 
     135           0 :         assert(conn->sock != NULL);
     136           0 :         rc = spdk_sock_group_remove_sock(pg->sock_group, conn->sock);
     137           0 :         if (rc < 0) {
     138           0 :                 SPDK_ERRLOG("Failed to remove sock=%p of conn=%p\n", conn->sock, conn);
     139             :         }
     140             : 
     141           0 :         conn->is_stopped = true;
     142           0 :         STAILQ_REMOVE(&pg->connections, conn, spdk_iscsi_conn, pg_link);
     143           0 : }
     144             : 
     145             : static int
     146           0 : login_timeout(void *arg)
     147             : {
     148           0 :         struct spdk_iscsi_conn *conn = arg;
     149             : 
     150           0 :         if (conn->state < ISCSI_CONN_STATE_EXITING) {
     151           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
     152             :         }
     153           0 :         spdk_poller_unregister(&conn->login_timer);
     154             : 
     155           0 :         return SPDK_POLLER_BUSY;
     156             : }
     157             : 
     158             : static void
     159           0 : iscsi_conn_start(void *ctx)
     160             : {
     161           0 :         struct spdk_iscsi_conn *conn = ctx;
     162             : 
     163           0 :         iscsi_poll_group_add_conn(conn->pg, conn);
     164             : 
     165           0 :         conn->login_timer = SPDK_POLLER_REGISTER(login_timeout, conn, ISCSI_LOGIN_TIMEOUT * 1000000);
     166           0 : }
     167             : 
     168             : int
     169           0 : iscsi_conn_construct(struct spdk_iscsi_portal *portal,
     170             :                      struct spdk_sock *sock)
     171             : {
     172             :         struct spdk_iscsi_poll_group *pg;
     173             :         struct spdk_iscsi_conn *conn;
     174             :         int i, rc;
     175             : 
     176           0 :         conn = allocate_conn();
     177           0 :         if (conn == NULL) {
     178           0 :                 SPDK_ERRLOG("Could not allocate connection.\n");
     179           0 :                 return -1;
     180             :         }
     181             : 
     182           0 :         pthread_mutex_lock(&g_iscsi.mutex);
     183           0 :         conn->timeout = g_iscsi.timeout * spdk_get_ticks_hz(); /* seconds to TSC */
     184           0 :         conn->nopininterval = g_iscsi.nopininterval;
     185           0 :         conn->nopininterval *= spdk_get_ticks_hz(); /* seconds to TSC */
     186           0 :         conn->last_nopin = spdk_get_ticks();
     187           0 :         conn->nop_outstanding = false;
     188           0 :         conn->data_out_cnt = 0;
     189           0 :         conn->data_in_cnt = 0;
     190           0 :         conn->disable_chap = portal->group->disable_chap;
     191           0 :         conn->require_chap = portal->group->require_chap;
     192           0 :         conn->mutual_chap = portal->group->mutual_chap;
     193           0 :         conn->chap_group = portal->group->chap_group;
     194           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
     195           0 :         conn->MaxRecvDataSegmentLength = 8192; /* RFC3720(12.12) */
     196             : 
     197           0 :         conn->portal = portal;
     198           0 :         conn->pg_tag = portal->group->tag;
     199           0 :         memcpy(conn->portal_host, portal->host, strlen(portal->host));
     200           0 :         memcpy(conn->portal_port, portal->port, strlen(portal->port));
     201           0 :         conn->sock = sock;
     202             : 
     203           0 :         conn->state = ISCSI_CONN_STATE_INVALID;
     204           0 :         conn->login_phase = ISCSI_SECURITY_NEGOTIATION_PHASE;
     205           0 :         conn->ttt = 0;
     206             : 
     207           0 :         conn->partial_text_parameter = NULL;
     208             : 
     209           0 :         for (i = 0; i < MAX_CONNECTION_PARAMS; i++) {
     210           0 :                 conn->conn_param_state_negotiated[i] = false;
     211             :         }
     212             : 
     213           0 :         for (i = 0; i < MAX_SESSION_PARAMS; i++) {
     214           0 :                 conn->sess_param_state_negotiated[i] = false;
     215             :         }
     216             : 
     217           0 :         conn->pdu_recv_state = ISCSI_PDU_RECV_STATE_AWAIT_PDU_READY;
     218             : 
     219           0 :         TAILQ_INIT(&conn->write_pdu_list);
     220           0 :         TAILQ_INIT(&conn->snack_pdu_list);
     221           0 :         TAILQ_INIT(&conn->queued_r2t_tasks);
     222           0 :         TAILQ_INIT(&conn->active_r2t_tasks);
     223           0 :         TAILQ_INIT(&conn->queued_datain_tasks);
     224           0 :         TAILQ_INIT(&conn->luns);
     225             : 
     226           0 :         rc = spdk_sock_getaddr(sock, conn->target_addr, sizeof conn->target_addr, NULL,
     227           0 :                                conn->initiator_addr, sizeof conn->initiator_addr, NULL);
     228           0 :         if (rc < 0) {
     229           0 :                 SPDK_ERRLOG("spdk_sock_getaddr() failed\n");
     230           0 :                 goto error_return;
     231             :         }
     232             : 
     233             :         /* set low water mark */
     234           0 :         rc = spdk_sock_set_recvlowat(conn->sock, 1);
     235           0 :         if (rc != 0) {
     236           0 :                 SPDK_ERRLOG("spdk_sock_set_recvlowat() failed\n");
     237           0 :                 goto error_return;
     238             :         }
     239             : 
     240             :         /* set default params */
     241           0 :         rc = iscsi_conn_params_init(&conn->params);
     242           0 :         if (rc < 0) {
     243           0 :                 SPDK_ERRLOG("iscsi_conn_params_init() failed\n");
     244           0 :                 goto error_return;
     245             :         }
     246           0 :         conn->logout_request_timer = NULL;
     247           0 :         conn->logout_timer = NULL;
     248           0 :         conn->shutdown_timer = NULL;
     249           0 :         SPDK_DEBUGLOG(iscsi, "Launching connection on acceptor thread\n");
     250           0 :         conn->pending_task_cnt = 0;
     251             : 
     252             :         /* Get the first poll group. */
     253           0 :         pg = TAILQ_FIRST(&g_iscsi.poll_group_head);
     254           0 :         if (pg == NULL) {
     255           0 :                 SPDK_ERRLOG("There is no poll group.\n");
     256           0 :                 assert(false);
     257             :                 goto error_return;
     258             :         }
     259             : 
     260           0 :         conn->pg = pg;
     261           0 :         conn->trace_id = spdk_trace_register_owner(OWNER_TYPE_ISCSI_CONN, conn->initiator_addr);
     262           0 :         spdk_thread_send_msg(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(pg)),
     263             :                              iscsi_conn_start, conn);
     264           0 :         return 0;
     265             : 
     266           0 : error_return:
     267           0 :         iscsi_param_free(conn->params);
     268           0 :         free_conn(conn);
     269           0 :         return -1;
     270             : }
     271             : 
     272             : void
     273          10 : iscsi_conn_free_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
     274             : {
     275             :         iscsi_conn_xfer_complete_cb cb_fn;
     276             :         void *cb_arg;
     277             : 
     278          10 :         cb_fn = pdu->cb_fn;
     279          10 :         cb_arg = pdu->cb_arg;
     280             : 
     281          10 :         assert(cb_fn != NULL);
     282          10 :         pdu->cb_fn = NULL;
     283             : 
     284          10 :         if (pdu->task) {
     285           9 :                 iscsi_task_put(pdu->task);
     286             :         }
     287          10 :         iscsi_put_pdu(pdu);
     288             : 
     289          10 :         cb_fn(cb_arg);
     290          10 : }
     291             : 
     292             : static int
     293           4 : iscsi_conn_free_tasks(struct spdk_iscsi_conn *conn)
     294             : {
     295             :         struct spdk_iscsi_pdu *pdu, *tmp_pdu;
     296             :         struct spdk_iscsi_task *iscsi_task, *tmp_iscsi_task;
     297             : 
     298           7 :         TAILQ_FOREACH_SAFE(pdu, &conn->snack_pdu_list, tailq, tmp_pdu) {
     299           3 :                 TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq);
     300           3 :                 iscsi_conn_free_pdu(conn, pdu);
     301             :         }
     302             : 
     303          10 :         TAILQ_FOREACH_SAFE(iscsi_task, &conn->queued_datain_tasks, link, tmp_iscsi_task) {
     304           6 :                 if (!iscsi_task->is_queued) {
     305           5 :                         TAILQ_REMOVE(&conn->queued_datain_tasks, iscsi_task, link);
     306           5 :                         iscsi_task_put(iscsi_task);
     307             :                 }
     308             :         }
     309             : 
     310             :         /* We have to parse conn->write_pdu_list in the end.  In iscsi_conn_free_pdu(),
     311             :          *  iscsi_conn_handle_queued_datain_tasks() may be called, and
     312             :          *  iscsi_conn_handle_queued_datain_tasks() will parse conn->queued_datain_tasks
     313             :          *  and may stack some PDUs to conn->write_pdu_list.  Hence when we come here, we
     314             :          *  have to ensure there is no associated task in conn->queued_datain_tasks.
     315             :          */
     316          11 :         TAILQ_FOREACH_SAFE(pdu, &conn->write_pdu_list, tailq, tmp_pdu) {
     317           7 :                 TAILQ_REMOVE(&conn->write_pdu_list, pdu, tailq);
     318           7 :                 iscsi_conn_free_pdu(conn, pdu);
     319             :         }
     320             : 
     321           4 :         if (conn->pending_task_cnt) {
     322           0 :                 return -1;
     323             :         }
     324             : 
     325           4 :         return 0;
     326             : }
     327             : 
     328             : static void
     329           0 : iscsi_conn_cleanup_backend(struct spdk_iscsi_conn *conn)
     330             : {
     331             :         int rc;
     332             :         struct spdk_iscsi_tgt_node *target;
     333             : 
     334           0 :         if (conn->sess->connections > 1) {
     335             :                 /* connection specific cleanup */
     336           0 :         } else if (!g_iscsi.AllowDuplicateIsid) {
     337             :                 /*
     338             :                  * a> a target is connected by a single initiator, cleanup backend cancels inflight
     339             :                  *    IOs and the resources (of this initiator) are reclaimed as soon as possible.
     340             :                  * b> a target is connected by multiple initiators, one of these initiators
     341             :                  *    disconnects with inflight IOs, resetting backend bdev leads all the inflight
     342             :                  *    IOs (of multiple initiators) aborted. In this scenario, drain inflight IOs of
     343             :                  *    the disconnected initiator instead.
     344             :                  */
     345           0 :                 target = conn->sess->target;
     346           0 :                 if (target != NULL && iscsi_get_active_conns(target) == 1) {
     347           0 :                         rc = iscsi_tgt_node_cleanup_luns(conn, target);
     348           0 :                         if (rc < 0) {
     349           0 :                                 SPDK_ERRLOG("target abort failed\n");
     350             :                         }
     351             :                 }
     352             :         }
     353           0 : }
     354             : 
     355             : static void
     356           0 : iscsi_conn_free(struct spdk_iscsi_conn *conn)
     357             : {
     358             :         struct spdk_iscsi_sess *sess;
     359             :         int idx;
     360             :         uint32_t i;
     361             : 
     362           0 :         pthread_mutex_lock(&g_conns_mutex);
     363             : 
     364           0 :         if (conn->sess == NULL) {
     365           0 :                 goto end;
     366             :         }
     367             : 
     368           0 :         idx = -1;
     369           0 :         sess = conn->sess;
     370           0 :         conn->sess = NULL;
     371             : 
     372           0 :         for (i = 0; i < sess->connections; i++) {
     373           0 :                 if (sess->conns[i] == conn) {
     374           0 :                         idx = i;
     375           0 :                         break;
     376             :                 }
     377             :         }
     378             : 
     379           0 :         if (idx < 0) {
     380           0 :                 SPDK_ERRLOG("remove conn not found\n");
     381             :         } else {
     382           0 :                 for (i = idx; i < sess->connections - 1; i++) {
     383           0 :                         sess->conns[i] = sess->conns[i + 1];
     384             :                 }
     385           0 :                 sess->conns[sess->connections - 1] = NULL;
     386           0 :                 sess->connections--;
     387             : 
     388           0 :                 if (sess->connections == 0) {
     389             :                         /* cleanup last connection */
     390           0 :                         SPDK_DEBUGLOG(iscsi,
     391             :                                       "cleanup last conn free sess\n");
     392           0 :                         iscsi_free_sess(sess);
     393             :                 }
     394             :         }
     395             : 
     396           0 :         SPDK_DEBUGLOG(iscsi, "Terminating connections(tsih %d): %d\n",
     397             :                       sess->tsih, sess->connections);
     398             : 
     399           0 : end:
     400           0 :         SPDK_DEBUGLOG(iscsi, "cleanup free conn\n");
     401           0 :         iscsi_param_free(conn->params);
     402           0 :         _free_conn(conn);
     403             : 
     404           0 :         pthread_mutex_unlock(&g_conns_mutex);
     405           0 : }
     406             : 
     407             : static void
     408           0 : iscsi_conn_close_lun(struct spdk_iscsi_conn *conn,
     409             :                      struct spdk_iscsi_lun *iscsi_lun)
     410             : {
     411           0 :         if (iscsi_lun == NULL) {
     412           0 :                 return;
     413             :         }
     414             : 
     415           0 :         spdk_scsi_lun_free_io_channel(iscsi_lun->desc);
     416           0 :         spdk_scsi_lun_close(iscsi_lun->desc);
     417           0 :         spdk_poller_unregister(&iscsi_lun->remove_poller);
     418             : 
     419           0 :         TAILQ_REMOVE(&conn->luns, iscsi_lun, tailq);
     420             : 
     421           0 :         free(iscsi_lun);
     422             : 
     423             : }
     424             : 
     425             : static void
     426           0 : iscsi_conn_close_luns(struct spdk_iscsi_conn *conn)
     427             : {
     428             :         struct spdk_iscsi_lun *iscsi_lun, *tmp;
     429             : 
     430           0 :         TAILQ_FOREACH_SAFE(iscsi_lun, &conn->luns, tailq, tmp) {
     431           0 :                 iscsi_conn_close_lun(conn, iscsi_lun);
     432             :         }
     433           0 : }
     434             : 
     435             : static bool
     436           0 : iscsi_conn_check_tasks_for_lun(struct spdk_iscsi_conn *conn,
     437             :                                struct spdk_scsi_lun *lun)
     438             : {
     439             :         struct spdk_iscsi_pdu *pdu, *tmp_pdu;
     440             :         struct spdk_iscsi_task *task;
     441             : 
     442           0 :         assert(lun != NULL);
     443             : 
     444             :         /* We can remove deferred PDUs safely because they are already flushed. */
     445           0 :         TAILQ_FOREACH_SAFE(pdu, &conn->snack_pdu_list, tailq, tmp_pdu) {
     446           0 :                 if (lun == pdu->task->scsi.lun) {
     447           0 :                         TAILQ_REMOVE(&conn->snack_pdu_list, pdu, tailq);
     448           0 :                         iscsi_conn_free_pdu(conn, pdu);
     449             :                 }
     450             :         }
     451             : 
     452           0 :         TAILQ_FOREACH(task, &conn->queued_datain_tasks, link) {
     453           0 :                 if (lun == task->scsi.lun) {
     454           0 :                         return false;
     455             :                 }
     456             :         }
     457             : 
     458             :         /* This check loop works even when connection exits in the middle of LUN hotplug
     459             :          *  because all PDUs in write_pdu_list are removed in iscsi_conn_free_tasks().
     460             :          */
     461           0 :         TAILQ_FOREACH(pdu, &conn->write_pdu_list, tailq) {
     462           0 :                 if (pdu->task && lun == pdu->task->scsi.lun) {
     463           0 :                         return false;
     464             :                 }
     465             :         }
     466             : 
     467           0 :         return true;
     468             : }
     469             : 
     470             : static int
     471           0 : iscsi_conn_remove_lun(void *ctx)
     472             : {
     473           0 :         struct spdk_iscsi_lun *iscsi_lun = ctx;
     474           0 :         struct spdk_iscsi_conn *conn = iscsi_lun->conn;
     475           0 :         struct spdk_scsi_lun *lun = iscsi_lun->lun;
     476             : 
     477           0 :         if (!iscsi_conn_check_tasks_for_lun(conn, lun)) {
     478           0 :                 return SPDK_POLLER_BUSY;
     479             :         }
     480           0 :         iscsi_conn_close_lun(conn, iscsi_lun);
     481           0 :         return SPDK_POLLER_BUSY;
     482             : }
     483             : 
     484             : static void
     485           0 : _iscsi_conn_hotremove_lun(void *ctx)
     486             : {
     487           0 :         struct spdk_iscsi_lun *iscsi_lun = ctx;
     488           0 :         struct spdk_iscsi_conn *conn = iscsi_lun->conn;
     489           0 :         struct spdk_scsi_lun *lun = iscsi_lun->lun;
     490             : 
     491           0 :         assert(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(conn->pg)) ==
     492             :                spdk_get_thread());
     493             : 
     494             :         /* If a connection is already in stating status, just return */
     495           0 :         if (conn->state >= ISCSI_CONN_STATE_EXITING) {
     496           0 :                 return;
     497             :         }
     498             : 
     499           0 :         iscsi_clear_all_transfer_task(conn, lun, NULL);
     500             : 
     501           0 :         iscsi_lun->remove_poller = SPDK_POLLER_REGISTER(iscsi_conn_remove_lun, iscsi_lun,
     502             :                                    1000);
     503             : }
     504             : 
     505             : static void
     506           0 : iscsi_conn_hotremove_lun(struct spdk_scsi_lun *lun, void *remove_ctx)
     507             : {
     508           0 :         struct spdk_iscsi_lun *iscsi_lun = remove_ctx;
     509           0 :         struct spdk_iscsi_conn *conn = iscsi_lun->conn;
     510             : 
     511           0 :         spdk_thread_send_msg(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(conn->pg)),
     512             :                              _iscsi_conn_hotremove_lun, iscsi_lun);
     513           0 : }
     514             : 
     515             : static int
     516           0 : iscsi_conn_open_lun(struct spdk_iscsi_conn *conn, struct spdk_scsi_lun *lun)
     517             : {
     518             :         int rc;
     519             :         struct spdk_iscsi_lun *iscsi_lun;
     520             : 
     521           0 :         iscsi_lun = calloc(1, sizeof(*iscsi_lun));
     522           0 :         if (iscsi_lun == NULL) {
     523           0 :                 return -ENOMEM;
     524             :         }
     525             : 
     526           0 :         iscsi_lun->conn = conn;
     527           0 :         iscsi_lun->lun = lun;
     528             : 
     529           0 :         rc = spdk_scsi_lun_open(lun, iscsi_conn_hotremove_lun, iscsi_lun, &iscsi_lun->desc);
     530           0 :         if (rc != 0) {
     531           0 :                 free(iscsi_lun);
     532           0 :                 return rc;
     533             :         }
     534             : 
     535           0 :         rc = spdk_scsi_lun_allocate_io_channel(iscsi_lun->desc);
     536           0 :         if (rc != 0) {
     537           0 :                 spdk_scsi_lun_close(iscsi_lun->desc);
     538           0 :                 free(iscsi_lun);
     539           0 :                 return rc;
     540             :         }
     541             : 
     542           0 :         TAILQ_INSERT_TAIL(&conn->luns, iscsi_lun, tailq);
     543             : 
     544           0 :         return 0;
     545             : }
     546             : 
     547             : static int
     548           0 : iscsi_conn_open_luns(struct spdk_iscsi_conn *conn)
     549             : {
     550             :         int rc;
     551             :         struct spdk_scsi_lun *lun;
     552             : 
     553           0 :         for (lun = spdk_scsi_dev_get_first_lun(conn->dev); lun != NULL;
     554           0 :              lun = spdk_scsi_dev_get_next_lun(lun)) {
     555           0 :                 rc = iscsi_conn_open_lun(conn, lun);
     556           0 :                 if (rc != 0) {
     557           0 :                         goto error;
     558             :                 }
     559             :         }
     560             : 
     561           0 :         return 0;
     562             : 
     563           0 : error:
     564           0 :         iscsi_conn_close_luns(conn);
     565           0 :         return -1;
     566             : }
     567             : 
     568             : /**
     569             :  *  This function will stop executing the specified connection.
     570             :  */
     571             : static void
     572           0 : iscsi_conn_stop(struct spdk_iscsi_conn *conn)
     573             : {
     574             :         struct spdk_iscsi_tgt_node *target;
     575             : 
     576           0 :         assert(conn->state == ISCSI_CONN_STATE_EXITED);
     577           0 :         assert(conn->data_in_cnt == 0);
     578           0 :         assert(conn->data_out_cnt == 0);
     579             : 
     580           0 :         if (conn->sess != NULL &&
     581           0 :             conn->sess->session_type == SESSION_TYPE_NORMAL &&
     582           0 :             conn->full_feature) {
     583           0 :                 target = conn->sess->target;
     584             : 
     585           0 :                 pthread_mutex_lock(&g_iscsi.mutex);
     586           0 :                 pthread_mutex_lock(&target->mutex);
     587           0 :                 if (conn->scheduled != 0) {
     588           0 :                         target->num_active_conns--;
     589           0 :                         if (target->num_active_conns == 0) {
     590           0 :                                 assert(target->pg != NULL);
     591           0 :                                 target->pg->num_active_targets--;
     592             :                         }
     593             :                 }
     594           0 :                 pthread_mutex_unlock(&target->mutex);
     595           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
     596             : 
     597           0 :                 iscsi_conn_close_luns(conn);
     598             :         }
     599             : 
     600           0 :         assert(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(conn->pg)) ==
     601             :                spdk_get_thread());
     602           0 : }
     603             : 
     604             : static int
     605           0 : _iscsi_conn_check_shutdown(void *arg)
     606             : {
     607           0 :         struct spdk_iscsi_conn *conn = arg;
     608             :         int rc;
     609             : 
     610           0 :         rc = iscsi_conn_free_tasks(conn);
     611           0 :         if (rc < 0) {
     612           0 :                 return SPDK_POLLER_BUSY;
     613             :         }
     614             : 
     615           0 :         spdk_poller_unregister(&conn->shutdown_timer);
     616             : 
     617           0 :         iscsi_conn_stop(conn);
     618           0 :         iscsi_conn_free(conn);
     619             : 
     620           0 :         return SPDK_POLLER_BUSY;
     621             : }
     622             : 
     623             : static void
     624           0 : _iscsi_conn_destruct(struct spdk_iscsi_conn *conn)
     625             : {
     626             :         int rc;
     627             : 
     628           0 :         iscsi_poll_group_remove_conn(conn->pg, conn);
     629           0 :         spdk_sock_close(&conn->sock);
     630           0 :         iscsi_clear_all_transfer_task(conn, NULL, NULL);
     631           0 :         spdk_poller_unregister(&conn->logout_request_timer);
     632           0 :         spdk_poller_unregister(&conn->logout_timer);
     633           0 :         spdk_poller_unregister(&conn->login_timer);
     634             : 
     635           0 :         rc = iscsi_conn_free_tasks(conn);
     636           0 :         if (rc < 0) {
     637             :                 /* The connection cannot be freed yet. Check back later. */
     638           0 :                 conn->shutdown_timer = SPDK_POLLER_REGISTER(_iscsi_conn_check_shutdown, conn, 1000);
     639             :         } else {
     640           0 :                 iscsi_conn_stop(conn);
     641           0 :                 iscsi_conn_free(conn);
     642             :         }
     643           0 : }
     644             : 
     645             : static int
     646           0 : _iscsi_conn_check_pending_tasks(void *arg)
     647             : {
     648           0 :         struct spdk_iscsi_conn *conn = arg;
     649             : 
     650           0 :         if (conn->dev != NULL &&
     651           0 :             spdk_scsi_dev_has_pending_tasks(conn->dev, conn->initiator_port)) {
     652           0 :                 return SPDK_POLLER_BUSY;
     653             :         }
     654             : 
     655           0 :         spdk_poller_unregister(&conn->shutdown_timer);
     656             : 
     657           0 :         _iscsi_conn_destruct(conn);
     658             : 
     659           0 :         return SPDK_POLLER_BUSY;
     660             : }
     661             : 
     662             : void
     663           0 : iscsi_conn_destruct(struct spdk_iscsi_conn *conn)
     664             : {
     665             :         struct spdk_iscsi_pdu *pdu;
     666             :         struct spdk_iscsi_task *task;
     667             :         int opcode;
     668             : 
     669             :         /* If a connection is already in exited status, just return */
     670           0 :         if (conn->state >= ISCSI_CONN_STATE_EXITED) {
     671           0 :                 return;
     672             :         }
     673             : 
     674           0 :         conn->state = ISCSI_CONN_STATE_EXITED;
     675             : 
     676             :         /*
     677             :          * Each connection pre-allocates its next PDU - make sure these get
     678             :          *  freed here.
     679             :          */
     680           0 :         pdu = conn->pdu_in_progress;
     681           0 :         if (pdu) {
     682             :                 /* remove the task left in the PDU too. */
     683           0 :                 task = pdu->task;
     684           0 :                 if (task) {
     685           0 :                         opcode = pdu->bhs.opcode;
     686           0 :                         switch (opcode) {
     687           0 :                         case ISCSI_OP_SCSI:
     688             :                         case ISCSI_OP_SCSI_DATAOUT:
     689           0 :                                 spdk_scsi_task_process_abort(&task->scsi);
     690           0 :                                 iscsi_task_cpl(&task->scsi);
     691           0 :                                 break;
     692           0 :                         default:
     693           0 :                                 SPDK_ERRLOG("unexpected opcode %x\n", opcode);
     694           0 :                                 iscsi_task_put(task);
     695           0 :                                 break;
     696             :                         }
     697             :                 }
     698           0 :                 iscsi_put_pdu(pdu);
     699           0 :                 conn->pdu_in_progress = NULL;
     700             :         }
     701             : 
     702           0 :         if (conn->sess != NULL && conn->pending_task_cnt > 0) {
     703           0 :                 iscsi_conn_cleanup_backend(conn);
     704             :         }
     705             : 
     706           0 :         if (conn->dev != NULL &&
     707           0 :             spdk_scsi_dev_has_pending_tasks(conn->dev, conn->initiator_port)) {
     708           0 :                 conn->shutdown_timer = SPDK_POLLER_REGISTER(_iscsi_conn_check_pending_tasks, conn, 1000);
     709             :         } else {
     710           0 :                 _iscsi_conn_destruct(conn);
     711             :         }
     712             : }
     713             : 
     714             : int
     715           0 : iscsi_get_active_conns(struct spdk_iscsi_tgt_node *target)
     716             : {
     717             :         struct spdk_iscsi_conn *conn;
     718           0 :         int num = 0;
     719             : 
     720           0 :         if (g_conns_array == MAP_FAILED) {
     721           0 :                 return 0;
     722             :         }
     723             : 
     724           0 :         pthread_mutex_lock(&g_conns_mutex);
     725           0 :         TAILQ_FOREACH(conn, &g_active_conns, conn_link) {
     726           0 :                 if (target == NULL || conn->target == target) {
     727           0 :                         num++;
     728             :                 }
     729             :         }
     730           0 :         pthread_mutex_unlock(&g_conns_mutex);
     731           0 :         return num;
     732             : }
     733             : 
     734             : static void
     735           0 : iscsi_conn_check_shutdown_cb(void *arg1)
     736             : {
     737           0 :         _iscsi_conns_cleanup();
     738           0 :         shutdown_iscsi_conns_done();
     739           0 : }
     740             : 
     741             : static int
     742           0 : iscsi_conn_check_shutdown(void *arg)
     743             : {
     744           0 :         if (iscsi_get_active_conns(NULL) != 0) {
     745           0 :                 return SPDK_POLLER_BUSY;
     746             :         }
     747             : 
     748           0 :         spdk_poller_unregister(&g_shutdown_timer);
     749             : 
     750           0 :         spdk_thread_send_msg(spdk_get_thread(), iscsi_conn_check_shutdown_cb, NULL);
     751             : 
     752           0 :         return SPDK_POLLER_BUSY;
     753             : }
     754             : 
     755             : static void
     756           0 : iscsi_send_logout_request(struct spdk_iscsi_conn *conn)
     757             : {
     758             :         struct spdk_iscsi_pdu *rsp_pdu;
     759             :         struct iscsi_bhs_async *rsph;
     760             : 
     761           0 :         rsp_pdu = iscsi_get_pdu(conn);
     762           0 :         assert(rsp_pdu != NULL);
     763             : 
     764           0 :         rsph = (struct iscsi_bhs_async *)&rsp_pdu->bhs;
     765           0 :         rsp_pdu->data = NULL;
     766             : 
     767           0 :         rsph->opcode = ISCSI_OP_ASYNC;
     768           0 :         to_be32(&rsph->ffffffff, 0xFFFFFFFF);
     769           0 :         rsph->async_event = 1;
     770           0 :         to_be16(&rsph->param3, ISCSI_LOGOUT_REQUEST_TIMEOUT);
     771             : 
     772           0 :         to_be32(&rsph->stat_sn, conn->StatSN);
     773           0 :         conn->StatSN++;
     774           0 :         to_be32(&rsph->exp_cmd_sn, conn->sess->ExpCmdSN);
     775           0 :         to_be32(&rsph->max_cmd_sn, conn->sess->MaxCmdSN);
     776             : 
     777           0 :         iscsi_conn_write_pdu(conn, rsp_pdu, iscsi_conn_pdu_generic_complete, NULL);
     778           0 : }
     779             : 
     780             : static int
     781           0 : logout_request_timeout(void *arg)
     782             : {
     783           0 :         struct spdk_iscsi_conn *conn = arg;
     784             : 
     785           0 :         if (conn->state < ISCSI_CONN_STATE_EXITING) {
     786           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
     787             :         }
     788             : 
     789           0 :         spdk_poller_unregister(&conn->logout_request_timer);
     790             : 
     791           0 :         return SPDK_POLLER_BUSY;
     792             : }
     793             : 
     794             : /* If the connection is running and logout is not requested yet, request logout
     795             :  * to initiator and wait for the logout process to start.
     796             :  */
     797             : static void
     798           0 : _iscsi_conn_request_logout(void *ctx)
     799             : {
     800           0 :         struct spdk_iscsi_conn *conn = ctx;
     801             : 
     802           0 :         if (conn->state > ISCSI_CONN_STATE_RUNNING ||
     803           0 :             conn->logout_request_timer != NULL) {
     804           0 :                 return;
     805             :         }
     806             : 
     807           0 :         iscsi_send_logout_request(conn);
     808             : 
     809           0 :         conn->logout_request_timer = SPDK_POLLER_REGISTER(logout_request_timeout,
     810             :                                      conn, ISCSI_LOGOUT_REQUEST_TIMEOUT * 1000000);
     811             : }
     812             : 
     813             : static void
     814           0 : iscsi_conn_request_logout(struct spdk_iscsi_conn *conn)
     815             : {
     816             :         struct spdk_thread *thread;
     817             : 
     818           0 :         if (conn->state == ISCSI_CONN_STATE_INVALID) {
     819             :                 /* Move it to EXITING state if the connection is in login. */
     820           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
     821           0 :                 spdk_poller_unregister(&conn->login_timer);
     822           0 :         } else if (conn->state == ISCSI_CONN_STATE_RUNNING &&
     823           0 :                    conn->logout_request_timer == NULL) {
     824           0 :                 thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(conn->pg));
     825           0 :                 spdk_thread_send_msg(thread, _iscsi_conn_request_logout, conn);
     826             :         }
     827           0 : }
     828             : 
     829             : void
     830           0 : iscsi_conns_request_logout(struct spdk_iscsi_tgt_node *target, int pg_tag)
     831             : {
     832             :         struct spdk_iscsi_conn  *conn;
     833             : 
     834           0 :         if (g_conns_array == MAP_FAILED) {
     835           0 :                 return;
     836             :         }
     837             : 
     838           0 :         pthread_mutex_lock(&g_conns_mutex);
     839           0 :         TAILQ_FOREACH(conn, &g_active_conns, conn_link) {
     840           0 :                 if ((target == NULL) ||
     841           0 :                     (conn->target == target && (pg_tag < 0 || conn->pg_tag == pg_tag))) {
     842           0 :                         iscsi_conn_request_logout(conn);
     843             :                 }
     844             :         }
     845           0 :         pthread_mutex_unlock(&g_conns_mutex);
     846             : }
     847             : 
     848             : void
     849           0 : shutdown_iscsi_conns(void)
     850             : {
     851           0 :         iscsi_conns_request_logout(NULL, -1);
     852             : 
     853           0 :         g_shutdown_timer = SPDK_POLLER_REGISTER(iscsi_conn_check_shutdown, NULL, 1000);
     854           0 : }
     855             : 
     856             : /* Do not set conn->state if the connection has already started exiting.
     857             :  *  This ensures we do not move a connection from EXITED state back to EXITING.
     858             :  */
     859             : static void
     860           0 : _iscsi_conn_drop(void *ctx)
     861             : {
     862           0 :         struct spdk_iscsi_conn *conn = ctx;
     863             : 
     864           0 :         if (conn->state < ISCSI_CONN_STATE_EXITING) {
     865           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
     866             :         }
     867           0 : }
     868             : 
     869             : int
     870           0 : iscsi_drop_conns(struct spdk_iscsi_conn *conn, const char *conn_match,
     871             :                  int drop_all)
     872             : {
     873             :         struct spdk_iscsi_conn  *xconn;
     874             :         const char              *xconn_match;
     875             :         struct spdk_thread      *thread;
     876             :         int                     num;
     877             : 
     878           0 :         SPDK_DEBUGLOG(iscsi, "iscsi_drop_conns\n");
     879             : 
     880           0 :         num = 0;
     881           0 :         pthread_mutex_lock(&g_conns_mutex);
     882           0 :         if (g_conns_array == MAP_FAILED) {
     883           0 :                 goto exit;
     884             :         }
     885             : 
     886           0 :         TAILQ_FOREACH(xconn, &g_active_conns, conn_link) {
     887           0 :                 if (xconn == conn) {
     888           0 :                         continue;
     889             :                 }
     890             : 
     891           0 :                 if (!drop_all && xconn->initiator_port == NULL) {
     892           0 :                         continue;
     893             :                 }
     894             : 
     895           0 :                 xconn_match =
     896           0 :                         drop_all ? xconn->initiator_name : spdk_scsi_port_get_name(xconn->initiator_port);
     897             : 
     898           0 :                 if (!strcasecmp(conn_match, xconn_match) &&
     899           0 :                     conn->target == xconn->target) {
     900             : 
     901           0 :                         if (num == 0) {
     902             :                                 /*
     903             :                                  * Only print this message before we report the
     904             :                                  *  first dropped connection.
     905             :                                  */
     906           0 :                                 SPDK_ERRLOG("drop old connections %s by %s\n",
     907             :                                             conn->target->name, conn_match);
     908             :                         }
     909             : 
     910           0 :                         SPDK_ERRLOG("exiting conn by %s (%s)\n",
     911             :                                     xconn_match, xconn->initiator_addr);
     912           0 :                         if (xconn->sess != NULL) {
     913           0 :                                 SPDK_DEBUGLOG(iscsi, "TSIH=%u\n", xconn->sess->tsih);
     914             :                         } else {
     915           0 :                                 SPDK_DEBUGLOG(iscsi, "TSIH=xx\n");
     916             :                         }
     917             : 
     918           0 :                         SPDK_DEBUGLOG(iscsi, "CID=%u\n", xconn->cid);
     919             : 
     920           0 :                         thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(xconn->pg));
     921           0 :                         spdk_thread_send_msg(thread, _iscsi_conn_drop, xconn);
     922             : 
     923           0 :                         num++;
     924             :                 }
     925             :         }
     926             : 
     927           0 : exit:
     928           0 :         pthread_mutex_unlock(&g_conns_mutex);
     929             : 
     930           0 :         if (num != 0) {
     931           0 :                 SPDK_ERRLOG("exiting %d conns\n", num);
     932             :         }
     933             : 
     934           0 :         return 0;
     935             : }
     936             : 
     937             : static int
     938           7 : _iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,
     939             :                                      struct spdk_iscsi_task *task)
     940             : {
     941             :         struct spdk_iscsi_task *subtask;
     942             :         uint32_t remaining_size;
     943             : 
     944           7 :         if (conn->data_in_cnt >= g_iscsi.MaxLargeDataInPerConnection) {
     945           2 :                 return -1;
     946             :         }
     947             : 
     948           5 :         assert(task->current_data_offset <= task->scsi.transfer_len);
     949             :         /* Stop split and abort read I/O for remaining data. */
     950           5 :         if (task->current_data_offset < task->scsi.transfer_len) {
     951           5 :                 remaining_size = task->scsi.transfer_len - task->current_data_offset;
     952           5 :                 subtask = iscsi_task_get(conn, task, iscsi_task_cpl);
     953           5 :                 assert(subtask != NULL);
     954           5 :                 subtask->scsi.offset = task->current_data_offset;
     955           5 :                 subtask->scsi.length = remaining_size;
     956           5 :                 spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
     957           5 :                 task->current_data_offset += subtask->scsi.length;
     958             : 
     959           5 :                 subtask->scsi.transfer_len = subtask->scsi.length;
     960           5 :                 spdk_scsi_task_process_abort(&subtask->scsi);
     961           5 :                 iscsi_task_cpl(&subtask->scsi);
     962             :         }
     963             : 
     964             :         /* Remove the primary task from the list because all subtasks are submitted
     965             :          *  or aborted.
     966             :          */
     967           5 :         assert(task->current_data_offset == task->scsi.transfer_len);
     968           5 :         TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
     969           5 :         return 0;
     970             : }
     971             : 
     972             : int
     973           0 : iscsi_conn_abort_queued_datain_task(struct spdk_iscsi_conn *conn,
     974             :                                     uint32_t ref_task_tag)
     975             : {
     976             :         struct spdk_iscsi_task *task;
     977             : 
     978           0 :         TAILQ_FOREACH(task, &conn->queued_datain_tasks, link) {
     979           0 :                 if (task->tag == ref_task_tag) {
     980           0 :                         return _iscsi_conn_abort_queued_datain_task(conn, task);
     981             :                 }
     982             :         }
     983             : 
     984           0 :         return 0;
     985             : }
     986             : 
     987             : int
     988           2 : iscsi_conn_abort_queued_datain_tasks(struct spdk_iscsi_conn *conn,
     989             :                                      struct spdk_scsi_lun *lun,
     990             :                                      struct spdk_iscsi_pdu *pdu)
     991             : {
     992             :         struct spdk_iscsi_task *task, *task_tmp;
     993             :         struct spdk_iscsi_pdu *pdu_tmp;
     994             :         int rc;
     995             : 
     996          13 :         TAILQ_FOREACH_SAFE(task, &conn->queued_datain_tasks, link, task_tmp) {
     997          11 :                 pdu_tmp = iscsi_task_get_pdu(task);
     998          11 :                 if ((lun == NULL || lun == task->scsi.lun) &&
     999           6 :                     (pdu == NULL || (spdk_sn32_lt(pdu_tmp->cmd_sn, pdu->cmd_sn)))) {
    1000           3 :                         rc = _iscsi_conn_abort_queued_datain_task(conn, task);
    1001           3 :                         if (rc != 0) {
    1002           0 :                                 return rc;
    1003             :                         }
    1004             :                 }
    1005             :         }
    1006             : 
    1007           2 :         return 0;
    1008             : }
    1009             : 
    1010             : int
    1011           0 : iscsi_conn_handle_queued_datain_tasks(struct spdk_iscsi_conn *conn)
    1012             : {
    1013             :         struct spdk_iscsi_task *task;
    1014             : 
    1015           0 :         while (!TAILQ_EMPTY(&conn->queued_datain_tasks) &&
    1016           0 :                conn->data_in_cnt < g_iscsi.MaxLargeDataInPerConnection) {
    1017           0 :                 task = TAILQ_FIRST(&conn->queued_datain_tasks);
    1018           0 :                 assert(task->current_data_offset <= task->scsi.transfer_len);
    1019           0 :                 if (task->current_data_offset < task->scsi.transfer_len) {
    1020             :                         struct spdk_iscsi_task *subtask;
    1021           0 :                         uint32_t remaining_size = 0;
    1022             : 
    1023           0 :                         remaining_size = task->scsi.transfer_len - task->current_data_offset;
    1024           0 :                         subtask = iscsi_task_get(conn, task, iscsi_task_cpl);
    1025           0 :                         assert(subtask != NULL);
    1026           0 :                         subtask->scsi.offset = task->current_data_offset;
    1027           0 :                         spdk_scsi_task_set_data(&subtask->scsi, NULL, 0);
    1028             : 
    1029           0 :                         if (spdk_scsi_dev_get_lun(conn->dev, task->lun_id) == NULL) {
    1030             :                                 /* Stop submitting split read I/Os for remaining data. */
    1031           0 :                                 TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
    1032           0 :                                 task->current_data_offset += remaining_size;
    1033           0 :                                 assert(task->current_data_offset == task->scsi.transfer_len);
    1034           0 :                                 subtask->scsi.transfer_len = remaining_size;
    1035           0 :                                 spdk_scsi_task_process_null_lun(&subtask->scsi);
    1036           0 :                                 iscsi_task_cpl(&subtask->scsi);
    1037           0 :                                 return 0;
    1038             :                         }
    1039             : 
    1040           0 :                         subtask->scsi.length = spdk_min(SPDK_BDEV_LARGE_BUF_MAX_SIZE, remaining_size);
    1041           0 :                         task->current_data_offset += subtask->scsi.length;
    1042           0 :                         iscsi_queue_task(conn, subtask);
    1043             :                 }
    1044           0 :                 if (task->current_data_offset == task->scsi.transfer_len) {
    1045           0 :                         TAILQ_REMOVE(&conn->queued_datain_tasks, task, link);
    1046             :                 }
    1047             :         }
    1048           0 :         return 0;
    1049             : }
    1050             : 
    1051             : void
    1052           0 : iscsi_task_mgmt_cpl(struct spdk_scsi_task *scsi_task)
    1053             : {
    1054           0 :         struct spdk_iscsi_task *task = iscsi_task_from_scsi_task(scsi_task);
    1055             : 
    1056           0 :         iscsi_task_mgmt_response(task->conn, task);
    1057           0 :         iscsi_task_put(task);
    1058           0 : }
    1059             : 
    1060             : static void
    1061          16 : process_completed_read_subtask_list_in_order(struct spdk_iscsi_conn *conn,
    1062             :                 struct spdk_iscsi_task *primary)
    1063             : {
    1064             :         struct spdk_iscsi_task *subtask, *tmp;
    1065             : 
    1066          42 :         TAILQ_FOREACH_SAFE(subtask, &primary->subtask_list, subtask_link, tmp) {
    1067          26 :                 if (subtask->scsi.offset == primary->bytes_completed) {
    1068          26 :                         TAILQ_REMOVE(&primary->subtask_list, subtask, subtask_link);
    1069          26 :                         primary->bytes_completed += subtask->scsi.length;
    1070          26 :                         if (primary->bytes_completed == primary->scsi.transfer_len) {
    1071           7 :                                 iscsi_task_put(primary);
    1072             :                         }
    1073          26 :                         iscsi_task_response(conn, subtask);
    1074          26 :                         iscsi_task_put(subtask);
    1075             :                 } else {
    1076           0 :                         break;
    1077             :                 }
    1078             :         }
    1079          16 : }
    1080             : 
    1081             : static void
    1082          27 : process_read_task_completion(struct spdk_iscsi_conn *conn,
    1083             :                              struct spdk_iscsi_task *task,
    1084             :                              struct spdk_iscsi_task *primary)
    1085             : {
    1086             :         struct spdk_iscsi_task *tmp;
    1087             : 
    1088          27 :         if (task->scsi.status != SPDK_SCSI_STATUS_GOOD) {
    1089           1 :                 if (primary->scsi.status == SPDK_SCSI_STATUS_GOOD) {
    1090             :                         /* If the status of the completed subtask, task, is the
    1091             :                          * first failure, copy it to out-of-order subtasks, and
    1092             :                          * remember it as the status of the SCSI Read Command.
    1093             :                          */
    1094           3 :                         TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) {
    1095           2 :                                 spdk_scsi_task_copy_status(&tmp->scsi, &task->scsi);
    1096             :                         }
    1097           1 :                         spdk_scsi_task_copy_status(&primary->scsi, &task->scsi);
    1098             :                 }
    1099          26 :         } else if (primary->scsi.status != SPDK_SCSI_STATUS_GOOD) {
    1100             :                 /* Even if the status of the completed subtask is success,
    1101             :                  * if there are any failed subtask ever, copy the first failed
    1102             :                  * status to it.
    1103             :                  */
    1104           3 :                 spdk_scsi_task_copy_status(&task->scsi, &primary->scsi);
    1105             :         }
    1106             : 
    1107          27 :         if (task == primary) {
    1108             :                 /* If read I/O size is not larger than SPDK_BDEV_LARGE_BUF_MAX_SIZE,
    1109             :                  * the primary task which processes the SCSI Read Command PDU is
    1110             :                  * submitted directly. Hence send SCSI Response PDU for the primary
    1111             :                  * task simply.
    1112             :                  */
    1113           0 :                 primary->bytes_completed = task->scsi.length;
    1114           0 :                 assert(primary->bytes_completed == task->scsi.transfer_len);
    1115           0 :                 iscsi_task_response(conn, task);
    1116           0 :                 iscsi_task_put(task);
    1117          27 :         } else if (!conn->sess->DataSequenceInOrder) {
    1118             :                 /* If DataSequenceInOrder is No, send SCSI Response PDU for the completed
    1119             :                  * subtask without any deferral.
    1120             :                  */
    1121           0 :                 primary->bytes_completed += task->scsi.length;
    1122           0 :                 if (primary->bytes_completed == primary->scsi.transfer_len) {
    1123           0 :                         iscsi_task_put(primary);
    1124             :                 }
    1125           0 :                 iscsi_task_response(conn, task);
    1126           0 :                 iscsi_task_put(task);
    1127             :         } else {
    1128             :                 /* If DataSequenceInOrder is Yes, if the completed subtask is out-of-order,
    1129             :                  * it is deferred until all preceding subtasks send SCSI Response PDU.
    1130             :                  */
    1131          27 :                 if (task->scsi.offset != primary->bytes_completed) {
    1132          11 :                         TAILQ_FOREACH(tmp, &primary->subtask_list, subtask_link) {
    1133           8 :                                 if (task->scsi.offset < tmp->scsi.offset) {
    1134           8 :                                         TAILQ_INSERT_BEFORE(tmp, task, subtask_link);
    1135           8 :                                         return;
    1136             :                                 }
    1137             :                         }
    1138             : 
    1139           3 :                         TAILQ_INSERT_TAIL(&primary->subtask_list, task, subtask_link);
    1140             :                 } else {
    1141          16 :                         TAILQ_INSERT_HEAD(&primary->subtask_list, task, subtask_link);
    1142          16 :                         process_completed_read_subtask_list_in_order(conn, primary);
    1143             :                 }
    1144             :         }
    1145             : }
    1146             : 
    1147             : static void
    1148           4 : process_non_read_task_completion(struct spdk_iscsi_conn *conn,
    1149             :                                  struct spdk_iscsi_task *task,
    1150             :                                  struct spdk_iscsi_task *primary)
    1151             : {
    1152           4 :         primary->bytes_completed += task->scsi.length;
    1153             : 
    1154           4 :         if (task == primary) {
    1155             :                 /* This was a small write with no R2T. */
    1156           0 :                 iscsi_task_response(conn, task);
    1157           0 :                 iscsi_task_put(task);
    1158           0 :                 return;
    1159             :         }
    1160             : 
    1161           4 :         if (task->scsi.status == SPDK_SCSI_STATUS_GOOD) {
    1162           3 :                 primary->scsi.data_transferred += task->scsi.data_transferred;
    1163           1 :         } else if (primary->scsi.status == SPDK_SCSI_STATUS_GOOD) {
    1164             :                 /* If the status of this subtask is the first failure, copy it to
    1165             :                  * the primary task.
    1166             :                  */
    1167           1 :                 spdk_scsi_task_copy_status(&primary->scsi, &task->scsi);
    1168             :         }
    1169             : 
    1170           4 :         if (primary->bytes_completed == primary->scsi.transfer_len) {
    1171             :                 /* If LUN is removed in the middle of the iSCSI write sequence,
    1172             :                  *  primary might complete the write to the initiator because it is not
    1173             :                  *  ensured that the initiator will send all data requested by R2Ts.
    1174             :                  *
    1175             :                  * We check it and skip the following if primary is completed. (see
    1176             :                  *  iscsi_clear_all_transfer_task() in iscsi.c.)
    1177             :                  */
    1178           2 :                 if (primary->is_r2t_active) {
    1179           1 :                         iscsi_task_response(conn, primary);
    1180           1 :                         iscsi_del_transfer_task(conn, primary->tag);
    1181             :                 } else {
    1182           1 :                         iscsi_task_response(conn, task);
    1183             :                 }
    1184             :         }
    1185           4 :         iscsi_task_put(task);
    1186             : }
    1187             : 
    1188             : void
    1189           5 : iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
    1190             : {
    1191             :         struct spdk_iscsi_task *primary;
    1192           5 :         struct spdk_iscsi_task *task = iscsi_task_from_scsi_task(scsi_task);
    1193           5 :         struct spdk_iscsi_conn *conn = task->conn;
    1194           5 :         struct spdk_iscsi_pdu *pdu = task->pdu;
    1195             : 
    1196           5 :         spdk_trace_record(TRACE_ISCSI_TASK_DONE, conn->trace_id, 0, (uintptr_t)task);
    1197             : 
    1198           5 :         task->is_queued = false;
    1199           5 :         primary = iscsi_task_get_primary(task);
    1200             : 
    1201           5 :         if (iscsi_task_is_read(primary)) {
    1202           5 :                 process_read_task_completion(conn, task, primary);
    1203             :         } else {
    1204           0 :                 process_non_read_task_completion(conn, task, primary);
    1205             :         }
    1206           5 :         if (!task->parent) {
    1207           0 :                 spdk_trace_record(TRACE_ISCSI_PDU_COMPLETED, conn->trace_id, 0, (uintptr_t)pdu);
    1208             :         }
    1209           5 : }
    1210             : 
    1211             : static void
    1212           0 : iscsi_conn_send_nopin(struct spdk_iscsi_conn *conn)
    1213             : {
    1214             :         struct spdk_iscsi_pdu *rsp_pdu;
    1215             :         struct iscsi_bhs_nop_in *rsp;
    1216             :         /* Only send nopin if we have logged in and are in a normal session. */
    1217           0 :         if (conn->sess == NULL ||
    1218           0 :             !conn->full_feature ||
    1219           0 :             !iscsi_param_eq_val(conn->sess->params, "SessionType", "Normal")) {
    1220           0 :                 return;
    1221             :         }
    1222           0 :         SPDK_DEBUGLOG(iscsi, "send NOPIN isid=%"PRIx64", tsih=%u, cid=%u\n",
    1223             :                       conn->sess->isid, conn->sess->tsih, conn->cid);
    1224           0 :         SPDK_DEBUGLOG(iscsi, "StatSN=%u, ExpCmdSN=%u, MaxCmdSN=%u\n",
    1225             :                       conn->StatSN, conn->sess->ExpCmdSN,
    1226             :                       conn->sess->MaxCmdSN);
    1227           0 :         rsp_pdu = iscsi_get_pdu(conn);
    1228           0 :         rsp = (struct iscsi_bhs_nop_in *) &rsp_pdu->bhs;
    1229           0 :         rsp_pdu->data = NULL;
    1230             :         /*
    1231             :          * iscsi_get_pdu() memset's the PDU for us, so only fill out the needed
    1232             :          *  fields.
    1233             :          */
    1234           0 :         rsp->opcode = ISCSI_OP_NOPIN;
    1235           0 :         rsp->flags = 0x80;
    1236             :         /*
    1237             :          * Technically the to_be32() is not needed here, since
    1238             :          *  to_be32(0xFFFFFFFU) returns 0xFFFFFFFFU.
    1239             :          */
    1240           0 :         to_be32(&rsp->itt, 0xFFFFFFFFU);
    1241           0 :         to_be32(&rsp->ttt, conn->id);
    1242           0 :         to_be32(&rsp->stat_sn, conn->StatSN);
    1243           0 :         to_be32(&rsp->exp_cmd_sn, conn->sess->ExpCmdSN);
    1244           0 :         to_be32(&rsp->max_cmd_sn, conn->sess->MaxCmdSN);
    1245           0 :         iscsi_conn_write_pdu(conn, rsp_pdu, iscsi_conn_pdu_generic_complete, NULL);
    1246           0 :         conn->last_nopin = spdk_get_ticks();
    1247           0 :         conn->nop_outstanding = true;
    1248             : }
    1249             : 
    1250             : void
    1251           0 : iscsi_conn_handle_nop(struct spdk_iscsi_conn *conn)
    1252             : {
    1253             :         uint64_t        tsc;
    1254             : 
    1255             :         /**
    1256             :           * This function will be executed by nop_poller of iSCSI polling group, so
    1257             :           * we need to check the connection state first, then do the nop interval
    1258             :           * expiration check work.
    1259             :           */
    1260           0 :         if ((conn->state == ISCSI_CONN_STATE_EXITED) ||
    1261           0 :             (conn->state == ISCSI_CONN_STATE_EXITING)) {
    1262           0 :                 return;
    1263             :         }
    1264             : 
    1265             :         /* Check for nop interval expiration */
    1266           0 :         tsc = spdk_get_ticks();
    1267           0 :         if (conn->nop_outstanding) {
    1268           0 :                 if ((tsc - conn->last_nopin) > conn->timeout) {
    1269           0 :                         SPDK_ERRLOG("Timed out waiting for NOP-Out response from initiator\n");
    1270           0 :                         SPDK_ERRLOG("  tsc=0x%" PRIx64 ", last_nopin=0x%" PRIx64 "\n", tsc, conn->last_nopin);
    1271           0 :                         SPDK_ERRLOG("  initiator=%s, target=%s\n", conn->initiator_name,
    1272             :                                     conn->target_short_name);
    1273           0 :                         conn->state = ISCSI_CONN_STATE_EXITING;
    1274             :                 }
    1275           0 :         } else if (tsc - conn->last_nopin > conn->nopininterval) {
    1276           0 :                 iscsi_conn_send_nopin(conn);
    1277             :         }
    1278             : }
    1279             : 
    1280             : /**
    1281             :  * \brief Reads data for the specified iSCSI connection from its TCP socket.
    1282             :  *
    1283             :  * The TCP socket is marked as non-blocking, so this function may not read
    1284             :  * all data requested.
    1285             :  *
    1286             :  * Returns SPDK_ISCSI_CONNECTION_FATAL if the recv() operation indicates a fatal
    1287             :  * error with the TCP connection (including if the TCP connection was closed
    1288             :  * unexpectedly.
    1289             :  *
    1290             :  * Otherwise returns the number of bytes successfully read.
    1291             :  */
    1292             : int
    1293           0 : iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes,
    1294             :                      void *buf)
    1295             : {
    1296             :         int ret;
    1297             : 
    1298           0 :         if (bytes == 0) {
    1299           0 :                 return 0;
    1300             :         }
    1301             : 
    1302           0 :         ret = spdk_sock_recv(conn->sock, buf, bytes);
    1303             : 
    1304           0 :         if (ret > 0) {
    1305           0 :                 spdk_trace_record(TRACE_ISCSI_READ_FROM_SOCKET_DONE, conn->trace_id, ret, 0);
    1306           0 :                 return ret;
    1307             :         }
    1308             : 
    1309           0 :         if (ret < 0) {
    1310           0 :                 if (errno == EAGAIN || errno == EWOULDBLOCK) {
    1311           0 :                         return 0;
    1312             :                 }
    1313             : 
    1314             :                 /* For connect reset issue, do not output error log */
    1315           0 :                 if (errno == ECONNRESET) {
    1316           0 :                         SPDK_DEBUGLOG(iscsi, "spdk_sock_recv() failed, errno %d: %s\n",
    1317             :                                       errno, spdk_strerror(errno));
    1318             :                 } else {
    1319           0 :                         SPDK_ERRLOG("spdk_sock_recv() failed, errno %d: %s\n",
    1320             :                                     errno, spdk_strerror(errno));
    1321             :                 }
    1322             :         }
    1323             : 
    1324             :         /* connection closed */
    1325           0 :         return SPDK_ISCSI_CONNECTION_FATAL;
    1326             : }
    1327             : 
    1328             : int
    1329           0 : iscsi_conn_readv_data(struct spdk_iscsi_conn *conn,
    1330             :                       struct iovec *iov, int iovcnt)
    1331             : {
    1332             :         int ret;
    1333             : 
    1334           0 :         if (iov == NULL || iovcnt == 0) {
    1335           0 :                 return 0;
    1336             :         }
    1337             : 
    1338           0 :         if (iovcnt == 1) {
    1339           0 :                 return iscsi_conn_read_data(conn, iov[0].iov_len,
    1340             :                                             iov[0].iov_base);
    1341             :         }
    1342             : 
    1343           0 :         ret = spdk_sock_readv(conn->sock, iov, iovcnt);
    1344             : 
    1345           0 :         if (ret > 0) {
    1346           0 :                 spdk_trace_record(TRACE_ISCSI_READ_FROM_SOCKET_DONE, conn->trace_id, ret, 0);
    1347           0 :                 return ret;
    1348             :         }
    1349             : 
    1350           0 :         if (ret < 0) {
    1351           0 :                 if (errno == EAGAIN || errno == EWOULDBLOCK) {
    1352           0 :                         return 0;
    1353             :                 }
    1354             : 
    1355             :                 /* For connect reset issue, do not output error log */
    1356           0 :                 if (errno == ECONNRESET) {
    1357           0 :                         SPDK_DEBUGLOG(iscsi, "spdk_sock_readv() failed, errno %d: %s\n",
    1358             :                                       errno, spdk_strerror(errno));
    1359             :                 } else {
    1360           0 :                         SPDK_ERRLOG("spdk_sock_readv() failed, errno %d: %s\n",
    1361             :                                     errno, spdk_strerror(errno));
    1362             :                 }
    1363             :         }
    1364             : 
    1365             :         /* connection closed */
    1366           0 :         return SPDK_ISCSI_CONNECTION_FATAL;
    1367             : }
    1368             : 
    1369             : static bool
    1370           0 : iscsi_is_free_pdu_deferred(struct spdk_iscsi_pdu *pdu)
    1371             : {
    1372           0 :         if (pdu == NULL) {
    1373           0 :                 return false;
    1374             :         }
    1375             : 
    1376           0 :         if (pdu->bhs.opcode == ISCSI_OP_R2T ||
    1377           0 :             pdu->bhs.opcode == ISCSI_OP_SCSI_DATAIN) {
    1378           0 :                 return true;
    1379             :         }
    1380             : 
    1381           0 :         return false;
    1382             : }
    1383             : 
    1384             : static int
    1385           0 : iscsi_dif_verify(struct spdk_iscsi_pdu *pdu, struct spdk_dif_ctx *dif_ctx)
    1386             : {
    1387           0 :         struct iovec iov;
    1388           0 :         struct spdk_dif_error err_blk = {};
    1389             :         uint32_t num_blocks;
    1390             :         int rc;
    1391             : 
    1392           0 :         iov.iov_base = pdu->data;
    1393           0 :         iov.iov_len = pdu->data_buf_len;
    1394           0 :         num_blocks = pdu->data_buf_len / dif_ctx->block_size;
    1395             : 
    1396           0 :         rc = spdk_dif_verify(&iov, 1, num_blocks, dif_ctx, &err_blk);
    1397           0 :         if (rc != 0) {
    1398           0 :                 SPDK_ERRLOG("DIF error detected. type=%d, offset=%" PRIu32 "\n",
    1399             :                             err_blk.err_type, err_blk.err_offset);
    1400             :         }
    1401             : 
    1402           0 :         return rc;
    1403             : }
    1404             : 
    1405             : static void
    1406           0 : _iscsi_conn_pdu_write_done(void *cb_arg, int err)
    1407             : {
    1408           0 :         struct spdk_iscsi_pdu *pdu = cb_arg;
    1409           0 :         struct spdk_iscsi_conn *conn = pdu->conn;
    1410             : 
    1411           0 :         assert(conn != NULL);
    1412             : 
    1413           0 :         if (spdk_unlikely(conn->state >= ISCSI_CONN_STATE_EXITING)) {
    1414             :                 /* The other policy will recycle the resource */
    1415           0 :                 return;
    1416             :         }
    1417             : 
    1418           0 :         TAILQ_REMOVE(&conn->write_pdu_list, pdu, tailq);
    1419             : 
    1420           0 :         if (err != 0) {
    1421           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
    1422             :         }
    1423             : 
    1424           0 :         if ((conn->full_feature) &&
    1425           0 :             (conn->sess->ErrorRecoveryLevel >= 1) &&
    1426           0 :             iscsi_is_free_pdu_deferred(pdu)) {
    1427           0 :                 SPDK_DEBUGLOG(iscsi, "stat_sn=%d\n",
    1428             :                               from_be32(&pdu->bhs.stat_sn));
    1429           0 :                 TAILQ_INSERT_TAIL(&conn->snack_pdu_list, pdu,
    1430             :                                   tailq);
    1431             :         } else {
    1432           0 :                 iscsi_conn_free_pdu(conn, pdu);
    1433             :         }
    1434             : }
    1435             : 
    1436             : void
    1437           0 : iscsi_conn_pdu_generic_complete(void *cb_arg)
    1438             : {
    1439           0 : }
    1440             : 
    1441             : void
    1442           0 : iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
    1443             :                      iscsi_conn_xfer_complete_cb cb_fn,
    1444             :                      void *cb_arg)
    1445             : {
    1446             :         uint32_t crc32c;
    1447             :         ssize_t rc;
    1448             : 
    1449           0 :         if (spdk_unlikely(pdu->dif_insert_or_strip)) {
    1450           0 :                 rc = iscsi_dif_verify(pdu, &pdu->dif_ctx);
    1451           0 :                 if (rc != 0) {
    1452           0 :                         iscsi_conn_free_pdu(conn, pdu);
    1453           0 :                         conn->state = ISCSI_CONN_STATE_EXITING;
    1454           0 :                         return;
    1455             :                 }
    1456             :         }
    1457             : 
    1458           0 :         if (pdu->bhs.opcode != ISCSI_OP_LOGIN_RSP) {
    1459             :                 /* Header Digest */
    1460           0 :                 if (conn->header_digest) {
    1461           0 :                         crc32c = iscsi_pdu_calc_header_digest(pdu);
    1462           0 :                         MAKE_DIGEST_WORD(pdu->header_digest, crc32c);
    1463             :                 }
    1464             : 
    1465             :                 /* Data Digest */
    1466           0 :                 if (conn->data_digest && DGET24(pdu->bhs.data_segment_len) != 0) {
    1467           0 :                         crc32c = iscsi_pdu_calc_data_digest(pdu);
    1468           0 :                         MAKE_DIGEST_WORD(pdu->data_digest, crc32c);
    1469             :                 }
    1470             :         }
    1471             : 
    1472           0 :         pdu->cb_fn = cb_fn;
    1473           0 :         pdu->cb_arg = cb_arg;
    1474           0 :         TAILQ_INSERT_TAIL(&conn->write_pdu_list, pdu, tailq);
    1475             : 
    1476           0 :         if (spdk_unlikely(conn->state >= ISCSI_CONN_STATE_EXITING)) {
    1477           0 :                 return;
    1478             :         }
    1479           0 :         pdu->sock_req.iovcnt = iscsi_build_iovs(conn, pdu->iov, SPDK_COUNTOF(pdu->iov), pdu,
    1480           0 :                                                 &pdu->mapped_length);
    1481           0 :         pdu->sock_req.cb_fn = _iscsi_conn_pdu_write_done;
    1482           0 :         pdu->sock_req.cb_arg = pdu;
    1483             : 
    1484           0 :         spdk_sock_writev_async(conn->sock, &pdu->sock_req);
    1485             : }
    1486             : 
    1487             : static void
    1488           0 : iscsi_conn_sock_cb(void *arg, struct spdk_sock_group *group, struct spdk_sock *sock)
    1489             : {
    1490           0 :         struct spdk_iscsi_conn *conn = arg;
    1491             :         int rc;
    1492             : 
    1493           0 :         assert(conn != NULL);
    1494             : 
    1495           0 :         if ((conn->state == ISCSI_CONN_STATE_EXITED) ||
    1496           0 :             (conn->state == ISCSI_CONN_STATE_EXITING)) {
    1497           0 :                 return;
    1498             :         }
    1499             : 
    1500             :         /* Handle incoming PDUs */
    1501           0 :         rc = iscsi_handle_incoming_pdus(conn);
    1502           0 :         if (rc < 0) {
    1503           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
    1504             :         }
    1505             : }
    1506             : 
    1507             : static void
    1508           0 : iscsi_conn_full_feature_migrate(void *arg)
    1509             : {
    1510           0 :         struct spdk_iscsi_conn *conn = arg;
    1511             :         int rc;
    1512             : 
    1513           0 :         assert(conn->state != ISCSI_CONN_STATE_EXITED);
    1514             : 
    1515             :         /* Note: it is possible that connection could have moved to EXITING
    1516             :          * state after this message was sent. We will still add it to the
    1517             :          * poll group in this case.  When the poll group is polled
    1518             :          * again, it will call iscsi_conn_destruct() on it.
    1519             :          */
    1520             : 
    1521           0 :         if (conn->sess->session_type == SESSION_TYPE_NORMAL) {
    1522           0 :                 rc = iscsi_conn_open_luns(conn);
    1523           0 :                 if (rc != 0) {
    1524             :                         /* If opening LUNs failed, it is a fatal error. At the first poll in the
    1525             :                          * assigned poll group, this connection will be destructed.
    1526             :                          */
    1527           0 :                         conn->state = ISCSI_CONN_STATE_EXITING;
    1528             :                 }
    1529             :         }
    1530             : 
    1531             :         /* Add this connection to the assigned poll group. */
    1532           0 :         iscsi_poll_group_add_conn(conn->pg, conn);
    1533           0 : }
    1534             : 
    1535             : static struct spdk_iscsi_poll_group *
    1536           0 : iscsi_get_idlest_poll_group(void)
    1537             : {
    1538           0 :         struct spdk_iscsi_poll_group *pg, *idle_pg = NULL;
    1539           0 :         uint32_t min_num_targets = UINT32_MAX;
    1540             : 
    1541           0 :         TAILQ_FOREACH(pg, &g_iscsi.poll_group_head, link) {
    1542           0 :                 if (pg->num_active_targets == 0) {
    1543           0 :                         return pg;
    1544           0 :                 } else if (pg->num_active_targets < min_num_targets) {
    1545           0 :                         min_num_targets = pg->num_active_targets;
    1546           0 :                         idle_pg = pg;
    1547             :                 }
    1548             :         }
    1549             : 
    1550           0 :         return idle_pg;
    1551             : }
    1552             : 
    1553             : void
    1554           0 : iscsi_conn_schedule(struct spdk_iscsi_conn *conn)
    1555             : {
    1556             :         struct spdk_iscsi_poll_group    *pg;
    1557             :         struct spdk_iscsi_tgt_node      *target;
    1558             : 
    1559           0 :         if (conn->sess->session_type != SESSION_TYPE_NORMAL) {
    1560             :                 /* Leave all non-normal sessions on the acceptor
    1561             :                  * thread. */
    1562           0 :                 return;
    1563             :         }
    1564           0 :         pthread_mutex_lock(&g_iscsi.mutex);
    1565             : 
    1566           0 :         target = conn->sess->target;
    1567           0 :         pthread_mutex_lock(&target->mutex);
    1568           0 :         target->num_active_conns++;
    1569           0 :         if (target->num_active_conns == 1) {
    1570             :                 /**
    1571             :                  * This is the only active connection for this target node.
    1572             :                  *  Pick the idlest poll group.
    1573             :                  */
    1574           0 :                 pg = iscsi_get_idlest_poll_group();
    1575           0 :                 assert(pg != NULL);
    1576             : 
    1577           0 :                 pg->num_active_targets++;
    1578             : 
    1579             :                 /* Save the pg in the target node so it can be used for any other connections to this target node. */
    1580           0 :                 target->pg = pg;
    1581             :         } else {
    1582             :                 /**
    1583             :                  * There are other active connections for this target node.
    1584             :                  */
    1585           0 :                 pg = target->pg;
    1586             :         }
    1587             : 
    1588           0 :         pthread_mutex_unlock(&target->mutex);
    1589           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
    1590             : 
    1591           0 :         assert(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(conn->pg)) ==
    1592             :                spdk_get_thread());
    1593             : 
    1594             :         /* Remove this connection from the previous poll group */
    1595           0 :         iscsi_poll_group_remove_conn(conn->pg, conn);
    1596             : 
    1597           0 :         conn->pg = pg;
    1598           0 :         conn->scheduled = 1;
    1599             : 
    1600           0 :         spdk_thread_send_msg(spdk_io_channel_get_thread(spdk_io_channel_from_ctx(pg)),
    1601             :                              iscsi_conn_full_feature_migrate, conn);
    1602             : }
    1603             : 
    1604             : static int
    1605           0 : logout_timeout(void *arg)
    1606             : {
    1607           0 :         struct spdk_iscsi_conn *conn = arg;
    1608             : 
    1609           0 :         if (conn->state < ISCSI_CONN_STATE_EXITING) {
    1610           0 :                 conn->state = ISCSI_CONN_STATE_EXITING;
    1611             :         }
    1612             : 
    1613           0 :         spdk_poller_unregister(&conn->logout_timer);
    1614             : 
    1615           0 :         return SPDK_POLLER_BUSY;
    1616             : }
    1617             : 
    1618             : void
    1619           0 : iscsi_conn_logout(struct spdk_iscsi_conn *conn)
    1620             : {
    1621           0 :         conn->is_logged_out = true;
    1622           0 :         conn->logout_timer = SPDK_POLLER_REGISTER(logout_timeout, conn, ISCSI_LOGOUT_TIMEOUT * 1000000);
    1623           0 : }
    1624             : 
    1625             : static const char *
    1626           0 : iscsi_conn_get_state(struct spdk_iscsi_conn *conn)
    1627             : {
    1628           0 :         switch (conn->state) {
    1629           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_CONN_STATE_INVALID, "invalid");
    1630           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_CONN_STATE_RUNNING, "running");
    1631           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_CONN_STATE_EXITING, "exiting");
    1632           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_CONN_STATE_EXITED, "exited");
    1633             :         }
    1634           0 :         return "unknown";
    1635             : }
    1636             : 
    1637             : static const char *
    1638           0 : iscsi_conn_get_login_phase(struct spdk_iscsi_conn *conn)
    1639             : {
    1640           0 :         switch (conn->login_phase) {
    1641           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_SECURITY_NEGOTIATION_PHASE, "security_negotiation_phase");
    1642           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_OPERATIONAL_NEGOTIATION_PHASE, "operational_negotiation_phase");
    1643           0 :                 SPDK_ISCSI_CONNECTION_STATUS(ISCSI_FULL_FEATURE_PHASE, "full_feature_phase");
    1644             :         }
    1645           0 :         return "not_started";
    1646             : }
    1647             : 
    1648             : static void
    1649           0 : iscsi_conn_trace(void)
    1650             : {
    1651           0 :         spdk_trace_register_owner_type(OWNER_TYPE_ISCSI_CONN, 'c');
    1652           0 :         spdk_trace_register_object(OBJECT_ISCSI_PDU, 'p');
    1653           0 :         spdk_trace_register_description("ISCSI_READ_DONE", TRACE_ISCSI_READ_FROM_SOCKET_DONE,
    1654             :                                         OWNER_TYPE_ISCSI_CONN, OBJECT_NONE, 0,
    1655             :                                         SPDK_TRACE_ARG_TYPE_INT, "");
    1656           0 :         spdk_trace_register_description("ISCSI_READ_PDU", TRACE_ISCSI_READ_PDU,
    1657             :                                         OWNER_TYPE_ISCSI_CONN, OBJECT_ISCSI_PDU, 1,
    1658             :                                         SPDK_TRACE_ARG_TYPE_INT, "opc");
    1659           0 :         spdk_trace_register_description("ISCSI_TASK_DONE", TRACE_ISCSI_TASK_DONE,
    1660             :                                         OWNER_TYPE_ISCSI_CONN, OBJECT_SCSI_TASK, 0,
    1661             :                                         SPDK_TRACE_ARG_TYPE_INT, "");
    1662           0 :         spdk_trace_register_description("ISCSI_TASK_QUEUE", TRACE_ISCSI_TASK_QUEUE,
    1663             :                                         OWNER_TYPE_ISCSI_CONN, OBJECT_SCSI_TASK, 1,
    1664             :                                         SPDK_TRACE_ARG_TYPE_PTR, "pdu");
    1665           0 :         spdk_trace_register_description("ISCSI_TASK_EXECUTED", TRACE_ISCSI_TASK_EXECUTED,
    1666             :                                         OWNER_TYPE_ISCSI_CONN, OBJECT_ISCSI_PDU, 0,
    1667             :                                         SPDK_TRACE_ARG_TYPE_INT, "");
    1668           0 :         spdk_trace_register_description("ISCSI_PDU_COMPLETED", TRACE_ISCSI_PDU_COMPLETED,
    1669             :                                         OWNER_TYPE_ISCSI_CONN, OBJECT_ISCSI_PDU, 0,
    1670             :                                         SPDK_TRACE_ARG_TYPE_INT, "");
    1671           0 :         spdk_trace_tpoint_register_relation(TRACE_SOCK_REQ_QUEUE, OBJECT_ISCSI_PDU, 0);
    1672           0 :         spdk_trace_tpoint_register_relation(TRACE_SOCK_REQ_PEND, OBJECT_ISCSI_PDU, 0);
    1673           0 :         spdk_trace_tpoint_register_relation(TRACE_SOCK_REQ_COMPLETE, OBJECT_ISCSI_PDU, 0);
    1674           0 : }
    1675           1 : SPDK_TRACE_REGISTER_FN(iscsi_conn_trace, "iscsi_conn", TRACE_GROUP_ISCSI)
    1676             : 
    1677             : void
    1678           0 : iscsi_conn_info_json(struct spdk_json_write_ctx *w, struct spdk_iscsi_conn *conn)
    1679             : {
    1680             :         uint16_t tsih;
    1681             : 
    1682           0 :         if (!conn->is_valid) {
    1683           0 :                 return;
    1684             :         }
    1685             : 
    1686           0 :         spdk_json_write_object_begin(w);
    1687             : 
    1688           0 :         spdk_json_write_named_int32(w, "id", conn->id);
    1689             : 
    1690           0 :         spdk_json_write_named_int32(w, "cid", conn->cid);
    1691             : 
    1692             :         /*
    1693             :          * If we try to return data for a connection that has not
    1694             :          *  logged in yet, the session will not be set.  So in this
    1695             :          *  case, return -1 for the tsih rather than segfaulting
    1696             :          *  on the null conn->sess.
    1697             :          */
    1698           0 :         if (conn->sess == NULL) {
    1699           0 :                 tsih = -1;
    1700             :         } else {
    1701           0 :                 tsih = conn->sess->tsih;
    1702             :         }
    1703           0 :         spdk_json_write_named_int32(w, "tsih", tsih);
    1704             : 
    1705           0 :         spdk_json_write_named_string(w, "state", iscsi_conn_get_state(conn));
    1706             : 
    1707           0 :         spdk_json_write_named_string(w, "login_phase", iscsi_conn_get_login_phase(conn));
    1708             : 
    1709           0 :         spdk_json_write_named_string(w, "initiator_addr", conn->initiator_addr);
    1710             : 
    1711           0 :         spdk_json_write_named_string(w, "target_addr", conn->target_addr);
    1712             : 
    1713           0 :         spdk_json_write_named_string(w, "target_node_name", conn->target_short_name);
    1714             : 
    1715           0 :         spdk_json_write_named_string(w, "thread_name",
    1716           0 :                                      spdk_thread_get_name(spdk_get_thread()));
    1717             : 
    1718           0 :         spdk_json_write_object_end(w);
    1719             : }

Generated by: LCOV version 1.15