LCOV - code coverage report
Current view: top level - lib/iscsi - iscsi_subsystem.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 706 0.0 %
Date: 2024-12-02 01:43:33 Functions: 0 54 0.0 %

          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/string.h"
       8             : #include "spdk/likely.h"
       9             : 
      10             : #include "iscsi/iscsi.h"
      11             : #include "iscsi/init_grp.h"
      12             : #include "iscsi/portal_grp.h"
      13             : #include "iscsi/conn.h"
      14             : #include "iscsi/task.h"
      15             : #include "iscsi/tgt_node.h"
      16             : 
      17             : #include "spdk/log.h"
      18             : 
      19             : struct spdk_iscsi_opts *g_spdk_iscsi_opts = NULL;
      20             : 
      21             : static struct spdk_thread *g_init_thread = NULL;
      22             : static spdk_iscsi_init_cb g_init_cb_fn = NULL;
      23             : static void *g_init_cb_arg = NULL;
      24             : 
      25             : static spdk_iscsi_fini_cb g_fini_cb_fn;
      26             : static void *g_fini_cb_arg;
      27             : 
      28             : #define ISCSI_DATA_BUFFER_ALIGNMENT     (0x1000)
      29             : #define ISCSI_DATA_BUFFER_MASK          (ISCSI_DATA_BUFFER_ALIGNMENT - 1)
      30             : 
      31             : static void
      32           0 : mobj_ctor(struct spdk_mempool *mp, __attribute__((unused)) void *arg,
      33             :           void *_m, __attribute__((unused)) unsigned i)
      34             : {
      35           0 :         struct spdk_mobj *m = _m;
      36             : 
      37           0 :         m->mp = mp;
      38           0 :         m->buf = (uint8_t *)m + sizeof(struct spdk_mobj);
      39           0 :         m->buf = (void *)((uintptr_t)((uint8_t *)m->buf + ISCSI_DATA_BUFFER_ALIGNMENT) &
      40             :                           ~ISCSI_DATA_BUFFER_MASK);
      41           0 : }
      42             : 
      43             : static int
      44           0 : iscsi_initialize_pdu_pool(void)
      45             : {
      46           0 :         struct spdk_iscsi_globals *iscsi = &g_iscsi;
      47           0 :         int imm_mobj_size = SPDK_BDEV_BUF_SIZE_WITH_MD(iscsi_get_max_immediate_data_size()) +
      48           0 :                             sizeof(struct spdk_mobj) + ISCSI_DATA_BUFFER_ALIGNMENT;
      49           0 :         int dout_mobj_size = SPDK_BDEV_BUF_SIZE_WITH_MD(SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH) +
      50             :                              sizeof(struct spdk_mobj) + ISCSI_DATA_BUFFER_ALIGNMENT;
      51             : 
      52             :         /* create PDU pool */
      53           0 :         iscsi->pdu_pool = spdk_mempool_create("PDU_Pool",
      54           0 :                                               iscsi->pdu_pool_size,
      55             :                                               sizeof(struct spdk_iscsi_pdu),
      56             :                                               256, SPDK_ENV_NUMA_ID_ANY);
      57           0 :         if (!iscsi->pdu_pool) {
      58           0 :                 if (spdk_mempool_lookup("PDU_Pool") != NULL) {
      59           0 :                         SPDK_ERRLOG("Cannot create PDU pool: already exists\n");
      60           0 :                         SPDK_ERRLOG("Probably running in multiprocess environment, which is "
      61             :                                     "unsupported by the iSCSI library\n");
      62             :                 } else {
      63           0 :                         SPDK_ERRLOG("create PDU pool failed\n");
      64             :                 }
      65           0 :                 return -1;
      66             :         }
      67             : 
      68           0 :         iscsi->pdu_immediate_data_pool = spdk_mempool_create_ctor("PDU_immediate_data_Pool",
      69           0 :                                          iscsi->immediate_data_pool_size,
      70             :                                          imm_mobj_size, 256,
      71             :                                          SPDK_ENV_NUMA_ID_ANY,
      72             :                                          mobj_ctor, NULL);
      73           0 :         if (!iscsi->pdu_immediate_data_pool) {
      74           0 :                 SPDK_ERRLOG("create PDU immediate data pool failed\n");
      75           0 :                 return -1;
      76             :         }
      77             : 
      78           0 :         iscsi->pdu_data_out_pool = spdk_mempool_create_ctor("PDU_data_out_Pool",
      79           0 :                                    iscsi->data_out_pool_size,
      80             :                                    dout_mobj_size, 256,
      81             :                                    SPDK_ENV_NUMA_ID_ANY,
      82             :                                    mobj_ctor, NULL);
      83           0 :         if (!iscsi->pdu_data_out_pool) {
      84           0 :                 SPDK_ERRLOG("create PDU data out pool failed\n");
      85           0 :                 return -1;
      86             :         }
      87             : 
      88           0 :         return 0;
      89             : }
      90             : 
      91             : static void
      92           0 : iscsi_sess_ctor(struct spdk_mempool *pool, void *arg, void *session_buf,
      93             :                 unsigned index)
      94             : {
      95           0 :         struct spdk_iscsi_globals               *iscsi = arg;
      96           0 :         struct spdk_iscsi_sess  *sess = session_buf;
      97             : 
      98           0 :         iscsi->session[index] = sess;
      99             : 
     100             :         /* tsih 0 is reserved, so start tsih values at 1. */
     101           0 :         sess->tsih = index + 1;
     102           0 : }
     103             : 
     104             : #define DEFAULT_TASK_POOL_SIZE 32768
     105             : 
     106             : static int
     107           0 : iscsi_initialize_task_pool(void)
     108             : {
     109           0 :         struct spdk_iscsi_globals *iscsi = &g_iscsi;
     110             : 
     111             :         /* create scsi_task pool */
     112           0 :         iscsi->task_pool = spdk_mempool_create("SCSI_TASK_Pool",
     113             :                                                DEFAULT_TASK_POOL_SIZE,
     114             :                                                sizeof(struct spdk_iscsi_task),
     115             :                                                128, SPDK_ENV_NUMA_ID_ANY);
     116           0 :         if (!iscsi->task_pool) {
     117           0 :                 SPDK_ERRLOG("create task pool failed\n");
     118           0 :                 return -1;
     119             :         }
     120             : 
     121           0 :         return 0;
     122             : }
     123             : 
     124             : #define SESSION_POOL_SIZE(iscsi)        (iscsi->MaxSessions)
     125             : static int
     126           0 : iscsi_initialize_session_pool(void)
     127             : {
     128           0 :         struct spdk_iscsi_globals *iscsi = &g_iscsi;
     129             : 
     130           0 :         iscsi->session_pool = spdk_mempool_create_ctor("Session_Pool",
     131           0 :                               SESSION_POOL_SIZE(iscsi),
     132             :                               sizeof(struct spdk_iscsi_sess), 0,
     133             :                               SPDK_ENV_NUMA_ID_ANY,
     134             :                               iscsi_sess_ctor, iscsi);
     135           0 :         if (!iscsi->session_pool) {
     136           0 :                 SPDK_ERRLOG("create session pool failed\n");
     137           0 :                 return -1;
     138             :         }
     139             : 
     140           0 :         return 0;
     141             : }
     142             : 
     143             : static int
     144           0 : iscsi_initialize_all_pools(void)
     145             : {
     146           0 :         if (iscsi_initialize_pdu_pool() != 0) {
     147           0 :                 return -1;
     148             :         }
     149             : 
     150           0 :         if (iscsi_initialize_session_pool() != 0) {
     151           0 :                 return -1;
     152             :         }
     153             : 
     154           0 :         if (iscsi_initialize_task_pool() != 0) {
     155           0 :                 return -1;
     156             :         }
     157             : 
     158           0 :         return 0;
     159             : }
     160             : 
     161             : static void
     162           0 : iscsi_check_pool(struct spdk_mempool *pool, size_t count)
     163             : {
     164           0 :         if (pool && spdk_mempool_count(pool) != count) {
     165           0 :                 SPDK_ERRLOG("spdk_mempool_count(%s) == %zu, should be %zu\n",
     166             :                             spdk_mempool_get_name(pool), spdk_mempool_count(pool), count);
     167             :         }
     168           0 : }
     169             : 
     170             : static void
     171           0 : iscsi_check_pools(void)
     172             : {
     173           0 :         struct spdk_iscsi_globals *iscsi = &g_iscsi;
     174             : 
     175           0 :         iscsi_check_pool(iscsi->pdu_pool, iscsi->pdu_pool_size);
     176           0 :         iscsi_check_pool(iscsi->session_pool, SESSION_POOL_SIZE(iscsi));
     177           0 :         iscsi_check_pool(iscsi->pdu_immediate_data_pool, iscsi->immediate_data_pool_size);
     178           0 :         iscsi_check_pool(iscsi->pdu_data_out_pool, iscsi->data_out_pool_size);
     179           0 :         iscsi_check_pool(iscsi->task_pool, DEFAULT_TASK_POOL_SIZE);
     180           0 : }
     181             : 
     182             : static void
     183           0 : iscsi_free_pools(void)
     184             : {
     185           0 :         struct spdk_iscsi_globals *iscsi = &g_iscsi;
     186             : 
     187           0 :         spdk_mempool_free(iscsi->pdu_pool);
     188           0 :         spdk_mempool_free(iscsi->session_pool);
     189           0 :         spdk_mempool_free(iscsi->pdu_immediate_data_pool);
     190           0 :         spdk_mempool_free(iscsi->pdu_data_out_pool);
     191           0 :         spdk_mempool_free(iscsi->task_pool);
     192           0 : }
     193             : 
     194             : void
     195           0 : iscsi_put_pdu(struct spdk_iscsi_pdu *pdu)
     196             : {
     197           0 :         if (!pdu) {
     198           0 :                 return;
     199             :         }
     200             : 
     201           0 :         assert(pdu->ref > 0);
     202           0 :         pdu->ref--;
     203             : 
     204           0 :         if (pdu->ref == 0) {
     205           0 :                 if (pdu->mobj[0]) {
     206           0 :                         iscsi_datapool_put(pdu->mobj[0]);
     207             :                 }
     208           0 :                 if (pdu->mobj[1]) {
     209           0 :                         iscsi_datapool_put(pdu->mobj[1]);
     210             :                 }
     211             : 
     212           0 :                 if (pdu->data && !pdu->data_from_mempool) {
     213           0 :                         free(pdu->data);
     214             :                 }
     215             : 
     216           0 :                 spdk_mempool_put(g_iscsi.pdu_pool, (void *)pdu);
     217             :         }
     218             : }
     219             : 
     220           0 : struct spdk_iscsi_pdu *iscsi_get_pdu(struct spdk_iscsi_conn *conn)
     221             : {
     222             :         struct spdk_iscsi_pdu *pdu;
     223             : 
     224           0 :         assert(conn != NULL);
     225           0 :         pdu = spdk_mempool_get(g_iscsi.pdu_pool);
     226           0 :         if (!pdu) {
     227           0 :                 SPDK_ERRLOG("Unable to get PDU\n");
     228           0 :                 abort();
     229             :         }
     230             : 
     231             :         /* we do not want to zero out the last part of the structure reserved for AHS and sense data */
     232           0 :         memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs));
     233           0 :         pdu->ref = 1;
     234           0 :         pdu->conn = conn;
     235             :         /* Initialize CRC. */
     236           0 :         pdu->crc32c = SPDK_CRC32C_INITIAL;
     237             : 
     238           0 :         return pdu;
     239             : }
     240             : 
     241             : static void
     242           0 : iscsi_log_globals(void)
     243             : {
     244           0 :         SPDK_DEBUGLOG(iscsi, "AuthFile %s\n",
     245             :                       g_iscsi.authfile ? g_iscsi.authfile : "(none)");
     246           0 :         SPDK_DEBUGLOG(iscsi, "NodeBase %s\n", g_iscsi.nodebase);
     247           0 :         SPDK_DEBUGLOG(iscsi, "MaxSessions %d\n", g_iscsi.MaxSessions);
     248           0 :         SPDK_DEBUGLOG(iscsi, "MaxConnectionsPerSession %d\n",
     249             :                       g_iscsi.MaxConnectionsPerSession);
     250           0 :         SPDK_DEBUGLOG(iscsi, "MaxQueueDepth %d\n", g_iscsi.MaxQueueDepth);
     251           0 :         SPDK_DEBUGLOG(iscsi, "DefaultTime2Wait %d\n",
     252             :                       g_iscsi.DefaultTime2Wait);
     253           0 :         SPDK_DEBUGLOG(iscsi, "DefaultTime2Retain %d\n",
     254             :                       g_iscsi.DefaultTime2Retain);
     255           0 :         SPDK_DEBUGLOG(iscsi, "FirstBurstLength %d\n",
     256             :                       g_iscsi.FirstBurstLength);
     257           0 :         SPDK_DEBUGLOG(iscsi, "ImmediateData %s\n",
     258             :                       g_iscsi.ImmediateData ? "Yes" : "No");
     259           0 :         SPDK_DEBUGLOG(iscsi, "AllowDuplicateIsid %s\n",
     260             :                       g_iscsi.AllowDuplicateIsid ? "Yes" : "No");
     261           0 :         SPDK_DEBUGLOG(iscsi, "ErrorRecoveryLevel %d\n",
     262             :                       g_iscsi.ErrorRecoveryLevel);
     263           0 :         SPDK_DEBUGLOG(iscsi, "Timeout %d\n", g_iscsi.timeout);
     264           0 :         SPDK_DEBUGLOG(iscsi, "NopInInterval %d\n",
     265             :                       g_iscsi.nopininterval);
     266           0 :         if (g_iscsi.disable_chap) {
     267           0 :                 SPDK_DEBUGLOG(iscsi,
     268             :                               "DiscoveryAuthMethod None\n");
     269           0 :         } else if (!g_iscsi.require_chap) {
     270           0 :                 SPDK_DEBUGLOG(iscsi,
     271             :                               "DiscoveryAuthMethod Auto\n");
     272             :         } else {
     273           0 :                 SPDK_DEBUGLOG(iscsi,
     274             :                               "DiscoveryAuthMethod %s %s\n",
     275             :                               g_iscsi.require_chap ? "CHAP" : "",
     276             :                               g_iscsi.mutual_chap ? "Mutual" : "");
     277             :         }
     278             : 
     279           0 :         if (g_iscsi.chap_group == 0) {
     280           0 :                 SPDK_DEBUGLOG(iscsi,
     281             :                               "DiscoveryAuthGroup None\n");
     282             :         } else {
     283           0 :                 SPDK_DEBUGLOG(iscsi,
     284             :                               "DiscoveryAuthGroup AuthGroup%d\n",
     285             :                               g_iscsi.chap_group);
     286             :         }
     287             : 
     288           0 :         SPDK_DEBUGLOG(iscsi, "MaxLargeDataInPerConnection %d\n",
     289             :                       g_iscsi.MaxLargeDataInPerConnection);
     290             : 
     291           0 :         SPDK_DEBUGLOG(iscsi, "MaxR2TPerConnection %d\n",
     292             :                       g_iscsi.MaxR2TPerConnection);
     293           0 : }
     294             : 
     295             : #define NUM_PDU_PER_CONNECTION(opts)    (2 * (opts->MaxQueueDepth +  \
     296             :                                          opts->MaxLargeDataInPerConnection + \
     297             :                                          2 * opts->MaxR2TPerConnection + 8))
     298             : #define PDU_POOL_SIZE(opts)             (opts->MaxSessions * NUM_PDU_PER_CONNECTION(opts))
     299             : #define IMMEDIATE_DATA_POOL_SIZE(opts)  (opts->MaxSessions * 128)
     300             : #define DATA_OUT_POOL_SIZE(opts)        (opts->MaxSessions * MAX_DATA_OUT_PER_CONNECTION)
     301             : 
     302             : static void
     303           0 : iscsi_opts_init(struct spdk_iscsi_opts *opts)
     304             : {
     305           0 :         opts->MaxSessions = DEFAULT_MAX_SESSIONS;
     306           0 :         opts->MaxConnectionsPerSession = DEFAULT_MAX_CONNECTIONS_PER_SESSION;
     307           0 :         opts->MaxQueueDepth = DEFAULT_MAX_QUEUE_DEPTH;
     308           0 :         opts->DefaultTime2Wait = DEFAULT_DEFAULTTIME2WAIT;
     309           0 :         opts->DefaultTime2Retain = DEFAULT_DEFAULTTIME2RETAIN;
     310           0 :         opts->FirstBurstLength = SPDK_ISCSI_FIRST_BURST_LENGTH;
     311           0 :         opts->ImmediateData = DEFAULT_IMMEDIATEDATA;
     312           0 :         opts->AllowDuplicateIsid = false;
     313           0 :         opts->ErrorRecoveryLevel = DEFAULT_ERRORRECOVERYLEVEL;
     314           0 :         opts->timeout = DEFAULT_TIMEOUT;
     315           0 :         opts->nopininterval = DEFAULT_NOPININTERVAL;
     316           0 :         opts->disable_chap = false;
     317           0 :         opts->require_chap = false;
     318           0 :         opts->mutual_chap = false;
     319           0 :         opts->chap_group = 0;
     320           0 :         opts->authfile = NULL;
     321           0 :         opts->nodebase = NULL;
     322           0 :         opts->MaxLargeDataInPerConnection = DEFAULT_MAX_LARGE_DATAIN_PER_CONNECTION;
     323           0 :         opts->MaxR2TPerConnection = DEFAULT_MAXR2T;
     324           0 :         opts->pdu_pool_size = PDU_POOL_SIZE(opts);
     325           0 :         opts->immediate_data_pool_size = IMMEDIATE_DATA_POOL_SIZE(opts);
     326           0 :         opts->data_out_pool_size = DATA_OUT_POOL_SIZE(opts);
     327           0 : }
     328             : 
     329             : struct spdk_iscsi_opts *
     330           0 : iscsi_opts_alloc(void)
     331             : {
     332             :         struct spdk_iscsi_opts *opts;
     333             : 
     334           0 :         opts = calloc(1, sizeof(*opts));
     335           0 :         if (!opts) {
     336           0 :                 SPDK_ERRLOG("calloc() failed for iscsi options\n");
     337           0 :                 return NULL;
     338             :         }
     339             : 
     340           0 :         iscsi_opts_init(opts);
     341             : 
     342           0 :         return opts;
     343             : }
     344             : 
     345             : void
     346           0 : iscsi_opts_free(struct spdk_iscsi_opts *opts)
     347             : {
     348           0 :         free(opts->authfile);
     349           0 :         free(opts->nodebase);
     350           0 :         free(opts);
     351           0 : }
     352             : 
     353             : /* Deep copy of spdk_iscsi_opts */
     354             : struct spdk_iscsi_opts *
     355           0 : iscsi_opts_copy(struct spdk_iscsi_opts *src)
     356             : {
     357             :         struct spdk_iscsi_opts *dst;
     358             : 
     359           0 :         dst = calloc(1, sizeof(*dst));
     360           0 :         if (!dst) {
     361           0 :                 SPDK_ERRLOG("calloc() failed for iscsi options\n");
     362           0 :                 return NULL;
     363             :         }
     364             : 
     365           0 :         if (src->authfile) {
     366           0 :                 dst->authfile = strdup(src->authfile);
     367           0 :                 if (!dst->authfile) {
     368           0 :                         free(dst);
     369           0 :                         SPDK_ERRLOG("failed to strdup for auth file %s\n", src->authfile);
     370           0 :                         return NULL;
     371             :                 }
     372             :         }
     373             : 
     374           0 :         if (src->nodebase) {
     375           0 :                 dst->nodebase = strdup(src->nodebase);
     376           0 :                 if (!dst->nodebase) {
     377           0 :                         free(dst->authfile);
     378           0 :                         free(dst);
     379           0 :                         SPDK_ERRLOG("failed to strdup for nodebase %s\n", src->nodebase);
     380           0 :                         return NULL;
     381             :                 }
     382             :         }
     383             : 
     384           0 :         dst->MaxSessions = src->MaxSessions;
     385           0 :         dst->MaxConnectionsPerSession = src->MaxConnectionsPerSession;
     386           0 :         dst->MaxQueueDepth = src->MaxQueueDepth;
     387           0 :         dst->DefaultTime2Wait = src->DefaultTime2Wait;
     388           0 :         dst->DefaultTime2Retain = src->DefaultTime2Retain;
     389           0 :         dst->FirstBurstLength = src->FirstBurstLength;
     390           0 :         dst->ImmediateData = src->ImmediateData;
     391           0 :         dst->AllowDuplicateIsid = src->AllowDuplicateIsid;
     392           0 :         dst->ErrorRecoveryLevel = src->ErrorRecoveryLevel;
     393           0 :         dst->timeout = src->timeout;
     394           0 :         dst->nopininterval = src->nopininterval;
     395           0 :         dst->disable_chap = src->disable_chap;
     396           0 :         dst->require_chap = src->require_chap;
     397           0 :         dst->mutual_chap = src->mutual_chap;
     398           0 :         dst->chap_group = src->chap_group;
     399           0 :         dst->MaxLargeDataInPerConnection = src->MaxLargeDataInPerConnection;
     400           0 :         dst->MaxR2TPerConnection = src->MaxR2TPerConnection;
     401           0 :         dst->pdu_pool_size = src->pdu_pool_size;
     402           0 :         dst->immediate_data_pool_size = src->immediate_data_pool_size;
     403           0 :         dst->data_out_pool_size = src->data_out_pool_size;
     404             : 
     405           0 :         return dst;
     406             : }
     407             : 
     408             : static int
     409           0 : iscsi_opts_verify(struct spdk_iscsi_opts *opts)
     410             : {
     411           0 :         if (!opts->nodebase) {
     412           0 :                 opts->nodebase = strdup(SPDK_ISCSI_DEFAULT_NODEBASE);
     413           0 :                 if (opts->nodebase == NULL) {
     414           0 :                         SPDK_ERRLOG("strdup() failed for default nodebase\n");
     415           0 :                         return -ENOMEM;
     416             :                 }
     417             :         }
     418             : 
     419           0 :         if (opts->MaxSessions == 0 || opts->MaxSessions > 65535) {
     420           0 :                 SPDK_ERRLOG("%d is invalid. MaxSessions must be more than 0 and no more than 65535\n",
     421             :                             opts->MaxSessions);
     422           0 :                 return -EINVAL;
     423             :         }
     424             : 
     425           0 :         if (opts->MaxConnectionsPerSession == 0 || opts->MaxConnectionsPerSession > 65535) {
     426           0 :                 SPDK_ERRLOG("%d is invalid. MaxConnectionsPerSession must be more than 0 and no more than 65535\n",
     427             :                             opts->MaxConnectionsPerSession);
     428           0 :                 return -EINVAL;
     429             :         }
     430             : 
     431           0 :         if (opts->MaxQueueDepth == 0 || opts->MaxQueueDepth > 256) {
     432           0 :                 SPDK_ERRLOG("%d is invalid. MaxQueueDepth must be more than 0 and no more than 256\n",
     433             :                             opts->MaxQueueDepth);
     434           0 :                 return -EINVAL;
     435             :         }
     436             : 
     437           0 :         if (opts->DefaultTime2Wait > 3600) {
     438           0 :                 SPDK_ERRLOG("%d is invalid. DefaultTime2Wait must be no more than 3600\n",
     439             :                             opts->DefaultTime2Wait);
     440           0 :                 return -EINVAL;
     441             :         }
     442             : 
     443           0 :         if (opts->DefaultTime2Retain > 3600) {
     444           0 :                 SPDK_ERRLOG("%d is invalid. DefaultTime2Retain must be no more than 3600\n",
     445             :                             opts->DefaultTime2Retain);
     446           0 :                 return -EINVAL;
     447             :         }
     448             : 
     449           0 :         if (opts->FirstBurstLength >= SPDK_ISCSI_MIN_FIRST_BURST_LENGTH) {
     450           0 :                 if (opts->FirstBurstLength > SPDK_ISCSI_MAX_BURST_LENGTH) {
     451           0 :                         SPDK_ERRLOG("FirstBurstLength %d shall not exceed MaxBurstLength %d\n",
     452             :                                     opts->FirstBurstLength, SPDK_ISCSI_MAX_BURST_LENGTH);
     453           0 :                         return -EINVAL;
     454             :                 }
     455             :         } else {
     456           0 :                 SPDK_ERRLOG("FirstBurstLength %d shall be no less than %d\n",
     457             :                             opts->FirstBurstLength, SPDK_ISCSI_MIN_FIRST_BURST_LENGTH);
     458           0 :                 return -EINVAL;
     459             :         }
     460             : 
     461           0 :         if (opts->ErrorRecoveryLevel > 2) {
     462           0 :                 SPDK_ERRLOG("ErrorRecoveryLevel %d is not supported.\n", opts->ErrorRecoveryLevel);
     463           0 :                 return -EINVAL;
     464             :         }
     465             : 
     466           0 :         if (opts->timeout < 0) {
     467           0 :                 SPDK_ERRLOG("%d is invalid. timeout must not be less than 0\n", opts->timeout);
     468           0 :                 return -EINVAL;
     469             :         }
     470             : 
     471           0 :         if (opts->nopininterval < 0 || opts->nopininterval > MAX_NOPININTERVAL) {
     472           0 :                 SPDK_ERRLOG("%d is invalid. nopinterval must be between 0 and %d\n",
     473             :                             opts->nopininterval, MAX_NOPININTERVAL);
     474           0 :                 return -EINVAL;
     475             :         }
     476             : 
     477           0 :         if (!iscsi_check_chap_params(opts->disable_chap, opts->require_chap,
     478           0 :                                      opts->mutual_chap, opts->chap_group)) {
     479           0 :                 SPDK_ERRLOG("CHAP params in opts are illegal combination\n");
     480           0 :                 return -EINVAL;
     481             :         }
     482             : 
     483           0 :         if (opts->MaxLargeDataInPerConnection == 0) {
     484           0 :                 SPDK_ERRLOG("0 is invalid. MaxLargeDataInPerConnection must be more than 0\n");
     485           0 :                 return -EINVAL;
     486             :         }
     487             : 
     488           0 :         if (opts->MaxR2TPerConnection == 0) {
     489           0 :                 SPDK_ERRLOG("0 is invalid. MaxR2TPerConnection must be more than 0\n");
     490           0 :                 return -EINVAL;
     491             :         }
     492             : 
     493           0 :         if (opts->pdu_pool_size == 0) {
     494           0 :                 SPDK_ERRLOG("0 is invalid. pdu_pool_size must be more than 0\n");
     495           0 :                 return -EINVAL;
     496             :         }
     497             : 
     498           0 :         if (opts->immediate_data_pool_size == 0) {
     499           0 :                 SPDK_ERRLOG("0 is invalid. immediate_data_pool_size must be more than 0\n");
     500           0 :                 return -EINVAL;
     501             :         }
     502             : 
     503           0 :         if (opts->data_out_pool_size == 0) {
     504           0 :                 SPDK_ERRLOG("0 is invalid. data_out_pool_size must be more than 0\n");
     505           0 :                 return -EINVAL;
     506             :         }
     507             : 
     508           0 :         return 0;
     509             : }
     510             : 
     511             : static int
     512           0 : iscsi_set_global_params(struct spdk_iscsi_opts *opts)
     513             : {
     514             :         int rc;
     515             : 
     516           0 :         rc = iscsi_opts_verify(opts);
     517           0 :         if (rc != 0) {
     518           0 :                 SPDK_ERRLOG("spdk_iscsi_opts_verify() failed\n");
     519           0 :                 return rc;
     520             :         }
     521             : 
     522           0 :         if (opts->authfile != NULL) {
     523           0 :                 g_iscsi.authfile = strdup(opts->authfile);
     524           0 :                 if (!g_iscsi.authfile) {
     525           0 :                         SPDK_ERRLOG("failed to strdup for auth file %s\n", opts->authfile);
     526           0 :                         return -ENOMEM;
     527             :                 }
     528             :         }
     529             : 
     530           0 :         g_iscsi.nodebase = strdup(opts->nodebase);
     531           0 :         if (!g_iscsi.nodebase) {
     532           0 :                 SPDK_ERRLOG("failed to strdup for nodebase %s\n", opts->nodebase);
     533           0 :                 return -ENOMEM;
     534             :         }
     535             : 
     536           0 :         g_iscsi.MaxSessions = opts->MaxSessions;
     537           0 :         g_iscsi.MaxConnectionsPerSession = opts->MaxConnectionsPerSession;
     538           0 :         g_iscsi.MaxQueueDepth = opts->MaxQueueDepth;
     539           0 :         g_iscsi.DefaultTime2Wait = opts->DefaultTime2Wait;
     540           0 :         g_iscsi.DefaultTime2Retain = opts->DefaultTime2Retain;
     541           0 :         g_iscsi.FirstBurstLength = opts->FirstBurstLength;
     542           0 :         g_iscsi.ImmediateData = opts->ImmediateData;
     543           0 :         g_iscsi.AllowDuplicateIsid = opts->AllowDuplicateIsid;
     544           0 :         g_iscsi.ErrorRecoveryLevel = opts->ErrorRecoveryLevel;
     545           0 :         g_iscsi.timeout = opts->timeout;
     546           0 :         g_iscsi.nopininterval = opts->nopininterval;
     547           0 :         g_iscsi.disable_chap = opts->disable_chap;
     548           0 :         g_iscsi.require_chap = opts->require_chap;
     549           0 :         g_iscsi.mutual_chap = opts->mutual_chap;
     550           0 :         g_iscsi.chap_group = opts->chap_group;
     551           0 :         g_iscsi.MaxLargeDataInPerConnection = opts->MaxLargeDataInPerConnection;
     552           0 :         g_iscsi.MaxR2TPerConnection = opts->MaxR2TPerConnection;
     553           0 :         g_iscsi.pdu_pool_size = opts->pdu_pool_size;
     554           0 :         g_iscsi.immediate_data_pool_size = opts->immediate_data_pool_size;
     555           0 :         g_iscsi.data_out_pool_size = opts->data_out_pool_size;
     556             : 
     557           0 :         iscsi_log_globals();
     558             : 
     559           0 :         return 0;
     560             : }
     561             : 
     562             : int
     563           0 : iscsi_set_discovery_auth(bool disable_chap, bool require_chap, bool mutual_chap,
     564             :                          int32_t chap_group)
     565             : {
     566           0 :         if (!iscsi_check_chap_params(disable_chap, require_chap, mutual_chap,
     567             :                                      chap_group)) {
     568           0 :                 SPDK_ERRLOG("CHAP params are illegal combination\n");
     569           0 :                 return -EINVAL;
     570             :         }
     571             : 
     572           0 :         pthread_mutex_lock(&g_iscsi.mutex);
     573           0 :         g_iscsi.disable_chap = disable_chap;
     574           0 :         g_iscsi.require_chap = require_chap;
     575           0 :         g_iscsi.mutual_chap = mutual_chap;
     576           0 :         g_iscsi.chap_group = chap_group;
     577           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
     578             : 
     579           0 :         return 0;
     580             : }
     581             : 
     582             : int
     583           0 : iscsi_auth_group_add_secret(struct spdk_iscsi_auth_group *group,
     584             :                             const char *user, const char *secret,
     585             :                             const char *muser, const char *msecret)
     586             : {
     587             :         struct spdk_iscsi_auth_secret *_secret;
     588             :         size_t len;
     589             : 
     590           0 :         if (user == NULL || secret == NULL) {
     591           0 :                 SPDK_ERRLOG("user and secret must be specified\n");
     592           0 :                 return -EINVAL;
     593             :         }
     594             : 
     595           0 :         if (muser != NULL && msecret == NULL) {
     596           0 :                 SPDK_ERRLOG("msecret must be specified with muser\n");
     597           0 :                 return -EINVAL;
     598             :         }
     599             : 
     600           0 :         TAILQ_FOREACH(_secret, &group->secret_head, tailq) {
     601           0 :                 if (strcmp(_secret->user, user) == 0) {
     602           0 :                         SPDK_ERRLOG("user for secret is duplicated\n");
     603           0 :                         return -EEXIST;
     604             :                 }
     605             :         }
     606             : 
     607           0 :         _secret = calloc(1, sizeof(*_secret));
     608           0 :         if (_secret == NULL) {
     609           0 :                 SPDK_ERRLOG("calloc() failed for CHAP secret\n");
     610           0 :                 return -ENOMEM;
     611             :         }
     612             : 
     613           0 :         len = strnlen(user, sizeof(_secret->user));
     614           0 :         if (len > sizeof(_secret->user) - 1) {
     615           0 :                 SPDK_ERRLOG("CHAP user longer than %zu characters: %s\n",
     616             :                             sizeof(_secret->user) - 1, user);
     617           0 :                 free(_secret);
     618           0 :                 return -EINVAL;
     619             :         }
     620           0 :         memcpy(_secret->user, user, len);
     621             : 
     622           0 :         len = strnlen(secret, sizeof(_secret->secret));
     623           0 :         if (len > sizeof(_secret->secret) - 1) {
     624           0 :                 SPDK_ERRLOG("CHAP secret longer than %zu characters: %s\n",
     625             :                             sizeof(_secret->secret) - 1, secret);
     626           0 :                 free(_secret);
     627           0 :                 return -EINVAL;
     628             :         }
     629           0 :         memcpy(_secret->secret, secret, len);
     630             : 
     631           0 :         if (muser != NULL) {
     632           0 :                 len = strnlen(muser, sizeof(_secret->muser));
     633           0 :                 if (len > sizeof(_secret->muser) - 1) {
     634           0 :                         SPDK_ERRLOG("Mutual CHAP user longer than %zu characters: %s\n",
     635             :                                     sizeof(_secret->muser) - 1, muser);
     636           0 :                         free(_secret);
     637           0 :                         return -EINVAL;
     638             :                 }
     639           0 :                 memcpy(_secret->muser, muser, len);
     640             : 
     641           0 :                 len = strnlen(msecret, sizeof(_secret->msecret));
     642           0 :                 if (len > sizeof(_secret->msecret) - 1) {
     643           0 :                         SPDK_ERRLOG("Mutual CHAP secret longer than %zu characters: %s\n",
     644             :                                     sizeof(_secret->msecret) - 1, msecret);
     645           0 :                         free(_secret);
     646           0 :                         return -EINVAL;
     647             :                 }
     648           0 :                 memcpy(_secret->msecret, msecret, len);
     649             :         }
     650             : 
     651           0 :         TAILQ_INSERT_TAIL(&group->secret_head, _secret, tailq);
     652           0 :         return 0;
     653             : }
     654             : 
     655             : int
     656           0 : iscsi_auth_group_delete_secret(struct spdk_iscsi_auth_group *group,
     657             :                                const char *user)
     658             : {
     659             :         struct spdk_iscsi_auth_secret *_secret;
     660             : 
     661           0 :         if (user == NULL) {
     662           0 :                 SPDK_ERRLOG("user must be specified\n");
     663           0 :                 return -EINVAL;
     664             :         }
     665             : 
     666           0 :         TAILQ_FOREACH(_secret, &group->secret_head, tailq) {
     667           0 :                 if (strcmp(_secret->user, user) == 0) {
     668           0 :                         break;
     669             :                 }
     670             :         }
     671             : 
     672           0 :         if (_secret == NULL) {
     673           0 :                 SPDK_ERRLOG("secret is not found\n");
     674           0 :                 return -ENODEV;
     675             :         }
     676             : 
     677           0 :         TAILQ_REMOVE(&group->secret_head, _secret, tailq);
     678           0 :         free(_secret);
     679             : 
     680           0 :         return 0;
     681             : }
     682             : 
     683             : int
     684           0 : iscsi_add_auth_group(int32_t tag, struct spdk_iscsi_auth_group **_group)
     685             : {
     686             :         struct spdk_iscsi_auth_group *group;
     687             : 
     688           0 :         TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) {
     689           0 :                 if (group->tag == tag) {
     690           0 :                         SPDK_ERRLOG("Auth group (%d) already exists\n", tag);
     691           0 :                         return -EEXIST;
     692             :                 }
     693             :         }
     694             : 
     695           0 :         group = calloc(1, sizeof(*group));
     696           0 :         if (group == NULL) {
     697           0 :                 SPDK_ERRLOG("calloc() failed for auth group\n");
     698           0 :                 return -ENOMEM;
     699             :         }
     700             : 
     701           0 :         TAILQ_INIT(&group->secret_head);
     702           0 :         group->tag = tag;
     703             : 
     704           0 :         TAILQ_INSERT_TAIL(&g_iscsi.auth_group_head, group, tailq);
     705             : 
     706           0 :         *_group = group;
     707           0 :         return 0;
     708             : }
     709             : 
     710             : void
     711           0 : iscsi_delete_auth_group(struct spdk_iscsi_auth_group *group)
     712             : {
     713             :         struct spdk_iscsi_auth_secret *_secret, *tmp;
     714             : 
     715           0 :         TAILQ_REMOVE(&g_iscsi.auth_group_head, group, tailq);
     716             : 
     717           0 :         TAILQ_FOREACH_SAFE(_secret, &group->secret_head, tailq, tmp) {
     718           0 :                 TAILQ_REMOVE(&group->secret_head, _secret, tailq);
     719           0 :                 free(_secret);
     720             :         }
     721           0 :         free(group);
     722           0 : }
     723             : 
     724             : struct spdk_iscsi_auth_group *
     725           0 : iscsi_find_auth_group_by_tag(int32_t tag)
     726             : {
     727             :         struct spdk_iscsi_auth_group *group;
     728             : 
     729           0 :         TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) {
     730           0 :                 if (group->tag == tag) {
     731           0 :                         return group;
     732             :                 }
     733             :         }
     734             : 
     735           0 :         return NULL;
     736             : }
     737             : 
     738             : static void
     739           0 : iscsi_auth_groups_destroy(void)
     740             : {
     741             :         struct spdk_iscsi_auth_group *group, *tmp;
     742             : 
     743           0 :         TAILQ_FOREACH_SAFE(group, &g_iscsi.auth_group_head, tailq, tmp) {
     744           0 :                 iscsi_delete_auth_group(group);
     745             :         }
     746           0 : }
     747             : 
     748             : static int
     749           0 : iscsi_parse_auth_group(struct spdk_conf_section *sp)
     750             : {
     751             :         int rc;
     752             :         int i;
     753             :         int tag;
     754             :         const char *val, *user, *secret, *muser, *msecret;
     755           0 :         struct spdk_iscsi_auth_group *group = NULL;
     756             : 
     757           0 :         val = spdk_conf_section_get_val(sp, "Comment");
     758           0 :         if (val != NULL) {
     759           0 :                 SPDK_DEBUGLOG(iscsi, "Comment %s\n", val);
     760             :         }
     761             : 
     762           0 :         tag = spdk_conf_section_get_num(sp);
     763             : 
     764           0 :         rc = iscsi_add_auth_group(tag, &group);
     765           0 :         if (rc != 0) {
     766           0 :                 SPDK_ERRLOG("Failed to add auth group\n");
     767           0 :                 return rc;
     768             :         }
     769             : 
     770           0 :         for (i = 0; ; i++) {
     771           0 :                 val = spdk_conf_section_get_nval(sp, "Auth", i);
     772           0 :                 if (val == NULL) {
     773           0 :                         break;
     774             :                 }
     775             : 
     776           0 :                 user = spdk_conf_section_get_nmval(sp, "Auth", i, 0);
     777           0 :                 secret = spdk_conf_section_get_nmval(sp, "Auth", i, 1);
     778           0 :                 muser = spdk_conf_section_get_nmval(sp, "Auth", i, 2);
     779           0 :                 msecret = spdk_conf_section_get_nmval(sp, "Auth", i, 3);
     780             : 
     781           0 :                 rc = iscsi_auth_group_add_secret(group, user, secret, muser, msecret);
     782           0 :                 if (rc != 0) {
     783           0 :                         SPDK_ERRLOG("Failed to add secret to auth group\n");
     784           0 :                         iscsi_delete_auth_group(group);
     785           0 :                         return rc;
     786             :                 }
     787             :         }
     788             : 
     789           0 :         return 0;
     790             : }
     791             : 
     792             : static int
     793           0 : iscsi_parse_auth_info(void)
     794             : {
     795             :         struct spdk_conf *config;
     796             :         struct spdk_conf_section *sp;
     797             :         int rc;
     798             : 
     799           0 :         config = spdk_conf_allocate();
     800           0 :         if (!config) {
     801           0 :                 SPDK_ERRLOG("Failed to allocate config file\n");
     802           0 :                 return -ENOMEM;
     803             :         }
     804             : 
     805           0 :         rc = spdk_conf_read(config, g_iscsi.authfile);
     806           0 :         if (rc != 0) {
     807           0 :                 SPDK_INFOLOG(iscsi, "Failed to load auth file\n");
     808           0 :                 spdk_conf_free(config);
     809           0 :                 return rc;
     810             :         }
     811             : 
     812           0 :         sp = spdk_conf_first_section(config);
     813           0 :         while (sp != NULL) {
     814           0 :                 if (spdk_conf_section_match_prefix(sp, "AuthGroup")) {
     815           0 :                         if (spdk_conf_section_get_num(sp) == 0) {
     816           0 :                                 SPDK_ERRLOG("Group 0 is invalid\n");
     817           0 :                                 iscsi_auth_groups_destroy();
     818           0 :                                 spdk_conf_free(config);
     819           0 :                                 return -EINVAL;
     820             :                         }
     821             : 
     822           0 :                         rc = iscsi_parse_auth_group(sp);
     823           0 :                         if (rc != 0) {
     824           0 :                                 SPDK_ERRLOG("parse_auth_group() failed\n");
     825           0 :                                 iscsi_auth_groups_destroy();
     826           0 :                                 spdk_conf_free(config);
     827           0 :                                 return rc;
     828             :                         }
     829             :                 }
     830           0 :                 sp = spdk_conf_next_section(sp);
     831             :         }
     832             : 
     833           0 :         spdk_conf_free(config);
     834           0 :         return 0;
     835             : }
     836             : 
     837             : static struct spdk_iscsi_auth_secret *
     838           0 : iscsi_find_auth_secret(const char *authuser, int ag_tag)
     839             : {
     840             :         struct spdk_iscsi_auth_group *group;
     841             :         struct spdk_iscsi_auth_secret *_secret;
     842             : 
     843           0 :         TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) {
     844           0 :                 if (group->tag == ag_tag) {
     845           0 :                         TAILQ_FOREACH(_secret, &group->secret_head, tailq) {
     846           0 :                                 if (strcmp(_secret->user, authuser) == 0) {
     847           0 :                                         return _secret;
     848             :                                 }
     849             :                         }
     850             :                 }
     851             :         }
     852             : 
     853           0 :         return NULL;
     854             : }
     855             : 
     856             : int
     857           0 : iscsi_chap_get_authinfo(struct iscsi_chap_auth *auth, const char *authuser,
     858             :                         int ag_tag)
     859             : {
     860             :         struct spdk_iscsi_auth_secret *_secret;
     861             : 
     862           0 :         if (authuser == NULL) {
     863           0 :                 return -EINVAL;
     864             :         }
     865             : 
     866           0 :         if (auth->user[0] != '\0') {
     867           0 :                 memset(auth->user, 0, sizeof(auth->user));
     868           0 :                 memset(auth->secret, 0, sizeof(auth->secret));
     869           0 :                 memset(auth->muser, 0, sizeof(auth->muser));
     870           0 :                 memset(auth->msecret, 0, sizeof(auth->msecret));
     871             :         }
     872             : 
     873           0 :         pthread_mutex_lock(&g_iscsi.mutex);
     874             : 
     875           0 :         _secret = iscsi_find_auth_secret(authuser, ag_tag);
     876           0 :         if (_secret == NULL) {
     877           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
     878             : 
     879           0 :                 SPDK_ERRLOG("CHAP secret is not found: user:%s, tag:%d\n",
     880             :                             authuser, ag_tag);
     881           0 :                 return -ENOENT;
     882             :         }
     883             : 
     884           0 :         memcpy(auth->user, _secret->user, sizeof(auth->user));
     885           0 :         memcpy(auth->secret, _secret->secret, sizeof(auth->secret));
     886             : 
     887           0 :         if (_secret->muser[0] != '\0') {
     888           0 :                 memcpy(auth->muser, _secret->muser, sizeof(auth->muser));
     889           0 :                 memcpy(auth->msecret, _secret->msecret, sizeof(auth->msecret));
     890             :         }
     891             : 
     892           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
     893           0 :         return 0;
     894             : }
     895             : 
     896             : static int
     897           0 : iscsi_initialize_global_params(void)
     898             : {
     899             :         int rc;
     900             : 
     901           0 :         if (!g_spdk_iscsi_opts) {
     902           0 :                 g_spdk_iscsi_opts = iscsi_opts_alloc();
     903           0 :                 if (!g_spdk_iscsi_opts) {
     904           0 :                         SPDK_ERRLOG("iscsi_opts_alloc_failed() failed\n");
     905           0 :                         return -ENOMEM;
     906             :                 }
     907             :         }
     908             : 
     909           0 :         rc = iscsi_set_global_params(g_spdk_iscsi_opts);
     910           0 :         if (rc != 0) {
     911           0 :                 SPDK_ERRLOG("iscsi_set_global_params() failed\n");
     912             :         }
     913             : 
     914           0 :         iscsi_opts_free(g_spdk_iscsi_opts);
     915           0 :         g_spdk_iscsi_opts = NULL;
     916             : 
     917           0 :         return rc;
     918             : }
     919             : 
     920             : static void
     921           0 : iscsi_init_complete(int rc)
     922             : {
     923           0 :         spdk_iscsi_init_cb cb_fn = g_init_cb_fn;
     924           0 :         void *cb_arg = g_init_cb_arg;
     925             : 
     926           0 :         g_init_cb_fn = NULL;
     927           0 :         g_init_cb_arg = NULL;
     928             : 
     929           0 :         cb_fn(cb_arg, rc);
     930           0 : }
     931             : 
     932             : static void
     933           0 : iscsi_parse_configuration(void)
     934             : {
     935           0 :         int rc = 0;
     936             : 
     937           0 :         if (g_iscsi.authfile != NULL) {
     938           0 :                 if (access(g_iscsi.authfile, R_OK) == 0) {
     939           0 :                         rc = iscsi_parse_auth_info();
     940           0 :                         if (rc < 0) {
     941           0 :                                 SPDK_ERRLOG("iscsi_parse_auth_info() failed\n");
     942             :                         }
     943             :                 } else {
     944           0 :                         SPDK_INFOLOG(iscsi, "CHAP secret file is not found in the path %s\n",
     945             :                                      g_iscsi.authfile);
     946             :                 }
     947             :         }
     948             : 
     949           0 :         iscsi_init_complete(rc);
     950           0 : }
     951             : 
     952             : static int
     953           0 : iscsi_poll_group_poll(void *ctx)
     954             : {
     955           0 :         struct spdk_iscsi_poll_group *group = ctx;
     956             :         struct spdk_iscsi_conn *conn, *tmp;
     957             :         int rc;
     958             : 
     959           0 :         if (spdk_unlikely(STAILQ_EMPTY(&group->connections))) {
     960           0 :                 return SPDK_POLLER_IDLE;
     961             :         }
     962             : 
     963           0 :         rc = spdk_sock_group_poll(group->sock_group);
     964           0 :         if (rc < 0) {
     965           0 :                 SPDK_ERRLOG("Failed to poll sock_group=%p\n", group->sock_group);
     966             :         }
     967             : 
     968           0 :         STAILQ_FOREACH_SAFE(conn, &group->connections, pg_link, tmp) {
     969           0 :                 if (conn->state == ISCSI_CONN_STATE_EXITING) {
     970           0 :                         iscsi_conn_destruct(conn);
     971             :                 }
     972             :         }
     973             : 
     974           0 :         return rc != 0 ? SPDK_POLLER_BUSY : SPDK_POLLER_IDLE;
     975             : }
     976             : 
     977             : static int
     978           0 : iscsi_poll_group_handle_nop(void *ctx)
     979             : {
     980           0 :         struct spdk_iscsi_poll_group *group = ctx;
     981             :         struct spdk_iscsi_conn *conn, *tmp;
     982             : 
     983           0 :         STAILQ_FOREACH_SAFE(conn, &group->connections, pg_link, tmp) {
     984           0 :                 iscsi_conn_handle_nop(conn);
     985             :         }
     986             : 
     987           0 :         return SPDK_POLLER_BUSY;
     988             : }
     989             : 
     990             : static int
     991           0 : iscsi_poll_group_create(void *io_device, void *ctx_buf)
     992             : {
     993           0 :         struct spdk_iscsi_poll_group *pg = ctx_buf;
     994             : 
     995           0 :         STAILQ_INIT(&pg->connections);
     996           0 :         pg->sock_group = spdk_sock_group_create(NULL);
     997           0 :         assert(pg->sock_group != NULL);
     998             : 
     999           0 :         pg->poller = SPDK_POLLER_REGISTER(iscsi_poll_group_poll, pg, 0);
    1000             :         /* set the period to 1 sec */
    1001           0 :         pg->nop_poller = SPDK_POLLER_REGISTER(iscsi_poll_group_handle_nop, pg, 1000000);
    1002             : 
    1003           0 :         return 0;
    1004             : }
    1005             : 
    1006             : static void
    1007           0 : iscsi_poll_group_destroy(void *io_device, void *ctx_buf)
    1008             : {
    1009           0 :         struct spdk_iscsi_poll_group *pg = ctx_buf;
    1010             :         struct spdk_io_channel *ch;
    1011             :         struct spdk_thread *thread;
    1012             : 
    1013           0 :         assert(pg->poller != NULL);
    1014           0 :         assert(pg->sock_group != NULL);
    1015             : 
    1016           0 :         spdk_sock_group_close(&pg->sock_group);
    1017           0 :         spdk_poller_unregister(&pg->poller);
    1018           0 :         spdk_poller_unregister(&pg->nop_poller);
    1019             : 
    1020           0 :         ch = spdk_io_channel_from_ctx(pg);
    1021           0 :         thread = spdk_io_channel_get_thread(ch);
    1022             : 
    1023           0 :         assert(thread == spdk_get_thread());
    1024             : 
    1025           0 :         spdk_thread_exit(thread);
    1026           0 : }
    1027             : 
    1028             : static void
    1029           0 : _iscsi_init_thread_done(void *ctx)
    1030             : {
    1031           0 :         struct spdk_iscsi_poll_group *pg = ctx;
    1032             : 
    1033           0 :         TAILQ_INSERT_TAIL(&g_iscsi.poll_group_head, pg, link);
    1034           0 :         if (--g_iscsi.refcnt == 0) {
    1035           0 :                 iscsi_parse_configuration();
    1036             :         }
    1037           0 : }
    1038             : 
    1039             : static void
    1040           0 : _iscsi_init_thread(void *ctx)
    1041             : {
    1042             :         struct spdk_io_channel *ch;
    1043             :         struct spdk_iscsi_poll_group *pg;
    1044             : 
    1045           0 :         ch = spdk_get_io_channel(&g_iscsi);
    1046           0 :         pg = spdk_io_channel_get_ctx(ch);
    1047             : 
    1048           0 :         spdk_thread_send_msg(g_init_thread, _iscsi_init_thread_done, pg);
    1049           0 : }
    1050             : 
    1051             : static void
    1052           0 : initialize_iscsi_poll_group(void)
    1053             : {
    1054           0 :         struct spdk_cpuset tmp_cpumask = {};
    1055             :         uint32_t i;
    1056           0 :         char thread_name[32];
    1057             :         struct spdk_thread *thread;
    1058             : 
    1059           0 :         spdk_io_device_register(&g_iscsi, iscsi_poll_group_create, iscsi_poll_group_destroy,
    1060             :                                 sizeof(struct spdk_iscsi_poll_group), "iscsi_tgt");
    1061             : 
    1062             :         /* Create threads for CPU cores active for this application, and send a
    1063             :          * message to each thread to create a poll group on it.
    1064             :          */
    1065           0 :         g_init_thread = spdk_get_thread();
    1066           0 :         assert(g_init_thread != NULL);
    1067           0 :         assert(g_iscsi.refcnt == 0);
    1068             : 
    1069           0 :         SPDK_ENV_FOREACH_CORE(i) {
    1070           0 :                 spdk_cpuset_zero(&tmp_cpumask);
    1071           0 :                 spdk_cpuset_set_cpu(&tmp_cpumask, i, true);
    1072           0 :                 snprintf(thread_name, sizeof(thread_name), "iscsi_poll_group_%u", i);
    1073             : 
    1074           0 :                 thread = spdk_thread_create(thread_name, &tmp_cpumask);
    1075           0 :                 assert(thread != NULL);
    1076             : 
    1077           0 :                 g_iscsi.refcnt++;
    1078           0 :                 spdk_thread_send_msg(thread, _iscsi_init_thread, NULL);
    1079             :         }
    1080           0 : }
    1081             : 
    1082             : static int
    1083           0 : iscsi_parse_globals(void)
    1084             : {
    1085             :         int rc;
    1086             : 
    1087           0 :         rc = iscsi_initialize_global_params();
    1088           0 :         if (rc != 0) {
    1089           0 :                 SPDK_ERRLOG("iscsi_initialize_iscsi_global_params() failed\n");
    1090           0 :                 return rc;
    1091             :         }
    1092             : 
    1093           0 :         g_iscsi.session = calloc(1, sizeof(struct spdk_iscsi_sess *) * g_iscsi.MaxSessions);
    1094           0 :         if (!g_iscsi.session) {
    1095           0 :                 SPDK_ERRLOG("calloc() failed for session array\n");
    1096           0 :                 return -1;
    1097             :         }
    1098             : 
    1099             :         /*
    1100             :          * For now, just support same number of total connections, rather
    1101             :          *  than MaxSessions * MaxConnectionsPerSession.  After we add better
    1102             :          *  handling for low resource conditions from our various buffer
    1103             :          *  pools, we can bump this up to support more connections.
    1104             :          */
    1105           0 :         g_iscsi.MaxConnections = g_iscsi.MaxSessions;
    1106             : 
    1107           0 :         rc = iscsi_initialize_all_pools();
    1108           0 :         if (rc != 0) {
    1109           0 :                 SPDK_ERRLOG("initialize_all_pools() failed\n");
    1110           0 :                 free(g_iscsi.session);
    1111           0 :                 g_iscsi.session = NULL;
    1112           0 :                 return -1;
    1113             :         }
    1114             : 
    1115           0 :         rc = initialize_iscsi_conns();
    1116           0 :         if (rc < 0) {
    1117           0 :                 SPDK_ERRLOG("initialize_iscsi_conns() failed\n");
    1118           0 :                 free(g_iscsi.session);
    1119           0 :                 g_iscsi.session = NULL;
    1120           0 :                 return rc;
    1121             :         }
    1122             : 
    1123           0 :         initialize_iscsi_poll_group();
    1124           0 :         return 0;
    1125             : }
    1126             : 
    1127             : void
    1128           0 : spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg)
    1129             : {
    1130             :         int rc;
    1131             : 
    1132           0 :         assert(cb_fn != NULL);
    1133           0 :         g_init_cb_fn = cb_fn;
    1134           0 :         g_init_cb_arg = cb_arg;
    1135             : 
    1136           0 :         rc = iscsi_parse_globals();
    1137           0 :         if (rc < 0) {
    1138           0 :                 SPDK_ERRLOG("iscsi_parse_globals() failed\n");
    1139           0 :                 iscsi_init_complete(-1);
    1140             :         }
    1141             : 
    1142             :         /*
    1143             :          * iscsi_parse_configuration() will be called as the callback to
    1144             :          * spdk_initialize_iscsi_poll_group() and will complete iSCSI
    1145             :          * subsystem initialization.
    1146             :          */
    1147           0 : }
    1148             : 
    1149             : void
    1150           0 : spdk_iscsi_fini(spdk_iscsi_fini_cb cb_fn, void *cb_arg)
    1151             : {
    1152           0 :         g_fini_cb_fn = cb_fn;
    1153           0 :         g_fini_cb_arg = cb_arg;
    1154             : 
    1155           0 :         iscsi_portal_grp_close_all();
    1156           0 :         shutdown_iscsi_conns();
    1157           0 : }
    1158             : 
    1159             : static void
    1160           0 : iscsi_fini_done(void *io_device)
    1161             : {
    1162           0 :         g_fini_cb_fn(g_fini_cb_arg);
    1163           0 : }
    1164             : 
    1165             : static void
    1166           0 : _iscsi_fini_dev_unreg(struct spdk_io_channel_iter *i, int status)
    1167             : {
    1168           0 :         iscsi_check_pools();
    1169           0 :         iscsi_free_pools();
    1170           0 :         free(g_iscsi.session);
    1171             : 
    1172           0 :         assert(TAILQ_EMPTY(&g_iscsi.poll_group_head));
    1173             : 
    1174           0 :         iscsi_shutdown_tgt_nodes();
    1175           0 :         iscsi_init_grps_destroy();
    1176           0 :         iscsi_portal_grps_destroy();
    1177           0 :         iscsi_auth_groups_destroy();
    1178             : 
    1179           0 :         free(g_iscsi.authfile);
    1180           0 :         free(g_iscsi.nodebase);
    1181             : 
    1182           0 :         pthread_mutex_destroy(&g_iscsi.mutex);
    1183           0 :         if (g_init_thread != NULL) {
    1184             :                 /* g_init_thread is set just after the io_device is
    1185             :                  * registered, so we can use it to determine if it
    1186             :                  * needs to be unregistered (in cases where iscsi init
    1187             :                  * fails).
    1188             :                  */
    1189           0 :                 spdk_io_device_unregister(&g_iscsi, iscsi_fini_done);
    1190             :         } else {
    1191           0 :                 iscsi_fini_done(NULL);
    1192             :         }
    1193           0 : }
    1194             : 
    1195             : static void
    1196           0 : _iscsi_fini_thread(struct spdk_io_channel_iter *i)
    1197             : {
    1198             :         struct spdk_io_channel *ch;
    1199             :         struct spdk_iscsi_poll_group *pg;
    1200             : 
    1201           0 :         ch = spdk_io_channel_iter_get_channel(i);
    1202           0 :         pg = spdk_io_channel_get_ctx(ch);
    1203             : 
    1204           0 :         pthread_mutex_lock(&g_iscsi.mutex);
    1205           0 :         TAILQ_REMOVE(&g_iscsi.poll_group_head, pg, link);
    1206           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
    1207             : 
    1208           0 :         spdk_put_io_channel(ch);
    1209             : 
    1210           0 :         spdk_for_each_channel_continue(i, 0);
    1211           0 : }
    1212             : 
    1213             : void
    1214           0 : shutdown_iscsi_conns_done(void)
    1215             : {
    1216           0 :         spdk_for_each_channel(&g_iscsi, _iscsi_fini_thread, NULL, _iscsi_fini_dev_unreg);
    1217           0 : }
    1218             : 
    1219             : void
    1220           0 : iscsi_opts_info_json(struct spdk_json_write_ctx *w)
    1221             : {
    1222           0 :         spdk_json_write_object_begin(w);
    1223             : 
    1224           0 :         if (g_iscsi.authfile != NULL) {
    1225           0 :                 spdk_json_write_named_string(w, "auth_file", g_iscsi.authfile);
    1226             :         }
    1227           0 :         spdk_json_write_named_string(w, "node_base", g_iscsi.nodebase);
    1228             : 
    1229           0 :         spdk_json_write_named_uint32(w, "max_sessions", g_iscsi.MaxSessions);
    1230           0 :         spdk_json_write_named_uint32(w, "max_connections_per_session",
    1231             :                                      g_iscsi.MaxConnectionsPerSession);
    1232             : 
    1233           0 :         spdk_json_write_named_uint32(w, "max_queue_depth", g_iscsi.MaxQueueDepth);
    1234             : 
    1235           0 :         spdk_json_write_named_uint32(w, "default_time2wait", g_iscsi.DefaultTime2Wait);
    1236           0 :         spdk_json_write_named_uint32(w, "default_time2retain", g_iscsi.DefaultTime2Retain);
    1237             : 
    1238           0 :         spdk_json_write_named_uint32(w, "first_burst_length", g_iscsi.FirstBurstLength);
    1239             : 
    1240           0 :         spdk_json_write_named_bool(w, "immediate_data", g_iscsi.ImmediateData);
    1241             : 
    1242           0 :         spdk_json_write_named_bool(w, "allow_duplicated_isid", g_iscsi.AllowDuplicateIsid);
    1243             : 
    1244           0 :         spdk_json_write_named_uint32(w, "error_recovery_level", g_iscsi.ErrorRecoveryLevel);
    1245             : 
    1246           0 :         spdk_json_write_named_int32(w, "nop_timeout", g_iscsi.timeout);
    1247           0 :         spdk_json_write_named_int32(w, "nop_in_interval", g_iscsi.nopininterval);
    1248             : 
    1249           0 :         spdk_json_write_named_bool(w, "disable_chap", g_iscsi.disable_chap);
    1250           0 :         spdk_json_write_named_bool(w, "require_chap", g_iscsi.require_chap);
    1251           0 :         spdk_json_write_named_bool(w, "mutual_chap", g_iscsi.mutual_chap);
    1252           0 :         spdk_json_write_named_int32(w, "chap_group", g_iscsi.chap_group);
    1253             : 
    1254           0 :         spdk_json_write_named_uint32(w, "max_large_datain_per_connection",
    1255             :                                      g_iscsi.MaxLargeDataInPerConnection);
    1256           0 :         spdk_json_write_named_uint32(w, "max_r2t_per_connection",
    1257             :                                      g_iscsi.MaxR2TPerConnection);
    1258             : 
    1259           0 :         spdk_json_write_named_uint32(w, "pdu_pool_size", g_iscsi.pdu_pool_size);
    1260           0 :         spdk_json_write_named_uint32(w, "immediate_data_pool_size",
    1261             :                                      g_iscsi.immediate_data_pool_size);
    1262           0 :         spdk_json_write_named_uint32(w, "data_out_pool_size", g_iscsi.data_out_pool_size);
    1263             : 
    1264           0 :         spdk_json_write_object_end(w);
    1265           0 : }
    1266             : 
    1267             : static void
    1268           0 : iscsi_auth_group_info_json(struct spdk_iscsi_auth_group *group,
    1269             :                            struct spdk_json_write_ctx *w)
    1270             : {
    1271             :         struct spdk_iscsi_auth_secret *_secret;
    1272             : 
    1273           0 :         spdk_json_write_object_begin(w);
    1274             : 
    1275           0 :         spdk_json_write_named_int32(w, "tag", group->tag);
    1276             : 
    1277           0 :         spdk_json_write_named_array_begin(w, "secrets");
    1278           0 :         TAILQ_FOREACH(_secret, &group->secret_head, tailq) {
    1279           0 :                 spdk_json_write_object_begin(w);
    1280             : 
    1281           0 :                 spdk_json_write_named_string(w, "user", _secret->user);
    1282           0 :                 spdk_json_write_named_string(w, "secret", _secret->secret);
    1283             : 
    1284           0 :                 if (_secret->muser[0] != '\0') {
    1285           0 :                         spdk_json_write_named_string(w, "muser", _secret->muser);
    1286           0 :                         spdk_json_write_named_string(w, "msecret", _secret->msecret);
    1287             :                 }
    1288             : 
    1289           0 :                 spdk_json_write_object_end(w);
    1290             :         }
    1291           0 :         spdk_json_write_array_end(w);
    1292             : 
    1293           0 :         spdk_json_write_object_end(w);
    1294           0 : }
    1295             : 
    1296             : static void
    1297           0 : iscsi_auth_group_config_json(struct spdk_iscsi_auth_group *group,
    1298             :                              struct spdk_json_write_ctx *w)
    1299             : {
    1300           0 :         spdk_json_write_object_begin(w);
    1301             : 
    1302           0 :         spdk_json_write_named_string(w, "method", "iscsi_create_auth_group");
    1303             : 
    1304           0 :         spdk_json_write_name(w, "params");
    1305           0 :         iscsi_auth_group_info_json(group, w);
    1306             : 
    1307           0 :         spdk_json_write_object_end(w);
    1308           0 : }
    1309             : 
    1310             : void
    1311           0 : iscsi_auth_groups_info_json(struct spdk_json_write_ctx *w)
    1312             : {
    1313             :         struct spdk_iscsi_auth_group *group;
    1314             : 
    1315           0 :         TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) {
    1316           0 :                 iscsi_auth_group_info_json(group, w);
    1317             :         }
    1318           0 : }
    1319             : 
    1320             : static void
    1321           0 : iscsi_auth_groups_config_json(struct spdk_json_write_ctx *w)
    1322             : {
    1323             :         struct spdk_iscsi_auth_group *group;
    1324             : 
    1325           0 :         TAILQ_FOREACH(group, &g_iscsi.auth_group_head, tailq) {
    1326           0 :                 iscsi_auth_group_config_json(group, w);
    1327             :         }
    1328           0 : }
    1329             : 
    1330             : static void
    1331           0 : iscsi_opts_config_json(struct spdk_json_write_ctx *w)
    1332             : {
    1333           0 :         spdk_json_write_object_begin(w);
    1334             : 
    1335           0 :         spdk_json_write_named_string(w, "method", "iscsi_set_options");
    1336             : 
    1337           0 :         spdk_json_write_name(w, "params");
    1338           0 :         iscsi_opts_info_json(w);
    1339             : 
    1340           0 :         spdk_json_write_object_end(w);
    1341           0 : }
    1342             : 
    1343             : void
    1344           0 : spdk_iscsi_config_json(struct spdk_json_write_ctx *w)
    1345             : {
    1346           0 :         spdk_json_write_array_begin(w);
    1347           0 :         iscsi_opts_config_json(w);
    1348           0 :         iscsi_portal_grps_config_json(w);
    1349           0 :         iscsi_init_grps_config_json(w);
    1350           0 :         iscsi_tgt_nodes_config_json(w);
    1351           0 :         iscsi_auth_groups_config_json(w);
    1352           0 :         spdk_json_write_array_end(w);
    1353           0 : }
    1354             : 
    1355           0 : SPDK_LOG_REGISTER_COMPONENT(iscsi)

Generated by: LCOV version 1.15