diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a32f24b3..023814093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,12 @@ The prototype for spdk_poller_fn() has been modified; it now returns a value ind whether or not the poller did any work. Existing pollers will need to be updated to return a value. +### iSCSI initiator + +An iSCSI initiator bdev module has been added to SPDK. This module should be considered +experimental pending additional features and tests. More details can be found in +lib/bdev/iscsi/README. + ## v18.01: Blobstore Thin Provisioning ### Build System diff --git a/CONFIG b/CONFIG index 2edd0fee2..363a5d657 100644 --- a/CONFIG +++ b/CONFIG @@ -95,3 +95,6 @@ CONFIG_NVML?=n # Build with VPP CONFIG_VPP?=n + +# Requires libiscsi development libraries. +CONFIG_ISCSI_INITIATOR?=n diff --git a/configure b/configure index 919dd1d0a..f16c262b1 100755 --- a/configure +++ b/configure @@ -47,6 +47,8 @@ function usage() echo " No path required." echo " rdma [disabled]" echo " No path required." + echo " iscsi-initiator [disabled]" + echo " No path required." echo " vtune Required to profile I/O under Intel VTune Amplifier XE." echo " example: /opt/intel/vtune_amplifier_xe_version" echo "" @@ -133,6 +135,12 @@ for i in "$@"; do --without-rdma) CONFIG_RDMA=n ;; + --with-iscsi-initiator) + CONFIG_ISCSI_INITIATOR=y + ;; + --without-iscsi-initiator) + CONFIG_ISCSI_INITIATOR=n + ;; --with-dpdk=*) check_dir "$i" CONFIG_DPDK_DIR=$(readlink -f ${i#*=}) @@ -306,6 +314,9 @@ fi if [ -n "$CONFIG_RDMA" ]; then echo "CONFIG_RDMA?=$CONFIG_RDMA" >> CONFIG.local fi +if [ -n "$CONFIG_ISCSI_INITIATOR" ]; then + echo "CONFIG_ISCSI_INITIATOR?=$CONFIG_ISCSI_INITIATOR" >> CONFIG.local +fi if [ -n "$CONFIG_RBD" ]; then echo "CONFIG_RBD?=$CONFIG_RBD" >> CONFIG.local fi diff --git a/lib/bdev/Makefile b/lib/bdev/Makefile index aec8c0aa5..3abf6fd2c 100644 --- a/lib/bdev/Makefile +++ b/lib/bdev/Makefile @@ -46,6 +46,7 @@ DIRS-y += error gpt lvol malloc null nvme passthru rpc split ifeq ($(OS),Linux) DIRS-y += aio +DIRS-$(CONFIG_ISCSI_INITIATOR) += iscsi DIRS-$(CONFIG_VIRTIO) += virtio DIRS-$(CONFIG_NVML) += pmem endif diff --git a/lib/bdev/iscsi/Makefile b/lib/bdev/iscsi/Makefile new file mode 100644 index 000000000..dfaff337a --- /dev/null +++ b/lib/bdev/iscsi/Makefile @@ -0,0 +1,46 @@ +# +# BSD LICENSE +# +# Copyright (c) Intel Corporation. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +SPDK_ROOT_DIR := $(abspath $(CURDIR)/../../..) +include $(SPDK_ROOT_DIR)/mk/spdk.common.mk + +CFLAGS += -I$(SPDK_ROOT_DIR)/lib/bdev/ +# CentOS 7 libiscsi package has functions declared inline but not +# defined in the header file. Not aware of any way to disable +# this warning so just make sure the warning isn't treated as +# an error. +CFLAGS += -Wno-error +C_SRCS = bdev_iscsi.c +LIBNAME = bdev_iscsi + +include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/lib/bdev/iscsi/README b/lib/bdev/iscsi/README new file mode 100644 index 000000000..3e66e4383 --- /dev/null +++ b/lib/bdev/iscsi/README @@ -0,0 +1,24 @@ +This is a very rough initial cut at an SPDK iSCSI initiator bdev module. It +only performs operations (connect, login, read cap, read/write). +But this passes basic verify tests with bdevperf and with fio. + +Configuration file for iSCSI initiator is in the following format. +Note that the "/0" at the end means "LUN 0". + +[iSCSI_Initiator] + URL iscsi://127.0.0.1/iqn.2016-06.io.spdk:disk1/0 iSCSI0 + +To Do Items +=========== +1) Create RPCs. +2) Use asynchronous polling for connect/login/disconnect. Read/write is already + using libiscsi event framework. +3) Choose initiator name as part of RPC configuration. Currently this is hardcoded + with g_initiator string. +4) Implement reset path. +5) Implement unmap path. +6) Use REPORT_LUNS to dynamically find all of the block devices attached to the + iSCSI target node instead of hard-coding LUN 0. This will need some extra + investigation in libiscsi. Currently the full URL is used which includes the LUN. + Not sure yet how we can login to target node and then submit IO to different + LUNs. Let's treat this as low priority for now. diff --git a/lib/bdev/iscsi/bdev_iscsi.c b/lib/bdev/iscsi/bdev_iscsi.c new file mode 100644 index 000000000..1096c75f5 --- /dev/null +++ b/lib/bdev/iscsi/bdev_iscsi.c @@ -0,0 +1,505 @@ +/*- + * BSD LICENSE + * + * Copyright (c) Intel Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "spdk/stdinc.h" + +#include "spdk/bdev.h" +#include "spdk/conf.h" +#include "spdk/env.h" +#include "spdk/fd.h" +#include "spdk/io_channel.h" +#include "spdk/json.h" +#include "spdk/util.h" +#include "spdk/rpc.h" +#include "spdk/string.h" + +#include "spdk_internal/log.h" +#include "spdk_internal/bdev.h" + +#include "iscsi/iscsi.h" +#include "iscsi/scsi-lowlevel.h" + +struct bdev_iscsi_lun; + +#define DEFAULT_INITIATOR_NAME "iqn.2016-06.io.spdk:init" +static char *g_initiator; + +static int bdev_iscsi_initialize(void); +static TAILQ_HEAD(, bdev_iscsi_lun) g_iscsi_lun_head; + +struct bdev_iscsi_io { + struct spdk_thread *submit_td; + enum spdk_bdev_io_status status; + int scsi_status; + enum spdk_scsi_sense sk; + uint8_t asc; + uint8_t ascq; +}; + +struct bdev_iscsi_lun { + struct spdk_bdev bdev; + struct iscsi_context *context; + struct iscsi_url *url; + pthread_mutex_t mutex; + uint32_t ch_count; + struct bdev_iscsi_io_channel *master_ch; + struct spdk_thread *master_td; + TAILQ_ENTRY(bdev_iscsi_lun) link; +}; + +struct bdev_iscsi_io_channel { + struct spdk_poller *poller; + struct bdev_iscsi_lun *lun; +}; + +static int +bdev_iscsi_get_ctx_size(void) +{ + return sizeof(struct bdev_iscsi_io); +} + +static void bdev_iscsi_finish(void) +{ + struct bdev_iscsi_lun *lun; + + while (!TAILQ_EMPTY(&g_iscsi_lun_head)) { + lun = TAILQ_FIRST(&g_iscsi_lun_head); + TAILQ_REMOVE(&g_iscsi_lun_head, lun, link); + iscsi_logout_sync(lun->context); + iscsi_destroy_context(lun->context); + iscsi_destroy_url(lun->url); + } +} + +static struct spdk_bdev_module g_iscsi_bdev_module = { + .name = "iscsi", + .module_init = bdev_iscsi_initialize, + .module_fini = bdev_iscsi_finish, + .get_ctx_size = bdev_iscsi_get_ctx_size, +}; + +SPDK_BDEV_MODULE_REGISTER(&g_iscsi_bdev_module); + +static void +_bdev_iscsi_io_complete(void *_iscsi_io) +{ + struct bdev_iscsi_io *iscsi_io = _iscsi_io; + + if (iscsi_io->status == SPDK_BDEV_IO_STATUS_SUCCESS) { + spdk_bdev_io_complete_scsi_status(spdk_bdev_io_from_ctx(iscsi_io), iscsi_io->scsi_status, + iscsi_io->sk, iscsi_io->asc, iscsi_io->ascq); + } else { + spdk_bdev_io_complete(spdk_bdev_io_from_ctx(iscsi_io), iscsi_io->status); + } +} + +static void +bdev_iscsi_io_complete(struct bdev_iscsi_io *iscsi_io, enum spdk_bdev_io_status status) +{ + iscsi_io->status = status; + if (iscsi_io->submit_td != NULL) { + spdk_thread_send_msg(iscsi_io->submit_td, _bdev_iscsi_io_complete, iscsi_io); + } else { + _bdev_iscsi_io_complete(iscsi_io); + } +} + +static void +bdev_iscsi_rw_cb(struct iscsi_context *context, int status, void *_task, void *_iscsi_io) +{ + struct scsi_task *task = _task; + struct bdev_iscsi_io *iscsi_io = _iscsi_io; + + iscsi_io->scsi_status = task->status; + iscsi_io->sk = task->sense.key; + iscsi_io->asc = (task->sense.ascq >> 8) & 0xFF; + iscsi_io->ascq = task->sense.ascq & 0xFF; + + scsi_free_scsi_task(task); + bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_SUCCESS); +} + +static void +bdev_iscsi_readv(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io, + struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t lba) +{ + struct scsi_task *task; + + SPDK_DEBUGLOG(SPDK_LOG_ISCSI_INIT, "read %d iovs size %lu to lba: %#lx\n", + iovcnt, nbytes, lba); + + task = iscsi_read16_task(lun->context, 0, lba, nbytes, lun->bdev.blocklen, 0, 0, 0, 0, 0, + bdev_iscsi_rw_cb, iscsi_io); + if (task == NULL) { + SPDK_ERRLOG("failed to get read16_task\n"); + bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED); + return; + } + +#if defined(LIBISCSI_FEATURE_IOVECTOR) + scsi_task_set_iov_in(task, (struct scsi_iovec *)iov, iovcnt); +#else + int i; + for (i = 0; i < iovcnt; i++) { + scsi_task_add_data_in_buffer(task, iov[i].iov_len, iov[i].iov_base); + } +#endif +} + +static void +bdev_iscsi_writev(struct bdev_iscsi_lun *lun, struct bdev_iscsi_io *iscsi_io, + struct iovec *iov, int iovcnt, uint64_t nbytes, uint64_t lba) +{ + struct scsi_task *task; + + SPDK_DEBUGLOG(SPDK_LOG_ISCSI_INIT, "write %d iovs size %lu to lba: %#lx\n", + iovcnt, nbytes, lba); + + task = iscsi_write16_task(lun->context, 0, lba, NULL, nbytes, lun->bdev.blocklen, 0, 0, 0, 0, 0, + bdev_iscsi_rw_cb, iscsi_io); + if (task == NULL) { + SPDK_ERRLOG("failed to get write16_task\n"); + bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED); + return; + } + +#if defined(LIBISCSI_FEATURE_IOVECTOR) + scsi_task_set_iov_out(task, (struct scsi_iovec *)iov, iovcnt); +#else + int i; + for (i = 0; i < iovcnt; i++) { + scsi_task_add_data_in_buffer(task, iov[i].iov_len, iov[i].iov_base); + } +#endif +} + +static int +bdev_iscsi_destruct(void *ctx) +{ + struct bdev_iscsi_lun *lun = ctx; + int rc = 0; + + TAILQ_REMOVE(&g_iscsi_lun_head, lun, link); + return rc; +} + +static int +bdev_iscsi_poll(void *arg) +{ + struct bdev_iscsi_io_channel *ch = arg; + struct bdev_iscsi_lun *lun = ch->lun; + struct pollfd pfd; + + pfd.fd = iscsi_get_fd(lun->context); + pfd.events = iscsi_which_events(lun->context); + + if (poll(&pfd, 1, 0) < 0) { + SPDK_ERRLOG("poll failed\n"); + return -1; + } + + if (pfd.revents != 0) { + if (iscsi_service(lun->context, pfd.revents) < 0) { + SPDK_ERRLOG("iscsi_service failed: %s\n", iscsi_get_error(lun->context)); + } + } + + return 0; +} + +static void bdev_iscsi_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io) +{ + bdev_iscsi_readv((struct bdev_iscsi_lun *)bdev_io->bdev->ctxt, + (struct bdev_iscsi_io *)bdev_io->driver_ctx, + bdev_io->u.bdev.iovs, + bdev_io->u.bdev.iovcnt, + bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen, + bdev_io->u.bdev.offset_blocks); +} + +static void _bdev_iscsi_submit_request(void *_bdev_io) +{ + struct spdk_bdev_io *bdev_io = _bdev_io; + struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx; + struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt; + + switch (bdev_io->type) { + case SPDK_BDEV_IO_TYPE_READ: + spdk_bdev_io_get_buf(bdev_io, bdev_iscsi_get_buf_cb, + bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen); + break; + + case SPDK_BDEV_IO_TYPE_WRITE: + bdev_iscsi_writev(lun, iscsi_io, + bdev_io->u.bdev.iovs, + bdev_io->u.bdev.iovcnt, + bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen, + bdev_io->u.bdev.offset_blocks); + break; + default: + bdev_iscsi_io_complete(iscsi_io, SPDK_BDEV_IO_STATUS_FAILED); + break; + } +} + +static void bdev_iscsi_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) +{ + struct spdk_thread *submit_td = spdk_io_channel_get_thread(_ch); + struct bdev_iscsi_io *iscsi_io = (struct bdev_iscsi_io *)bdev_io->driver_ctx; + struct bdev_iscsi_lun *lun = (struct bdev_iscsi_lun *)bdev_io->bdev->ctxt; + + if (lun->master_td != submit_td) { + iscsi_io->submit_td = submit_td; + spdk_thread_send_msg(lun->master_td, _bdev_iscsi_submit_request, bdev_io); + return; + } + + _bdev_iscsi_submit_request(bdev_io); +} + +static bool +bdev_iscsi_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type) +{ + switch (io_type) { + case SPDK_BDEV_IO_TYPE_READ: + case SPDK_BDEV_IO_TYPE_WRITE: + return true; + + default: + return false; + } +} + +static int +bdev_iscsi_create_cb(void *io_device, void *ctx_buf) +{ + struct bdev_iscsi_io_channel *ch = ctx_buf; + struct bdev_iscsi_lun *lun = io_device; + + pthread_mutex_lock(&lun->mutex); + if (lun->ch_count == 0) { + assert(lun->master_ch == NULL); + assert(lun->master_td == NULL); + lun->master_ch = ch; + lun->master_td = spdk_get_thread(); + ch->poller = spdk_poller_register(bdev_iscsi_poll, ch, 0); + ch->lun = lun; + } + lun->ch_count++; + pthread_mutex_unlock(&lun->mutex); + + return 0; +} + +static void +bdev_iscsi_destroy_cb(void *io_device, void *ctx_buf) +{ + struct bdev_iscsi_io_channel *io_channel = ctx_buf; + struct bdev_iscsi_lun *lun = io_device; + + pthread_mutex_lock(&lun->mutex); + lun->ch_count--; + if (lun->ch_count == 0) { + assert(lun->master_ch != NULL); + assert(lun->master_td != NULL); + lun->master_ch = NULL; + lun->master_td = NULL; + spdk_poller_unregister(&io_channel->poller); + } + pthread_mutex_unlock(&lun->mutex); +} + +static struct spdk_io_channel * +bdev_iscsi_get_io_channel(void *ctx) +{ + struct bdev_iscsi_lun *lun = ctx; + + return spdk_get_io_channel(lun); +} + +static int +bdev_iscsi_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) +{ + struct bdev_iscsi_lun *lun = ctx; + + spdk_json_write_name(w, "iscsi"); + spdk_json_write_object_begin(w); + spdk_json_write_name(w, "initiator_name"); + spdk_json_write_string(w, g_initiator); + spdk_json_write_name(w, "target"); + spdk_json_write_string(w, lun->url->target); + spdk_json_write_object_end(w); + + return 0; +} + +static const struct spdk_bdev_fn_table iscsi_fn_table = { + .destruct = bdev_iscsi_destruct, + .submit_request = bdev_iscsi_submit_request, + .io_type_supported = bdev_iscsi_io_type_supported, + .get_io_channel = bdev_iscsi_get_io_channel, + .dump_info_json = bdev_iscsi_dump_info_json, +}; + +static void iscsi_free_lun(struct bdev_iscsi_lun *lun) +{ + if (lun == NULL) { + return; + } + free(lun->bdev.name); + free(lun); +} + +static struct spdk_bdev * +create_iscsi_lun(struct iscsi_context *context, struct iscsi_url *url, + const char *name, uint64_t num_blocks, uint32_t block_size) +{ + struct bdev_iscsi_lun *lun; + int rc; + + lun = calloc(sizeof(*lun), 1); + if (!lun) { + SPDK_ERRLOG("Unable to allocate enough memory for iscsi backend\n"); + return NULL; + } + + lun->context = context; + lun->url = url; + + pthread_mutex_init(&lun->mutex, NULL); + + lun->bdev.name = strdup(name); + if (!lun->bdev.name) { + goto error_return; + } + lun->bdev.product_name = "iSCSI LUN"; + lun->bdev.module = &g_iscsi_bdev_module; + lun->bdev.blocklen = block_size; + lun->bdev.blockcnt = num_blocks; + lun->bdev.ctxt = lun; + + lun->bdev.fn_table = &iscsi_fn_table; + + spdk_io_device_register(lun, bdev_iscsi_create_cb, bdev_iscsi_destroy_cb, + sizeof(struct bdev_iscsi_io_channel)); + rc = spdk_bdev_register(&lun->bdev); + if (rc) { + spdk_io_device_unregister(lun, NULL); + goto error_return; + } + + TAILQ_INSERT_TAIL(&g_iscsi_lun_head, lun, link); + return &lun->bdev; + +error_return: + iscsi_free_lun(lun); + return NULL; +} + +static int +bdev_iscsi_initialize(void) +{ + struct spdk_conf_section *sp; + struct iscsi_context *context; + struct iscsi_url *url; + struct spdk_bdev *bdev; + struct scsi_task *task; + struct scsi_readcapacity16 *readcap16; + char *val, *bdev_name; + int i, rc; + + sp = spdk_conf_find_section(NULL, "iSCSI_Initiator"); + if (sp == NULL) { + return 0; + } + + val = spdk_conf_section_get_val(sp, "initiator_name"); + if (val) { + g_initiator = val; + } else { + g_initiator = DEFAULT_INITIATOR_NAME; + } + + TAILQ_INIT(&g_iscsi_lun_head); + + i = 0; + while (true) { + val = spdk_conf_section_get_nmval(sp, "URL", i, 0); + if (val == NULL) { + break; + } + + bdev_name = spdk_conf_section_get_nmval(sp, "URL", i, 1); + if (bdev_name == NULL) { + SPDK_ERRLOG("no bdev name specified for URL %s\n", val); + break; + } + + context = iscsi_create_context(g_initiator); + if (context == NULL) { + SPDK_ERRLOG("could not create iscsi context\n"); + break; + } + + url = iscsi_parse_full_url(context, val); + if (url == NULL) { + SPDK_ERRLOG("could not parse URL\n"); + break; + } + + iscsi_set_session_type(context, ISCSI_SESSION_NORMAL); + iscsi_set_header_digest(context, ISCSI_HEADER_DIGEST_NONE); + rc = iscsi_full_connect_sync(context, url->portal, url->lun); + if (rc != 0) { + SPDK_ERRLOG("could not login\n"); + break; + } + + task = iscsi_readcapacity16_sync(context, 0); + readcap16 = scsi_datain_unmarshall(task); + scsi_free_scsi_task(task); + + bdev = create_iscsi_lun(context, url, bdev_name, + readcap16->returned_lba + 1, readcap16->block_length); + if (!bdev) { + SPDK_ERRLOG("Unable to create iscsi bdev\n"); + break; + } + + i++; + } + + return 0; +} + +SPDK_LOG_REGISTER_COMPONENT("iscsi_init", SPDK_LOG_ISCSI_INIT) diff --git a/mk/spdk.modules.mk b/mk/spdk.modules.mk index c3a6fa784..9399ef6df 100644 --- a/mk/spdk.modules.mk +++ b/mk/spdk.modules.mk @@ -43,6 +43,11 @@ endif ifeq ($(OS),Linux) BLOCKDEV_MODULES_LIST += bdev_aio bdev_virtio virtio BLOCKDEV_MODULES_DEPS += -laio +ifeq ($(CONFIG_ISCSI_INITIATOR),y) +BLOCKDEV_MODULES_LIST += bdev_iscsi +# Fedora installs libiscsi to /usr/lib64/iscsi for some reason. +BLOCKDEV_MODULES_DEPS += -L/usr/lib64/iscsi -liscsi +endif endif ifeq ($(CONFIG_RBD),y) diff --git a/scripts/pkgdep.sh b/scripts/pkgdep.sh index b5a1e623b..adde27a29 100755 --- a/scripts/pkgdep.sh +++ b/scripts/pkgdep.sh @@ -11,7 +11,7 @@ if [ -s /etc/redhat-release ]; then fi yum install -y gcc gcc-c++ make CUnit-devel libaio-devel openssl-devel \ git astyle-devel python-pep8 lcov python clang-analyzer libuuid-devel \ - sg3_utils + sg3_utils libiscsi-devel # Additional dependencies for NVMe over Fabrics yum install -y libibverbs-devel librdmacm-devel # Additional dependencies for DPDK @@ -23,7 +23,7 @@ if [ -s /etc/redhat-release ]; then elif [ -f /etc/debian_version ]; then # Includes Ubuntu, Debian apt-get install -y gcc g++ make libcunit1-dev libaio-dev libssl-dev \ - git astyle pep8 lcov clang uuid-dev sg3-utils + git astyle pep8 lcov clang uuid-dev sg3-utils libiscsi-dev # Additional dependencies for NVMe over Fabrics apt-get install -y libibverbs-dev librdmacm-dev # Additional dependencies for DPDK diff --git a/test/common/autotest_common.sh b/test/common/autotest_common.sh index 0cf3024a0..886b01eec 100755 --- a/test/common/autotest_common.sh +++ b/test/common/autotest_common.sh @@ -116,6 +116,12 @@ if [ -d /usr/include/rbd ] && [ -d /usr/include/rados ]; then config_params+=' --with-rbd' fi +if [ -d /usr/include/iscsi ]; then + libiscsi_version=`grep LIBISCSI_API_VERSION /usr/include/iscsi/iscsi.h | head -1 | awk '{print $3}' | awk -F '(' '{print $2}' | awk -F ')' '{print $1}'` + if [ $libiscsi_version -ge 20150621 ]; then + config_params+=' --with-iscsi-initiator' + fi +fi export config_params if [ -z "$output_dir" ]; then