LCOV - code coverage report
Current view: top level - module/bdev/iscsi - bdev_iscsi.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 525 0.0 %
Date: 2024-11-05 10:06:02 Functions: 0 49 0.0 %

          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           0 : bdev_iscsi_get_opts(struct spdk_bdev_iscsi_opts *opts)
     110             : {
     111           0 :         *opts = g_opts;
     112           0 : }
     113             : 
     114             : int
     115           0 : bdev_iscsi_set_opts(struct spdk_bdev_iscsi_opts *opts)
     116             : {
     117             :         /* make the poller period equal to timeout / 30 */
     118           0 :         opts->timeout_poller_period_us = (opts->timeout_sec * 1000000ULL) /
     119             :                                          BDEV_ISCSI_TIMEOUT_POLL_PERIOD_DIVISOR;
     120             : 
     121           0 :         g_opts = *opts;
     122             : 
     123           0 :         return 0;
     124             : }
     125             : 
     126             : static void
     127           0 : complete_conn_req(struct bdev_iscsi_conn_req *req, struct spdk_bdev *bdev,
     128             :                   int status)
     129             : {
     130           0 :         TAILQ_REMOVE(&g_iscsi_conn_req, req, link);
     131           0 :         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           0 :         req->status = status;
     138           0 : }
     139             : 
     140             : static int
     141           0 : bdev_iscsi_get_ctx_size(void)
     142             : {
     143           0 :         return sizeof(struct bdev_iscsi_io);
     144             : }
     145             : 
     146             : static void
     147           0 : _iscsi_free_lun(void *arg)
     148             : {
     149           0 :         struct bdev_iscsi_lun *lun = arg;
     150             : 
     151           0 :         assert(lun != NULL);
     152           0 :         iscsi_destroy_context(lun->context);
     153           0 :         pthread_mutex_destroy(&lun->mutex);
     154           0 :         free(lun->bdev.name);
     155           0 :         free(lun->url);
     156           0 :         free(lun->initiator_iqn);
     157             : 
     158           0 :         spdk_bdev_destruct_done(&lun->bdev, 0);
     159           0 :         free(lun);
     160           0 : }
     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           0 : 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           0 :         TAILQ_FOREACH_SAFE(req, &g_iscsi_conn_req, link, tmp) {
     183           0 :                 _bdev_iscsi_conn_req_free(req);
     184             :         }
     185             : 
     186           0 :         if (g_conn_poller) {
     187           0 :                 spdk_poller_unregister(&g_conn_poller);
     188             :         }
     189           0 : }
     190             : 
     191             : static void
     192           0 : bdev_iscsi_opts_config_json(struct spdk_json_write_ctx *w)
     193             : {
     194           0 :         spdk_json_write_object_begin(w);
     195             : 
     196           0 :         spdk_json_write_named_string(w, "method", "bdev_iscsi_set_options");
     197             : 
     198           0 :         spdk_json_write_named_object_begin(w, "params");
     199           0 :         spdk_json_write_named_uint64(w, "timeout_sec", g_opts.timeout_sec);
     200           0 :         spdk_json_write_object_end(w);
     201             : 
     202           0 :         spdk_json_write_object_end(w);
     203           0 : }
     204             : 
     205             : static int
     206           0 : bdev_iscsi_config_json(struct spdk_json_write_ctx *w)
     207             : {
     208           0 :         bdev_iscsi_opts_config_json(w);
     209           0 :         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           0 : SPDK_BDEV_MODULE_REGISTER(iscsi, &g_iscsi_bdev_module);
     221             : 
     222             : static void
     223           0 : _bdev_iscsi_io_complete(void *_iscsi_io)
     224             : {
     225           0 :         struct bdev_iscsi_io *iscsi_io = _iscsi_io;
     226             : 
     227           0 :         if (iscsi_io->status == SPDK_BDEV_IO_STATUS_SUCCESS) {
     228           0 :                 spdk_bdev_io_complete_scsi_status(spdk_bdev_io_from_ctx(iscsi_io), iscsi_io->scsi_status,
     229           0 :                                                   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           0 : }
     234             : 
     235             : static void
     236           0 : bdev_iscsi_io_complete(struct bdev_iscsi_io *iscsi_io, enum spdk_bdev_io_status status)
     237             : {
     238           0 :         iscsi_io->status = status;
     239           0 :         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           0 :                 _bdev_iscsi_io_complete(iscsi_io);
     243             :         }
     244           0 : }
     245             : 
     246             : static bool
     247           0 : _bdev_iscsi_is_size_change(int status, struct scsi_task *task)
     248             : {
     249           0 :         if (status == SPDK_SCSI_STATUS_CHECK_CONDITION &&
     250           0 :             (uint8_t)task->sense.key == SPDK_SCSI_SENSE_UNIT_ATTENTION &&
     251           0 :             task->sense.ascq == 0x2a09) {
     252             :                 /* ASCQ: SCSI_SENSE_ASCQ_CAPACITY_DATA_HAS_CHANGED (0x2a09) */
     253           0 :                 return true;
     254             :         }
     255             : 
     256           0 :         return false;
     257             : }
     258             : 
     259             : /* Common call back function for read/write/flush command */
     260             : static void
     261           0 : bdev_iscsi_command_cb(struct iscsi_context *context, int status, void *_task, void *_iscsi_io)
     262             : {
     263           0 :         struct scsi_task *task = _task;
     264           0 :         struct bdev_iscsi_io *iscsi_io = _iscsi_io;
     265             :         struct spdk_bdev_io *bdev_io;
     266             : 
     267           0 :         iscsi_io->scsi_status = status;
     268           0 :         iscsi_io->sk = (uint8_t)task->sense.key;
     269           0 :         iscsi_io->asc = (task->sense.ascq >> 8) & 0xFF;
     270           0 :         iscsi_io->ascq = task->sense.ascq & 0xFF;
     271             : 
     272           0 :         if (_bdev_iscsi_is_size_change(status, task)) {
     273           0 :                 bdev_iscsi_readcapacity16(context, iscsi_io->lun);
     274             : 
     275             :                 /* Retry this failed IO immediately */
     276           0 :                 bdev_io = spdk_bdev_io_from_ctx(iscsi_io);
     277           0 :                 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           0 :                         _bdev_iscsi_submit_request(bdev_io);
     282             :                 }
     283             :         } else {
     284           0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_SUCCESS);
     285             :         }
     286             : 
     287           0 :         scsi_free_scsi_task(task);
     288           0 : }
     289             : 
     290             : static int
     291           0 : bdev_iscsi_resize(struct spdk_bdev *bdev, const uint64_t new_size_in_block)
     292             : {
     293             :         int rc;
     294             : 
     295           0 :         assert(bdev->module == &g_iscsi_bdev_module);
     296             : 
     297           0 :         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           0 :         rc = spdk_bdev_notify_blockcnt_change(bdev, new_size_in_block);
     303           0 :         if (rc != 0) {
     304           0 :                 SPDK_ERRLOG("failed to notify block cnt change.\n");
     305           0 :                 return rc;
     306             :         }
     307             : 
     308           0 :         return 0;
     309             : }
     310             : 
     311             : static void
     312           0 : bdev_iscsi_readcapacity16_cb(struct iscsi_context *context, int status, void *_task,
     313             :                              void *private_data)
     314             : {
     315           0 :         struct bdev_iscsi_lun *lun = private_data;
     316             :         struct scsi_readcapacity16 *readcap16;
     317           0 :         struct scsi_task *task = _task;
     318           0 :         uint64_t size_in_block = 0;
     319             :         int rc;
     320             : 
     321           0 :         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           0 :         readcap16 = scsi_datain_unmarshall(task);
     327           0 :         if (!readcap16) {
     328           0 :                 SPDK_ERRLOG("Read capacity error\n");
     329           0 :                 goto ret;
     330             :         }
     331             : 
     332           0 :         size_in_block = readcap16->returned_lba + 1;
     333             : 
     334           0 :         rc = bdev_iscsi_resize(&lun->bdev, size_in_block);
     335           0 :         if (rc != 0) {
     336           0 :                 SPDK_ERRLOG("Bdev (%s) resize error: %d\n", lun->bdev.name, rc);
     337             :         }
     338             : 
     339           0 : ret:
     340           0 :         scsi_free_scsi_task(task);
     341           0 : }
     342             : 
     343             : static void
     344           0 : bdev_iscsi_readcapacity16(struct iscsi_context *context, struct bdev_iscsi_lun *lun)
     345             : {
     346             :         struct scsi_task *task;
     347             : 
     348           0 :         task = iscsi_readcapacity16_task(context, lun->lun_id,
     349             :                                          bdev_iscsi_readcapacity16_cb, lun);
     350           0 :         if (task == NULL) {
     351           0 :                 SPDK_ERRLOG("failed to get readcapacity16_task\n");
     352             :         }
     353           0 : }
     354             : 
     355             : static void
     356           0 : 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           0 :         SPDK_DEBUGLOG(iscsi_init, "read %d iovs size %lu to lba: %#lx\n",
     362             :                       iovcnt, nbytes, lba);
     363             : 
     364           0 :         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           0 :         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           0 :         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           0 : 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           0 :         SPDK_DEBUGLOG(iscsi_init, "write %d iovs size %lu to lba: %#lx\n",
     389             :                       iovcnt, nbytes, lba);
     390             : 
     391           0 :         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           0 :         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           0 :         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           0 : bdev_iscsi_destruct_cb(void *ctx)
     412             : {
     413           0 :         struct bdev_iscsi_lun *lun = ctx;
     414             : 
     415           0 :         spdk_poller_unregister(&lun->no_main_ch_poller);
     416           0 :         spdk_io_device_unregister(lun, _iscsi_free_lun);
     417           0 : }
     418             : 
     419             : static int
     420           0 : bdev_iscsi_destruct(void *ctx)
     421             : {
     422           0 :         struct bdev_iscsi_lun *lun = ctx;
     423             : 
     424           0 :         assert(lun->no_main_ch_poller_td);
     425           0 :         spdk_thread_send_msg(lun->no_main_ch_poller_td, bdev_iscsi_destruct_cb, lun);
     426           0 :         return 1;
     427             : }
     428             : 
     429             : static void
     430           0 : 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           0 :         task = iscsi_synchronizecache16_task(lun->context, lun->lun_id, lba,
     436             :                                              num_blocks, 0, immed, bdev_iscsi_command_cb, iscsi_io);
     437           0 :         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           0 : 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           0 :         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           0 :         num_unmap_list = spdk_divide_round_up(num_blocks, lun->max_unmap);
     455           0 :         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           0 :         remaining = num_blocks;
     461           0 :         offset = lba;
     462           0 :         num_unmap_list = 0;
     463           0 :         entry = &list[0];
     464             : 
     465             :         do {
     466           0 :                 unmap_blocks = spdk_min(remaining, lun->max_unmap);
     467           0 :                 entry->lba = offset;
     468           0 :                 entry->num = unmap_blocks;
     469           0 :                 num_unmap_list++;
     470           0 :                 remaining -= unmap_blocks;
     471           0 :                 offset += unmap_blocks;
     472           0 :                 entry++;
     473           0 :         } while (remaining > 0);
     474             : 
     475           0 :         task = iscsi_unmap_task(lun->context, lun->lun_id, 0, 0, list, num_unmap_list,
     476             :                                 bdev_iscsi_command_cb, iscsi_io);
     477           0 :         if (task != NULL) {
     478           0 :                 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           0 : bdev_iscsi_poll_lun(void *_lun)
     528             : {
     529           0 :         struct bdev_iscsi_lun *lun = _lun;
     530           0 :         struct pollfd pfd = {};
     531             : 
     532           0 :         pfd.fd = iscsi_get_fd(lun->context);
     533           0 :         pfd.events = iscsi_which_events(lun->context);
     534             : 
     535           0 :         if (poll(&pfd, 1, 0) < 0) {
     536           0 :                 SPDK_ERRLOG("poll failed\n");
     537           0 :                 return SPDK_POLLER_IDLE;
     538             :         }
     539             : 
     540           0 :         if (pfd.revents != 0) {
     541           0 :                 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           0 :                 return SPDK_POLLER_BUSY;
     546             :         }
     547             : 
     548           0 :         return SPDK_POLLER_IDLE;
     549             : }
     550             : 
     551             : static int
     552           0 : bdev_iscsi_poll_lun_timeout(void *_lun)
     553             : {
     554           0 :         struct bdev_iscsi_lun *lun = _lun;
     555             :         /* passing 0 here to iscsi_service means do nothing except for timeout checks */
     556           0 :         iscsi_service(lun->context, 0);
     557           0 :         return SPDK_POLLER_BUSY;
     558             : }
     559             : 
     560             : static int
     561           0 : bdev_iscsi_no_main_ch_poll(void *arg)
     562             : {
     563           0 :         struct bdev_iscsi_lun *lun = arg;
     564           0 :         enum spdk_thread_poller_rc rc = SPDK_POLLER_IDLE;
     565             : 
     566           0 :         if (pthread_mutex_trylock(&lun->mutex)) {
     567             :                 /* Don't care about the error code here. */
     568           0 :                 return SPDK_POLLER_IDLE;
     569             :         }
     570             : 
     571           0 :         if (lun->ch_count == 0) {
     572           0 :                 rc = bdev_iscsi_poll_lun(arg);
     573             :         }
     574             : 
     575           0 :         pthread_mutex_unlock(&lun->mutex);
     576           0 :         return rc;
     577             : }
     578             : 
     579             : static void
     580           0 : bdev_iscsi_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
     581             :                       bool success)
     582             : {
     583           0 :         if (!success) {
     584           0 :                 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED);
     585           0 :                 return;
     586             :         }
     587             : 
     588           0 :         bdev_iscsi_readv((struct bdev_iscsi_lun *)bdev_io->bdev->ctxt,
     589           0 :                          (struct bdev_iscsi_io *)bdev_io->driver_ctx,
     590             :                          bdev_io->u.bdev.iovs,
     591             :                          bdev_io->u.bdev.iovcnt,
     592           0 :                          bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen,
     593             :                          bdev_io->u.bdev.offset_blocks);
     594             : }
     595             : 
     596             : static void
     597           0 : _bdev_iscsi_submit_request(void *_bdev_io)
     598             : {
     599           0 :         struct spdk_bdev_io *bdev_io = _bdev_io;
     600           0 :         struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx;
     601           0 :         struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt;
     602             : 
     603           0 :         switch (bdev_io->type) {
     604           0 :         case SPDK_BDEV_IO_TYPE_READ:
     605           0 :                 spdk_bdev_io_get_buf(bdev_io, bdev_iscsi_get_buf_cb,
     606           0 :                                      bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
     607           0 :                 break;
     608             : 
     609           0 :         case SPDK_BDEV_IO_TYPE_WRITE:
     610           0 :                 bdev_iscsi_writev(lun, iscsi_io,
     611             :                                   bdev_io->u.bdev.iovs,
     612             :                                   bdev_io->u.bdev.iovcnt,
     613           0 :                                   bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen,
     614             :                                   bdev_io->u.bdev.offset_blocks);
     615           0 :                 break;
     616           0 :         case SPDK_BDEV_IO_TYPE_FLUSH:
     617           0 :                 bdev_iscsi_flush(lun, iscsi_io,
     618           0 :                                  bdev_io->u.bdev.num_blocks,
     619             :                                  ISCSI_IMMEDIATE_DATA_NO,
     620             :                                  bdev_io->u.bdev.offset_blocks);
     621           0 :                 break;
     622           0 :         case SPDK_BDEV_IO_TYPE_RESET:
     623           0 :                 bdev_iscsi_reset(bdev_io);
     624           0 :                 break;
     625           0 :         case SPDK_BDEV_IO_TYPE_UNMAP:
     626           0 :                 bdev_iscsi_unmap(lun, iscsi_io,
     627             :                                  bdev_io->u.bdev.offset_blocks,
     628             :                                  bdev_io->u.bdev.num_blocks);
     629           0 :                 break;
     630           0 :         default:
     631           0 :                 bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED);
     632           0 :                 break;
     633             :         }
     634           0 : }
     635             : 
     636             : static void
     637           0 : bdev_iscsi_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io)
     638             : {
     639           0 :         struct spdk_thread *submit_td = spdk_io_channel_get_thread(_ch);
     640           0 :         struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx;
     641           0 :         struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt;
     642             : 
     643           0 :         iscsi_io->lun = lun;
     644             : 
     645           0 :         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           0 :                 iscsi_io->submit_td = NULL;
     651             :         }
     652             : 
     653           0 :         _bdev_iscsi_submit_request(bdev_io);
     654             : }
     655             : 
     656             : static bool
     657           0 : bdev_iscsi_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
     658             : {
     659           0 :         struct bdev_iscsi_lun *lun = ctx;
     660             : 
     661           0 :         switch (io_type) {
     662           0 :         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           0 :                 return true;
     667             : 
     668           0 :         case SPDK_BDEV_IO_TYPE_UNMAP:
     669           0 :                 return lun->unmap_supported;
     670           0 :         default:
     671           0 :                 return false;
     672             :         }
     673             : }
     674             : 
     675             : static int
     676           0 : bdev_iscsi_create_cb(void *io_device, void *ctx_buf)
     677             : {
     678           0 :         struct bdev_iscsi_io_channel *ch = ctx_buf;
     679           0 :         struct bdev_iscsi_lun *lun = io_device;
     680             : 
     681           0 :         pthread_mutex_lock(&lun->mutex);
     682           0 :         if (lun->ch_count == 0) {
     683           0 :                 assert(lun->main_td == NULL);
     684           0 :                 lun->main_td = spdk_get_thread();
     685           0 :                 lun->poller = SPDK_POLLER_REGISTER(bdev_iscsi_poll_lun, lun, 0);
     686           0 :                 if (g_opts.timeout_sec > 0) {
     687           0 :                         lun->timeout_poller = SPDK_POLLER_REGISTER(bdev_iscsi_poll_lun_timeout, lun,
     688             :                                               g_opts.timeout_poller_period_us);
     689             :                 }
     690           0 :                 ch->lun = lun;
     691             :         }
     692           0 :         lun->ch_count++;
     693           0 :         pthread_mutex_unlock(&lun->mutex);
     694             : 
     695           0 :         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           0 : bdev_iscsi_destroy_cb(void *io_device, void *ctx_buf)
     723             : {
     724           0 :         struct bdev_iscsi_lun *lun = io_device;
     725             :         struct spdk_thread *thread;
     726             : 
     727           0 :         pthread_mutex_lock(&lun->mutex);
     728           0 :         lun->ch_count--;
     729           0 :         if (lun->ch_count == 0) {
     730           0 :                 assert(lun->main_td != NULL);
     731             : 
     732           0 :                 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           0 :                 lun->main_td = NULL;
     744           0 :                 spdk_poller_unregister(&lun->poller);
     745           0 :                 spdk_poller_unregister(&lun->timeout_poller);
     746             :         }
     747           0 :         pthread_mutex_unlock(&lun->mutex);
     748             : }
     749             : 
     750             : static struct spdk_io_channel *
     751           0 : bdev_iscsi_get_io_channel(void *ctx)
     752             : {
     753           0 :         struct bdev_iscsi_lun *lun = ctx;
     754             : 
     755           0 :         return spdk_get_io_channel(lun);
     756             : }
     757             : 
     758             : static int
     759           0 : bdev_iscsi_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
     760             : {
     761           0 :         struct bdev_iscsi_lun *lun = ctx;
     762             : 
     763           0 :         spdk_json_write_named_object_begin(w, "iscsi");
     764           0 :         spdk_json_write_named_string(w, "initiator_name", lun->initiator_iqn);
     765           0 :         spdk_json_write_named_string(w, "url", lun->url);
     766           0 :         spdk_json_write_object_end(w);
     767             : 
     768           0 :         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           0 : 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           0 :         lun = calloc(1, sizeof(*lun));
     808           0 :         if (!lun) {
     809           0 :                 SPDK_ERRLOG("Unable to allocate enough memory for iscsi backend\n");
     810           0 :                 return -ENOMEM;
     811             :         }
     812             : 
     813           0 :         lun->context = req->context;
     814           0 :         lun->lun_id = req->lun;
     815           0 :         lun->url = req->url;
     816           0 :         lun->initiator_iqn = req->initiator_iqn;
     817             : 
     818           0 :         pthread_mutex_init(&lun->mutex, NULL);
     819             : 
     820           0 :         lun->bdev.name = req->bdev_name;
     821           0 :         lun->bdev.product_name = "iSCSI LUN";
     822           0 :         lun->bdev.module = &g_iscsi_bdev_module;
     823           0 :         lun->bdev.blocklen = block_size;
     824           0 :         lun->bdev.phys_blocklen = block_size * (1 << lbppbe);
     825           0 :         lun->bdev.blockcnt = num_blocks;
     826           0 :         lun->bdev.ctxt = lun;
     827           0 :         lun->unmap_supported = req->unmap_supported;
     828           0 :         if (lun->unmap_supported) {
     829           0 :                 lun->max_unmap = req->max_unmap;
     830           0 :                 lun->bdev.max_unmap = req->max_unmap;
     831           0 :                 lun->bdev.max_unmap_segments = BDEV_ISCSI_MAX_UNMAP_BLOCK_DESCS_COUNT;
     832             :         }
     833             : 
     834           0 :         lun->bdev.fn_table = &iscsi_fn_table;
     835             : 
     836           0 :         spdk_io_device_register(lun, bdev_iscsi_create_cb, bdev_iscsi_destroy_cb,
     837             :                                 sizeof(struct bdev_iscsi_io_channel),
     838           0 :                                 req->bdev_name);
     839           0 :         rc = spdk_bdev_register(&lun->bdev);
     840           0 :         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           0 :         lun->no_main_ch_poller_td = spdk_get_thread();
     848           0 :         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           0 :         *bdev = &lun->bdev;
     852           0 :         return 0;
     853             : }
     854             : 
     855             : static void
     856           0 : iscsi_readcapacity16_cb(struct iscsi_context *iscsi, int status,
     857             :                         void *command_data, void *private_data)
     858             : {
     859           0 :         struct bdev_iscsi_conn_req *req = private_data;
     860             :         struct scsi_readcapacity16 *readcap16;
     861           0 :         struct spdk_bdev *bdev = NULL;
     862           0 :         struct scsi_task *task = command_data;
     863           0 :         struct scsi_task *retry_task = NULL;
     864             : 
     865           0 :         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           0 :         readcap16 = scsi_datain_unmarshall(task);
     879           0 :         if (!readcap16) {
     880           0 :                 status = -ENOMEM;
     881           0 :                 goto ret;
     882             :         }
     883             : 
     884           0 :         status = create_iscsi_lun(req, readcap16->returned_lba + 1, readcap16->block_length, &bdev,
     885           0 :                                   readcap16->lbppbe);
     886           0 :         if (status) {
     887           0 :                 SPDK_ERRLOG("Unable to create iscsi bdev: %s (%d)\n", spdk_strerror(-status), status);
     888             :         }
     889             : 
     890           0 : ret:
     891           0 :         scsi_free_scsi_task(task);
     892           0 :         complete_conn_req(req, bdev, status);
     893             : }
     894             : 
     895             : static void
     896           0 : bdev_iscsi_inquiry_bl_cb(struct iscsi_context *context, int status, void *_task, void *private_data)
     897             : {
     898           0 :         struct scsi_task *task = _task;
     899           0 :         struct scsi_inquiry_block_limits *bl_inq = NULL;
     900           0 :         struct bdev_iscsi_conn_req *req = private_data;
     901             : 
     902           0 :         if (status == SPDK_SCSI_STATUS_GOOD) {
     903           0 :                 bl_inq = scsi_datain_unmarshall(task);
     904           0 :                 if (bl_inq != NULL) {
     905           0 :                         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           0 :                                 req->max_unmap = bl_inq->max_unmap;
     910             :                         }
     911             :                 }
     912             :         }
     913             : 
     914           0 :         scsi_free_scsi_task(task);
     915           0 :         task = iscsi_readcapacity16_task(context, req->lun, iscsi_readcapacity16_cb, req);
     916           0 :         if (task) {
     917           0 :                 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           0 : bdev_iscsi_inquiry_lbp_cb(struct iscsi_context *context, int status, void *_task,
     926             :                           void *private_data)
     927             : {
     928           0 :         struct scsi_task *task = _task;
     929           0 :         struct scsi_inquiry_logical_block_provisioning *lbp_inq = NULL;
     930           0 :         struct bdev_iscsi_conn_req *req = private_data;
     931             : 
     932           0 :         if (status == SPDK_SCSI_STATUS_GOOD) {
     933           0 :                 lbp_inq = scsi_datain_unmarshall(task);
     934           0 :                 if (lbp_inq != NULL && lbp_inq->lbpu) {
     935           0 :                         req->unmap_supported = true;
     936           0 :                         scsi_free_scsi_task(task);
     937             : 
     938           0 :                         task = iscsi_inquiry_task(context, req->lun, 1,
     939             :                                                   SCSI_INQUIRY_PAGECODE_BLOCK_LIMITS,
     940             :                                                   255, bdev_iscsi_inquiry_bl_cb, req);
     941           0 :                         if (task) {
     942           0 :                                 return;
     943             :                         }
     944             :                 }
     945             :         } else {
     946           0 :                 scsi_free_scsi_task(task);
     947             :         }
     948             : 
     949           0 :         task = iscsi_readcapacity16_task(context, req->lun, iscsi_readcapacity16_cb, req);
     950           0 :         if (task) {
     951           0 :                 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           0 : iscsi_connect_cb(struct iscsi_context *iscsi, int status,
     960             :                  void *command_data, void *private_data)
     961             : {
     962           0 :         struct bdev_iscsi_conn_req *req = private_data;
     963             :         struct scsi_task *task;
     964             : 
     965           0 :         if (status != SPDK_SCSI_STATUS_GOOD) {
     966           0 :                 goto ret;
     967             :         }
     968             : 
     969           0 :         task = iscsi_inquiry_task(iscsi, req->lun, 1,
     970             :                                   SCSI_INQUIRY_PAGECODE_LOGICAL_BLOCK_PROVISIONING,
     971             :                                   255, bdev_iscsi_inquiry_lbp_cb, req);
     972           0 :         if (task) {
     973           0 :                 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           0 : 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           0 :         if (TAILQ_EMPTY(&g_iscsi_conn_req)) {
     989           0 :                 spdk_poller_unregister(&g_conn_poller);
     990           0 :                 return SPDK_POLLER_IDLE;
     991             :         }
     992             : 
     993           0 :         TAILQ_FOREACH_SAFE(req, &g_iscsi_conn_req, link, tmp) {
     994           0 :                 context = req->context;
     995           0 :                 pfd.fd = iscsi_get_fd(context);
     996           0 :                 pfd.events = iscsi_which_events(context);
     997           0 :                 pfd.revents = 0;
     998           0 :                 if (poll(&pfd, 1, 0) < 0) {
     999           0 :                         SPDK_ERRLOG("poll failed\n");
    1000           0 :                         return SPDK_POLLER_BUSY;
    1001             :                 }
    1002             : 
    1003           0 :                 if (pfd.revents != 0) {
    1004           0 :                         if (iscsi_service(context, pfd.revents) < 0) {
    1005           0 :                                 SPDK_ERRLOG("iscsi_service failed: %s\n", iscsi_get_error(context));
    1006             :                         }
    1007             :                 }
    1008             : 
    1009           0 :                 if (req->status == 0) {
    1010             :                         /*
    1011             :                          * The request completed successfully.
    1012             :                          */
    1013           0 :                         free(req);
    1014           0 :                 } 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           0 :         return SPDK_POLLER_BUSY;
    1024             : }
    1025             : 
    1026             : int
    1027           0 : 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           0 :         struct iscsi_url *iscsi_url = NULL;
    1032             :         int rc;
    1033             : 
    1034           0 :         if (!bdev_name || !url || !initiator_iqn || strlen(initiator_iqn) == 0 || !cb_fn) {
    1035           0 :                 return -EINVAL;
    1036             :         }
    1037             : 
    1038           0 :         req = calloc(1, sizeof(struct bdev_iscsi_conn_req));
    1039           0 :         if (!req) {
    1040           0 :                 SPDK_ERRLOG("Cannot allocate pointer of struct bdev_iscsi_conn_req\n");
    1041           0 :                 return -ENOMEM;
    1042             :         }
    1043             : 
    1044           0 :         req->status = SCSI_STATUS_GOOD;
    1045           0 :         req->bdev_name = strdup(bdev_name);
    1046           0 :         req->url = strdup(url);
    1047           0 :         req->initiator_iqn = strdup(initiator_iqn);
    1048           0 :         req->context = iscsi_create_context(initiator_iqn);
    1049           0 :         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           0 :         req->create_cb = cb_fn;
    1056           0 :         req->create_cb_arg = cb_arg;
    1057             : 
    1058           0 :         iscsi_url = iscsi_parse_full_url(req->context, url);
    1059           0 :         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           0 :         req->lun = iscsi_url->lun;
    1066           0 :         rc = iscsi_set_session_type(req->context, ISCSI_SESSION_NORMAL);
    1067           0 :         rc = rc ? rc : iscsi_set_header_digest(req->context, ISCSI_HEADER_DIGEST_NONE);
    1068           0 :         rc = rc ? rc : iscsi_set_targetname(req->context, iscsi_url->target);
    1069           0 :         rc = rc ? rc : iscsi_set_timeout(req->context, g_opts.timeout_sec);
    1070           0 :         rc = rc ? rc : iscsi_full_connect_async(req->context, iscsi_url->portal, iscsi_url->lun,
    1071             :                                                 iscsi_connect_cb, req);
    1072           0 :         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           0 :         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           0 :         iscsi_destroy_url(iscsi_url);
    1082           0 :         req->status = -1;
    1083           0 :         TAILQ_INSERT_TAIL(&g_iscsi_conn_req, req, link);
    1084           0 :         if (!g_conn_poller) {
    1085           0 :                 g_conn_poller = SPDK_POLLER_REGISTER(iscsi_bdev_conn_poll, NULL, BDEV_ISCSI_CONNECTION_POLL_US);
    1086             :         }
    1087             : 
    1088           0 :         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           0 : bdev_iscsi_initialize(void)
    1120             : {
    1121           0 :         return 0;
    1122             : }
    1123             : 
    1124           0 : SPDK_LOG_REGISTER_COMPONENT(iscsi_init)

Generated by: LCOV version 1.15