LCOV - code coverage report
Current view: top level - spdk/module/bdev/iscsi - bdev_iscsi.c (source / functions) Hit Total Coverage
Test: Combined Lines: 364 525 69.3 %
Date: 2024-07-12 13:06:24 Functions: 42 49 85.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 117 243 48.1 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2017 Intel Corporation.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/stdinc.h"
       7                 :            : 
       8                 :            : #include "spdk/bdev.h"
       9                 :            : #include "spdk/env.h"
      10                 :            : #include "spdk/fd.h"
      11                 :            : #include "spdk/thread.h"
      12                 :            : #include "spdk/json.h"
      13                 :            : #include "spdk/util.h"
      14                 :            : #include "spdk/rpc.h"
      15                 :            : #include "spdk/string.h"
      16                 :            : #include "spdk/iscsi_spec.h"
      17                 :            : 
      18                 :            : #include "spdk/log.h"
      19                 :            : #include "spdk/bdev_module.h"
      20                 :            : 
      21                 :            : #include "iscsi/iscsi.h"
      22                 :            : #include "iscsi/scsi-lowlevel.h"
      23                 :            : 
      24                 :            : #include "bdev_iscsi.h"
      25                 :            : 
      26                 :            : struct bdev_iscsi_lun;
      27                 :            : 
      28                 :            : #define BDEV_ISCSI_CONNECTION_POLL_US 500 /* 0.5 ms */
      29                 :            : #define BDEV_ISCSI_NO_MAIN_CH_POLL_US 10000 /* 10ms */
      30                 :            : 
      31                 :            : #define BDEV_ISCSI_TIMEOUT_POLL_PERIOD_DEFAULT  1000000ULL /* 1 s */
      32                 :            : #define BDEV_ISCSI_TIMEOUT_DEFAULT 30 /* 30 s */
      33                 :            : #define BDEV_ISCSI_TIMEOUT_POLL_PERIOD_DIVISOR 30
      34                 :            : 
      35                 :            : #define DEFAULT_INITIATOR_NAME "iqn.2016-06.io.spdk:init"
      36                 :            : 
      37                 :            : /* MAXIMUM UNMAP LBA COUNT:
      38                 :            :  * indicates the maximum  number of LBAs that may be unmapped
      39                 :            :  * by an UNMAP command.
      40                 :            :  */
      41                 :            : #define BDEV_ISCSI_DEFAULT_MAX_UNMAP_LBA_COUNT (32768)
      42                 :            : 
      43                 :            : /* MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT:
      44                 :            :  * indicates the maximum number of UNMAP block descriptors that
      45                 :            :  * shall be contained in the parameter data transferred to the
      46                 :            :  * device server for an UNMAP command.
      47                 :            :  */
      48                 :            : #define BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT (1)
      49                 :            : 
      50                 :            : static int bdev_iscsi_initialize(void);
      51                 :            : static void bdev_iscsi_readcapacity16(struct iscsi_context *context, struct bdev_iscsi_lun *lun);
      52                 :            : static void _bdev_iscsi_submit_request(void *_bdev_io);
      53                 :            : 
      54                 :            : static TAILQ_HEAD(, bdev_iscsi_conn_req) g_iscsi_conn_req = TAILQ_HEAD_INITIALIZER(
      55                 :            :                         g_iscsi_conn_req);
      56                 :            : static struct spdk_poller *g_conn_poller = NULL;
      57                 :            : 
      58                 :            : struct bdev_iscsi_io {
      59                 :            :         struct spdk_thread *submit_td;
      60                 :            :         struct bdev_iscsi_lun *lun;
      61                 :            :         enum spdk_bdev_io_status status;
      62                 :            :         int scsi_status;
      63                 :            :         enum spdk_scsi_sense sk;
      64                 :            :         uint8_t asc;
      65                 :            :         uint8_t ascq;
      66                 :            : };
      67                 :            : 
      68                 :            : struct bdev_iscsi_lun {
      69                 :            :         struct spdk_bdev                bdev;
      70                 :            :         struct iscsi_context            *context;
      71                 :            :         char                            *initiator_iqn;
      72                 :            :         int                             lun_id;
      73                 :            :         char                            *url;
      74                 :            :         pthread_mutex_t                 mutex;
      75                 :            :         uint32_t                        ch_count;
      76                 :            :         struct spdk_thread              *main_td;
      77                 :            :         struct spdk_poller              *no_main_ch_poller;
      78                 :            :         struct spdk_thread              *no_main_ch_poller_td;
      79                 :            :         bool                            unmap_supported;
      80                 :            :         uint32_t                        max_unmap;
      81                 :            :         struct spdk_poller              *poller;
      82                 :            :         struct spdk_poller              *timeout_poller;
      83                 :            : };
      84                 :            : 
      85                 :            : struct bdev_iscsi_io_channel {
      86                 :            :         struct bdev_iscsi_lun   *lun;
      87                 :            : };
      88                 :            : 
      89                 :            : struct bdev_iscsi_conn_req {
      90                 :            :         char                                    *url;
      91                 :            :         char                                    *bdev_name;
      92                 :            :         char                                    *initiator_iqn;
      93                 :            :         struct iscsi_context                    *context;
      94                 :            :         spdk_bdev_iscsi_create_cb               create_cb;
      95                 :            :         void                                    *create_cb_arg;
      96                 :            :         bool                                    unmap_supported;
      97                 :            :         uint32_t                                max_unmap;
      98                 :            :         int                                     lun;
      99                 :            :         int                                     status;
     100                 :            :         TAILQ_ENTRY(bdev_iscsi_conn_req)        link;
     101                 :            : };
     102                 :            : 
     103                 :            : static struct spdk_bdev_iscsi_opts g_opts = {
     104                 :            :         .timeout_sec = BDEV_ISCSI_TIMEOUT_DEFAULT,
     105                 :            :         .timeout_poller_period_us = BDEV_ISCSI_TIMEOUT_POLL_PERIOD_DEFAULT,
     106                 :            : };
     107                 :            : 
     108                 :            : void
     109                 :        208 : bdev_iscsi_get_opts(struct spdk_bdev_iscsi_opts *opts)
     110                 :            : {
     111                 :        208 :         *opts = g_opts;
     112                 :        208 : }
     113                 :            : 
     114                 :            : int
     115                 :        208 : bdev_iscsi_set_opts(struct spdk_bdev_iscsi_opts *opts)
     116                 :            : {
     117                 :            :         /* make the poller period equal to timeout / 30 */
     118                 :        208 :         opts->timeout_poller_period_us = (opts->timeout_sec * 1000000ULL) /
     119                 :            :                                          BDEV_ISCSI_TIMEOUT_POLL_PERIOD_DIVISOR;
     120                 :            : 
     121                 :        208 :         g_opts = *opts;
     122                 :            : 
     123                 :        208 :         return 0;
     124                 :            : }
     125                 :            : 
     126                 :            : static void
     127                 :          9 : complete_conn_req(struct bdev_iscsi_conn_req *req, struct spdk_bdev *bdev,
     128                 :            :                   int status)
     129                 :            : {
     130         [ -  + ]:          9 :         TAILQ_REMOVE(&g_iscsi_conn_req, req, link);
     131                 :          9 :         req->create_cb(req->create_cb_arg, bdev, status);
     132                 :            : 
     133                 :            :         /*
     134                 :            :          * we are still running in the context of iscsi_service()
     135                 :            :          * so do not tear down its data structures here
     136                 :            :          */
     137                 :          9 :         req->status = status;
     138                 :          9 : }
     139                 :            : 
     140                 :            : static int
     141                 :       1716 : bdev_iscsi_get_ctx_size(void)
     142                 :            : {
     143                 :       1716 :         return sizeof(struct bdev_iscsi_io);
     144                 :            : }
     145                 :            : 
     146                 :            : static void
     147                 :          9 : _iscsi_free_lun(void *arg)
     148                 :            : {
     149                 :          9 :         struct bdev_iscsi_lun *lun = arg;
     150                 :            : 
     151         [ -  + ]:          9 :         assert(lun != NULL);
     152                 :          9 :         iscsi_destroy_context(lun->context);
     153         [ -  + ]:          9 :         pthread_mutex_destroy(&lun->mutex);
     154                 :          9 :         free(lun->bdev.name);
     155                 :          9 :         free(lun->url);
     156                 :          9 :         free(lun->initiator_iqn);
     157                 :            : 
     158                 :          9 :         spdk_bdev_destruct_done(&lun->bdev, 0);
     159                 :          9 :         free(lun);
     160                 :          9 : }
     161                 :            : 
     162                 :            : static void
     163                 :          0 : _bdev_iscsi_conn_req_free(struct bdev_iscsi_conn_req *req)
     164                 :            : {
     165                 :          0 :         free(req->initiator_iqn);
     166                 :          0 :         free(req->bdev_name);
     167                 :          0 :         free(req->url);
     168                 :            :         /* destroy will call iscsi_disconnect() implicitly if connected */
     169                 :          0 :         iscsi_destroy_context(req->context);
     170                 :          0 :         free(req);
     171                 :          0 : }
     172                 :            : 
     173                 :            : static void
     174                 :       1716 : bdev_iscsi_finish(void)
     175                 :            : {
     176                 :            :         struct bdev_iscsi_conn_req *req, *tmp;
     177                 :            : 
     178                 :            :         /* clear out pending connection requests here. We cannot
     179                 :            :          * simply set the state to a non SCSI_STATUS_GOOD state as
     180                 :            :          * the connection poller won't run anymore
     181                 :            :          */
     182         [ -  + ]:       1716 :         TAILQ_FOREACH_SAFE(req, &g_iscsi_conn_req, link, tmp) {
     183                 :          0 :                 _bdev_iscsi_conn_req_free(req);
     184                 :            :         }
     185                 :            : 
     186         [ -  + ]:       1716 :         if (g_conn_poller) {
     187                 :          0 :                 spdk_poller_unregister(&g_conn_poller);
     188                 :            :         }
     189                 :       1716 : }
     190                 :            : 
     191                 :            : static void
     192                 :        131 : bdev_iscsi_opts_config_json(struct spdk_json_write_ctx *w)
     193                 :            : {
     194                 :        131 :         spdk_json_write_object_begin(w);
     195                 :            : 
     196                 :        131 :         spdk_json_write_named_string(w, "method", "bdev_iscsi_set_options");
     197                 :            : 
     198                 :        131 :         spdk_json_write_named_object_begin(w, "params");
     199                 :        131 :         spdk_json_write_named_uint64(w, "timeout_sec", g_opts.timeout_sec);
     200                 :        131 :         spdk_json_write_object_end(w);
     201                 :            : 
     202                 :        131 :         spdk_json_write_object_end(w);
     203                 :        131 : }
     204                 :            : 
     205                 :            : static int
     206                 :        131 : bdev_iscsi_config_json(struct spdk_json_write_ctx *w)
     207                 :            : {
     208                 :        131 :         bdev_iscsi_opts_config_json(w);
     209                 :        131 :         return 0;
     210                 :            : }
     211                 :            : 
     212                 :            : static struct spdk_bdev_module g_iscsi_bdev_module = {
     213                 :            :         .name           = "iscsi",
     214                 :            :         .module_init    = bdev_iscsi_initialize,
     215                 :            :         .module_fini    = bdev_iscsi_finish,
     216                 :            :         .config_json    = bdev_iscsi_config_json,
     217                 :            :         .get_ctx_size   = bdev_iscsi_get_ctx_size,
     218                 :            : };
     219                 :            : 
     220                 :       1850 : SPDK_BDEV_MODULE_REGISTER(iscsi, &g_iscsi_bdev_module);
     221                 :            : 
     222                 :            : static void
     223                 :    1922753 : _bdev_iscsi_io_complete(void *_iscsi_io)
     224                 :            : {
     225                 :    1922753 :         struct bdev_iscsi_io *iscsi_io = _iscsi_io;
     226                 :            : 
     227         [ +  - ]:    1922753 :         if (iscsi_io->status == SPDK_BDEV_IO_STATUS_SUCCESS) {
     228                 :    1922753 :                 spdk_bdev_io_complete_scsi_status(spdk_bdev_io_from_ctx(iscsi_io), iscsi_io->scsi_status,
     229                 :    1922753 :                                                   iscsi_io->sk, iscsi_io->asc, iscsi_io->ascq);
     230                 :            :         } else {
     231                 :          0 :                 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(iscsi_io), iscsi_io->status);
     232                 :            :         }
     233                 :    1922753 : }
     234                 :            : 
     235                 :            : static void
     236                 :    1922753 : bdev_iscsi_io_complete(struct bdev_iscsi_io *iscsi_io, enum spdk_bdev_io_status status)
     237                 :            : {
     238                 :    1922753 :         iscsi_io->status = status;
     239         [ -  + ]:    1922753 :         if (iscsi_io->submit_td != NULL) {
     240                 :          0 :                 spdk_thread_send_msg(iscsi_io->submit_td, _bdev_iscsi_io_complete, iscsi_io);
     241                 :            :         } else {
     242                 :    1922753 :                 _bdev_iscsi_io_complete(iscsi_io);
     243                 :            :         }
     244                 :    1922753 : }
     245                 :            : 
     246                 :            : static bool
     247                 :    1922754 : _bdev_iscsi_is_size_change(int status, struct scsi_task *task)
     248                 :            : {
     249         [ +  + ]:    1922754 :         if (status == SPDK_SCSI_STATUS_CHECK_CONDITION &&
     250         [ +  - ]:          1 :             (uint8_t)task->sense.key == SPDK_SCSI_SENSE_UNIT_ATTENTION &&
     251         [ +  - ]:          1 :             task->sense.ascq == 0x2a09) {
     252                 :            :                 /* ASCQ: SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED (0x2a09) */
     253                 :          1 :                 return true;
     254                 :            :         }
     255                 :            : 
     256                 :    1922753 :         return false;
     257                 :            : }
     258                 :            : 
     259                 :            : /* Common call back function for read/write/flush command */
     260                 :            : static void
     261                 :    1922754 : bdev_iscsi_command_cb(struct iscsi_context *context, int status, void *_task, void *_iscsi_io)
     262                 :            : {
     263                 :    1922754 :         struct scsi_task *task = _task;
     264                 :    1922754 :         struct bdev_iscsi_io *iscsi_io = _iscsi_io;
     265                 :            :         struct spdk_bdev_io *bdev_io;
     266                 :            : 
     267                 :    1922754 :         iscsi_io->scsi_status = status;
     268                 :    1922754 :         iscsi_io->sk = (uint8_t)task->sense.key;
     269                 :    1922754 :         iscsi_io->asc = (task->sense.ascq >> 8) & 0xFF;
     270                 :    1922754 :         iscsi_io->ascq = task->sense.ascq & 0xFF;
     271                 :            : 
     272         [ +  + ]:    1922754 :         if (_bdev_iscsi_is_size_change(status, task)) {
     273                 :          1 :                 bdev_iscsi_readcapacity16(context, iscsi_io->lun);
     274                 :            : 
     275                 :            :                 /* Retry this failed IO immediately */
     276                 :          1 :                 bdev_io = spdk_bdev_io_from_ctx(iscsi_io);
     277         [ -  + ]:          1 :                 if (iscsi_io->submit_td != NULL) {
     278                 :          0 :                         spdk_thread_send_msg(iscsi_io->lun->main_td,
     279                 :            :                                              _bdev_iscsi_submit_request, bdev_io);
     280                 :            :                 } else {
     281                 :          1 :                         _bdev_iscsi_submit_request(bdev_io);
     282                 :            :                 }
     283                 :            :         } else {
     284                 :    1922753 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_SUCCESS);
     285                 :            :         }
     286                 :            : 
     287                 :    1922754 :         scsi_free_scsi_task(task);
     288                 :    1922754 : }
     289                 :            : 
     290                 :            : static int
     291                 :          1 : bdev_iscsi_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_block)
     292                 :            : {
     293                 :            :         int rc;
     294                 :            : 
     295         [ -  + ]:          1 :         assert(bdev->module == &g_iscsi_bdev_module);
     296                 :            : 
     297         [ -  + ]:          1 :         if (new_size_in_block <= bdev->blockcnt) {
     298                 :          0 :                 SPDK_ERRLOG("The new bdev size must be larger than current bdev size.\n");
     299                 :          0 :                 return -EINVAL;
     300                 :            :         }
     301                 :            : 
     302                 :          1 :         rc = spdk_bdev_notify_blockcnt_change(bdev, new_size_in_block);
     303         [ -  + ]:          1 :         if (rc != 0) {
     304                 :          0 :                 SPDK_ERRLOG("failed to notify block cnt change.\n");
     305                 :          0 :                 return rc;
     306                 :            :         }
     307                 :            : 
     308                 :          1 :         return 0;
     309                 :            : }
     310                 :            : 
     311                 :            : static void
     312                 :          1 : bdev_iscsi_readcapacity16_cb(struct iscsi_context *context, int status, void *_task,
     313                 :            :                              void *private_data)
     314                 :            : {
     315                 :          1 :         struct bdev_iscsi_lun *lun = private_data;
     316                 :            :         struct scsi_readcapacity16 *readcap16;
     317                 :          1 :         struct scsi_task *task = _task;
     318                 :          1 :         uint64_t size_in_block = 0;
     319                 :            :         int rc;
     320                 :            : 
     321         [ -  + ]:          1 :         if (status != SPDK_SCSI_STATUS_GOOD) {
     322                 :          0 :                 SPDK_ERRLOG("iSCSI error: %s\n", iscsi_get_error(context));
     323                 :          0 :                 goto ret;
     324                 :            :         }
     325                 :            : 
     326                 :          1 :         readcap16 = scsi_datain_unmarshall(task);
     327         [ -  + ]:          1 :         if (!readcap16) {
     328                 :          0 :                 SPDK_ERRLOG("Read capacity error\n");
     329                 :          0 :                 goto ret;
     330                 :            :         }
     331                 :            : 
     332                 :          1 :         size_in_block = readcap16->returned_lba + 1;
     333                 :            : 
     334                 :          1 :         rc = bdev_iscsi_resize(&lun->bdev, size_in_block);
     335         [ +  - ]:          1 :         if (rc != 0) {
     336                 :          0 :                 SPDK_ERRLOG("Bdev (%s) resize error: %d\n", lun->bdev.name, rc);
     337                 :            :         }
     338                 :            : 
     339                 :          1 : ret:
     340                 :          1 :         scsi_free_scsi_task(task);
     341                 :          1 : }
     342                 :            : 
     343                 :            : static void
     344                 :          1 : bdev_iscsi_readcapacity16(struct iscsi_context *context, struct bdev_iscsi_lun *lun)
     345                 :            : {
     346                 :            :         struct scsi_task *task;
     347                 :            : 
     348                 :          1 :         task = iscsi_readcapacity16_task(context, lun->lun_id,
     349                 :            :                                          bdev_iscsi_readcapacity16_cb, lun);
     350         [ -  + ]:          1 :         if (task == NULL) {
     351                 :          0 :                 SPDK_ERRLOG("failed to get readcapacity16_task\n");
     352                 :            :         }
     353                 :          1 : }
     354                 :            : 
     355                 :            : static void
     356                 :     848940 : bdev_iscsi_readv(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io,
     357                 :            :                  struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t lba)
     358                 :            : {
     359                 :            :         struct scsi_task *task;
     360                 :            : 
     361   [ -  +  -  + ]:     848940 :         SPDK_DEBUGLOG(iscsi_init, "read %d iovs size %lu to lba: %#lx\n",
     362                 :            :                       iovcnt, nbytes, lba);
     363                 :            : 
     364                 :     848940 :         task = iscsi_read16_task(lun->context, lun->lun_id, lba, nbytes, lun->bdev.blocklen, 0, 0, 0, 0, 0,
     365                 :            :                                  bdev_iscsi_command_cb, iscsi_io);
     366         [ -  + ]:     848940 :         if (task == NULL) {
     367                 :          0 :                 SPDK_ERRLOG("failed to get read16_task\n");
     368                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     369                 :          0 :                 return;
     370                 :            :         }
     371                 :            : 
     372                 :            : #if defined(LIBISCSI_FEATURE_IOVECTOR)
     373                 :     848940 :         scsi_task_set_iov_in(task, (struct scsi_iovec *)iov, iovcnt);
     374                 :            : #else
     375                 :            :         int i;
     376                 :            :         for (i = 0; i < iovcnt; i++) {
     377                 :            :                 scsi_task_add_data_in_buffer(task, iov[i].iov_len, iov[i].iov_base);
     378                 :            :         }
     379                 :            : #endif
     380                 :            : }
     381                 :            : 
     382                 :            : static void
     383                 :     307546 : bdev_iscsi_writev(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io,
     384                 :            :                   struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t lba)
     385                 :            : {
     386                 :            :         struct scsi_task *task;
     387                 :            : 
     388   [ -  +  -  + ]:     307546 :         SPDK_DEBUGLOG(iscsi_init, "write %d iovs size %lu to lba: %#lx\n",
     389                 :            :                       iovcnt, nbytes, lba);
     390                 :            : 
     391                 :     307546 :         task = iscsi_write16_task(lun->context, lun->lun_id, lba, NULL, nbytes, lun->bdev.blocklen, 0, 0, 0,
     392                 :            :                                   0, 0,
     393                 :            :                                   bdev_iscsi_command_cb, iscsi_io);
     394         [ -  + ]:     307546 :         if (task == NULL) {
     395                 :          0 :                 SPDK_ERRLOG("failed to get write16_task\n");
     396                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     397                 :          0 :                 return;
     398                 :            :         }
     399                 :            : 
     400                 :            : #if defined(LIBISCSI_FEATURE_IOVECTOR)
     401                 :     307546 :         scsi_task_set_iov_out(task, (struct scsi_iovec *)iov, iovcnt);
     402                 :            : #else
     403                 :            :         int i;
     404                 :            :         for (i = 0; i < iovcnt; i++) {
     405                 :            :                 scsi_task_add_data_in_buffer(task, iov[i].iov_len, iov[i].iov_base);
     406                 :            :         }
     407                 :            : #endif
     408                 :            : }
     409                 :            : 
     410                 :            : static void
     411                 :          9 : bdev_iscsi_destruct_cb(void *ctx)
     412                 :            : {
     413                 :          9 :         struct bdev_iscsi_lun *lun = ctx;
     414                 :            : 
     415                 :          9 :         spdk_poller_unregister(&lun->no_main_ch_poller);
     416                 :          9 :         spdk_io_device_unregister(lun, _iscsi_free_lun);
     417                 :          9 : }
     418                 :            : 
     419                 :            : static int
     420                 :          9 : bdev_iscsi_destruct(void *ctx)
     421                 :            : {
     422                 :          9 :         struct bdev_iscsi_lun *lun = ctx;
     423                 :            : 
     424         [ -  + ]:          9 :         assert(lun->no_main_ch_poller_td);
     425                 :          9 :         spdk_thread_send_msg(lun->no_main_ch_poller_td, bdev_iscsi_destruct_cb, lun);
     426                 :          9 :         return 1;
     427                 :            : }
     428                 :            : 
     429                 :            : static void
     430                 :     456277 : bdev_iscsi_flush(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io, uint32_t num_blocks,
     431                 :            :                  int immed, uint64_t lba)
     432                 :            : {
     433                 :            :         struct scsi_task *task;
     434                 :            : 
     435                 :     456277 :         task = iscsi_synchronizecache16_task(lun->context, lun->lun_id, lba,
     436                 :            :                                              num_blocks, 0, immed, bdev_iscsi_command_cb, iscsi_io);
     437         [ -  + ]:     456277 :         if (task == NULL) {
     438                 :          0 :                 SPDK_ERRLOG("failed to get sync16_task\n");
     439                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     440                 :          0 :                 return;
     441                 :            :         }
     442                 :            : }
     443                 :            : 
     444                 :            : static void
     445                 :     309991 : bdev_iscsi_unmap(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io,
     446                 :            :                  uint64_t lba, uint64_t num_blocks)
     447                 :            : {
     448                 :            :         struct scsi_task *task;
     449                 :     309991 :         struct unmap_list list[BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT] = {};
     450                 :            :         struct unmap_list *entry;
     451                 :            :         uint32_t num_unmap_list;
     452                 :            :         uint64_t offset, remaining, unmap_blocks;
     453                 :            : 
     454                 :     309991 :         num_unmap_list = spdk_divide_round_up(num_blocks, lun->max_unmap);
     455         [ -  + ]:     309991 :         if (num_unmap_list > BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT) {
     456                 :          0 :                 SPDK_ERRLOG("Too many unmap entries\n");
     457                 :          0 :                 goto failed;
     458                 :            :         }
     459                 :            : 
     460                 :     309991 :         remaining = num_blocks;
     461                 :     309991 :         offset = lba;
     462                 :     309991 :         num_unmap_list = 0;
     463                 :     309991 :         entry = &list[0];
     464                 :            : 
     465                 :            :         do {
     466                 :     309991 :                 unmap_blocks = spdk_min(remaining, lun->max_unmap);
     467                 :     309991 :                 entry->lba = offset;
     468                 :     309991 :                 entry->num = unmap_blocks;
     469                 :     309991 :                 num_unmap_list++;
     470                 :     309991 :                 remaining -= unmap_blocks;
     471                 :     309991 :                 offset += unmap_blocks;
     472                 :     309991 :                 entry++;
     473         [ -  + ]:     309991 :         } while (remaining > 0);
     474                 :            : 
     475                 :     309991 :         task = iscsi_unmap_task(lun->context, lun->lun_id, 0, 0, list, num_unmap_list,
     476                 :            :                                 bdev_iscsi_command_cb, iscsi_io);
     477         [ +  - ]:     309991 :         if (task != NULL) {
     478                 :     309991 :                 return;
     479                 :            :         }
     480                 :          0 :         SPDK_ERRLOG("failed to get unmap_task\n");
     481                 :            : 
     482                 :          0 : failed:
     483                 :          0 :         bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     484                 :            : }
     485                 :            : 
     486                 :            : static void
     487                 :          0 : bdev_iscsi_reset_cb(struct iscsi_context *context __attribute__((unused)), int status,
     488                 :            :                     void *command_data, void *private_data)
     489                 :            : {
     490                 :            :         uint32_t tmf_response;
     491                 :          0 :         struct bdev_iscsi_io *iscsi_io = private_data;
     492                 :            : 
     493                 :          0 :         tmf_response = *(uint32_t *)command_data;
     494         [ #  # ]:          0 :         if (tmf_response == ISCSI_TASK_FUNC_RESP_COMPLETE) {
     495                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_SUCCESS);
     496                 :            :         } else {
     497                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     498                 :            :         }
     499                 :          0 : }
     500                 :            : 
     501                 :            : static void
     502                 :          0 : _bdev_iscsi_reset(void *_bdev_io)
     503                 :            : {
     504                 :            :         int rc;
     505                 :          0 :         struct spdk_bdev_io *bdev_io = _bdev_io;
     506                 :          0 :         struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt;
     507                 :          0 :         struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx;
     508                 :          0 :         struct iscsi_context *context = lun->context;
     509                 :            : 
     510                 :          0 :         rc = iscsi_task_mgmt_lun_reset_async(context, lun->lun_id,
     511                 :            :                                              bdev_iscsi_reset_cb, iscsi_io);
     512         [ #  # ]:          0 :         if (rc != 0) {
     513                 :          0 :                 SPDK_ERRLOG("failed to do iscsi reset\n");
     514                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     515                 :          0 :                 return;
     516                 :            :         }
     517                 :            : }
     518                 :            : 
     519                 :            : static void
     520                 :          0 : bdev_iscsi_reset(struct spdk_bdev_io *bdev_io)
     521                 :            : {
     522                 :          0 :         struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt;
     523                 :          0 :         spdk_thread_send_msg(lun->main_td, _bdev_iscsi_reset, bdev_io);
     524                 :          0 : }
     525                 :            : 
     526                 :            : static int
     527                 :    5745846 : bdev_iscsi_poll_lun(void *_lun)
     528                 :            : {
     529                 :    5745846 :         struct bdev_iscsi_lun *lun = _lun;
     530                 :    5745846 :         struct pollfd pfd = {};
     531                 :            : 
     532                 :    5745846 :         pfd.fd = iscsi_get_fd(lun->context);
     533                 :    5745846 :         pfd.events = iscsi_which_events(lun->context);
     534                 :            : 
     535         [ -  + ]:    5745846 :         if (poll(&pfd, 1, 0) < 0) {
     536                 :          0 :                 SPDK_ERRLOG("poll failed\n");
     537                 :          0 :                 return SPDK_POLLER_IDLE;
     538                 :            :         }
     539                 :            : 
     540         [ +  + ]:    5745846 :         if (pfd.revents != 0) {
     541         [ -  + ]:     317781 :                 if (iscsi_service(lun->context, pfd.revents) < 0) {
     542                 :          0 :                         SPDK_ERRLOG("iscsi_service failed: %s\n", iscsi_get_error(lun->context));
     543                 :            :                 }
     544                 :            : 
     545                 :     317781 :                 return SPDK_POLLER_BUSY;
     546                 :            :         }
     547                 :            : 
     548                 :    5428065 :         return SPDK_POLLER_IDLE;
     549                 :            : }
     550                 :            : 
     551                 :            : static int
     552                 :         34 : bdev_iscsi_poll_lun_timeout(void *_lun)
     553                 :            : {
     554                 :         34 :         struct bdev_iscsi_lun *lun = _lun;
     555                 :            :         /* passing 0 here to iscsi_service means do nothing except for timeout checks */
     556                 :         34 :         iscsi_service(lun->context, 0);
     557                 :         34 :         return SPDK_POLLER_BUSY;
     558                 :            : }
     559                 :            : 
     560                 :            : static int
     561                 :       3663 : bdev_iscsi_no_main_ch_poll(void *arg)
     562                 :            : {
     563                 :       3663 :         struct bdev_iscsi_lun *lun = arg;
     564                 :       3663 :         enum spdk_thread_poller_rc rc = SPDK_POLLER_IDLE;
     565                 :            : 
     566   [ -  +  -  + ]:       3663 :         if (pthread_mutex_trylock(&lun->mutex)) {
     567                 :            :                 /* Don't care about the error code here. */
     568                 :          0 :                 return SPDK_POLLER_IDLE;
     569                 :            :         }
     570                 :            : 
     571         [ +  + ]:       3663 :         if (lun->ch_count == 0) {
     572                 :        271 :                 rc = bdev_iscsi_poll_lun(arg);
     573                 :            :         }
     574                 :            : 
     575         [ -  + ]:       3663 :         pthread_mutex_unlock(&lun->mutex);
     576                 :       3663 :         return rc;
     577                 :            : }
     578                 :            : 
     579                 :            : static void
     580                 :     848940 : bdev_iscsi_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
     581                 :            :                       bool success)
     582                 :            : {
     583         [ -  + ]:     848940 :         if (!success) {
     584                 :          0 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
     585                 :          0 :                 return;
     586                 :            :         }
     587                 :            : 
     588                 :    2546820 :         bdev_iscsi_readv((struct bdev_iscsi_lun *)bdev_io->bdev->ctxt,
     589                 :     848940 :                          (struct bdev_iscsi_io *)bdev_io->driver_ctx,
     590                 :            :                          bdev_io->u.bdev.iovs,
     591                 :            :                          bdev_io->u.bdev.iovcnt,
     592                 :     848940 :                          bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen,
     593                 :            :                          bdev_io->u.bdev.offset_blocks);
     594                 :            : }
     595                 :            : 
     596                 :            : static void
     597                 :    1922754 : _bdev_iscsi_submit_request(void *_bdev_io)
     598                 :            : {
     599                 :    1922754 :         struct spdk_bdev_io *bdev_io = _bdev_io;
     600                 :    1922754 :         struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx;
     601                 :    1922754 :         struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt;
     602                 :            : 
     603   [ +  +  +  -  :    1922754 :         switch (bdev_io->type) {
                   +  - ]
     604                 :     848940 :         case SPDK_BDEV_IO_TYPE_READ:
     605                 :     848940 :                 spdk_bdev_io_get_buf(bdev_io, bdev_iscsi_get_buf_cb,
     606                 :     848940 :                                      bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
     607                 :     848940 :                 break;
     608                 :            : 
     609                 :     307546 :         case SPDK_BDEV_IO_TYPE_WRITE:
     610                 :     615092 :                 bdev_iscsi_writev(lun, iscsi_io,
     611                 :            :                                   bdev_io->u.bdev.iovs,
     612                 :            :                                   bdev_io->u.bdev.iovcnt,
     613                 :     307546 :                                   bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen,
     614                 :            :                                   bdev_io->u.bdev.offset_blocks);
     615                 :     307546 :                 break;
     616                 :     456277 :         case SPDK_BDEV_IO_TYPE_FLUSH:
     617                 :     456277 :                 bdev_iscsi_flush(lun, iscsi_io,
     618                 :     456277 :                                  bdev_io->u.bdev.num_blocks,
     619                 :            :                                  ISCSI_IMMEDIATE_DATA_NO,
     620                 :            :                                  bdev_io->u.bdev.offset_blocks);
     621                 :     456277 :                 break;
     622                 :          0 :         case SPDK_BDEV_IO_TYPE_RESET:
     623                 :          0 :                 bdev_iscsi_reset(bdev_io);
     624                 :          0 :                 break;
     625                 :     309991 :         case SPDK_BDEV_IO_TYPE_UNMAP:
     626                 :     309991 :                 bdev_iscsi_unmap(lun, iscsi_io,
     627                 :            :                                  bdev_io->u.bdev.offset_blocks,
     628                 :            :                                  bdev_io->u.bdev.num_blocks);
     629                 :     309991 :                 break;
     630                 :          0 :         default:
     631                 :          0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     632                 :          0 :                 break;
     633                 :            :         }
     634                 :    1922754 : }
     635                 :            : 
     636                 :            : static void
     637                 :    1922753 : bdev_iscsi_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
     638                 :            : {
     639                 :    1922753 :         struct spdk_thread *submit_td = spdk_io_channel_get_thread(_ch);
     640                 :    1922753 :         struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx;
     641                 :    1922753 :         struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt;
     642                 :            : 
     643                 :    1922753 :         iscsi_io->lun = lun;
     644                 :            : 
     645         [ -  + ]:    1922753 :         if (lun->main_td != submit_td) {
     646                 :          0 :                 iscsi_io->submit_td = submit_td;
     647                 :          0 :                 spdk_thread_send_msg(lun->main_td, _bdev_iscsi_submit_request, bdev_io);
     648                 :          0 :                 return;
     649                 :            :         } else {
     650                 :    1922753 :                 iscsi_io->submit_td = NULL;
     651                 :            :         }
     652                 :            : 
     653                 :    1922753 :         _bdev_iscsi_submit_request(bdev_io);
     654                 :            : }
     655                 :            : 
     656                 :            : static bool
     657                 :         53 : bdev_iscsi_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
     658                 :            : {
     659                 :         53 :         struct bdev_iscsi_lun *lun = ctx;
     660                 :            : 
     661      [ +  +  + ]:         53 :         switch (io_type) {
     662                 :         10 :         case SPDK_BDEV_IO_TYPE_READ:
     663                 :            :         case SPDK_BDEV_IO_TYPE_WRITE:
     664                 :            :         case SPDK_BDEV_IO_TYPE_FLUSH:
     665                 :            :         case SPDK_BDEV_IO_TYPE_RESET:
     666                 :         10 :                 return true;
     667                 :            : 
     668                 :          4 :         case SPDK_BDEV_IO_TYPE_UNMAP:
     669         [ -  + ]:          4 :                 return lun->unmap_supported;
     670                 :         39 :         default:
     671                 :         39 :                 return false;
     672                 :            :         }
     673                 :            : }
     674                 :            : 
     675                 :            : static int
     676                 :         18 : bdev_iscsi_create_cb(void *io_device, void *ctx_buf)
     677                 :            : {
     678                 :         18 :         struct bdev_iscsi_io_channel *ch = ctx_buf;
     679                 :         18 :         struct bdev_iscsi_lun *lun = io_device;
     680                 :            : 
     681         [ -  + ]:         18 :         pthread_mutex_lock(&lun->mutex);
     682         [ +  - ]:         18 :         if (lun->ch_count == 0) {
     683         [ -  + ]:         18 :                 assert(lun->main_td == NULL);
     684                 :         18 :                 lun->main_td = spdk_get_thread();
     685                 :         18 :                 lun->poller = SPDK_POLLER_REGISTER(bdev_iscsi_poll_lun, lun, 0);
     686         [ +  - ]:         18 :                 if (g_opts.timeout_sec > 0) {
     687                 :         18 :                         lun->timeout_poller = SPDK_POLLER_REGISTER(bdev_iscsi_poll_lun_timeout, lun,
     688                 :            :                                               g_opts.timeout_poller_period_us);
     689                 :            :                 }
     690                 :         18 :                 ch->lun = lun;
     691                 :            :         }
     692                 :         18 :         lun->ch_count++;
     693         [ -  + ]:         18 :         pthread_mutex_unlock(&lun->mutex);
     694                 :            : 
     695                 :         18 :         return 0;
     696                 :            : }
     697                 :            : 
     698                 :            : static void
     699                 :          0 : _iscsi_destroy_cb(void *ctx)
     700                 :            : {
     701                 :          0 :         struct bdev_iscsi_lun *lun = ctx;
     702                 :            : 
     703         [ #  # ]:          0 :         pthread_mutex_lock(&lun->mutex);
     704                 :            : 
     705         [ #  # ]:          0 :         assert(lun->main_td == spdk_get_thread());
     706         [ #  # ]:          0 :         assert(lun->ch_count > 0);
     707                 :            : 
     708                 :          0 :         lun->ch_count--;
     709         [ #  # ]:          0 :         if (lun->ch_count > 0) {
     710         [ #  # ]:          0 :                 pthread_mutex_unlock(&lun->mutex);
     711                 :          0 :                 return;
     712                 :            :         }
     713                 :            : 
     714                 :          0 :         lun->main_td = NULL;
     715                 :          0 :         spdk_poller_unregister(&lun->poller);
     716                 :          0 :         spdk_poller_unregister(&lun->timeout_poller);
     717                 :            : 
     718         [ #  # ]:          0 :         pthread_mutex_unlock(&lun->mutex);
     719                 :            : }
     720                 :            : 
     721                 :            : static void
     722                 :         18 : bdev_iscsi_destroy_cb(void *io_device, void *ctx_buf)
     723                 :            : {
     724                 :         18 :         struct bdev_iscsi_lun *lun = io_device;
     725                 :            :         struct spdk_thread *thread;
     726                 :            : 
     727         [ -  + ]:         18 :         pthread_mutex_lock(&lun->mutex);
     728                 :         18 :         lun->ch_count--;
     729         [ +  - ]:         18 :         if (lun->ch_count == 0) {
     730         [ -  + ]:         18 :                 assert(lun->main_td != NULL);
     731                 :            : 
     732         [ -  + ]:         18 :                 if (lun->main_td != spdk_get_thread()) {
     733                 :            :                         /* The final channel was destroyed on a different thread
     734                 :            :                          * than where the first channel was created. Pass a message
     735                 :            :                          * to the main thread to unregister the poller. */
     736                 :          0 :                         lun->ch_count++;
     737                 :          0 :                         thread = lun->main_td;
     738         [ #  # ]:          0 :                         pthread_mutex_unlock(&lun->mutex);
     739                 :          0 :                         spdk_thread_send_msg(thread, _iscsi_destroy_cb, lun);
     740                 :          0 :                         return;
     741                 :            :                 }
     742                 :            : 
     743                 :         18 :                 lun->main_td = NULL;
     744                 :         18 :                 spdk_poller_unregister(&lun->poller);
     745                 :         18 :                 spdk_poller_unregister(&lun->timeout_poller);
     746                 :            :         }
     747         [ -  + ]:         18 :         pthread_mutex_unlock(&lun->mutex);
     748                 :            : }
     749                 :            : 
     750                 :            : static struct spdk_io_channel *
     751                 :         18 : bdev_iscsi_get_io_channel(void *ctx)
     752                 :            : {
     753                 :         18 :         struct bdev_iscsi_lun *lun = ctx;
     754                 :            : 
     755                 :         18 :         return spdk_get_io_channel(lun);
     756                 :            : }
     757                 :            : 
     758                 :            : static int
     759                 :          2 : bdev_iscsi_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
     760                 :            : {
     761                 :          2 :         struct bdev_iscsi_lun *lun = ctx;
     762                 :            : 
     763                 :          2 :         spdk_json_write_named_object_begin(w, "iscsi");
     764                 :          2 :         spdk_json_write_named_string(w, "initiator_name", lun->initiator_iqn);
     765                 :          2 :         spdk_json_write_named_string(w, "url", lun->url);
     766                 :          2 :         spdk_json_write_object_end(w);
     767                 :            : 
     768                 :          2 :         return 0;
     769                 :            : }
     770                 :            : 
     771                 :            : static void
     772                 :          0 : bdev_iscsi_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
     773                 :            : {
     774                 :          0 :         struct bdev_iscsi_lun *lun = bdev->ctxt;
     775                 :            : 
     776         [ #  # ]:          0 :         pthread_mutex_lock(&lun->mutex);
     777                 :          0 :         spdk_json_write_object_begin(w);
     778                 :            : 
     779                 :          0 :         spdk_json_write_named_string(w, "method", "bdev_iscsi_create");
     780                 :            : 
     781                 :          0 :         spdk_json_write_named_object_begin(w, "params");
     782                 :          0 :         spdk_json_write_named_string(w, "name", bdev->name);
     783                 :          0 :         spdk_json_write_named_string(w, "initiator_iqn", lun->initiator_iqn);
     784                 :          0 :         spdk_json_write_named_string(w, "url", lun->url);
     785                 :          0 :         spdk_json_write_object_end(w);
     786                 :            : 
     787                 :          0 :         spdk_json_write_object_end(w);
     788         [ #  # ]:          0 :         pthread_mutex_unlock(&lun->mutex);
     789                 :          0 : }
     790                 :            : 
     791                 :            : static const struct spdk_bdev_fn_table iscsi_fn_table = {
     792                 :            :         .destruct               = bdev_iscsi_destruct,
     793                 :            :         .submit_request         = bdev_iscsi_submit_request,
     794                 :            :         .io_type_supported      = bdev_iscsi_io_type_supported,
     795                 :            :         .get_io_channel         = bdev_iscsi_get_io_channel,
     796                 :            :         .dump_info_json         = bdev_iscsi_dump_info_json,
     797                 :            :         .write_config_json      = bdev_iscsi_write_config_json,
     798                 :            : };
     799                 :            : 
     800                 :            : static int
     801                 :          9 : create_iscsi_lun(struct bdev_iscsi_conn_req *req, uint64_t num_blocks,
     802                 :            :                  uint32_t block_size, struct spdk_bdev **bdev, uint8_t lbppbe)
     803                 :            : {
     804                 :            :         struct bdev_iscsi_lun *lun;
     805                 :            :         int rc;
     806                 :            : 
     807                 :          9 :         lun = calloc(sizeof(*lun), 1);
     808         [ -  + ]:          9 :         if (!lun) {
     809                 :          0 :                 SPDK_ERRLOG("Unable to allocate enough memory for iscsi backend\n");
     810                 :          0 :                 return -ENOMEM;
     811                 :            :         }
     812                 :            : 
     813                 :          9 :         lun->context = req->context;
     814                 :          9 :         lun->lun_id = req->lun;
     815                 :          9 :         lun->url = req->url;
     816                 :          9 :         lun->initiator_iqn = req->initiator_iqn;
     817                 :            : 
     818         [ -  + ]:          9 :         pthread_mutex_init(&lun->mutex, NULL);
     819                 :            : 
     820                 :          9 :         lun->bdev.name = req->bdev_name;
     821                 :          9 :         lun->bdev.product_name = "iSCSI LUN";
     822                 :          9 :         lun->bdev.module = &g_iscsi_bdev_module;
     823                 :          9 :         lun->bdev.blocklen = block_size;
     824         [ -  + ]:          9 :         lun->bdev.phys_blocklen = block_size * (1 << lbppbe);
     825                 :          9 :         lun->bdev.blockcnt = num_blocks;
     826                 :          9 :         lun->bdev.ctxt = lun;
     827         [ -  + ]:          9 :         lun->unmap_supported = req->unmap_supported;
     828   [ -  +  +  + ]:          9 :         if (lun->unmap_supported) {
     829                 :          8 :                 lun->max_unmap = req->max_unmap;
     830                 :          8 :                 lun->bdev.max_unmap = req->max_unmap;
     831                 :          8 :                 lun->bdev.max_unmap_segments = BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT;
     832                 :            :         }
     833                 :            : 
     834                 :          9 :         lun->bdev.fn_table = &iscsi_fn_table;
     835                 :            : 
     836                 :          9 :         spdk_io_device_register(lun, bdev_iscsi_create_cb, bdev_iscsi_destroy_cb,
     837                 :            :                                 sizeof(struct bdev_iscsi_io_channel),
     838                 :          9 :                                 req->bdev_name);
     839                 :          9 :         rc = spdk_bdev_register(&lun->bdev);
     840         [ -  + ]:          9 :         if (rc) {
     841                 :          0 :                 spdk_io_device_unregister(lun, NULL);
     842         [ #  # ]:          0 :                 pthread_mutex_destroy(&lun->mutex);
     843                 :          0 :                 free(lun);
     844                 :          0 :                 return rc;
     845                 :            :         }
     846                 :            : 
     847                 :          9 :         lun->no_main_ch_poller_td = spdk_get_thread();
     848                 :          9 :         lun->no_main_ch_poller = SPDK_POLLER_REGISTER(bdev_iscsi_no_main_ch_poll, lun,
     849                 :            :                                  BDEV_ISCSI_NO_MAIN_CH_POLL_US);
     850                 :            : 
     851                 :          9 :         *bdev = &lun->bdev;
     852                 :          9 :         return 0;
     853                 :            : }
     854                 :            : 
     855                 :            : static void
     856                 :          9 : iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
     857                 :            :                         void *command_data, void *private_data)
     858                 :            : {
     859                 :          9 :         struct bdev_iscsi_conn_req *req = private_data;
     860                 :            :         struct scsi_readcapacity16 *readcap16;
     861                 :          9 :         struct spdk_bdev *bdev = NULL;
     862                 :          9 :         struct scsi_task *task = command_data;
     863                 :          9 :         struct scsi_task *retry_task = NULL;
     864                 :            : 
     865         [ -  + ]:          9 :         if (status != SPDK_SCSI_STATUS_GOOD) {
     866                 :          0 :                 SPDK_ERRLOG("iSCSI error: %s\n", iscsi_get_error(iscsi));
     867         [ #  # ]:          0 :                 if (_bdev_iscsi_is_size_change(status, task)) {
     868                 :          0 :                         scsi_free_scsi_task(task);
     869                 :          0 :                         retry_task = iscsi_readcapacity16_task(iscsi, req->lun,
     870                 :            :                                                                iscsi_readcapacity16_cb, req);
     871         [ #  # ]:          0 :                         if (retry_task) {
     872                 :          0 :                                 return;
     873                 :            :                         }
     874                 :            :                 }
     875                 :          0 :                 goto ret;
     876                 :            :         }
     877                 :            : 
     878                 :          9 :         readcap16 = scsi_datain_unmarshall(task);
     879         [ -  + ]:          9 :         if (!readcap16) {
     880                 :          0 :                 status = -ENOMEM;
     881                 :          0 :                 goto ret;
     882                 :            :         }
     883                 :            : 
     884                 :          9 :         status = create_iscsi_lun(req, readcap16->returned_lba + 1, readcap16->block_length, &bdev,
     885                 :          9 :                                   readcap16->lbppbe);
     886         [ +  - ]:          9 :         if (status) {
     887                 :          0 :                 SPDK_ERRLOG("Unable to create iscsi bdev: %s (%d)\n", spdk_strerror(-status), status);
     888                 :            :         }
     889                 :            : 
     890                 :          9 : ret:
     891                 :          9 :         scsi_free_scsi_task(task);
     892                 :          9 :         complete_conn_req(req, bdev, status);
     893                 :            : }
     894                 :            : 
     895                 :            : static void
     896                 :          8 : bdev_iscsi_inquiry_bl_cb(struct iscsi_context *context, int status, void *_task, void *private_data)
     897                 :            : {
     898                 :          8 :         struct scsi_task *task = _task;
     899                 :          8 :         struct scsi_inquiry_block_limits *bl_inq = NULL;
     900                 :          8 :         struct bdev_iscsi_conn_req *req = private_data;
     901                 :            : 
     902         [ +  - ]:          8 :         if (status == SPDK_SCSI_STATUS_GOOD) {
     903                 :          8 :                 bl_inq = scsi_datain_unmarshall(task);
     904         [ +  - ]:          8 :                 if (bl_inq != NULL) {
     905         [ -  + ]:          8 :                         if (!bl_inq->max_unmap) {
     906                 :          0 :                                 SPDK_ERRLOG("Invalid max_unmap, use the default\n");
     907                 :          0 :                                 req->max_unmap = BDEV_ISCSI_DEFAULT_MAX_UNMAP_LBA_COUNT;
     908                 :            :                         } else {
     909                 :          8 :                                 req->max_unmap = bl_inq->max_unmap;
     910                 :            :                         }
     911                 :            :                 }
     912                 :            :         }
     913                 :            : 
     914                 :          8 :         scsi_free_scsi_task(task);
     915                 :          8 :         task = iscsi_readcapacity16_task(context, req->lun, iscsi_readcapacity16_cb, req);
     916         [ +  - ]:          8 :         if (task) {
     917                 :          8 :                 return;
     918                 :            :         }
     919                 :            : 
     920                 :          0 :         SPDK_ERRLOG("iSCSI error: %s\n", iscsi_get_error(req->context));
     921                 :          0 :         complete_conn_req(req, NULL, status);
     922                 :            : }
     923                 :            : 
     924                 :            : static void
     925                 :          9 : bdev_iscsi_inquiry_lbp_cb(struct iscsi_context *context, int status, void *_task,
     926                 :            :                           void *private_data)
     927                 :            : {
     928                 :          9 :         struct scsi_task *task = _task;
     929                 :          9 :         struct scsi_inquiry_logical_block_provisioning *lbp_inq = NULL;
     930                 :          9 :         struct bdev_iscsi_conn_req *req = private_data;
     931                 :            : 
     932         [ +  + ]:          9 :         if (status == SPDK_SCSI_STATUS_GOOD) {
     933                 :          8 :                 lbp_inq = scsi_datain_unmarshall(task);
     934   [ +  -  +  - ]:          8 :                 if (lbp_inq != NULL && lbp_inq->lbpu) {
     935                 :          8 :                         req->unmap_supported = true;
     936                 :          8 :                         scsi_free_scsi_task(task);
     937                 :            : 
     938                 :          8 :                         task = iscsi_inquiry_task(context, req->lun, 1,
     939                 :            :                                                   SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,
     940                 :            :                                                   255, bdev_iscsi_inquiry_bl_cb, req);
     941         [ +  - ]:          8 :                         if (task) {
     942                 :          8 :                                 return;
     943                 :            :                         }
     944                 :            :                 }
     945                 :            :         } else {
     946                 :          1 :                 scsi_free_scsi_task(task);
     947                 :            :         }
     948                 :            : 
     949                 :          1 :         task = iscsi_readcapacity16_task(context, req->lun, iscsi_readcapacity16_cb, req);
     950         [ +  - ]:          1 :         if (task) {
     951                 :          1 :                 return;
     952                 :            :         }
     953                 :            : 
     954                 :          0 :         SPDK_ERRLOG("iSCSI error: %s\n", iscsi_get_error(req->context));
     955                 :          0 :         complete_conn_req(req, NULL, status);
     956                 :            : }
     957                 :            : 
     958                 :            : static void
     959                 :          9 : iscsi_connect_cb(struct iscsi_context *iscsi, int status,
     960                 :            :                  void *command_data, void *private_data)
     961                 :            : {
     962                 :          9 :         struct bdev_iscsi_conn_req *req = private_data;
     963                 :            :         struct scsi_task *task;
     964                 :            : 
     965         [ -  + ]:          9 :         if (status != SPDK_SCSI_STATUS_GOOD) {
     966                 :          0 :                 goto ret;
     967                 :            :         }
     968                 :            : 
     969                 :          9 :         task = iscsi_inquiry_task(iscsi, req->lun, 1,
     970                 :            :                                   SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
     971                 :            :                                   255, bdev_iscsi_inquiry_lbp_cb, req);
     972         [ +  - ]:          9 :         if (task) {
     973                 :          9 :                 return;
     974                 :            :         }
     975                 :            : 
     976                 :          0 : ret:
     977                 :          0 :         SPDK_ERRLOG("iSCSI error: %s\n", iscsi_get_error(req->context));
     978                 :          0 :         complete_conn_req(req, NULL, status);
     979                 :            : }
     980                 :            : 
     981                 :            : static int
     982                 :        111 : iscsi_bdev_conn_poll(void *arg)
     983                 :            : {
     984                 :            :         struct bdev_iscsi_conn_req *req, *tmp;
     985                 :          0 :         struct pollfd pfd;
     986                 :            :         struct iscsi_context *context;
     987                 :            : 
     988         [ +  + ]:        111 :         if (TAILQ_EMPTY(&g_iscsi_conn_req)) {
     989                 :          9 :                 spdk_poller_unregister(&g_conn_poller);
     990                 :          9 :                 return SPDK_POLLER_IDLE;
     991                 :            :         }
     992                 :            : 
     993         [ +  + ]:        204 :         TAILQ_FOREACH_SAFE(req, &g_iscsi_conn_req, link, tmp) {
     994                 :        102 :                 context = req->context;
     995                 :        102 :                 pfd.fd = iscsi_get_fd(context);
     996                 :        102 :                 pfd.events = iscsi_which_events(context);
     997                 :        102 :                 pfd.revents = 0;
     998         [ -  + ]:        102 :                 if (poll(&pfd, 1, 0) < 0) {
     999                 :          0 :                         SPDK_ERRLOG("poll failed\n");
    1000                 :          0 :                         return SPDK_POLLER_BUSY;
    1001                 :            :                 }
    1002                 :            : 
    1003         [ +  + ]:        102 :                 if (pfd.revents != 0) {
    1004         [ -  + ]:         97 :                         if (iscsi_service(context, pfd.revents) < 0) {
    1005                 :          0 :                                 SPDK_ERRLOG("iscsi_service failed: %s\n", iscsi_get_error(context));
    1006                 :            :                         }
    1007                 :            :                 }
    1008                 :            : 
    1009         [ +  + ]:        102 :                 if (req->status == 0) {
    1010                 :            :                         /*
    1011                 :            :                          * The request completed successfully.
    1012                 :            :                          */
    1013                 :          9 :                         free(req);
    1014         [ -  + ]:         93 :                 } else if (req->status > 0) {
    1015                 :            :                         /*
    1016                 :            :                          * An error has occurred during connecting.  This req has already
    1017                 :            :                          * been removed from the g_iscsi_conn_req list, but we needed to
    1018                 :            :                          * wait until iscsi_service unwound before we could free the req.
    1019                 :            :                          */
    1020                 :          0 :                         _bdev_iscsi_conn_req_free(req);
    1021                 :            :                 }
    1022                 :            :         }
    1023                 :        102 :         return SPDK_POLLER_BUSY;
    1024                 :            : }
    1025                 :            : 
    1026                 :            : int
    1027                 :          9 : create_iscsi_disk(const char *bdev_name, const char *url, const char *initiator_iqn,
    1028                 :            :                   spdk_bdev_iscsi_create_cb cb_fn, void *cb_arg)
    1029                 :            : {
    1030                 :            :         struct bdev_iscsi_conn_req *req;
    1031                 :          9 :         struct iscsi_url *iscsi_url = NULL;
    1032                 :            :         int rc;
    1033                 :            : 
    1034   [ +  -  +  -  :          9 :         if (!bdev_name || !url || !initiator_iqn || strlen(initiator_iqn) == 0 || !cb_fn) {
          +  -  +  -  -  
                      + ]
    1035                 :          0 :                 return -EINVAL;
    1036                 :            :         }
    1037                 :            : 
    1038                 :          9 :         req = calloc(1, sizeof(struct bdev_iscsi_conn_req));
    1039         [ -  + ]:          9 :         if (!req) {
    1040                 :          0 :                 SPDK_ERRLOG("Cannot allocate pointer of struct bdev_iscsi_conn_req\n");
    1041                 :          0 :                 return -ENOMEM;
    1042                 :            :         }
    1043                 :            : 
    1044                 :          9 :         req->status = SCSI_STATUS_GOOD;
    1045         [ -  + ]:          9 :         req->bdev_name = strdup(bdev_name);
    1046         [ -  + ]:          9 :         req->url = strdup(url);
    1047         [ -  + ]:          9 :         req->initiator_iqn = strdup(initiator_iqn);
    1048                 :          9 :         req->context = iscsi_create_context(initiator_iqn);
    1049   [ +  -  +  -  :          9 :         if (!req->bdev_name || !req->url || !req->initiator_iqn || !req->context) {
             +  -  -  + ]
    1050                 :          0 :                 SPDK_ERRLOG("Out of memory\n");
    1051                 :          0 :                 rc = -ENOMEM;
    1052                 :          0 :                 goto err;
    1053                 :            :         }
    1054                 :            : 
    1055                 :          9 :         req->create_cb = cb_fn;
    1056                 :          9 :         req->create_cb_arg = cb_arg;
    1057                 :            : 
    1058                 :          9 :         iscsi_url = iscsi_parse_full_url(req->context, url);
    1059         [ -  + ]:          9 :         if (iscsi_url == NULL) {
    1060                 :          0 :                 SPDK_ERRLOG("could not parse URL: %s\n", iscsi_get_error(req->context));
    1061                 :          0 :                 rc = -EINVAL;
    1062                 :          0 :                 goto err;
    1063                 :            :         }
    1064                 :            : 
    1065                 :          9 :         req->lun = iscsi_url->lun;
    1066                 :          9 :         rc = iscsi_set_session_type(req->context, ISCSI_SESSION_NORMAL);
    1067         [ +  - ]:          9 :         rc = rc ? rc : iscsi_set_header_digest(req->context, ISCSI_HEADER_DIGEST_NONE);
    1068         [ +  - ]:          9 :         rc = rc ? rc : iscsi_set_targetname(req->context, iscsi_url->target);
    1069         [ +  - ]:          9 :         rc = rc ? rc : iscsi_set_timeout(req->context, g_opts.timeout_sec);
    1070         [ +  - ]:          9 :         rc = rc ? rc : iscsi_full_connect_async(req->context, iscsi_url->portal, iscsi_url->lun,
    1071                 :            :                                                 iscsi_connect_cb, req);
    1072   [ +  -  -  + ]:          9 :         if (rc == 0 && iscsi_url->user[0] != '\0') {
    1073                 :          0 :                 rc = iscsi_set_initiator_username_pwd(req->context, iscsi_url->user, iscsi_url->passwd);
    1074                 :            :         }
    1075                 :            : 
    1076         [ -  + ]:          9 :         if (rc < 0) {
    1077                 :          0 :                 SPDK_ERRLOG("Failed to connect provided URL=%s: %s\n", url, iscsi_get_error(req->context));
    1078                 :          0 :                 goto err;
    1079                 :            :         }
    1080                 :            : 
    1081                 :          9 :         iscsi_destroy_url(iscsi_url);
    1082                 :          9 :         req->status = -1;
    1083                 :          9 :         TAILQ_INSERT_TAIL(&g_iscsi_conn_req, req, link);
    1084         [ +  - ]:          9 :         if (!g_conn_poller) {
    1085                 :          9 :                 g_conn_poller = SPDK_POLLER_REGISTER(iscsi_bdev_conn_poll, NULL, BDEV_ISCSI_CONNECTION_POLL_US);
    1086                 :            :         }
    1087                 :            : 
    1088                 :          9 :         return 0;
    1089                 :            : 
    1090                 :          0 : err:
    1091                 :            :         /* iscsi_destroy_url() is not NULL-proof */
    1092         [ #  # ]:          0 :         if (iscsi_url) {
    1093                 :          0 :                 iscsi_destroy_url(iscsi_url);
    1094                 :            :         }
    1095                 :            : 
    1096         [ #  # ]:          0 :         if (req->context) {
    1097                 :          0 :                 iscsi_destroy_context(req->context);
    1098                 :            :         }
    1099                 :            : 
    1100                 :          0 :         free(req->initiator_iqn);
    1101                 :          0 :         free(req->bdev_name);
    1102                 :          0 :         free(req->url);
    1103                 :          0 :         free(req);
    1104                 :          0 :         return rc;
    1105                 :            : }
    1106                 :            : 
    1107                 :            : void
    1108                 :          0 : delete_iscsi_disk(const char *bdev_name, spdk_delete_iscsi_complete cb_fn, void *cb_arg)
    1109                 :            : {
    1110                 :            :         int rc;
    1111                 :            : 
    1112                 :          0 :         rc = spdk_bdev_unregister_by_name(bdev_name, &g_iscsi_bdev_module, cb_fn, cb_arg);
    1113         [ #  # ]:          0 :         if (rc != 0) {
    1114                 :          0 :                 cb_fn(cb_arg, rc);
    1115                 :            :         }
    1116                 :          0 : }
    1117                 :            : 
    1118                 :            : static int
    1119                 :       1716 : bdev_iscsi_initialize(void)
    1120                 :            : {
    1121                 :       1716 :         return 0;
    1122                 :            : }
    1123                 :            : 
    1124                 :       1850 : SPDK_LOG_REGISTER_COMPONENT(iscsi_init)

Generated by: LCOV version 1.14