bdev: add iSCSI initiator bdev module

This uses libiscsi to implement an iSCSI initiator bdev
module for SPDK.  Still a lots of work to do on this - posting
it in case anyone is interested in working on this further.

A number of todo items are listed in a README in the lib/bdev/iscsi
directory.

Signed-off-by: Jim Harris <james.r.harris@intel.com>
Signed-off-by: Ziye Yang <optimistyzy@gmail.com>
Change-Id: I060e33de0cd6796246789bf0e1bb4f2df59d8f71
Reviewed-on: https://review.gerrithub.io/390313
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
This commit is contained in:
Jim Harris 2017-12-04 10:07:04 -07:00
parent 7ca10f4f9e
commit 2af15344ab
10 changed files with 609 additions and 2 deletions

View File

@ -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

3
CONFIG
View File

@ -95,3 +95,6 @@ CONFIG_NVML?=n
# Build with VPP
CONFIG_VPP?=n
# Requires libiscsi development libraries.
CONFIG_ISCSI_INITIATOR?=n

11
configure vendored
View File

@ -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

View File

@ -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

46
lib/bdev/iscsi/Makefile Normal file
View File

@ -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

24
lib/bdev/iscsi/README Normal file
View File

@ -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.

505
lib/bdev/iscsi/bdev_iscsi.c Normal file
View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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