iSER is a new transport layer supported in Libiscsi,
iSER provides a zero-copy RDMA capable interface that can
improve performance.
New API is introduced in abstracion of the Libiscsi transport layer.
In order to use the new iSER transport, one need to add the ?iser option
at the end of Libiscsi URI.
For now iSER memory buffers are pre-allocated and pre-registered,
hence in order to work with iSER from QEMU, one need to enable MEMLOCK
attribute in the VM to be large enough for all iSER buffers and RDMA
resources.
A new functionallity is also introduced in this commit, a new API
to deploy zero-copy command submission. iSER is differing from TCP in
data-path, hence IO vectors must be transferred already when queueing
the PDU.
Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
block/iscsi.c | 45 +++++++++++++++++++++++++++++++++++++++++----
1 files changed, 41 insertions(+), 4 deletions(-)
diff --git a/block/iscsi.c b/block/iscsi.c
index 7e78ade..6b95636 100644
--- a/block/iscsi.c
+++ b/block/iscsi.c
@@ -41,6 +41,7 @@
#include "qapi/qmp/qstring.h"
#include "crypto/secret.h"
+#include "qemu/uri.h"
#include <iscsi/iscsi.h>
#include <iscsi/scsi-lowlevel.h>
@@ -484,6 +485,18 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
iscsi_co_init_iscsitask(iscsilun, &iTask);
retry:
if (iscsilun->use_16_for_rw) {
+#if LIBISCSI_API_VERSION >= (20160603)
+ iTask.task = iscsi_write16_iov_task(iscsilun->iscsi, iscsilun->lun,
lba,
+ NULL, num_sectors *
iscsilun->block_size,
+ iscsilun->block_size, 0, 0, fua,
0, 0,
+ iscsi_co_generic_cb, &iTask, (struct
scsi_iovec *)iov->iov, iov->niov);
+ } else {
+ iTask.task = iscsi_write10_iov_task(iscsilun->iscsi, iscsilun->lun,
lba,
+ NULL, num_sectors *
iscsilun->block_size,
+ iscsilun->block_size, 0, 0, fua,
0, 0,
+ iscsi_co_generic_cb, &iTask, (struct
scsi_iovec *)iov->iov, iov->niov);
+ }
+#else
iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
NULL, num_sectors *
iscsilun->block_size,
iscsilun->block_size, 0, 0, fua, 0, 0,
@@ -494,11 +507,14 @@ retry:
iscsilun->block_size, 0, 0, fua, 0, 0,
iscsi_co_generic_cb, &iTask);
}
+#endif
if (iTask.task == NULL) {
return -ENOMEM;
}
+#if LIBISCSI_API_VERSION < (20160603)
scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
iov->niov);
+#endif
while (!iTask.complete) {
iscsi_set_events(iscsilun);
qemu_coroutine_yield();
@@ -677,6 +693,19 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState
*bs,
iscsi_co_init_iscsitask(iscsilun, &iTask);
retry:
if (iscsilun->use_16_for_rw) {
+#if LIBISCSI_API_VERSION >= (20160603)
+ iTask.task = iscsi_read16_iov_task(iscsilun->iscsi, iscsilun->lun, lba,
+ num_sectors * iscsilun->block_size,
+ iscsilun->block_size, 0, 0, 0, 0, 0,
+ iscsi_co_generic_cb, &iTask, (struct
scsi_iovec *)iov->iov, iov->niov);
+ } else {
+ iTask.task = iscsi_read10_iov_task(iscsilun->iscsi, iscsilun->lun, lba,
+ num_sectors * iscsilun->block_size,
+ iscsilun->block_size,
+ 0, 0, 0, 0, 0,
+ iscsi_co_generic_cb, &iTask, (struct
scsi_iovec *)iov->iov, iov->niov);
+ }
+#else
iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
num_sectors * iscsilun->block_size,
iscsilun->block_size, 0, 0, 0, 0, 0,
@@ -688,11 +717,13 @@ retry:
0, 0, 0, 0, 0,
iscsi_co_generic_cb, &iTask);
}
+#endif
if (iTask.task == NULL) {
return -ENOMEM;
}
+#if LIBISCSI_API_VERSION < (20160603)
scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov,
iov->niov);
-
+#endif
while (!iTask.complete) {
iscsi_set_events(iscsilun);
qemu_coroutine_yield();
@@ -1477,9 +1508,9 @@ static int iscsi_open(BlockDriverState *bs, QDict
*options, int flags,
filename = qemu_opt_get(opts, "filename");
- iscsi_url = iscsi_parse_full_url(iscsi, filename);
+ iscsi_url = iscsi_parse_full_url(iscsi, uri_string_unescape(filename, -1,
NULL));
if (iscsi_url == NULL) {
- error_setg(errp, "Failed to parse URL : %s", filename);
+ error_setg(errp, "Failed to parse URL : %s",
uri_string_unescape(filename, -1, NULL));
ret = -EINVAL;
goto out;
}
@@ -1494,7 +1525,13 @@ static int iscsi_open(BlockDriverState *bs, QDict
*options, int flags,
ret = -ENOMEM;
goto out;
}
-
+#if LIBISCSI_API_VERSION >= (20160603)
+ if (iscsi_init_transport(iscsi, iscsi_url->transport)) {
+ error_setg(errp, ("Error initializing transport."));
+ ret = -EINVAL;
+ goto out;
+ }
+#endif
if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
error_setg(errp, "iSCSI: Failed to set target name.");
ret = -EINVAL;