[RFC 07/12] Libiscsi: Adding free_pdu function to transport abstraction

55 views
Skip to first unread message

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
include/iscsi-private.h | 1 +
include/iscsi.h | 3 ++
lib/connect.c | 12 +++++-----
lib/discovery.c | 4 +-
lib/init.c | 6 ++--
lib/iscsi-command.c | 16 +++++++-------
lib/login.c | 52 +++++++++++++++++++++++-----------------------
lib/nop.c | 6 ++--
lib/pdu.c | 26 +++++++++++-----------
lib/socket.c | 3 +-
lib/task_mgmt.c | 2 +-
11 files changed, 68 insertions(+), 63 deletions(-)

diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index d4cde4b..b307015 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -81,6 +81,7 @@ struct iscsi_transport {
int (*queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
struct iscsi_pdu* (*new_pdu)(struct iscsi_context *iscsi, size_t size);
int (*disconnect)(struct iscsi_context *iscsi);
+ void (*free_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
};

struct iscsi_tcp_transport {
diff --git a/include/iscsi.h b/include/iscsi.h
index 00b8458..a2694b6 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -78,6 +78,9 @@ EXTERN int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pd
EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca);

EXTERN void iscsi_init_tcp_transport(struct iscsi_context *iscsi);
+
+EXTERN void iscsi_tcp_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
+
/*
* The following three functions are used to integrate libiscsi in an event
* system.
diff --git a/lib/connect.c b/lib/connect.c
index b5e0ee4..db69181 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -279,7 +279,7 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi)
NULL, pdu->private_data);
}
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
while ((pdu = iscsi->waitpdu)) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
@@ -290,7 +290,7 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi)
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
NULL, pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
}

@@ -334,7 +334,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status,

ISCSI_LIST_REMOVE(&old_iscsi->waitpdu, pdu);
if (pdu->itt == 0xffffffff) {
- iscsi_free_pdu(old_iscsi, pdu);
+ iscsi->t->free_pdu(old_iscsi, pdu);
continue;
}

@@ -348,7 +348,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status,
pdu->callback(iscsi, SCSI_STATUS_CANCELLED,
NULL, pdu->private_data);
}
- iscsi_free_pdu(old_iscsi, pdu);
+ iscsi->t->free_pdu(old_iscsi, pdu);
continue;
}

@@ -366,7 +366,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status,
pdu->scsi_cbdata.private_data)) {
/* not much we can really do at this point */
}
- iscsi_free_pdu(old_iscsi, pdu);
+ iscsi->t->free_pdu(old_iscsi, pdu);
}

if (old_iscsi->incoming != NULL) {
@@ -377,7 +377,7 @@ void iscsi_reconnect_cb(struct iscsi_context *iscsi _U_, int status,
}

if (old_iscsi->outqueue_current != NULL && old_iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
- iscsi_free_pdu(old_iscsi, old_iscsi->outqueue_current);
+ iscsi->t->free_pdu(old_iscsi, old_iscsi->outqueue_current);
}

for (i = 0; i < old_iscsi->smalloc_free; i++) {
diff --git a/lib/discovery.c b/lib/discovery.c
index 07f826d..02be475 100644
--- a/lib/discovery.c
+++ b/lib/discovery.c
@@ -73,7 +73,7 @@ iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str)+1)
!= 0) {
iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed.");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

@@ -83,7 +83,7 @@ iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"text pdu.");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

diff --git a/lib/init.c b/lib/init.c
index 81b0568..fc48c28 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -343,7 +343,7 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
pdu->private_data);
}
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
while ((pdu = iscsi->waitpdu)) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
@@ -354,11 +354,11 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}

if (iscsi->outqueue_current != NULL && iscsi->outqueue_current->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
- iscsi_free_pdu(iscsi, iscsi->outqueue_current);
+ iscsi->t->free_pdu(iscsi, iscsi->outqueue_current);
}

if (iscsi->incoming != NULL) {
diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
index 95cb07f..8dacd08 100644
--- a/lib/iscsi-command.c
+++ b/lib/iscsi-command.c
@@ -94,7 +94,7 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
ISCSI_LIST_REMOVE(&iscsi->waitpdu, cmd_pdu);
cmd_pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
cmd_pdu->private_data);
- iscsi_free_pdu(iscsi, cmd_pdu);
+ iscsi->t->free_pdu(iscsi, cmd_pdu);
return -1;

}
@@ -141,8 +141,8 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
ISCSI_LIST_REMOVE(&iscsi->waitpdu, cmd_pdu);
cmd_pdu->callback(iscsi, SCSI_STATUS_ERROR, NULL,
cmd_pdu->private_data);
- iscsi_free_pdu(iscsi, cmd_pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, cmd_pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

@@ -284,7 +284,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"scsi pdu.");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

@@ -1898,7 +1898,7 @@ iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return 0;
}
}
@@ -1909,7 +1909,7 @@ iscsi_scsi_cancel_task(struct iscsi_context *iscsi,
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return 0;
}
}
@@ -1927,7 +1927,7 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
while ((pdu = iscsi->outqueue)) {
ISCSI_LIST_REMOVE(&iscsi->outqueue, pdu);
@@ -1935,6 +1935,6 @@ iscsi_scsi_cancel_all_tasks(struct iscsi_context *iscsi)
pdu->callback(iscsi, SCSI_STATUS_CANCELLED, NULL,
pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
}
diff --git a/lib/login.c b/lib/login.c
index 5592e70..9a55288 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -852,14 +852,14 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,

/* initiator name */
if (iscsi_login_add_initiatorname(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* optional alias */
if (iscsi->alias[0]) {
if (iscsi_login_add_alias(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}
}
@@ -867,134 +867,134 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
/* target name */
if (iscsi->session_type == ISCSI_SESSION_NORMAL) {
if (iscsi_login_add_targetname(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}
}

/* session type */
if (iscsi_login_add_sessiontype(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* header digest */
if (iscsi_login_add_headerdigest(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* auth method */
if (iscsi_login_add_authmethod(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* auth algorithm */
if (iscsi_login_add_authalgorithm(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* chap username */
if (iscsi_login_add_chap_username(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* chap response */
if (iscsi_login_add_chap_response(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* data digest */
if (iscsi_login_add_datadigest(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* initial r2t */
if (iscsi_login_add_initialr2t(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* immediate data */
if (iscsi_login_add_immediatedata(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* max burst length */
if (iscsi_login_add_maxburstlength(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* first burst length */
if (iscsi_login_add_firstburstlength(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* default time 2 wait */
if (iscsi_login_add_defaulttime2wait(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* default time 2 retain */
if (iscsi_login_add_defaulttime2retain(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* max outstanding r2t */
if (iscsi_login_add_maxoutstandingr2t(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* errorrecoverylevel */
if (iscsi_login_add_errorrecoverylevel(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* ifmarker */
if (iscsi_login_add_ifmarker(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* ofmarker */
if (iscsi_login_add_ofmarker(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* maxconnections */
if (iscsi_login_add_maxconnections(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* max recv data segment length */
if (iscsi_login_add_maxrecvdatasegmentlength(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* data pdu in order */
if (iscsi_login_add_datapduinorder(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

/* data sequence in order */
if (iscsi_login_add_datasequenceinorder(iscsi, pdu) != 0) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

@@ -1005,7 +1005,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"pdu.");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

@@ -1302,7 +1302,7 @@ iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"logout pdu.");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

diff --git a/lib/nop.c b/lib/nop.c
index d5031cc..6941b30 100644
--- a/lib/nop.c
+++ b/lib/nop.c
@@ -73,14 +73,14 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
if (data != NULL && len > 0) {
if (iscsi_pdu_add_data(iscsi, pdu, data, len) != 0) {
iscsi_set_error(iscsi, "Failed to add outdata to nop-out");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}
}

if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

@@ -124,7 +124,7 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt, uint32_t lu

if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

diff --git a/lib/pdu.c b/lib/pdu.c
index d6e4a84..28a57b8 100644
--- a/lib/pdu.c
+++ b/lib/pdu.c
@@ -131,7 +131,7 @@ iscsi_allocate_pdu(struct iscsi_context *iscsi, enum iscsi_opcode opcode,
}

void
-iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
+iscsi_tcp_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
if (pdu == NULL) {
iscsi_set_error(iscsi, "trying to free NULL pdu");
@@ -379,7 +379,7 @@ int iscsi_process_reject(struct iscsi_context *iscsi,
}

ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return 0;
}

@@ -528,7 +528,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
case ISCSI_PDU_LOGIN_RESPONSE:
if (iscsi_process_login_reply(iscsi, pdu, in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi login reply "
"failed");
return -1;
@@ -537,7 +537,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
case ISCSI_PDU_TEXT_RESPONSE:
if (iscsi_process_text_reply(iscsi, pdu, in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi text reply "
"failed");
return -1;
@@ -546,7 +546,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
case ISCSI_PDU_LOGOUT_RESPONSE:
if (iscsi_process_logout_reply(iscsi, pdu, in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi logout reply "
"failed");
return -1;
@@ -555,7 +555,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
case ISCSI_PDU_SCSI_RESPONSE:
if (iscsi_process_scsi_reply(iscsi, pdu, in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi response reply "
"failed");
return -1;
@@ -565,7 +565,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
if (iscsi_process_scsi_data_in(iscsi, pdu, in,
&is_finished) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi data in "
"failed");
return -1;
@@ -574,7 +574,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
case ISCSI_PDU_NOP_IN:
if (iscsi_process_nop_out_reply(iscsi, pdu, in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi nop-in failed");
return -1;
}
@@ -583,7 +583,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
if (iscsi_process_task_mgmt_reply(iscsi, pdu,
in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi task-mgmt failed");
return -1;
}
@@ -591,7 +591,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
case ISCSI_PDU_R2T:
if (iscsi_process_r2t(iscsi, pdu, in) != 0) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
iscsi_set_error(iscsi, "iscsi r2t "
"failed");
return -1;
@@ -606,7 +606,7 @@ iscsi_process_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)

if (is_finished) {
ISCSI_LIST_REMOVE(&iscsi->waitpdu, pdu);
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
return 0;
}
@@ -720,7 +720,7 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
pdu->callback(iscsi, SCSI_STATUS_TIMEOUT,
NULL, pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
for (pdu = iscsi->waitpdu; pdu; pdu = next_pdu) {
next_pdu = pdu->next;
@@ -740,6 +740,6 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
pdu->callback(iscsi, SCSI_STATUS_TIMEOUT,
NULL, pdu->private_data);
}
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
}
diff --git a/lib/socket.c b/lib/socket.c
index e329fc4..1ee8e87 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -80,6 +80,7 @@ static struct iscsi_transport tcp_transport =
.queue_pdu = iscsi_tcp_queue_pdu,
.new_pdu = iscsi_tcp_new_pdu,
.disconnect = iscsi_tcp_disconnect,
+ .free_pdu = iscsi_tcp_free_pdu,
};

void iscsi_init_tcp_transport(struct iscsi_context *iscsi)
@@ -810,7 +811,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
iscsi->is_corked = 1;
}
if (pdu->flags & ISCSI_PDU_DELETE_WHEN_SENT) {
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
}
iscsi->outqueue_current = NULL;
}
diff --git a/lib/task_mgmt.c b/lib/task_mgmt.c
index 983154f..fdfc3c2 100644
--- a/lib/task_mgmt.c
+++ b/lib/task_mgmt.c
@@ -84,7 +84,7 @@ iscsi_task_mgmt_async(struct iscsi_context *iscsi,

if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi taskmgmt pdu");
- iscsi_free_pdu(iscsi, pdu);
+ iscsi->t->free_pdu(iscsi, pdu);
return -1;
}

--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
socket: need to malloc hdr

include/iscsi-private: changing iscsi_in_pdu hdr to char*
instead of static array for more convinient iser
pdu creation.

To use iscsi_in_pdu in iSER without making a copy of it
we need to change hdr to pointer from static array,
Because of that, iscsi_tcp flow need to do szmalloc (small zero malloc)
hdr when creating new iscsi_in_pdu. iscsi_in_pdu is being malloced
once per each received pdu. This change is reducing iscsi_in_pdu struct
size but adding extra allocation of the same size we reduced
from the struct.

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
include/iscsi-private.h | 2 +-
lib/socket.c | 2 ++
2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index 9f09519..69d2f3e 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -55,7 +55,7 @@ struct iscsi_in_pdu {
struct iscsi_in_pdu *next;

long long hdr_pos;
- unsigned char hdr[ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE];
+ unsigned char *hdr;

long long data_pos;
unsigned char *data;
diff --git a/lib/socket.c b/lib/socket.c
index cb96cbf..315e7ae 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -568,6 +568,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)

if (iscsi->incoming == NULL) {
iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
+ iscsi->incoming->hdr = iscsi_szmalloc(iscsi, ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE);
if (iscsi->incoming == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
return -1;
@@ -970,6 +971,7 @@ int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
void
iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
{
+ iscsi_free(iscsi, in->hdr);
iscsi_free(iscsi, in->data);
in->data=NULL;
iscsi_sfree(iscsi, in);
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
iscsi-command: Adding struct scsi_iovec and int niov into all
write function (WRITE6, WRITE10, etc') parameters.

In TCP adding pdu to out queue and writing it to the
socket are happening concurrently, so one can add io
vectors to task after adding the pdu of the same task to the outqueue.

In iSER adding the pdu to out queue is equivelent to
sending the packet so one must publish io vectors before
putting the pdu on the out queue.

By doing so, if an application wants to use it's own
iovectors, it's just need to inject the
address of the first scsi_iovec and expected number of
io vectors.

if don't want to use this (application doesn't has
iovectors), putting NULL and 0 will match to
previous code.

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
examples/iscsi-dd.c | 4 +-
examples/iscsiclient.c | 18 ++++++------
examples/ld_iscsi.c | 2 +-
include/iscsi.h | 57 +++++++++++++++++++-------------------
lib/iscsi-command.c | 71 ++++++++++++++++++++++++++++++++++++++---------
lib/sync.c | 56 +++++++++++++++++++-------------------
6 files changed, 126 insertions(+), 82 deletions(-)

diff --git a/examples/iscsi-dd.c b/examples/iscsi-dd.c
index fadcafb..d1c79a9 100644
--- a/examples/iscsi-dd.c
+++ b/examples/iscsi-dd.c
@@ -131,7 +131,7 @@ void read_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, vo
task2 = iscsi_write16_task(client->dst_iscsi, client->dst_lun,
read16_cdb->lba, task->datain.data, task->datain.size,
client->dst_blocksize, 0, 0, 0, 0, 0,
- write_cb, wt);
+ write_cb, wt, NULL, 0);
} else {
read10_cdb = scsi_cdb_unmarshall(task, SCSI_OPCODE_READ10);
if (read10_cdb == NULL) {
@@ -141,7 +141,7 @@ void read_cb(struct iscsi_context *iscsi _U_, int status, void *command_data, vo
task2 = iscsi_write10_task(client->dst_iscsi, client->dst_lun,
read10_cdb->lba, task->datain.data, task->datain.size,
client->dst_blocksize, 0, 0, 0, 0, 0,
- write_cb, wt);
+ write_cb, wt, NULL, 0);
}
if (task2 == NULL) {
printf("failed to send read16 command\n");
diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c
index 8e6a5a8..8566fff 100644
--- a/examples/iscsiclient.c
+++ b/examples/iscsiclient.c
@@ -152,13 +152,6 @@ void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data,
for (i = 0;i < 512; i++) {
wb[i] = (511 - i) & 0xff;
}
- task = iscsi_write10_task(iscsi, clnt->lun, 0, NULL, 512, 512,
- 0, 0, 0, 0, 0,
- write10_1_cb, private_data);
- if (task == NULL) {
- printf("failed to send write10 command\n");
- exit(10);
- }
/* provide iovectors where to read the data.
*/
iov[0].iov_base = &wb[0];
@@ -167,7 +160,14 @@ void write10_cb(struct iscsi_context *iscsi _U_, int status, void *command_data,
iov[1].iov_len = 11;
iov[2].iov_base = &wb[15];
iov[2].iov_len = 512 - 15;
- scsi_task_set_iov_out(task, &iov[0], 3);
+
+ task = iscsi_write10_task(iscsi, clnt->lun, 0, NULL, 512, 512,
+ 0, 0, 0, 0, 0,
+ write10_1_cb, private_data, &iov[0], 3);
+ if (task == NULL) {
+ printf("failed to send write10 command\n");
+ exit(10);
+ }
}

void read10_1_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
@@ -209,7 +209,7 @@ void read10_1_cb(struct iscsi_context *iscsi, int status, void *command_data, vo
}
task = iscsi_write10_task(iscsi, clnt->lun, 0, wb, 512, 512,
0, 0, 0, 0, 0,
- write10_cb, private_data);
+ write10_cb, private_data, NULL, 0);
if (task == NULL) {
printf("failed to send write10 command\n");
exit(10);
diff --git a/examples/ld_iscsi.c b/examples/ld_iscsi.c
index 5ce0299..2d5e48c 100644
--- a/examples/ld_iscsi.c
+++ b/examples/ld_iscsi.c
@@ -466,7 +466,7 @@ ssize_t write(int fd, const void *buf, size_t count)

iscsi_fd_list[fd].in_flight = 1;
LD_ISCSI_DPRINTF(4,"write16_sync: lun %d, lba %"PRIu64", num_blocks: %"PRIu64", block_size: %d, offset: %"PRIu64" count: %lu",iscsi_fd_list[fd].lun,lba,num_blocks,iscsi_fd_list[fd].block_size,offset,(unsigned long)count);
- task = iscsi_write16_sync(iscsi_fd_list[fd].iscsi, iscsi_fd_list[fd].lun, lba, (unsigned char *) buf, count, iscsi_fd_list[fd].block_size, 0, 0, 0, 0, 0);
+ task = iscsi_write16_sync(iscsi_fd_list[fd].iscsi, iscsi_fd_list[fd].lun, lba, (unsigned char *) buf, count, iscsi_fd_list[fd].block_size, 0, 0, 0, 0, 0, NULL, 0);
iscsi_fd_list[fd].in_flight = 0;
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
LD_ISCSI_DPRINTF(0,"failed to send write16 command");
diff --git a/include/iscsi.h b/include/iscsi.h
index a5fad6d..d11d5c6 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <string.h>

+#include "scsi-lowlevel.h"
#if defined(WIN32)
#define EXTERN __declspec( dllexport )
#else
@@ -864,12 +865,12 @@ EXTERN struct scsi_task *
iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_writeverify10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int bytchk, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_read12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize,
@@ -879,12 +880,12 @@ EXTERN struct scsi_task *
iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_writeverify12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int bytchk, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_read16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
uint32_t datalen, int blocksize,
@@ -894,17 +895,17 @@ EXTERN struct scsi_task *
iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_writeatomic16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_startstopunit_task(struct iscsi_context *iscsi, int lun,
int immed, int pcm, int pc,
@@ -918,42 +919,42 @@ EXTERN struct scsi_task *
iscsi_compareandwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_writeverify16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int bytchk, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_verify10_task(struct iscsi_context *iscsi, int lun,
unsigned char *data, uint32_t datalen, uint32_t lba,
int vprotect, int dpo, int bytchk,
int blocksize, iscsi_command_cb cb,
- void *private_data);
+ void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_verify12_task(struct iscsi_context *iscsi, int lun,
unsigned char *data, uint32_t datalen, uint32_t lba,
int vprotect, int dpo, int bytchk,
int blocksize, iscsi_command_cb cb,
- void *private_data);
+ void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_verify16_task(struct iscsi_context *iscsi, int lun,
unsigned char *data, uint32_t datalen, uint64_t lba,
int vprotect, int dpo, int bytchk,
int blocksize, iscsi_command_cb cb,
- void *private_data);
+ void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_writesame10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen,
uint16_t num_blocks,
int anchor, int unmap, int wrprotect, int group,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_writesame16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen,
uint32_t num_blocks,
int anchor, int unmap, int wrprotect, int group,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_modeselect6_task(struct iscsi_context *iscsi, int lun,
int pf, int sp, struct scsi_mode_page *mp,
@@ -1061,12 +1062,12 @@ iscsi_read10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
EXTERN struct scsi_task *
iscsi_write10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number);
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_writeverify10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int bytchk, int group_number);
+ int wrprotect, int dpo, int bytchk, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_read12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
@@ -1076,12 +1077,12 @@ iscsi_read12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
EXTERN struct scsi_task *
iscsi_write12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number);
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_writeverify12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int bytchk, int group_number);
+ int wrprotect, int dpo, int bytchk, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_read16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
@@ -1091,17 +1092,17 @@ iscsi_read16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
EXTERN struct scsi_task *
iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number);
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_writeatomic16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int group_number);
+ int wrprotect, int dpo, int fua, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number);
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_startstopunit_sync(struct iscsi_context *iscsi, int lun,
@@ -1115,12 +1116,12 @@ iscsi_preventallow_sync(struct iscsi_context *iscsi, int lun,
EXTERN struct scsi_task *
iscsi_compareandwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number);
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_writeverify16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int bytchk, int group_number);
+ int wrprotect, int dpo, int bytchk, int group_number, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_readcapacity10_sync(struct iscsi_context *iscsi, int lun, int lba,
@@ -1165,31 +1166,31 @@ EXTERN struct scsi_task *
iscsi_verify10_sync(struct iscsi_context *iscsi, int lun,
unsigned char *data, uint32_t datalen, uint32_t lba,
int vprotect, int dpo, int bytchk,
- int blocksize);
+ int blocksize, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_verify12_sync(struct iscsi_context *iscsi, int lun,
unsigned char *data, uint32_t datalen, uint32_t lba,
int vprotect, int dpo, int bytchk,
- int blocksize);
+ int blocksize, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_verify16_sync(struct iscsi_context *iscsi, int lun,
unsigned char *data, uint32_t datalen, uint64_t lba,
int vprotect, int dpo, int bytchk,
- int blocksize);
+ int blocksize, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_writesame10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen,
uint16_t num_blocks,
- int anchor, int unmap, int wrprotect, int group);
+ int anchor, int unmap, int wrprotect, int group, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_writesame16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen,
uint32_t num_blocks,
- int anchor, int unmap, int wrprotect, int group);
+ int anchor, int unmap, int wrprotect, int group, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_persistent_reserve_in_sync(struct iscsi_context *iscsi, int lun,
diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
index 0d25808..acdcef4 100644
--- a/lib/iscsi-command.c
+++ b/lib/iscsi-command.c
@@ -851,7 +851,7 @@ struct scsi_task *
iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -872,6 +872,10 @@ iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -885,7 +889,7 @@ struct scsi_task *
iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -906,6 +910,9 @@ iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -919,7 +926,7 @@ struct scsi_task *
iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -940,6 +947,9 @@ iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -953,7 +963,7 @@ struct scsi_task *
iscsi_writeatomic16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -974,6 +984,9 @@ iscsi_writeatomic16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -987,7 +1000,7 @@ struct scsi_task *
iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1008,6 +1021,9 @@ iscsi_orwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1021,7 +1037,7 @@ struct scsi_task *
iscsi_compareandwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1042,6 +1058,9 @@ iscsi_compareandwrite_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1055,7 +1074,7 @@ struct scsi_task *
iscsi_writeverify10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int bytchk, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1076,6 +1095,9 @@ iscsi_writeverify10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1089,7 +1111,7 @@ struct scsi_task *
iscsi_writeverify12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int bytchk, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1110,6 +1132,9 @@ iscsi_writeverify12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1123,7 +1148,7 @@ struct scsi_task *
iscsi_writeverify16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
int wrprotect, int dpo, int bytchk, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1144,6 +1169,9 @@ iscsi_writeverify16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1156,7 +1184,7 @@ iscsi_writeverify16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
struct scsi_task *
iscsi_verify10_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
uint32_t datalen, uint32_t lba, int vprotect, int dpo, int bytchk, int blocksize,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1176,6 +1204,9 @@ iscsi_verify10_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1188,7 +1219,7 @@ iscsi_verify10_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
struct scsi_task *
iscsi_verify12_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
uint32_t datalen, uint32_t lba, int vprotect, int dpo, int bytchk, int blocksize,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1208,6 +1239,9 @@ iscsi_verify12_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1220,7 +1254,7 @@ iscsi_verify12_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
struct scsi_task *
iscsi_verify16_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
uint32_t datalen, uint64_t lba, int vprotect, int dpo, int bytchk, int blocksize,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1240,6 +1274,9 @@ iscsi_verify16_task(struct iscsi_context *iscsi, int lun, unsigned char *data,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
&d, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -1559,7 +1596,7 @@ iscsi_writesame10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen,
uint16_t num_blocks,
int anchor, int unmap, int wrprotect, int group,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1574,6 +1611,9 @@ iscsi_writesame10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (data != NULL) {
task->expxferlen = datalen;
} else {
@@ -1593,7 +1633,7 @@ iscsi_writesame16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen,
uint32_t num_blocks,
int anchor, int unmap, int wrprotect, int group,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;
struct iscsi_data d;
@@ -1608,6 +1648,9 @@ iscsi_writesame16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
d.data = data;
d.size = datalen;

+ if (iov != NULL)
+ scsi_task_set_iov_out(task, iov, niov);
+
if (data != NULL) {
task->expxferlen = datalen;
} else {
diff --git a/lib/sync.c b/lib/sync.c
index fcbf3da..444425f 100644
--- a/lib/sync.c
+++ b/lib/sync.c
@@ -758,7 +758,7 @@ iscsi_prefetch16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
struct scsi_task *
iscsi_write10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number)
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -766,7 +766,7 @@ iscsi_write10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,

if (iscsi_write10_task(iscsi, lun, lba, data, datalen, blocksize,
wrprotect, dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Write10 command");
return NULL;
@@ -780,7 +780,7 @@ iscsi_write10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
struct scsi_task *
iscsi_write12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number)
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov,int niov)
{
struct iscsi_sync_state state;

@@ -789,7 +789,7 @@ iscsi_write12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
if (iscsi_write12_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Write12 command");
return NULL;
@@ -803,7 +803,7 @@ iscsi_write12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
struct scsi_task *
iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number)
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -812,7 +812,7 @@ iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
if (iscsi_write16_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Write16 command");
return NULL;
@@ -826,7 +826,7 @@ iscsi_write16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
struct scsi_task *
iscsi_writeatomic16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int group_number)
+ int wrprotect, int dpo, int fua, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -835,7 +835,7 @@ iscsi_writeatomic16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
if (iscsi_writeatomic16_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, fua, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send WriteAtomic16 command");
return NULL;
@@ -849,7 +849,7 @@ iscsi_writeatomic16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
struct scsi_task *
iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number)
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -858,7 +858,7 @@ iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
if (iscsi_orwrite_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Orwrite command");
return NULL;
@@ -872,7 +872,7 @@ iscsi_orwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
struct scsi_task *
iscsi_compareandwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int fua, int fua_nv, int group_number)
+ int wrprotect, int dpo, int fua, int fua_nv, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -881,7 +881,7 @@ iscsi_compareandwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
if (iscsi_compareandwrite_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send CompareAndWrite command");
return NULL;
@@ -895,7 +895,7 @@ iscsi_compareandwrite_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
struct scsi_task *
iscsi_writeverify10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int bytchk, int group_number)
+ int wrprotect, int dpo, int bytchk, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -903,7 +903,7 @@ iscsi_writeverify10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,

if (iscsi_writeverify10_task(iscsi, lun, lba, data, datalen, blocksize,
wrprotect, dpo, bytchk, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Writeverify10 command");
return NULL;
@@ -917,7 +917,7 @@ iscsi_writeverify10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
struct scsi_task *
iscsi_writeverify12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int bytchk, int group_number)
+ int wrprotect, int dpo, int bytchk, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -926,7 +926,7 @@ iscsi_writeverify12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
if (iscsi_writeverify12_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, bytchk, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Writeverify12 command");
return NULL;
@@ -940,7 +940,7 @@ iscsi_writeverify12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
struct scsi_task *
iscsi_writeverify16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
- int wrprotect, int dpo, int bytchk, int group_number)
+ int wrprotect, int dpo, int bytchk, int group_number, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -949,7 +949,7 @@ iscsi_writeverify16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
if (iscsi_writeverify16_task(iscsi, lun, lba,
data, datalen, blocksize, wrprotect,
dpo, bytchk, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Writeverify16 command");
return NULL;
@@ -962,14 +962,14 @@ iscsi_writeverify16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,

struct scsi_task *
iscsi_verify10_sync(struct iscsi_context *iscsi, int lun, unsigned char *data, uint32_t datalen, uint32_t lba,
- int vprotect, int dpo, int bytchk, int blocksize)
+ int vprotect, int dpo, int bytchk, int blocksize, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

memset(&state, 0, sizeof(state));

if (iscsi_verify10_task(iscsi, lun, data, datalen, lba, vprotect, dpo, bytchk, blocksize,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Verify10 command");
return NULL;
@@ -982,14 +982,14 @@ iscsi_verify10_sync(struct iscsi_context *iscsi, int lun, unsigned char *data, u

struct scsi_task *
iscsi_verify12_sync(struct iscsi_context *iscsi, int lun, unsigned char *data, uint32_t datalen, uint32_t lba,
- int vprotect, int dpo, int bytchk, int blocksize)
+ int vprotect, int dpo, int bytchk, int blocksize, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

memset(&state, 0, sizeof(state));

if (iscsi_verify12_task(iscsi, lun, data, datalen, lba, vprotect, dpo, bytchk, blocksize,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Verify12 command");
return NULL;
@@ -1002,14 +1002,14 @@ iscsi_verify12_sync(struct iscsi_context *iscsi, int lun, unsigned char *data, u

struct scsi_task *
iscsi_verify16_sync(struct iscsi_context *iscsi, int lun, unsigned char *data, uint32_t datalen, uint64_t lba,
- int vprotect, int dpo, int bytchk, int blocksize)
+ int vprotect, int dpo, int bytchk, int blocksize, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

memset(&state, 0, sizeof(state));

if (iscsi_verify16_task(iscsi, lun, data, datalen, lba, vprotect, dpo, bytchk, blocksize,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Verify16 command");
return NULL;
@@ -1024,7 +1024,7 @@ struct scsi_task *
iscsi_writesame10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen,
uint16_t num_blocks,
- int anchor, int unmap, int wrprotect, int group)
+ int anchor, int unmap, int wrprotect, int group, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -1033,7 +1033,7 @@ iscsi_writesame10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
if (iscsi_writesame10_task(iscsi, lun, lba,
data, datalen, num_blocks,
anchor, unmap, wrprotect, group,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send WRITESAME10 command");
return NULL;
@@ -1048,7 +1048,7 @@ struct scsi_task *
iscsi_writesame16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen,
uint32_t num_blocks,
- int anchor, int unmap, int wrprotect, int group)
+ int anchor, int unmap, int wrprotect, int group, struct scsi_iovec *iov, int niov)
{
struct iscsi_sync_state state;

@@ -1057,7 +1057,7 @@ iscsi_writesame16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,
if (iscsi_writesame16_task(iscsi, lun, lba,
data, datalen, num_blocks,
anchor, unmap, wrprotect, group,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, iov, niov) == NULL) {
iscsi_set_error(iscsi,
"Failed to send WRITESAME16 command");
return NULL;
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
Hi,

This series includes the implementation of iSER transport option.
Patches are still under review so I'm sending them as RFC pathces.

Transport abstraction is dependent on transport parameter that is delivered when creating iscsi context.

Each one of the transport layer has it's own transport functions.
All library functionallity is independent to the transport abstraction.

Patches should be checked with an appropriate RDMA capable hardware.
Each test/example can choose the transport flag "-T" with wanted transport as a string (tcp/iser).

Waiting for comments,
Roy

Roy Shterman (12):
Libiscsi: Adding transport layer into all library utilities
Libiscsi: Adding connect function to transport abstraction
Libiscsi: Adding queue pdu function to transport abstraction
Libiscsi: Adding new_pdu function to transport abstraction
Libiscsi: Changing header iscsi_in_pdu
Libiscsi: Adding disconnect function to transport abstraction
Libiscsi: Adding free_pdu function to transport abstraction
Libiscsi: Change iscsi read tasks for future iser implementation
Libiscsi: Change iscsi write tasks for future iSER implementation
Libiscsi: Adding abstraction to async functions
Libiscsi: Adding transport into URL parsing
Libiscsi: iSER implementation

examples/Makefile.am | 2 +-
examples/iscsi-dd.c | 24 +-
examples/iscsiclient.c | 89 ++-
examples/ld_iscsi.c | 5 +-
include/iscsi-private.h | 33 +-
include/iscsi.h | 121 +++-
include/iser-private.h | 209 ++++++
lib/Makefile.am | 6 +-
lib/connect.c | 16 +-
lib/discovery.c | 6 +-
lib/init.c | 76 ++-
lib/iscsi-command.c | 115 +++-
lib/iser.c | 1429 ++++++++++++++++++++++++++++++++++++++++
lib/libiscsi.syms | 2 +
lib/login.c | 56 +-
lib/nop.c | 10 +-
lib/pdu.c | 38 +-
lib/socket.c | 221 ++++---
lib/sync.c | 64 +-
lib/task_mgmt.c | 4 +-
test-tool/iscsi-support.c | 5 +-
tests/Makefile.am | 2 +-
tests/prog_noop_reply.c | 20 +-
tests/prog_reconnect.c | 25 +-
tests/prog_reconnect_timeout.c | 25 +-
tests/prog_timeout.c | 18 +-
utils/Makefile.am | 2 +-
utils/iscsi-inq.c | 17 +-
utils/iscsi-ls.c | 26 +-
utils/iscsi-perf.c | 19 +-
utils/iscsi-readcapacity16.c | 16 +-
utils/iscsi-swp.c | 17 +-
32 files changed, 2388 insertions(+), 330 deletions(-)
create mode 100644 include/iser-private.h
create mode 100644 lib/iser.c

--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
This commit includes all iSER implementation in libscsi
library and utilities.

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
examples/Makefile.am | 2 +-
include/iscsi.h | 19 +-
include/iser-private.h | 209 +++++++
lib/Makefile.am | 6 +-
lib/init.c | 11 +
lib/iser.c | 1429 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/socket.c | 2 +-
tests/Makefile.am | 2 +-
utils/Makefile.am | 2 +-
9 files changed, 1673 insertions(+), 9 deletions(-)
create mode 100644 include/iser-private.h
create mode 100644 lib/iser.c

diff --git a/examples/Makefile.am b/examples/Makefile.am
index 42ad818..0de0b1f 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -1,6 +1,6 @@
AM_CPPFLAGS=-I. -I${srcdir}/../include "-D_U_=__attribute__((unused))" \
"-D_R_(A,B)=__attribute__((format(printf,A,B)))"
-AM_CFLAGS=$(WARN_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I/usr/include
LDADD = ../lib/libiscsi.la

noinst_PROGRAMS = iscsiclient iscsi-dd
diff --git a/include/iscsi.h b/include/iscsi.h
index 19cebe8..0778561 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -58,7 +58,8 @@ struct iscsi_pdu;

enum iscsi_transport_type {
ERR_TRANSPORT = -1,
- TCP_TRANSPORT = 0
+ TCP_TRANSPORT = 0,
+ ISER_TRANSPORT = 1
};

EXTERN enum iscsi_transport_type iscsi_get_transport(struct iscsi_context *iscsi);
@@ -67,7 +68,7 @@ EXTERN char *iscsi_parse_transport(const char *url);

static inline int iscsi_string_to_transport(char *transport) {

- return !strncmp(transport, "tcp", 3) ? TCP_TRANSPORT : ERR_TRANSPORT;
+ return !strncmp(transport, "tcp", 3) ? TCP_TRANSPORT : !strncmp(transport, "iser", 4) ? ISER_TRANSPORT : ERR_TRANSPORT;
}

EXTERN int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *sa, int ai_family);
@@ -76,19 +77,33 @@ EXTERN struct iscsi_pdu* iscsi_tcp_new_pdu(struct iscsi_context *iscsi, size_t s

EXTERN int iscsi_tcp_disconnect(struct iscsi_context *iscsi);

+EXTERN struct iscsi_pdu* iscsi_iser_new_pdu(struct iscsi_context *iscsi, size_t size);
+
+EXTERN int iscsi_iser_disconnect(struct iscsi_context *iscsi);
+
+EXTERN int iscsi_iser_connect(struct iscsi_context *iscsi, union socket_address* sa, int ai_family);
+
EXTERN int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
+EXTERN int iscsi_iser_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);

EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca);

EXTERN void iscsi_init_tcp_transport(struct iscsi_context *iscsi);
+EXTERN void iscsi_init_iser_transport(struct iscsi_context *iscsi);

EXTERN void iscsi_tcp_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
+EXTERN void iscsi_iser_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);

EXTERN int iscsi_tcp_service(struct iscsi_context *iscsi, int revents);
+EXTERN int iscsi_iser_service(struct iscsi_context *iscsi, int revents);

EXTERN int iscsi_tcp_get_fd(struct iscsi_context *iscsi);
+EXTERN int iscsi_iser_get_fd(struct iscsi_context *iscsi);

EXTERN int iscsi_tcp_which_events(struct iscsi_context *iscsi);
+EXTERN int iscsi_iser_which_events(struct iscsi_context *iscsi);
+
+EXTERN int iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi);
/*
* The following three functions are used to integrate libiscsi in an event
* system.
diff --git a/include/iser-private.h b/include/iser-private.h
new file mode 100644
index 0000000..c19c060
--- /dev/null
+++ b/include/iser-private.h
@@ -0,0 +1,209 @@
+/*
+ Copyright (c) 2014-2016, Mellanox Technologies, Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __iser_private_h__
+#define __iser_private_h__
+
+#include <stdint.h>
+#include <time.h>
+
+#include "iscsi-private.h"
+#include "scsi-lowlevel.h"
+#include <strings.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/ioctl.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <infiniband/verbs.h>
+#include <rdma/rdma_cma.h>
+#include <rdma/rdma_verbs.h>
+
+#define unlikely(x) __builtin_expect (!!(x), 0)
+
+#define ISER_VER 0x10
+#define ISER_WSV 0x08
+#define ISER_RSV 0x04
+
+#define NUM_MRS 0x100
+#define DATA_BUFFER_SIZE 0x40000
+
+#define ISER_HEADERS_LEN (sizeof(struct iser_hdr) + ISCSI_RAW_HEADER_SIZE)
+
+#define ISER_RECV_DATA_SEG_LEN 128
+#define ISER_RX_PAYLOAD_SIZE (ISER_HEADERS_LEN + ISER_RECV_DATA_SEG_LEN)
+
+#define ISER_RX_LOGIN_SIZE (ISER_HEADERS_LEN + ISCSI_DEF_MAX_RECV_SEG_LEN)
+
+#define ISCSI_DEF_MAX_RECV_SEG_LEN 8192
+
+#define BHSSC_FLAGS_R 0x40
+#define BHSSC_FLAGS_W 0x20
+
+#define ISER_MAX_CQ_LEN 1024
+
+#define ISER_ZBVA_NOT_SUPPORTED 0x80
+#define ISER_SEND_W_INV_NOT_SUPPORTED 0x40
+
+enum desc_type {
+ ISCSI_CONTROL = 0,
+ ISCSI_COMMAND};
+
+enum conn_state{
+ CONN_ERROR = 0,
+ CONN_DISCONNECTED,
+ CONN_ESTABLISHED};
+
+enum data_dir{
+ DATA_WRITE = 0,
+ DATA_READ};
+
+#define SHIFT_4K 12
+#define SIZE_4K (1ULL << SHIFT_4K)
+#define MASK_4K (~(SIZE_4K-1))
+
+#define ISER_DEF_XMIT_CMDS_MAX 512
+#define ISER_QP_MAX_RECV_DTOS (ISER_DEF_XMIT_CMDS_MAX)
+#define ISER_MIN_POSTED_RX (ISER_DEF_XMIT_CMDS_MAX >> 2)
+
+
+#define ISER_RX_PAD_SIZE (256 - (ISER_RX_PAYLOAD_SIZE + \
+ sizeof(struct ibv_mr*) + sizeof(struct ibv_sge)))
+
+/**
+ * struct iser_hdr - iSER header
+ *
+ * @flags: flags support (zbva, remote_inv)
+ * @rsvd: reserved
+ * @write_stag: write rkey
+ * @write_va: write virtual address
+ * @reaf_stag: read rkey
+ * @read_va: read virtual address
+ */
+
+struct iser_hdr {
+ uint8_t flags;
+ uint8_t rsvd[3];
+ uint32_t write_stag;
+ uint64_t write_va;
+ uint32_t read_stag;
+ uint64_t read_va;
+} __attribute__((packed));
+
+/**
+ * struct iser_rx_desc - iSER RX descriptor (for recv wr_id)
+ *
+ * @isr_hdr: iser header
+ * @iscsi_data: iscsi header
+ * @data: received data segment
+ * @rx_sg: ibv_sge of receive buffer
+ * @pad: padding
+ */
+
+
+struct iser_rx_desc {
+ struct iser_hdr iser_header;
+ char iscsi_header[ISCSI_RAW_HEADER_SIZE];
+ char data[ISER_RECV_DATA_SEG_LEN];
+ struct ibv_sge rx_sg;
+ struct ibv_mr *hdr_mr;
+ char pad[ISER_RX_PAD_SIZE];
+} __attribute__((packed));
+
+
+/**
+ * struct iser_tx_desc - iSER TX descriptor (for send wr_id)
+ *
+ * @iser_hdr: iser header
+ * @iscsi_header: iscsi header (bhs)
+ * @tx_sg: sg[0] points to iser/iscsi headers
+ * sg[1] optionally points to either of immediate data
+ * unsolicited data-out or control
+ * @num_sge: number sges used on this TX task
+ * @mr: iser/iscsi headers mr
+ * @data_mr: mr for case we need to allocate mr for read
+ * @next: next descriptor on the list
+ */
+
+struct iser_tx_desc {
+ struct iser_hdr iser_header;
+ unsigned char iscsi_header[ISCSI_RAW_HEADER_SIZE];
+ struct ibv_sge tx_sg[2];
+ int num_sge;
+ struct ibv_mr *hdr_mr;
+ char *data_buff;
+ struct ibv_mr *data_mr;
+ enum desc_type type;
+ enum data_dir data_dir;
+ struct iser_tx_desc *next;
+};
+
+struct iser_cm_hdr {
+ uint8_t flags;
+ uint8_t rsvd[3];
+} __packed;
+
+struct iser_pdu {
+ struct iscsi_pdu iscsi_pdu;
+ struct iser_tx_desc *desc;
+};
+
+struct iser_conn {
+ struct rdma_cm_id *cma_id;
+ struct rdma_event_channel *cma_channel;
+ struct rdma_cm_event *cma_event;
+
+ struct ibv_pd *pd;
+ struct ibv_cq *cq;
+ struct ibv_qp *qp;
+ struct ibv_comp_channel *comp_channel;
+
+ struct ibv_recv_wr rx_wr[ISER_MIN_POSTED_RX];
+
+ sem_t sem_connect;
+
+ struct ibv_mr *login_resp_mr;
+ struct ibv_mr *login_req_mr;
+ unsigned char *login_buf;
+ unsigned char *login_req_buf;
+ unsigned char *login_resp_buf;
+
+ pthread_t cmthread;
+
+ struct iser_rx_desc *rx_descs;
+ uint32_t num_rx_descs;
+ unsigned int rx_desc_head;
+
+ int post_recv_buf_count;
+ int qp_max_recv_dtos;
+ int min_posted_rx;
+ uint16_t max_cmds;
+
+ enum conn_state conn_state;
+
+ struct iser_tx_desc *tx_desc;
+};
+
+
+struct iser_transport { /* struct iser_conn */
+
+ struct iscsi_transport t;
+ struct iser_conn iser_conn;
+};
+
+#endif /* __iser_private_h__ */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 7306ae1..505c1e6 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,7 +4,7 @@ libiscsi_la_SOURCES = \
connect.c crc32c.c discovery.c init.c \
login.c nop.c pdu.c iscsi-command.c \
scsi-lowlevel.c socket.c sync.c task_mgmt.c \
- logging.c
+ logging.c iser.c

if !HAVE_LIBGCRYPT
libiscsi_la_SOURCES += md5.c
@@ -15,13 +15,13 @@ SOREVISON=1
SOAGE=0
libiscsi_la_LDFLAGS = \
-version-info $(SOCURRENT):$(SOREVISON):$(SOAGE) -bindir $(bindir) \
- -no-undefined -export-symbols ${srcdir}/libiscsi.syms
+ -no-undefined -export-symbols ${srcdir}/libiscsi.syms -libverbs -lrdmacm

libiscsi_la_CPPFLAGS = -I${srcdir}/../include -I$(srcdir)/include \
"-D_U_=__attribute__((unused))" \
"-D_R_(A,B)=__attribute__((format(printf,A,B)))"

-AM_CFLAGS=$(WARN_CFLAGS)
+AM_CFLAGS=$(WARN_CFLAGS) -I/usr/include

dist_noinst_DATA = libiscsi.syms libiscsi.def

diff --git a/lib/init.c b/lib/init.c
index 06dc962..284ec0c 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -32,6 +32,7 @@
#include <time.h>
#include "iscsi.h"
#include "iscsi-private.h"
+#include "iser-private.h"
#include "slist.h"


@@ -49,6 +50,16 @@ int iscsi_init_transport(struct iscsi_context *iscsi) {
}
iscsi->t = &tcp_transport->t;
iscsi_init_tcp_transport(iscsi);
+
+ } else if (iscsi->transport == ISER_TRANSPORT) {
+ struct iser_transport *iser_transport = iscsi_malloc(iscsi, sizeof(struct iser_transport));
+ if (iser_transport == NULL) {
+ iscsi_set_error(iscsi, "Couldn't allocate memory for transport\n");
+ return -1;
+ }
+ iscsi->t = &iser_transport->t;
+ iscsi_init_iser_transport(iscsi);
+
} else {
iscsi_set_error(iscsi, "Unfamilier transport type");
return -1;
diff --git a/lib/iser.c b/lib/iser.c
new file mode 100644
index 0000000..41f9c99
--- /dev/null
+++ b/lib/iser.c
@@ -0,0 +1,1429 @@
+/*
+ Copyright (c) 2014-2016, Mellanox Technologies, Ltd. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include "slist.h"
+#include <string.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include "iscsi.h"
+#include "iser-private.h"
+#include "iscsi-private.h"
+#include "scsi-lowlevel.h"
+#include <pthread.h>
+#include <semaphore.h>
+#include <poll.h>
+
+
+int cq_handle(struct iser_conn *iser_conn);
+
+static struct iscsi_transport iser_trans = {
+
+ .connect = iscsi_iser_connect,
+ .queue_pdu = iscsi_iser_queue_pdu,
+ .new_pdu = iscsi_iser_new_pdu,
+ .disconnect = iscsi_iser_disconnect,
+ .free_pdu = iscsi_iser_free_pdu,
+ .service = iscsi_iser_service,
+ .get_fd = iscsi_iser_get_fd,
+ .which_events = iscsi_iser_which_events,
+};
+
+void iscsi_init_iser_transport(struct iscsi_context *iscsi)
+{
+ iscsi->t = &iser_trans;
+
+ return;
+}
+/*
+ * iscsi_iser_get_fd() - Return completion queue
+ * event channel file descriptor.
+ */
+int
+iscsi_iser_get_fd(struct iscsi_context *iscsi)
+{
+ struct iser_transport *iser_transport;
+ struct iser_conn *iser_conn;
+
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+
+ iser_conn = &iser_transport->iser_conn;
+
+ return iser_conn->comp_channel->fd;
+}
+
+/*
+ * iscsi_iser_which_events() - Which events to wait for on file descriptor
+ * @iscsi_context: iscsi_context Unused
+ *
+ * Notes:
+ * CQ can only create POLLIN events, hence this function
+ * will return same value of 1 each time.
+ * Being used in QEMU iscsi block so we need compatability with TCP
+ */
+int
+iscsi_iser_which_events(struct iscsi_context *iscsi _U_)
+{
+ /* iSER is waiting to events from CQ that are always POLLIN */
+ return 1;
+}
+
+/*
+ * iscsi_iser_service() - Processing CQ events
+ * @iscsi_context: iscsi_context
+ * @revents: which events to handle
+ *
+ * Notes:
+ * CQ can only create POLLIN events, hence this function
+ * will poll the cq for completion until boundary or emptiness.
+ */
+int
+iscsi_iser_service(struct iscsi_context *iscsi, int revents)
+{
+ struct iser_transport *iser_transport;
+ int ret = 0;
+ struct iser_conn *iser_conn;
+
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+ iser_conn = &iser_transport->iser_conn;
+
+ if (revents == POLLIN)
+ ret = cq_handle(iser_conn);
+ else {
+ iscsi_set_error(iscsi, "revents is not POLLIN");
+ return -1;
+ }
+
+ if (ret) {
+ iscsi_set_error(iscsi, "CQ handle Failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * iser_free_rx_descriptors() - freeing descriptors memory
+ * @iser_conn: ib connection context
+ */
+void
+iser_free_rx_descriptors(struct iser_conn *iser_conn)
+{
+ struct iser_rx_desc *rx_desc;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+ int i;
+
+ rx_desc = iser_conn->rx_descs;
+ for (i = 0; i < iser_conn->qp_max_recv_dtos; i++, rx_desc++)
+ if (ibv_dereg_mr(rx_desc->hdr_mr))
+ iscsi_set_error(iscsi, "Failed ti deregister hdr mr");
+ iscsi_free(iscsi, iser_conn->rx_descs);
+
+ iser_conn->rx_descs = NULL;
+
+ return;
+}
+
+/*
+ * iser_free_login_buf() - freeing login buffer
+ * @iser_conn: ib connection context
+ */
+void
+iser_free_login_buf(struct iser_conn *iser_conn)
+{
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ iscsi_free(iscsi, iser_conn->login_buf);
+ iser_conn->login_buf = NULL;
+
+ return;
+}
+
+void
+iser_free_reg_mr(struct iser_conn *iser_conn)
+{
+ struct iser_tx_desc *tx_desc = iser_conn->tx_desc;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+ struct iser_tx_desc *temp_tx_desc;
+
+ while (tx_desc) {
+ ibv_dereg_mr(tx_desc->hdr_mr);
+ ibv_dereg_mr(tx_desc->data_mr);
+
+ if (tx_desc->data_buff)
+ iscsi_free(iscsi, tx_desc->data_buff);
+
+ temp_tx_desc = tx_desc;
+ tx_desc = tx_desc->next;
+ iscsi_free(iscsi, temp_tx_desc);
+ }
+ iser_conn->tx_desc = NULL;
+
+ return;
+}
+
+/*
+ * iser_free_iser_conn_res() - freeing ib context resources
+ * @iser_conn: ib connection context
+ */
+void
+iser_free_iser_conn_res(struct iser_conn *iser_conn, bool destroy)
+{
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ if (iser_conn->qp) {
+ rdma_destroy_qp(iser_conn->cma_id);
+ iser_conn->qp = NULL;
+ }
+
+ if (destroy) {
+
+ if (iser_conn->cmthread) {
+ pthread_cancel(iser_conn->cmthread);
+ iser_conn->cmthread = 0;
+ }
+
+ iser_free_reg_mr(iser_conn);
+
+ if (iser_conn->login_buf)
+ iser_free_login_buf(iser_conn);
+
+ if (iser_conn->rx_descs) {
+ iser_free_rx_descriptors(iser_conn);
+ iser_conn->rx_descs = NULL;
+ }
+
+ if (iser_conn->login_resp_mr) {
+ ret = ibv_dereg_mr(iser_conn->login_resp_mr);
+ if (ret)
+ iscsi_set_error(iscsi, "Failed to deregister login response mr");
+ }
+
+ if (iser_conn->cq) {
+ ret = ibv_destroy_cq(iser_conn->cq);
+ if (ret)
+ iscsi_set_error(iscsi, "Failed to destroy cq");
+ }
+
+ if (iser_conn->comp_channel) {
+ ret = ibv_destroy_comp_channel(iser_conn->comp_channel);
+ if (ret)
+ iscsi_set_error(iscsi, "Failed to destroy completion channel");
+ }
+
+ if (iser_conn->pd) {
+ ret = ibv_dealloc_pd(iser_conn->pd);
+ if (ret)
+ iscsi_set_error(iscsi, "Failed to deallocate pd");
+ }
+ }
+
+ return;
+}
+
+/*
+ * iser_conn_release() - releasing ib resources
+ * and destroying cm id
+ * @iser_conn: ib connection context
+ */
+void
+iser_conn_release(struct iser_conn *iser_conn)
+{
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ iser_free_iser_conn_res(iser_conn,true);
+
+ if (iser_conn->cma_id) {
+ ret = rdma_destroy_id(iser_conn->cma_id);
+ if (ret)
+ iscsi_set_error(iscsi, "Failed destroying cm id");
+
+ iser_conn->cma_id = NULL;
+ }
+
+ return;
+}
+
+/*
+ * iser_conn_terminate() - disconnecting rdma_cm
+ * @iser_conn: ib connection context
+ */
+void
+iser_conn_terminate(struct iser_conn *iser_conn)
+{
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ if(iser_conn->cma_id) {
+ ret = rdma_disconnect(iser_conn->cma_id);
+ if (ret)
+ iscsi_set_error(iscsi, "Failed to disconnect, conn: 0x%p, err %d\n",
+ iser_conn, ret);
+ }
+
+ return;
+}
+
+/*
+ * iscsi_iser_disconnect() - disconnecting iSER and
+ * freeing resources
+ * @iser_conn: ib connection context
+ */
+int
+iscsi_iser_disconnect(struct iscsi_context *iscsi) {
+
+ struct iser_transport *iser_transport;
+
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+
+ iser_conn_terminate(&iser_transport->iser_conn);
+
+ iser_conn_release(&iser_transport->iser_conn);
+
+ iscsi->fd = -1;
+ iscsi->is_connected = 0;
+ iscsi->is_corked = 0;
+
+ return 0;
+}
+
+struct iscsi_pdu*
+iscsi_iser_new_pdu(struct iscsi_context *iscsi, __attribute__((unused))size_t size) {
+
+ struct iscsi_pdu *pdu;
+ struct iser_pdu *iser_pdu;
+
+ iser_pdu = iscsi_zmalloc(iscsi, sizeof(*iser_pdu));
+ pdu = &iser_pdu->iscsi_pdu;
+ pdu->indata.data = NULL;
+
+ return pdu;
+}
+
+void
+iscsi_iser_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
+{
+ struct iser_pdu *iser_pdu;
+
+ if (pdu == NULL) {
+ iscsi_set_error(iscsi, "trying to free NULL pdu");
+ return;
+ }
+
+ iser_pdu = container_of(pdu, struct iser_pdu, iscsi_pdu);
+
+ if (pdu->outdata.size <= iscsi->smalloc_size) {
+ iscsi_sfree(iscsi, pdu->outdata.data);
+ } else {
+ iscsi_free(iscsi, pdu->outdata.data);
+ }
+ pdu->outdata.data = NULL;
+
+ if (pdu->indata.size <= iscsi->smalloc_size) {
+ iscsi_sfree(iscsi, pdu->indata.data);
+ } else {
+ iscsi_free(iscsi, pdu->indata.data);
+ }
+
+ pdu->indata.data = NULL;
+
+ if (iscsi->outqueue_current == pdu) {
+ iscsi->outqueue_current = NULL;
+ }
+
+ iscsi_free(iscsi, iser_pdu);
+}
+
+/**
+ ** iser_create_send_desc() - creating send descriptors
+ ** headers
+ ** @iser_pdu: iser pdu including iscsi pdu inside it
+ **/
+void iser_create_send_desc(struct iser_pdu *iser_pdu) {
+
+ unsigned char *iscsi_header = iser_pdu->iscsi_pdu.outdata.data;
+ struct iser_tx_desc *tx_desc = iser_pdu->desc;
+
+ memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
+ tx_desc->iser_header.flags = ISER_VER;
+ tx_desc->num_sge = 1;
+ memcpy(tx_desc->iscsi_header, iscsi_header, ISCSI_RAW_HEADER_SIZE);
+}
+
+/*
+ * iser_post_recvl() - posting login buffer receive request
+ * on receive queue
+ * @iser_conn: ib connection context
+ */
+int iser_post_recvl(struct iser_conn *iser_conn) {
+
+ struct ibv_recv_wr rx_wr;
+ struct ibv_recv_wr *rx_wr_failed;
+ struct ibv_sge sge;
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ sge.addr = (uintptr_t)iser_conn->login_resp_buf;
+ sge.length = ISER_RX_LOGIN_SIZE;
+ sge.lkey = iser_conn->login_resp_mr->lkey;
+
+ rx_wr.wr_id = (uintptr_t)iser_conn->login_resp_buf;
+ rx_wr.sg_list = &sge;
+ rx_wr.num_sge = 1;
+ rx_wr.next = NULL;
+
+ iser_conn->post_recv_buf_count++;
+ ret = ibv_post_recv(iser_conn->qp, &rx_wr, &rx_wr_failed);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to post recv login response\n");
+ iser_conn->post_recv_buf_count--;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * iser_post_send() - posting send requests
+ * on send queue
+ * @iser_conn: ib connection context
+ * @iser_tx_desc: send descriptor
+ * @signal: signal completion or not
+ *
+ * Notes:
+ * Need to handle signal better
+ */
+int iser_post_send(struct iser_conn *iser_conn, struct iser_tx_desc *tx_desc, bool signal) {
+
+ int ret;
+ struct ibv_send_wr send_wr;
+ struct ibv_send_wr *send_wr_failed;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ memset(&send_wr, 0, sizeof(send_wr));
+ send_wr.next = NULL;
+ send_wr.wr_id = (uintptr_t)tx_desc;
+ send_wr.sg_list = tx_desc->tx_sg;
+ send_wr.num_sge = tx_desc->num_sge;
+ send_wr.opcode = IBV_WR_SEND;
+ send_wr.send_flags = signal ? IBV_SEND_SIGNALED : 0;
+
+ ret = ibv_post_send(iser_conn->qp, &send_wr, &send_wr_failed);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to post send\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * iser_send_control() - sending iscsi pdu of type CONTROL
+ *
+ * @iser_transport: iser connection context
+ * @iser_pdu: iser pdu to send
+ */
+int iser_send_control(struct iser_transport *iser_transport, struct iser_pdu *iser_pdu) {
+
+ struct iser_tx_desc *tx_desc;
+ struct iser_conn *iser_conn = &iser_transport->iser_conn;
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+ size_t datalen;
+
+ if (iser_pdu == NULL) {
+ iscsi_set_error(iscsi, "Failed in iser_pdu");
+ return -1;
+ }
+ datalen = iser_pdu->iscsi_pdu.outdata.size - ISCSI_RAW_HEADER_SIZE;
+ tx_desc = iser_pdu->desc;
+ tx_desc->type = ISCSI_CONTROL;
+
+ iser_create_send_desc(iser_pdu);
+
+ if (datalen > 0) {
+ char* data = (char*)&iser_pdu->iscsi_pdu.outdata.data[ISCSI_RAW_HEADER_SIZE];
+ struct ibv_sge *tx_dsg = &tx_desc->tx_sg[1];
+
+ iser_conn->login_req_mr = ibv_reg_mr(iser_conn->pd, iser_conn->login_req_buf,
+ datalen , IBV_ACCESS_LOCAL_WRITE);
+ if (iser_conn->login_req_mr == NULL) {
+ iscsi_set_error(iscsi, "Failed Reg iser_conn->login_req_mr");
+ return -1;
+ }
+
+ memcpy(iser_conn->login_req_buf, data, datalen);
+
+ tx_dsg->addr = (uintptr_t)iser_conn->login_req_buf;
+ tx_dsg->length = datalen;
+ tx_dsg->lkey = iser_conn->login_req_mr->lkey;
+ tx_desc->num_sge = 2;
+ }
+
+ if (iser_pdu->iscsi_pdu.response_opcode == ISCSI_PDU_LOGIN_RESPONSE ||
+ iscsi->session_type == ISCSI_SESSION_DISCOVERY) {
+ ret = iser_post_recvl(iser_conn);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed Post Recv login");
+ return -1;
+ }
+ }
+
+ ret = iser_post_send(iser_conn, tx_desc, true);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to post send");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+/*
+ * iser_initialize_headers() - Initialize task headers
+ *
+ * @iser_pdu: iser pdu
+ * @iser_conn: iser_connection context
+ */
+int
+iser_initialize_headers(struct iser_pdu *iser_pdu, struct iser_conn *iser_conn)
+{
+ struct iser_tx_desc *tx_desc;
+
+ tx_desc = iser_conn->tx_desc;
+ ISCSI_LIST_REMOVE(&iser_conn->tx_desc, tx_desc);
+
+ iser_pdu->desc = tx_desc;
+
+ tx_desc->tx_sg[0].addr = (uintptr_t)tx_desc;
+ tx_desc->tx_sg[0].length = ISER_HEADERS_LEN;
+ tx_desc->tx_sg[0].lkey = tx_desc->hdr_mr->lkey;
+
+ return 0;
+}
+
+/*
+ * iser_prepare_read_cmd() - prepareing read command
+ *
+ * @iser_conn: ib connection context
+ * @iser_pdu: iser_pdu
+ *
+ * Notes:
+ * In case there isn't buffer from app
+ * we create buffer.
+ */
+static int
+iser_prepare_read_cmd(struct iser_conn *iser_conn,struct iser_pdu *iser_pdu)
+{
+ struct iser_hdr *hdr = &iser_pdu->desc->iser_header;
+ struct iser_tx_desc *tx_desc = iser_pdu->desc;
+ struct scsi_task *task = iser_pdu->iscsi_pdu.scsi_cbdata.task;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+ size_t data_size = task->expxferlen;
+
+ if (data_size > 0) {
+
+ if (task->iovector_in.iov == NULL) {
+ iser_pdu->iscsi_pdu.indata.data = iscsi_malloc(iscsi, data_size);
+ if (iser_pdu->iscsi_pdu.indata.data == NULL) {
+ iscsi_set_error(iscsi, "Failed to aloocate data buffer");
+ return -1;
+ }
+ iser_pdu->iscsi_pdu.indata.size = data_size;
+ }
+
+ tx_desc->data_dir = DATA_READ;
+ hdr->read_va = htobe64((uint64_t)tx_desc->data_buff);
+ hdr->read_stag = htobe32((uint32_t)tx_desc->data_mr->rkey);
+ hdr->flags |= ISER_RSV;
+
+ return 0;
+
+ } else {
+ iscsi_set_error(iscsi, "Read command with no expected transfer length");
+ return -1;
+ }
+}
+
+/*
+ * iser_prepare_write_cmd() - preparing write command
+ *
+ * @iser_conn: ib connection context
+ * @iser_pdu: iser pdu
+ */
+static int
+iser_prepare_write_cmd(struct iser_conn *iser_conn, struct iser_pdu *iser_pdu)
+{
+ struct iser_hdr *hdr = &iser_pdu->desc->iser_header;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+ struct iser_tx_desc *tx_desc = iser_pdu->desc;
+ struct scsi_iovector *iovector = iscsi_get_scsi_task_iovector_out(iscsi, &iser_pdu->iscsi_pdu);
+ int i, offset = 0;
+
+ if (iovector == NULL) {
+ iscsi_set_error(iscsi, "Can't find iovector data for DATA-OUT (RDMA)");
+ return -1;
+ }
+
+ tx_desc->data_dir = DATA_WRITE;
+
+ for(i = 0 ; i < iovector->niov ; i++) {
+ memcpy(&tx_desc->data_buff[offset], iovector->iov[i].iov_base, iovector->iov[i].iov_len);
+ offset += iovector->iov[i].iov_len;
+ }
+
+ hdr->flags |= ISER_WSV;
+ hdr->write_stag = htobe32((uint32_t)(tx_desc->data_mr->rkey));
+ hdr->write_va = htobe64((uint64_t)(tx_desc->data_buff));
+
+ return 0;
+}
+
+/*
+ * is_control_opcode() - check if iscsi opcode is of type CONTROL
+ *
+ * @opcode: iscsi opcode
+ */
+static bool
+is_control_opcode(uint8_t opcode)
+{
+ bool is_control = false;
+
+ switch (opcode & ISCSI_PDU_REJECT) {
+ case ISCSI_PDU_NOP_OUT:
+ case ISCSI_PDU_LOGIN_REQUEST:
+ case ISCSI_PDU_LOGOUT_REQUEST:
+ case ISCSI_PDU_TEXT_REQUEST:
+ is_control = true;
+ break;
+ case ISCSI_PDU_SCSI_REQUEST:
+ is_control = false;
+ break;
+ default:
+ is_control = false;
+ }
+
+ return is_control;
+}
+
+/*
+ * iser_send_command() - sending iscsi pdu of type COMMAND
+ *
+ * @iser_transport: iser connection context
+ * @iser_pdu: iser pdu to send
+ *
+ * Nots:
+ * Need to fix if failed prepareation return -1
+ */
+int
+iser_send_command(struct iser_transport *iser_transport,
+ struct iser_pdu *iser_pdu)
+{
+ struct iser_tx_desc *tx_desc = iser_pdu->desc;
+ struct iser_conn *iser_conn = &iser_transport->iser_conn;
+ int err = 0;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ tx_desc->type = ISCSI_COMMAND;
+
+ iser_create_send_desc(iser_pdu);
+
+ if (iser_pdu->desc->iscsi_header[1] & BHSSC_FLAGS_R) {
+ err = iser_prepare_read_cmd(iser_conn, iser_pdu);
+ if (err) {
+ iscsi_set_error(iscsi, "error in prepare read cmd\n");
+ return -1;
+ }
+ } else if (iser_pdu->desc->iscsi_header[1] & BHSSC_FLAGS_W) {
+ err = iser_prepare_write_cmd(iser_conn, iser_pdu);
+ if (err) {
+ iscsi_set_error(iscsi, "error in prepare write cmd\n");
+ return -1;
+ }
+ }
+
+ err = iser_post_send(iser_conn, tx_desc, true);
+ if (err)
+ return -1;
+ return 0;
+}
+
+
+/*
+ * iser_queue_pdu() - sending iscsi pdu
+ *
+ * @iscsi_context: iscsi context
+ * @iscsi_pdu: iscsi pdu
+ *
+ * Notes:
+ * Need to be compatible to TCP which has real queue,
+ * in iSER every queue pdu already sends all pdu (post_send)
+ */
+int iscsi_iser_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu) {
+
+ struct iser_pdu *iser_pdu;
+ struct iser_transport *iser_transport;
+ struct iser_conn *iser_conn;
+ uint8_t opcode;
+
+ if (pdu == NULL) {
+ iscsi_set_error(iscsi, "trying to queue NULL pdu");
+ return -1;
+ }
+
+ iser_pdu = container_of(pdu, struct iser_pdu, iscsi_pdu);
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+ iser_conn = &iser_transport->iser_conn;
+ opcode = pdu->outdata.data[0];
+
+ iscsi_pdu_set_expstatsn(pdu, iscsi->statsn + 1);
+ ISCSI_LIST_ADD_END(&iscsi->waitpdu, pdu);
+
+ if (iser_initialize_headers(iser_pdu, iser_conn)) {
+ iscsi_set_error(iscsi, "initialize headers Failed\n");
+ return -1;
+ }
+
+ if (unlikely(is_control_opcode(opcode))) {
+ if (iser_send_control(iser_transport, iser_pdu)) {
+ iscsi_set_error(iscsi, "iser_send_command Failed\n");
+ return -1;
+ }
+ } else {
+ if (iser_send_command(iser_transport, iser_pdu)) {
+ iscsi_set_error(iscsi, "iser_send_command Failed\n");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * iser_create_iser_conn_res() - creating ib connections resources
+ *
+ * @iser_conn: ib connection context
+ */
+static int iser_create_iser_conn_res(struct iser_conn *iser_conn) {
+
+ struct ibv_qp_init_attr init_attr;
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ memset(&init_attr, 0, sizeof(struct ibv_qp_init_attr));
+ init_attr.qp_context = (void *)iser_conn->cma_id->context;
+ init_attr.send_cq = iser_conn->cq;
+ init_attr.recv_cq = iser_conn->cq;
+ init_attr.cap.max_send_wr = ISER_QP_MAX_RECV_DTOS;
+ init_attr.cap.max_recv_wr = ISER_QP_MAX_RECV_DTOS;
+ init_attr.cap.max_send_sge = 2;
+ init_attr.cap.max_recv_sge = 1;
+ init_attr.qp_type = IBV_QPT_RC;
+
+ ret = rdma_create_qp(iser_conn->cma_id, iser_conn->pd, &init_attr);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to create qp\n");
+ return -1;
+ }
+ iser_conn->qp = iser_conn->cma_id->qp;
+
+ return ret;
+}
+
+/*
+ * iser_addr_handler() - handles RDMA_CM_EVENT_ADDR_RESOLVED
+ * event in rdma_cm
+ *
+ * @cma_id: connection manager id
+ */
+static int iser_addr_handler(struct rdma_cm_id *cma_id) {
+
+ struct iscsi_context *iscsi = cma_id->context;
+ struct iser_transport *iser_transport;
+ struct iser_conn *iser_conn;
+ int ret, flags;
+
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+ iser_conn = &iser_transport->iser_conn;
+
+ ret = rdma_resolve_route(cma_id, 1000);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed resolving address\n");
+ return -1;
+ }
+
+ iser_conn->pd = ibv_alloc_pd(cma_id->verbs);
+ if (!iser_conn->pd) {
+ iscsi_set_error(iscsi, "Failed to alloc pd\n");
+ return -1;
+ }
+ iser_conn->comp_channel = ibv_create_comp_channel(cma_id->verbs);
+ if (!iser_conn->comp_channel) {
+ iscsi_set_error(iscsi, "Failed to create comp channel");
+ goto pd_error;
+ }
+
+ flags = fcntl(iser_conn->comp_channel->fd, F_GETFL);
+ ret = fcntl(iser_conn->comp_channel->fd, F_SETFL, flags | O_NONBLOCK);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to set channel to nonblocking");
+ return -1;
+ }
+
+ iser_conn->cq = ibv_create_cq(cma_id->verbs,
+ ISER_MAX_CQ_LEN,
+ iser_transport,
+ iser_conn->comp_channel,
+ 0);
+ if (!iser_conn->cq) {
+ iscsi_set_error(iscsi, "Failed to create cq\n");
+ goto pd_error;
+ }
+
+ if (ibv_req_notify_cq(iser_conn->cq, 0)) {
+ iscsi_set_error(iscsi, "ibv_req_notify_cq failed\n");
+ goto cq_error;
+ }
+
+ iser_conn->login_buf = iscsi_malloc(iscsi, ISCSI_DEF_MAX_RECV_SEG_LEN + ISER_RX_LOGIN_SIZE);
+ if (!iser_conn->login_buf) {
+ iscsi_set_error(iscsi, "Failed to allocate memory for login_buf\n");
+ iscsi_free(iscsi, iser_conn->login_buf);
+ goto cq_error;
+ }
+
+ iser_conn->login_req_buf = iser_conn->login_buf;
+ iser_conn->login_resp_buf = iser_conn->login_buf + ISCSI_DEF_MAX_RECV_SEG_LEN;
+ iser_conn->login_resp_mr = ibv_reg_mr(iser_conn->pd, iser_conn->login_resp_buf,
+ ISER_RX_LOGIN_SIZE, IBV_ACCESS_LOCAL_WRITE);
+ if(!iser_conn->login_resp_mr) {
+ iscsi_set_error(iscsi, "Failed to reg login_resp_mr\n");
+ iscsi_free(iscsi, iser_conn->login_buf);
+ goto cq_error;
+ }
+
+ return 0;
+
+cq_error:
+ ibv_destroy_cq(iser_conn->cq);
+
+pd_error:
+ ibv_dealloc_pd(iser_conn->pd);
+
+ return -1;
+}
+/*
+ * iser_route_handler() - handles RDMA_CM_EVENT_ROUTE_RESOLVED
+ * event in rdma_cm
+ *
+ * @cma_id: connection manager id
+ */
+static int iser_route_handler(struct rdma_cm_id *cma_id) {
+
+ struct rdma_conn_param conn_param;
+ struct iser_cm_hdr req_hdr;
+ struct iscsi_context* iscsi = cma_id->context;
+ int ret;
+
+ struct iser_transport *iser_transport = container_of(iscsi->t, struct iser_transport, t);
+ struct iser_conn *iser_conn = &iser_transport->iser_conn;
+
+ ret = iser_create_iser_conn_res(iser_conn);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to create ib conn res\n");
+ goto login_mr_error;
+ }
+
+ memset(&conn_param, 0, sizeof(struct rdma_conn_param));
+ conn_param.responder_resources = 4;
+ conn_param.retry_count = 7;
+ conn_param.rnr_retry_count = 6;
+
+ memset(&req_hdr, 0, sizeof(req_hdr));
+ req_hdr.flags = (ISER_ZBVA_NOT_SUPPORTED |
+ ISER_SEND_W_INV_NOT_SUPPORTED);
+ conn_param.private_data = (void *)&req_hdr;
+ conn_param.private_data_len = sizeof(struct iser_cm_hdr);
+
+ ret = rdma_connect(cma_id, &conn_param);
+ if (ret) {
+ iscsi_set_error(iscsi, "conn %p failure connecting: %d", iser_transport, ret);
+ return -1;
+ }
+ return ret;
+
+login_mr_error:
+ ibv_dereg_mr(iser_conn->login_resp_mr);
+
+ ibv_destroy_cq(iser_conn->cq);
+
+ ibv_dealloc_pd(iser_conn->pd);
+
+ return -1;
+}
+
+/*
+ * iser_alloc_rx_descriptors() - allocation receive descriptors
+ *
+ * @iser_conn: ib connection context
+ * @cmds_max: maximum in flight commands
+ */
+int iser_alloc_rx_descriptors(struct iser_conn *iser_conn, int cmds_max)
+{
+ int i,j;
+ struct iser_rx_desc *rx_desc;
+ struct ibv_sge *rx_sg;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ iser_conn->qp_max_recv_dtos = cmds_max;
+ iser_conn->min_posted_rx = ISER_MIN_POSTED_RX;
+
+ iser_conn->num_rx_descs = cmds_max;
+
+ iser_conn->rx_descs = iscsi_malloc(iscsi, iser_conn->num_rx_descs * sizeof(*rx_desc));
+ if (!iser_conn->rx_descs) {
+ iscsi_set_error(iscsi, "Failed to allocate rx descriptors\n");
+ return -1;
+ }
+
+ rx_desc = iser_conn->rx_descs;
+
+ for (i = 0; i < iser_conn->qp_max_recv_dtos; i++, rx_desc++) {
+ rx_desc->hdr_mr = ibv_reg_mr(iser_conn->pd, rx_desc, ISER_RX_PAYLOAD_SIZE, IBV_ACCESS_LOCAL_WRITE);
+
+ if (rx_desc->hdr_mr == NULL) {
+ iscsi_set_error(iscsi, "Failed to register (%i) reg_mr\n", i);
+ goto fail_alloc_mrs;
+ }
+
+ rx_sg = &rx_desc->rx_sg;
+ rx_sg->addr = (uintptr_t)rx_desc;
+ rx_sg->length = ISER_RX_PAYLOAD_SIZE;
+ rx_sg->lkey = rx_desc->hdr_mr->lkey;
+ }
+
+ iser_conn->rx_desc_head = 0;
+
+ return 0;
+
+fail_alloc_mrs:
+
+ rx_desc = iser_conn->rx_descs;
+ for (j = 0; j < i ; j++, rx_desc++)
+ ibv_dereg_mr(rx_desc->hdr_mr);
+
+ iscsi_free(iscsi, iser_conn->rx_descs);
+
+ return -1;
+}
+
+/*
+ * iser_post_recvm() - posting receive requests
+ *
+ * @iser_conn: ib connection context
+ * @count: amount of receive requests to post on receive queue
+ */
+int
+iser_post_recvm(struct iser_conn *iser_conn, int count)
+{
+ struct ibv_recv_wr *rx_wr, *rx_wr_failed;
+ int i, ret;
+ unsigned int my_rx_head = iser_conn->rx_desc_head;
+ struct iser_rx_desc *rx_desc;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ for (rx_wr = iser_conn->rx_wr, i = 0; i < count; i++, rx_wr++) {
+ rx_desc = &iser_conn->rx_descs[my_rx_head];
+ rx_wr->wr_id = (uintptr_t)rx_desc;
+ rx_wr->sg_list = &rx_desc->rx_sg;
+ rx_wr->num_sge = 1;
+ rx_wr->next = rx_wr + 1;
+ my_rx_head = (my_rx_head + 1) % iser_conn->qp_max_recv_dtos;
+ }
+
+ rx_wr--;
+ rx_wr->next = NULL; /* mark end of work requests list */
+
+ iser_conn->post_recv_buf_count += count;
+ ret = ibv_post_recv(iser_conn->qp, iser_conn->rx_wr, &rx_wr_failed);
+ if (ret) {
+ iscsi_set_error(iscsi, "ib_post_recv failed ret=%d", ret);
+ iser_conn->post_recv_buf_count -= count;
+ } else
+ iser_conn->rx_desc_head = my_rx_head;
+
+ return ret;
+}
+
+int
+iser_reg_mr(struct iser_conn *iser_conn)
+{
+ int i;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+ struct iser_tx_desc *tx_desc;
+
+ for (i = 0 ; i < NUM_MRS ; i++) {
+
+ tx_desc = iscsi_malloc(iscsi, sizeof(*tx_desc));
+ if (tx_desc == NULL) {
+ iscsi_set_error(iscsi, "Out-Of-Memory, failed to allocate data buffer");
+ return -1;
+ }
+
+ tx_desc->hdr_mr = ibv_reg_mr(iser_conn->pd, tx_desc, ISER_HEADERS_LEN, IBV_ACCESS_LOCAL_WRITE);
+ if (tx_desc->hdr_mr == NULL) {
+ iscsi_set_error(iscsi, "Failed to register data mr");
+ return -1;
+ }
+
+ tx_desc->data_buff = iscsi_malloc(iscsi, DATA_BUFFER_SIZE);
+ if (tx_desc->data_buff == NULL) {
+ iscsi_set_error(iscsi, "Out-Of-Memory, failed to allocate data buffer");
+ return -1;
+ }
+
+ tx_desc->data_mr = ibv_reg_mr(iser_conn->pd, tx_desc->data_buff, DATA_BUFFER_SIZE,
+ IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_READ | IBV_ACCESS_REMOTE_WRITE);
+ if (tx_desc->data_mr == NULL) {
+ iscsi_set_error(iscsi, "Failed to register data mr");
+ return -1;
+ }
+
+ ISCSI_LIST_ADD_END(&iser_conn->tx_desc, tx_desc);
+ }
+
+ return 0;
+}
+
+/**
+ * iser_rcv_completion() - handling and processing receive completion
+ *
+ * @rx_desc: receive descriptor
+ * @iser_conn: ib connection context
+ *
+ * Notes:
+ * After changing mrs to in-advanced mrs need to add
+ * commant about memcpy of data from iSER buffer to
+ * App buffer
+ */
+int
+iser_rcv_completion(struct iser_rx_desc *rx_desc,
+ struct iser_conn *iser_conn)
+{
+ struct iscsi_in_pdu *in = NULL;
+ int outstanding, count = 0, err;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ in = iscsi_malloc(iscsi, sizeof(*in));
+
+ if ((unsigned char *)rx_desc == iser_conn->login_resp_buf)
+ if (iscsi->session_type == ISCSI_SESSION_NORMAL) {
+ if(iser_alloc_rx_descriptors(iser_conn,255)) {
+ iscsi_set_error(iscsi, "iser_alloc_rx_descriptors Failed\n");
+ return -1;
+ }
+ err = iser_post_recvm(iser_conn, ISER_MIN_POSTED_RX);
+ if (err) {
+ iscsi_set_error(iscsi, "posting %d rx bufs err %d", count, err);
+ return -1;
+ }
+ }
+ in->hdr = (unsigned char*)rx_desc->iscsi_header;
+ in->data_pos = iscsi_get_pdu_data_size(&in->hdr[0]);
+ in->data = (unsigned char*)rx_desc->data;
+
+ enum iscsi_opcode opcode = in->hdr[0] & 0x3f;
+ uint32_t itt = scsi_get_uint32(&in->hdr[16]);
+
+ if (opcode == ISCSI_PDU_NOP_IN && itt == 0xffffffff)
+ goto nop_target;
+
+ struct iscsi_pdu *iscsi_pdu;
+ struct iser_pdu *iser_pdu;
+ for (iscsi_pdu = iscsi->waitpdu ; iscsi_pdu ; iscsi_pdu = iscsi_pdu->next) {
+ if(iscsi_pdu->itt == itt)
+ break;
+ }
+
+ iser_pdu = container_of(iscsi_pdu, struct iser_pdu, iscsi_pdu);
+
+ /* in case of read completion we need to copy data *
+ * from pre-allocated buffers into application buffers */
+
+ if (iser_pdu->desc->type == ISCSI_COMMAND &&
+ iser_pdu->desc->data_dir == DATA_READ) {
+
+ int i, offset = 0;
+ struct scsi_task *task = iser_pdu->iscsi_pdu.scsi_cbdata.task;
+ struct scsi_iovector *iovector_in = &task->iovector_in;
+
+ if (iovector_in->iov == NULL) {
+ memcpy(iser_pdu->iscsi_pdu.indata.data, &iser_pdu->desc->data_buff[offset],
+ iser_pdu->iscsi_pdu.indata.size);
+ } else {
+ for (i = 0 ; i < iovector_in->niov ; i++) {
+ memcpy(iovector_in->iov[i].iov_base, &iser_pdu->desc->data_buff[offset],
+ iovector_in->iov[i].iov_len);
+ offset += iovector_in->iov[i].iov_len;
+ }
+ }
+ }
+
+ ISCSI_LIST_ADD_END(&iser_conn->tx_desc, iser_pdu->desc);
+
+nop_target:
+
+ /* decrementing conn->post_recv_buf_count only --after-- freeing the *
+ * task eliminates the need to worry on tasks which are completed in *
+ * parallel to the execution of iser_conn_term. So the code that waits *
+ * for the posted rx bufs refcount to become zero handles everything */
+ iser_conn->post_recv_buf_count--;
+
+ if ((unsigned char *)rx_desc == iser_conn->login_resp_buf)
+ goto receive;
+
+ outstanding = iser_conn->post_recv_buf_count;
+ if (outstanding + iser_conn->min_posted_rx <= iser_conn->qp_max_recv_dtos) {
+ if(iser_conn->qp_max_recv_dtos - outstanding > iser_conn->min_posted_rx)
+ count = iser_conn->min_posted_rx;
+ else
+ count = iser_conn->qp_max_recv_dtos - outstanding;
+ err = iser_post_recvm(iser_conn, count);
+ if (err) {
+ iscsi_set_error(iscsi, "posting %d rx bufs err %d", count, err);
+ return -1;
+ }
+ }
+
+receive:
+
+ err = iscsi_process_pdu(iscsi, in);
+ iscsi_free(iscsi, in);
+
+ return err;
+}
+
+/**
+ * iser_sndcompletion() - handling send completion
+ *
+ * @tx_desc: send descriptor
+ * @iser_conn: ib connection context
+ *
+ */
+int
+iser_snd_completion(struct iser_tx_desc *tx_desc _U_,
+ struct iser_conn *iser_conn _U_)
+{
+ return 0;
+}
+
+/**
+ * iser_handle_wc() - handling work completion
+ *
+ * @wc: work completion
+ * @iser_conn: ib connection context
+ *
+ */
+static int iser_handle_wc(struct ibv_wc *wc,struct iser_conn *iser_conn)
+{
+ struct iser_tx_desc *tx_desc;
+ struct iser_rx_desc *rx_desc;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ if (wc->status == IBV_WC_SUCCESS) {
+ if (wc->opcode == IBV_WC_RECV) {
+ rx_desc = (struct iser_rx_desc *)(uintptr_t)wc->wr_id;
+
+ return iser_rcv_completion(rx_desc, iser_conn);
+ } else
+ if (wc->opcode == IBV_WC_SEND) {
+ tx_desc = (struct iser_tx_desc *)(uintptr_t)wc->wr_id;
+
+ return iser_snd_completion(tx_desc, iser_conn);
+ } else {
+ iscsi_set_error(iscsi, "Unknown wc opcode %d\n", wc->opcode);
+
+ return -1;
+ }
+ } else {
+ if (wc->status != IBV_WC_WR_FLUSH_ERR) {
+ ISCSI_LOG(iscsi, 3, "wr id %lx status %d vend_err %x\n",
+ wc->wr_id, wc->status, wc->vendor_err);
+ return iscsi_service_reconnect_if_loggedin(iscsi);
+ } else {
+ iscsi_set_error(iscsi, "flush error: wr id %lx\n", wc->wr_id);
+
+ return 0;
+ }
+ }
+}
+
+/**
+ * cq_event_handler() - polling and handling completions
+ *
+ * @iser_conn: ib connection context
+ *
+ * Notes:
+ * Need to decide about how much competion to poll
+ * each time.
+ */
+static int cq_event_handler(struct iser_conn *iser_conn)
+{
+ struct ibv_wc wc[16];
+ unsigned int i;
+ unsigned int n;
+ unsigned int completed = 0;
+
+ while ((n = ibv_poll_cq(iser_conn->cq, 16, wc)) > 0) {
+ for (i = 0; i < n; i++)
+ if (iser_handle_wc(&wc[i], iser_conn))
+ return -1;
+
+ completed += n;
+ if (completed >= 512)
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * cq_handle() - handling completion queue event
+ *
+ * @iser_conn: ib connection context
+ *
+ * Notes:
+ * Need to check if it is possible
+ * to get cq event except POLLIN.
+ */
+int cq_handle(struct iser_conn *iser_conn)
+{
+ void *ev_ctx = NULL;
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ ibv_get_cq_event(iser_conn->comp_channel, &iser_conn->cq, &ev_ctx);
+ ret = ibv_req_notify_cq(iser_conn->cq, 0);
+
+ /* FIXME: aggregate ack cq event for efficiency */
+ ibv_ack_cq_events(iser_conn->cq, 1);
+ if (ret) {
+ iscsi_set_error(iscsi, "failed notify or ack CQ");
+ return -1;
+ }
+
+ ret = cq_event_handler(iser_conn);
+ if (ret) {
+ iscsi_set_error(iscsi, "failed CQ handler");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * iser_connected_handler() - handles RDMA_CM_EVENT_ESTABLISHED
+ * event in rdma_cm
+ *
+ * @cma_id: connection manager id
+ *
+ */
+static int iser_connected_handler(struct rdma_cm_id *cma_id) {
+
+ struct iscsi_context *iscsi = cma_id->context;
+ struct iser_transport *iser_transport;
+ struct iser_conn *iser_conn;
+
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+ if (iser_transport == NULL) {
+ iscsi_set_error(iscsi, "Failed init of transport\n");
+ return -1;
+ }
+
+ iser_conn = &iser_transport->iser_conn;
+
+ iser_conn->post_recv_buf_count = 0;
+
+ return iser_reg_mr(iser_conn);
+
+}
+
+/*
+ * iser_cma_handler() - handles rdma connection manager events
+ *
+ * @iser_conn: ib connection context
+ * @cma_id: connection manager id
+ * @event: rdma cm event
+ *
+ */
+int iser_cma_handler(struct iser_conn *iser_conn,struct rdma_cm_id *cma_id, struct rdma_cm_event *event) {
+
+ int ret = 0;
+
+ switch(event->event) {
+
+ case RDMA_CM_EVENT_ADDR_RESOLVED:
+ ret = iser_addr_handler(cma_id);
+ break;
+ case RDMA_CM_EVENT_ROUTE_RESOLVED:
+ ret = iser_route_handler(cma_id);
+ break;
+ case RDMA_CM_EVENT_ESTABLISHED:
+ ret = iser_connected_handler(cma_id);
+ if(ret)
+ iser_conn->conn_state = CONN_ERROR;
+ else
+ iser_conn->conn_state = CONN_ESTABLISHED;
+ sem_post(&iser_conn->sem_connect);
+ break;
+ case RDMA_CM_EVENT_ADDR_ERROR:
+ case RDMA_CM_EVENT_ROUTE_ERROR:
+ case RDMA_CM_EVENT_CONNECT_ERROR:
+ case RDMA_CM_EVENT_UNREACHABLE:
+ case RDMA_CM_EVENT_REJECTED:
+ iser_conn->conn_state = CONN_ERROR;
+ ret = -1;
+ sem_post(&iser_conn->sem_connect);
+ break;
+ case RDMA_CM_EVENT_DISCONNECTED:
+ case RDMA_CM_EVENT_ADDR_CHANGE:
+ case RDMA_CM_EVENT_TIMEWAIT_EXIT:
+ iser_conn->conn_state = CONN_DISCONNECTED;
+ ret = -1;
+ sem_post(&iser_conn->sem_connect);
+ break;
+ default:
+ iser_conn->conn_state = CONN_ERROR;
+ ret = -1;
+ sem_post(&iser_conn->sem_connect);
+ break;
+ }
+ return ret;
+}
+
+/*
+ * iser_connected_handler() - thread to catch rdma cm events
+ *
+ * @arg: ib connection context
+ *
+ * Notes:
+ * Need to check if copying event is necessery
+ */
+static void *cm_thread(void *arg)
+{
+ struct iser_conn *iser_conn = arg;
+ struct rdma_cm_event event_copy;
+ int ret;
+ struct iscsi_context *iscsi = iser_conn->cma_id->context;
+
+ while (1) {
+ ret = rdma_get_cm_event(iser_conn->cma_channel, &iser_conn->cma_event);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to get RDMA-CM Event\n");
+ pthread_exit(NULL);
+ }
+ memcpy(&event_copy, iser_conn->cma_event, sizeof(struct rdma_cm_event));
+ ret = iser_cma_handler(iser_conn, iser_conn->cma_id, &event_copy);
+ rdma_ack_cm_event(iser_conn->cma_event);
+ if (ret) {
+ iscsi_set_error(iscsi, "Failed to handle event\n");
+ pthread_exit(NULL);
+ }
+ }
+}
+
+/*
+ * iscsi_iser_connect() - creating rdma connection manager
+ * and connection it to target.
+ *
+ * @iscsi: iscsi context
+ * @sa: socket address for rdma cm connect
+ * @ai_family unused
+ *
+ * Notes:
+ * Need to move iser_reg_mr(headers) to iser_connected_handler.
+ */
+int iscsi_iser_connect(struct iscsi_context *iscsi, union socket_address *sa,__attribute__((unused)) int ai_family) {
+
+ struct iser_transport *iser_transport;
+ struct iser_conn *iser_conn;
+ int ret;
+
+ iser_transport = container_of(iscsi->t, struct iser_transport, t);
+ if (iser_transport == NULL) {
+ iscsi_set_error(iscsi, "Failed init of transport\n");
+ return -1;
+ }
+ iser_conn = &iser_transport->iser_conn;
+ sem_init(&iser_conn->sem_connect, 0, 0);
+
+ iser_conn->cma_channel = rdma_create_event_channel();
+
+ if (iser_conn->cma_channel == NULL) {
+ iscsi_set_error(iscsi, "Failed creating Event Channel\n");
+ return -1;
+ }
+
+ if (rdma_create_id(iser_conn->cma_channel, &iser_conn->cma_id, (void *)iscsi, RDMA_PS_TCP)) {
+ iscsi_set_error(iscsi, "Failed create channel_id");
+ return -1;
+ }
+
+ ret = pthread_create(&iser_conn->cmthread, NULL, cm_thread, iser_conn);
+ if(ret) {
+ iscsi_set_error(iscsi, "Failed create Connection Manager Thread");
+ return -1;
+ }
+
+ if(rdma_resolve_addr(iser_conn->cma_id, NULL, &sa->sa, 2000)) {
+ iscsi_set_error(iscsi, "Failed resolve address");
+ return -1;
+ }
+
+ sem_wait(&iser_conn->sem_connect);
+
+ switch(iser_conn->conn_state) {
+
+ case CONN_ERROR:
+ iscsi_set_error(iscsi, "Conn Error event");
+ return -1;
+
+ case CONN_DISCONNECTED:
+ iscsi_set_error(iscsi, "Conn disconnected event");
+ return -1;
+
+ case CONN_ESTABLISHED:
+ break;
+
+ default:
+ iscsi_set_error(iscsi, "Unknown State of connection");
+ return -1;
+
+ }
+
+
+ iscsi->is_connected = 1;
+ iscsi->socket_status_cb(iscsi, SCSI_STATUS_GOOD, NULL, iscsi->connect_data);
+ iscsi->socket_status_cb = NULL;
+
+ return 0;
+}
diff --git a/lib/socket.c b/lib/socket.c
index e036c4b..fa724cf 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -834,7 +834,7 @@ iscsi_write_to_socket(struct iscsi_context *iscsi)
return 0;
}

-static int
+int
iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi)
{
if (iscsi->is_loggedin) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 4378320..471e04e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,6 +1,6 @@
AM_CPPFLAGS = -I../include "-D_U_=__attribute__((unused))" \
"-D_R_(A,B)=__attribute__((format(printf,A,B)))"
-AM_CFLAGS = $(WARN_CFLAGS)
+AM_CFLAGS = $(WARN_CFLAGS) -I/usr/include
LDADD = ../lib/libiscsi.la

noinst_PROGRAMS = prog_reconnect prog_reconnect_timeout prog_noop_reply \
diff --git a/utils/Makefile.am b/utils/Makefile.am
index bde1c81..657ca9d 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -1,6 +1,6 @@
AM_CPPFLAGS = -I${srcdir}/../include "-D_U_=__attribute__((unused))" \
"-D_R_(A,B)=__attribute__((format(printf,A,B)))"
-AM_CFLAGS = $(WARN_CFLAGS)
+AM_CFLAGS = $(WARN_CFLAGS) -I/usr/include
LDADD = ../lib/libiscsi.la

bin_PROGRAMS = iscsi-inq iscsi-ls iscsi-perf iscsi-readcapacity16 \
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
include/iscsi-private: adding queue_pdu in transport function pointers
struct
include/iscsi: declaration of tcp_queue_pdu function

socket: adding queue_pdu function to transport initialization

all_library: changing iscsi_queue_pdu into iscsi->t->queue_pdu

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
include/iscsi-private.h | 2 +-
include/iscsi.h | 3 +++
lib/discovery.c | 2 +-
lib/iscsi-command.c | 4 ++--
lib/login.c | 4 ++--
lib/nop.c | 4 ++--
lib/socket.c | 5 +++--
lib/task_mgmt.c | 2 +-
8 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index 820cdcf..e69dc37 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -78,6 +78,7 @@ union socket_address {
struct iscsi_transport {

int (*connect)(struct iscsi_context *iscsi, union socket_address *sa, int ai_family);
+ int (*queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
};

struct iscsi_tcp_transport {
@@ -308,7 +309,6 @@ void iscsi_pdu_set_datasn(struct iscsi_pdu *pdu, uint32_t datasn);
void iscsi_pdu_set_bufferoffset(struct iscsi_pdu *pdu, uint32_t bufferoffset);
int iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
unsigned char *dptr, int dsize);
-int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);

int iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
unsigned char *dptr, int dsize, int pdualignment);
diff --git a/include/iscsi.h b/include/iscsi.h
index a6714df..d560915 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -34,6 +34,7 @@ extern "C" {
struct iscsi_context;
struct sockaddr;
union socket_address;
+struct iscsi_pdu;

/* API VERSION */
#define LIBISCSI_API_VERSION (20150621)
@@ -68,6 +69,8 @@ static inline int iscsi_string_to_transport(char *transport) {

EXTERN int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *sa, int ai_family);

+EXTERN int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
+
EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca);

EXTERN void iscsi_init_tcp_transport(struct iscsi_context *iscsi);
diff --git a/lib/discovery.c b/lib/discovery.c
index d38004d..07f826d 100644
--- a/lib/discovery.c
+++ b/lib/discovery.c
@@ -80,7 +80,7 @@ iscsi_discovery_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
pdu->callback = cb;
pdu->private_data = private_data;

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"text pdu.");
iscsi_free_pdu(iscsi, pdu);
diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
index 063f633..95cb07f 100644
--- a/lib/iscsi-command.c
+++ b/lib/iscsi-command.c
@@ -134,7 +134,7 @@ iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
pdu->callback = cmd_pdu->callback;
pdu->private_data = cmd_pdu->private_data;

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"scsi pdu.");
ISCSI_LIST_REMOVE(&iscsi->outqueue, cmd_pdu);
@@ -281,7 +281,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
pdu->callback = iscsi_scsi_response_cb;
pdu->private_data = &pdu->scsi_cbdata;

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"scsi pdu.");
iscsi_free_pdu(iscsi, pdu);
diff --git a/lib/login.c b/lib/login.c
index bd91953..5592e70 100644
--- a/lib/login.c
+++ b/lib/login.c
@@ -1002,7 +1002,7 @@ iscsi_login_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
pdu->callback = cb;
pdu->private_data = private_data;

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"pdu.");
iscsi_free_pdu(iscsi, pdu);
@@ -1299,7 +1299,7 @@ iscsi_logout_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
pdu->callback = cb;
pdu->private_data = private_data;

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "Out-of-memory: failed to queue iscsi "
"logout pdu.");
iscsi_free_pdu(iscsi, pdu);
diff --git a/lib/nop.c b/lib/nop.c
index 4b6d5ab..d5031cc 100644
--- a/lib/nop.c
+++ b/lib/nop.c
@@ -78,7 +78,7 @@ iscsi_nop_out_async(struct iscsi_context *iscsi, iscsi_command_cb cb,
}
}

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu");
iscsi_free_pdu(iscsi, pdu);
return -1;
@@ -122,7 +122,7 @@ iscsi_send_target_nop_out(struct iscsi_context *iscsi, uint32_t ttt, uint32_t lu
/* cmdsn is not increased if Immediate delivery*/
iscsi_pdu_set_cmdsn(pdu, iscsi->cmdsn);

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi nop-out pdu");
iscsi_free_pdu(iscsi, pdu);
return -1;
diff --git a/lib/socket.c b/lib/socket.c
index 529949d..2bd60a4 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -77,6 +77,7 @@ struct iscsi_transport;
static struct iscsi_transport tcp_transport =
{
.connect = iscsi_tcp_connect,
+ .queue_pdu = iscsi_tcp_queue_pdu,
};

void iscsi_init_tcp_transport(struct iscsi_context *iscsi)
@@ -935,8 +936,7 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
return 0;
}

-int
-iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
+int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
if (pdu == NULL) {
iscsi_set_error(iscsi, "trying to queue NULL pdu");
@@ -963,6 +963,7 @@ iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
iscsi_add_to_outqueue(iscsi, pdu);

return 0;
+
}

void
diff --git a/lib/task_mgmt.c b/lib/task_mgmt.c
index b00b6fa..983154f 100644
--- a/lib/task_mgmt.c
+++ b/lib/task_mgmt.c
@@ -82,7 +82,7 @@ iscsi_task_mgmt_async(struct iscsi_context *iscsi,
pdu->callback = cb;
pdu->private_data = private_data;

- if (iscsi_queue_pdu(iscsi, pdu) != 0) {
+ if (iscsi->t->queue_pdu(iscsi, pdu) != 0) {
iscsi_set_error(iscsi, "failed to queue iscsi taskmgmt pdu");
iscsi_free_pdu(iscsi, pdu);
return -1;
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
Preperation for iSER future implementation,
Default transport is TCP in every util.

iscsi url with transport parameter:

iscsi://[<username>[%<password>]@]" \
"<host>[:<port>]/<target-iqn>/<lun>/<transport_type>"

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
include/iscsi.h | 1 +
lib/init.c | 11 +++++++++++
2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/include/iscsi.h b/include/iscsi.h
index 55ec90b..19cebe8 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -180,6 +180,7 @@ struct iscsi_url {
char target_user[MAX_STRING_SIZE + 1];
char target_passwd[MAX_STRING_SIZE + 1];
int lun;
+ char transport[MAX_STRING_SIZE + 1];
struct iscsi_context *iscsi;
};

diff --git a/lib/init.c b/lib/init.c
index fc48c28..06dc962 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -506,6 +506,7 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
char *target = NULL;
char *lun;
char *tmp;
+ char *transport = NULL;
int l = 0;

if (strncmp(url, "iscsi://", 8)) {
@@ -596,6 +597,15 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)
return NULL;
}
*lun++ = 0;
+ transport = strchr(lun, '/');
+ if (transport == NULL) {
+ iscsi_set_error(iscsi, "Invalid URL %s\nCould not "
+ "parse <lun>\niSCSI URL must be of the form: "
+ "%s",
+ url, ISCSI_URL_SYNTAX);
+ return NULL;
+ }
+ *transport++ = 0;

l = strtol(lun, &tmp, 10);
if (*lun == 0 || *tmp != 0) {
@@ -642,6 +652,7 @@ iscsi_parse_url(struct iscsi_context *iscsi, const char *url, int full)

if (full) {
strncpy(iscsi_url->target, target, MAX_STRING_SIZE);
+ strncpy(iscsi_url->transport, transport, MAX_STRING_SIZE);
iscsi_url->lun = l;
}

--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
future iSER implementation will include different implementations
for all socket relative function. in iSER we get event only when
there is new entry in completion queue opposed to TCP that we get event
when we can write to the socket.

1. iscsi_get_fd -
TCP - returns socket fd.
ISER - returns completion queue channel fd.
2. iscsi_service -
TCP - processing the event type got from the socket
and handles it.
ISER - rearming the event mechanism in the completion queue
and polling all available completion queue entries for
process.
3. iscsi_which_events -
TCP - returns which type of event the library is waiting for
(Read, Write or both).
ISER - in iSER we are waiting only for POLLIN event, hence this
function always returns POLLIN.

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
include/iscsi-private.h | 3 +++
include/iscsi.h | 5 +++++
lib/socket.c | 28 +++++++++++++++++++++++++---
3 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index b307015..b4b0032 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -82,6 +82,9 @@ struct iscsi_transport {
struct iscsi_pdu* (*new_pdu)(struct iscsi_context *iscsi, size_t size);
int (*disconnect)(struct iscsi_context *iscsi);
void (*free_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
+ int (*service)(struct iscsi_context *iscsi, int revents);
+ int (*get_fd)(struct iscsi_context *iscsi);
+ int (*which_events)(struct iscsi_context *iscsi);
};

struct iscsi_tcp_transport {
diff --git a/include/iscsi.h b/include/iscsi.h
index d11d5c6..55ec90b 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -84,6 +84,11 @@ EXTERN void iscsi_init_tcp_transport(struct iscsi_context *iscsi);

EXTERN void iscsi_tcp_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);

+EXTERN int iscsi_tcp_service(struct iscsi_context *iscsi, int revents);
+
+EXTERN int iscsi_tcp_get_fd(struct iscsi_context *iscsi);
+
+EXTERN int iscsi_tcp_which_events(struct iscsi_context *iscsi);
/*
* The following three functions are used to integrate libiscsi in an event
* system.
diff --git a/lib/socket.c b/lib/socket.c
index 1ee8e87..e036c4b 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -81,6 +81,9 @@ static struct iscsi_transport tcp_transport =
.new_pdu = iscsi_tcp_new_pdu,
.disconnect = iscsi_tcp_disconnect,
.free_pdu = iscsi_tcp_free_pdu,
+ .service = iscsi_tcp_service,
+ .get_fd = iscsi_tcp_get_fd,
+ .which_events = iscsi_tcp_which_events,
};

void iscsi_init_tcp_transport(struct iscsi_context *iscsi)
@@ -411,8 +414,9 @@ iscsi_tcp_disconnect(struct iscsi_context *iscsi)
return 0;
}

+
int
-iscsi_get_fd(struct iscsi_context *iscsi)
+iscsi_tcp_get_fd(struct iscsi_context *iscsi)
{
if (iscsi->old_iscsi) {
return iscsi->old_iscsi->fd;
@@ -421,7 +425,13 @@ iscsi_get_fd(struct iscsi_context *iscsi)
}

int
-iscsi_which_events(struct iscsi_context *iscsi)
+iscsi_get_fd(struct iscsi_context *iscsi)
+{
+ return iscsi->t->get_fd(iscsi);
+}
+
+int
+iscsi_tcp_which_events(struct iscsi_context *iscsi)
{
int events = iscsi->is_connected ? POLLIN : POLLOUT;

@@ -442,6 +452,12 @@ iscsi_which_events(struct iscsi_context *iscsi)
}

int
+iscsi_which_events(struct iscsi_context *iscsi)
+{
+ return iscsi->t->which_events(iscsi);
+}
+
+int
iscsi_queue_length(struct iscsi_context *iscsi)
{
int i = 0;
@@ -838,7 +854,7 @@ iscsi_service_reconnect_if_loggedin(struct iscsi_context *iscsi)
}

int
-iscsi_service(struct iscsi_context *iscsi, int revents)
+iscsi_tcp_service(struct iscsi_context *iscsi, int revents)
{
if (iscsi->fd < 0) {
return 0;
@@ -940,6 +956,12 @@ iscsi_service(struct iscsi_context *iscsi, int revents)
return 0;
}

+int
+iscsi_service(struct iscsi_context *iscsi, int revents)
+{
+ return iscsi->t->service(iscsi, revents);
+}
+
int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
if (pdu == NULL) {
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
lib/init: initializing connection transport

lib/socket: Adding function to initialize tcp transport.
future commits will include adding iSER transport layer,
so each transport option will has it's own template of functions.

all_utils: adding transport argument in cmdline, default transport is
TCP, when iSER will be added, one will have the option to
choose by entering transport type

$cmdline -T iser/tcp

connect: adding transport initialization when creating context

include/iscsi-private: Adding iscsi_transport attribute in iscsi_context

include/iscsi: adding transport parser from string to int

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
examples/iscsi-dd.c | 16 ++++++++++--
examples/iscsiclient.c | 49 +++++++++++++++++++++++++++++++++++-----
examples/ld_iscsi.c | 3 +-
include/iscsi-private.h | 15 ++++++++++++
include/iscsi.h | 20 ++++++++++++++-
lib/connect.c | 2 +-
lib/init.c | 46 +++++++++++++++++++++++++++++++++++--
lib/libiscsi.syms | 2 +
lib/socket.c | 19 +++++++++++++++
test-tool/iscsi-support.c | 5 +++-
tests/prog_noop_reply.c | 18 ++++++++++++--
tests/prog_reconnect.c | 18 ++++++++++++--
tests/prog_reconnect_timeout.c | 18 ++++++++++++--
tests/prog_timeout.c | 18 ++++++++++++--
utils/iscsi-inq.c | 17 +++++++++++--
utils/iscsi-ls.c | 23 ++++++++++++++-----
utils/iscsi-perf.c | 15 ++++++++++-
utils/iscsi-readcapacity16.c | 16 ++++++++++--
utils/iscsi-swp.c | 17 +++++++++++--
19 files changed, 291 insertions(+), 46 deletions(-)

diff --git a/examples/iscsi-dd.c b/examples/iscsi-dd.c
index 998477e..e9964d0 100644
--- a/examples/iscsi-dd.c
+++ b/examples/iscsi-dd.c
@@ -196,6 +196,7 @@ int main(int argc, char *argv[])
int c;
struct pollfd pfd[2];
struct client client;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"dst", required_argument, NULL, 'd'},
@@ -206,15 +207,17 @@ int main(int argc, char *argv[])
{"max", required_argument, NULL, 'm'},
{"blocks", required_argument, NULL, 'b'},
{"ignore-errors", no_argument, NULL, 'n'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

memset(&client, 0, sizeof(client));

- while ((c = getopt_long(argc, argv, "d:s:i:m:b:p6n", long_options,
+ while ((c = getopt_long(argc, argv, "d:s:i:m:b:p6n:T:", long_options,
&option_index)) != -1) {
switch (c) {
+
case 'd':
dst_url = optarg;
break;
@@ -239,6 +242,9 @@ int main(int argc, char *argv[])
case 'n':
client.ignore_errors = 1;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
exit(1);
@@ -255,8 +261,12 @@ int main(int argc, char *argv[])
fprintf(stderr, " --dst iscsi://<host>[:<port>]/<target-iqn>/<lun>\n");
exit(10);
}
+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(10);
+ }

- client.src_iscsi = iscsi_create_context(initiator);
+ client.src_iscsi = iscsi_create_context(initiator, transport);
if (client.src_iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
exit(10);
@@ -308,7 +318,7 @@ int main(int argc, char *argv[])
scsi_free_scsi_task(task);
}

- client.dst_iscsi = iscsi_create_context(initiator);
+ client.dst_iscsi = iscsi_create_context(initiator, transport);
if (client.dst_iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
exit(10);
diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c
index 95dbe87..8828359 100644
--- a/examples/iscsiclient.c
+++ b/examples/iscsiclient.c
@@ -31,9 +31,6 @@
* many targets will just fail the operation completely if they thing alloc len is unreasonably big.
*/

-/* This is the host/port we connect to.*/
-#define TARGET "127.0.0.1:3260"
-
#if defined(WIN32)
#include <winsock2.h>
#include "win32/win32_compat.h"
@@ -43,6 +40,7 @@ WSADATA wsaData;
#include <poll.h>
#endif

+#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -51,6 +49,11 @@ WSADATA wsaData;
#include "iscsi.h"
#include "scsi-lowlevel.h"

+/* This is the default host:port we connect to.*/
+const char *target = "127.0.0.1:3260";
+/* default iscsi initiator name */
+const char *initiator_name = "iqn.2002-10.com.ronnie:client";
+
struct client_state {
int finished;
const char *message;
@@ -618,11 +621,21 @@ void discoveryconnect_cb(struct iscsi_context *iscsi, int status, void *command_
}


-int main(int argc _U_, char *argv[] _U_)
+int main(int argc, char *argv[])
{
struct iscsi_context *iscsi;
struct pollfd pfd;
struct client_state clnt;
+ int op;
+ int transport = TCP_TRANSPORT;
+
+ static struct option long_options[] = {
+ {"ip:port", required_argument, NULL, 'i'},
+ {"initiator-name", required_argument, NULL, 'n'},
+ {"transport", required_argument, NULL, 'T'},
+ {0,0,0,0}
+ };
+ int option_index;

printf("iscsi client\n");
#if defined(WIN32)
@@ -632,10 +645,34 @@ int main(int argc _U_, char *argv[] _U_)
}
#endif

+ while ((op = getopt_long(argc, argv, "i:n:T:", long_options,
+ &option_index)) != -1) {
+ switch (op) {
+
+ case 'i':
+ target = optarg;
+ break;
+ case 'n':
+ initiator_name = optarg;
+ break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
+ default:
+ printf("Unfamilier arg\n");
+ exit(10);
+
+ }
+ }
+
+ if (transport == -1) {
+ printf("Unrecognized transport\n\n");
+ exit(10);
+ }

memset(&clnt, 0, sizeof(clnt));

- iscsi = iscsi_create_context("iqn.2002-10.com.ronnie:client");
+ iscsi = iscsi_create_context(initiator_name, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
@@ -648,7 +685,7 @@ int main(int argc _U_, char *argv[] _U_)

clnt.message = "Hello iSCSI";
clnt.has_discovered_target = 0;
- if (iscsi_connect_async(iscsi, TARGET, discoveryconnect_cb, &clnt) != 0) {
+ if (iscsi_connect_async(iscsi, target, discoveryconnect_cb, &clnt) != 0) {
printf("iscsi_connect failed. %s\n", iscsi_get_error(iscsi));
exit(10);
}
diff --git a/examples/ld_iscsi.c b/examples/ld_iscsi.c
index 836ba93..5ce0299 100644
--- a/examples/ld_iscsi.c
+++ b/examples/ld_iscsi.c
@@ -64,6 +64,7 @@ int (*real_open)(__const char *path, int flags, mode_t mode);
int open(const char *path, int flags, mode_t mode)
{
int fd;
+ int transport = TCP_TRANSPORT;

if (!strncmp(path, "iscsi:", 6)) {
struct iscsi_context *iscsi;
@@ -77,7 +78,7 @@ int open(const char *path, int flags, mode_t mode)
return -1;
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
LD_ISCSI_DPRINTF(0,"Failed to create context");
errno = ENOMEM;
diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index 4e1c71c..654eb9e 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -66,7 +66,22 @@ void iscsi_free_iscsi_inqueue(struct iscsi_context *iscsi, struct iscsi_in_pdu *
/* max length of chap challange */
#define MAX_CHAP_C_LENGTH 2048

+struct iscsi_transport {
+
+ int temp;
+};
+
+struct iscsi_tcp_transport {
+
+ struct iscsi_transport t;
+
+};
+>>>>>>> Libiscsi: Adding transport layer into all library utilities
+
struct iscsi_context {
+
+ struct iscsi_transport *t;
+ enum iscsi_transport_type transport;
char initiator_name[MAX_STRING_SIZE+1];
char target_name[MAX_STRING_SIZE+1];
char target_address[MAX_STRING_SIZE+1]; /* If a redirect */
diff --git a/include/iscsi.h b/include/iscsi.h
index 4441447..d2b6019 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -19,6 +19,7 @@

#include <stdint.h>
#include <sys/types.h>
+#include <string.h>

#if defined(WIN32)
#define EXTERN __declspec( dllexport )
@@ -46,13 +47,27 @@ struct sockaddr;
* Syntax for normal and portal/discovery URLs.
*/
#define ISCSI_URL_SYNTAX "\"iscsi://[<username>[%<password>]@]" \
- "<host>[:<port>]/<target-iqn>/<lun>\""
+ "<host>[:<port>]/<target-iqn>/<lun>/<transport_type>\""
#define ISCSI_PORTAL_URL_SYNTAX "\"iscsi://[<username>[%<password>]@]" \
"<host>[:<port>]\""

+enum iscsi_transport_type {
+ ERR_TRANSPORT = -1,
+ TCP_TRANSPORT = 0
+};
+
+EXTERN enum iscsi_transport_type iscsi_get_transport(struct iscsi_context *iscsi);
+
+EXTERN char *iscsi_parse_transport(const char *url);
+
+static inline int iscsi_string_to_transport(char *transport) {
+
+ return !strncmp(transport, "tcp", 3) ? TCP_TRANSPORT : ERR_TRANSPORT;
+}

EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca);

+EXTERN void iscsi_init_tcp_transport(struct iscsi_context *iscsi);
/*
* The following three functions are used to integrate libiscsi in an event
* system.
@@ -231,7 +246,8 @@ EXTERN const char *iscsi_get_error(struct iscsi_context *iscsi);
* non-NULL: success
* NULL: error
*/
-EXTERN struct iscsi_context *iscsi_create_context(const char *initiator_name);
+
+EXTERN struct iscsi_context *iscsi_create_context(const char *initiator_name, enum iscsi_transport_type transport);

/*
* Destroy an existing ISCSI context and tear down any existing connection.
diff --git a/lib/connect.c b/lib/connect.c
index b7adb25..c130129 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -431,7 +431,7 @@ int iscsi_reconnect(struct iscsi_context *old_iscsi)
return -1;
}

- iscsi = iscsi_create_context(old_iscsi->initiator_name);
+ iscsi = iscsi_create_context(old_iscsi->initiator_name, old_iscsi->transport);
if (iscsi == NULL) {
ISCSI_LOG(old_iscsi, 2, "failed to create new context for reconnection");
return -1;
diff --git a/lib/init.c b/lib/init.c
index 835c218..fdf5a04 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -34,6 +34,29 @@
#include "iscsi-private.h"
#include "slist.h"

+
+/**
+ * Initialize transport type of session
+ */
+
+int iscsi_init_transport(struct iscsi_context *iscsi) {
+
+ if(iscsi->transport == TCP_TRANSPORT) {
+ struct iscsi_tcp_transport *tcp_transport = iscsi_malloc(iscsi, sizeof(struct iscsi_tcp_transport));
+ if (tcp_transport == NULL) {
+ iscsi_set_error(iscsi, "Couldn't allocate memory for transport\n");
+ return -1;
+ }
+ iscsi->t = &tcp_transport->t;
+ iscsi_init_tcp_transport(iscsi);
+ } else {
+ iscsi_set_error(iscsi, "Unfamilier transport type");
+ return -1;
+ }
+
+ return 0;
+}
+
/**
* Whether or not the internal memory allocator caches allocations. Disable
* memory allocation caching to improve the accuracy of Valgrind reports.
@@ -108,7 +131,7 @@ void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) {
}

struct iscsi_context *
-iscsi_create_context(const char *initiator_name)
+iscsi_create_context(const char *initiator_name, enum iscsi_transport_type transport)
{
struct iscsi_context *iscsi;
size_t required = ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE;
@@ -122,13 +145,20 @@ iscsi_create_context(const char *initiator_name)
if (iscsi == NULL) {
return NULL;
}
-
+
memset(iscsi, 0, sizeof(struct iscsi_context));

+ /* initalize transport of context */
+ iscsi->transport = transport;
+ if (iscsi_init_transport(iscsi)) {
+ iscsi_set_error(iscsi, "Failed allocating transport");
+ return NULL;
+ }
+
strncpy(iscsi->initiator_name,initiator_name,MAX_STRING_SIZE);

iscsi->fd = -1;
-
+
srand(time(NULL) ^ getpid() ^ (uint32_t) ((uintptr_t) iscsi));

/* initialize to a "random" isid */
@@ -651,6 +681,16 @@ iscsi_destroy_url(struct iscsi_url *iscsi_url)
free(iscsi_url);
}

+char *
+iscsi_parse_transport(const char *url)
+{
+ char del = '/';
+ char *transport;
+
+ transport = strrchr (url, del);
+
+ return ++transport;
+}

int
iscsi_set_initiator_username_pwd(struct iscsi_context *iscsi,
diff --git a/lib/libiscsi.syms b/lib/libiscsi.syms
index 3320e0e..4d21afd 100644
--- a/lib/libiscsi.syms
+++ b/lib/libiscsi.syms
@@ -14,6 +14,7 @@ iscsi_get_lba_status_sync
iscsi_get_lba_status_task
iscsi_get_target_address
iscsi_get_nops_in_flight
+iscsi_get_transport
iscsi_inquiry_sync
iscsi_inquiry_task
iscsi_is_logged_in
@@ -33,6 +34,7 @@ iscsi_modesense10_task
iscsi_nop_out_async
iscsi_parse_full_url
iscsi_parse_portal_url
+iscsi_parse_transport
iscsi_persistent_reserve_in_task
iscsi_persistent_reserve_in_sync
iscsi_persistent_reserve_out_task
diff --git a/lib/socket.c b/lib/socket.c
index 59e7026..d93a168 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -72,6 +72,25 @@
#include "slist.h"

static uint32_t iface_rr = 0;
+struct iscsi_transport;
+
+static struct iscsi_transport tcp_transport = {
+
+ .temp = 1,
+
+};
+
+void iscsi_init_tcp_transport(struct iscsi_context *iscsi)
+{
+ iscsi->t = &tcp_transport;
+
+ return;
+}
+
+enum iscsi_transport_type iscsi_get_transport(struct iscsi_context *iscsi) {
+
+ return iscsi->transport;
+}

void
iscsi_add_to_outqueue(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
diff --git a/test-tool/iscsi-support.c b/test-tool/iscsi-support.c
index c2db726..a52afb6 100644
--- a/test-tool/iscsi-support.c
+++ b/test-tool/iscsi-support.c
@@ -468,8 +468,11 @@ iscsi_context_login(const char *initiatorname, const char *url, int *lun)
{
struct iscsi_context *iscsi;
struct iscsi_url *iscsi_url;
+ char *transport;

- iscsi = iscsi_create_context(initiatorname);
+ transport = iscsi_parse_transport(url);
+
+ iscsi = iscsi_create_context(initiatorname, iscsi_string_to_transport(transport));
if (iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
return NULL;
diff --git a/tests/prog_noop_reply.c b/tests/prog_noop_reply.c
index 53072c8..114ec29 100644
--- a/tests/prog_noop_reply.c
+++ b/tests/prog_noop_reply.c
@@ -103,7 +103,7 @@ void tur_cb(struct iscsi_context *iscsi _U_, int status,
void print_usage(void)
{
fprintf(stderr, "Usage: prog_noop_reply [-?|--help] [--usage] "
- "[-i|--initiator-name=iqn-name]\n"
+ "[-i|--initiator-name=iqn-name] [-T|--transport]\n"
"\t\t<iscsi-portal-url>\n");
fprintf(stderr, "\n");
fprintf(stderr, "This command is used to test that if the target "
@@ -116,6 +116,8 @@ void print_help(void)
fprintf(stderr, "Usage: prog_noop_reply [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name "
"Initiatorname to use\n");
+ fprintf(stderr, " -T, --transport=transport "
+ "Transport type to use.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
fprintf(stderr, " -?, --help "
@@ -140,17 +142,19 @@ int main(int argc, char *argv[])
const char *url = NULL;
int c;
static int show_help = 0, show_usage = 0, debug = 0;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"usage", no_argument, NULL, 'u'},
{"debug", no_argument, NULL, 'd'},
{"initiator-name", required_argument, NULL, 'i'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?uUdi:s", long_options,
+ while ((c = getopt_long(argc, argv, "h?uUdi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -166,6 +170,9 @@ int main(int argc, char *argv[])
case 'i':
initiator = optarg;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -173,6 +180,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -199,7 +211,7 @@ int main(int argc, char *argv[])
exit(10);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
diff --git a/tests/prog_reconnect.c b/tests/prog_reconnect.c
index 99e5f41..d13a58f 100644
--- a/tests/prog_reconnect.c
+++ b/tests/prog_reconnect.c
@@ -161,7 +161,7 @@ void read_cb(struct iscsi_context *iscsi, int status,
void print_usage(void)
{
fprintf(stderr, "Usage: prog_reconnect [-?|--help] [--usage] "
- "[-i|--initiator-name=iqn-name]\n"
+ "[-i|--initiator-name=iqn-name] [-T|--transport=transport]\n"
"\t\t<iscsi-portal-url>\n");
fprintf(stderr, "\n");
fprintf(stderr, "This command is used to test that if the target "
@@ -174,6 +174,8 @@ void print_help(void)
fprintf(stderr, "Usage: prog_reconnect [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name "
"Initiatorname to use\n");
+ fprintf(stderr, " -T, --transport=transport "
+ "Transport type to use\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
fprintf(stderr, " -?, --help "
@@ -200,17 +202,19 @@ int main(int argc, char *argv[])
static int show_help = 0, show_usage = 0, debug = 0;
struct scsi_readcapacity10 *rc10;
struct scsi_task *task;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"usage", no_argument, NULL, 'u'},
{"debug", no_argument, NULL, 'd'},
{"initiator-name", required_argument, NULL, 'i'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?uUdi:s", long_options,
+ while ((c = getopt_long(argc, argv, "h?uUdi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -226,6 +230,9 @@ int main(int argc, char *argv[])
case 'i':
initiator = optarg;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -233,6 +240,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -259,7 +271,7 @@ int main(int argc, char *argv[])
exit(10);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
diff --git a/tests/prog_reconnect_timeout.c b/tests/prog_reconnect_timeout.c
index 07270b5..b50bc30 100644
--- a/tests/prog_reconnect_timeout.c
+++ b/tests/prog_reconnect_timeout.c
@@ -183,7 +183,7 @@ void read_cb(struct iscsi_context *iscsi, int status,
void print_usage(void)
{
fprintf(stderr, "Usage: prog_reconnect_timeout [-?|--help] [--usage] "
- "[-i|--initiator-name=iqn-name]\n"
+ "[-i|--initiator-name=iqn-name] [-T|--transport=transport]\n"
"\t\t<iscsi-portal-url>\n");
fprintf(stderr, "\n");
fprintf(stderr, "This command is used to test that during reconnect,"
@@ -197,6 +197,8 @@ void print_help(void)
fprintf(stderr, "Usage: prog_reconnect_timeout [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name "
"Initiatorname to use\n");
+ fprintf(stderr, " -T, --transport=transport "
+ "Transport type to use\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
fprintf(stderr, " -?, --help "
@@ -223,17 +225,19 @@ int main(int argc, char *argv[])
static int show_help = 0, show_usage = 0, debug = 0;
struct scsi_readcapacity10 *rc10;
struct scsi_task *task;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"usage", no_argument, NULL, 'u'},
{"debug", no_argument, NULL, 'd'},
{"initiator-name", required_argument, NULL, 'i'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?uUdi:s", long_options,
+ while ((c = getopt_long(argc, argv, "h?uUdi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -249,6 +253,9 @@ int main(int argc, char *argv[])
case 'i':
initiator = optarg;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -256,6 +263,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -282,7 +294,7 @@ int main(int argc, char *argv[])
exit(10);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
diff --git a/tests/prog_timeout.c b/tests/prog_timeout.c
index 12496a7..34b47d5 100644
--- a/tests/prog_timeout.c
+++ b/tests/prog_timeout.c
@@ -48,7 +48,7 @@ const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:prog-timeout";
void print_usage(void)
{
fprintf(stderr, "Usage: prog_timeout [-?|--help] [--usage] "
- "[-i|--initiator-name=iqn-name]\n"
+ "[-i|--initiator-name=iqn-name] [-T|--transport=transport]\n"
"\t\t<iscsi-portal-url>\n");
fprintf(stderr, "\n");
fprintf(stderr, "This command is used to test that if we do not "
@@ -61,6 +61,8 @@ void print_help(void)
fprintf(stderr, "Usage: prog_timeout [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name "
"Initiatorname to use\n");
+ fprintf(stderr, " -T, --transport=transport "
+ "Transport type to use\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
fprintf(stderr, " -?, --help "
@@ -113,17 +115,19 @@ int main(int argc, char *argv[])
int c;
static int show_help = 0, show_usage = 0, debug = 0;
uint32_t count;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"usage", no_argument, NULL, 'u'},
{"debug", no_argument, NULL, 'd'},
{"initiator-name", required_argument, NULL, 'i'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?uUdi:s", long_options,
+ while ((c = getopt_long(argc, argv, "h?uUdi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -139,6 +143,9 @@ int main(int argc, char *argv[])
case 'i':
initiator = optarg;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -146,6 +153,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -170,7 +182,7 @@ int main(int argc, char *argv[])
exit(10);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
diff --git a/utils/iscsi-inq.c b/utils/iscsi-inq.c
index 96a9513..8208c75 100644
--- a/utils/iscsi-inq.c
+++ b/utils/iscsi-inq.c
@@ -210,7 +210,7 @@ void do_inquiry(struct iscsi_context *iscsi, int lun, int evpd, int pc)
void print_usage(void)
{
fprintf(stderr, "Usage: iscsi-inq [-?] [-?|--help] [--usage] [-i|--initiator-name=iqn-name]\n"
- "\t\t[-e|--evpd=integer] [-c|--pagecode=integer] <iscsi-url>\n");
+ "\t\t[-e|--evpd=integer] [-c|--pagecode=integer] [-T|--transport=transport] <iscsi-url>\n");
}

void print_help(void)
@@ -219,6 +219,7 @@ void print_help(void)
fprintf(stderr, " -i, --initiator-name=iqn-name Initiatorname to use\n");
fprintf(stderr, " -e, --evpd=integer evpd\n");
fprintf(stderr, " -c, --pagecode=integer page code\n");
+ fprintf(stderr, " -T, --transport=transport Transport type to use\n");
fprintf(stderr, " -d, --debug=integer debug level (0=disabled)\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
@@ -241,6 +242,7 @@ int main(int argc, char *argv[])
int evpd = 0, pagecode = 0;
int show_help = 0, show_usage = 0, debug = 0;
int c;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
@@ -249,11 +251,12 @@ int main(int argc, char *argv[])
{"initiator-name", required_argument, NULL, 'i'},
{"evpd", required_argument, NULL, 'e'},
{"pagecode", required_argument, NULL, 'c'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?udi:e:c:", long_options,
+ while ((c = getopt_long(argc, argv, "h?udi:e:c:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -275,6 +278,9 @@ int main(int argc, char *argv[])
case 'c':
pagecode = atoi(optarg);
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -282,6 +288,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -292,7 +303,7 @@ int main(int argc, char *argv[])
exit(0);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
exit(10);
diff --git a/utils/iscsi-ls.c b/utils/iscsi-ls.c
index 0a06224..e48c0d2 100644
--- a/utils/iscsi-ls.c
+++ b/utils/iscsi-ls.c
@@ -166,7 +166,7 @@ tur_try_again:
printf("\n");
}

-void list_luns(struct client_state *clnt, const char *target, const char *portal)
+void list_luns(struct client_state *clnt, const char *target, const char *portal, enum iscsi_transport_type transport)
{
struct iscsi_context *iscsi;
struct scsi_task *task;
@@ -179,7 +179,7 @@ void list_luns(struct client_state *clnt, const char *target, const char *portal
return;
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
@@ -268,7 +268,7 @@ void discovery_cb(struct iscsi_context *iscsi, int status, void *command_data, v
printf("Target:%s Portal:%s\n", addr->target_name, portal->portal);
}
if (showluns != 0) {
- list_luns(private_data, addr->target_name, portal->portal);
+ list_luns(private_data, addr->target_name, portal->portal, iscsi_get_transport(iscsi));
}
portal = portal->next;
}
@@ -310,7 +310,7 @@ void discoveryconnect_cb(struct iscsi_context *iscsi, int status, void *command_
void print_usage(void)
{
fprintf(stderr, "Usage: iscsi-ls [-?|--help] [--usage] [-i|--initiator-name=iqn-name]\n"
- "\t\t[-s|--show-luns] <iscsi-portal-url>\n");
+ "\t\t[-s|--show-luns] [-T|--transport] <iscsi-portal-url>\n");
}

void print_help(void)
@@ -318,6 +318,7 @@ void print_help(void)
fprintf(stderr, "Usage: iscsi-ls [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name Initiatorname to use\n");
fprintf(stderr, " -s, --show-luns Show the luns for each target\n");
+ fprintf(stderr, " -T, --transport Transport type to use\n");
fprintf(stderr, " --url Output targets in URL format\n");
fprintf(stderr, " (does not work with -s)\n");
fprintf(stderr, "\n");
@@ -341,6 +342,7 @@ int main(int argc, char *argv[])
const char *url = NULL;
int c;
static int show_help = 0, show_usage = 0, debug = 0;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
@@ -349,11 +351,12 @@ int main(int argc, char *argv[])
{"show-luns", no_argument, NULL, 's'},
{"url", no_argument, NULL, 'U'},
{"initiator-name", required_argument, NULL, 'i'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?uUdi:s", long_options,
+ while ((c = getopt_long(argc, argv, "h?uUdi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -375,6 +378,9 @@ int main(int argc, char *argv[])
case 's':
showluns = 1;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -382,6 +388,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -408,7 +419,7 @@ int main(int argc, char *argv[])
exit(10);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
printf("Failed to create context\n");
exit(10);
diff --git a/utils/iscsi-perf.c b/utils/iscsi-perf.c
index 8098557..2f63805 100644
--- a/utils/iscsi-perf.c
+++ b/utils/iscsi-perf.c
@@ -246,6 +246,7 @@ int main(int argc, char *argv[])
int c;
struct pollfd pfd[1];
struct client client;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"initiator-name", required_argument, NULL, 'i'},
@@ -255,6 +256,7 @@ int main(int argc, char *argv[])
{"random", no_argument, NULL, 'r'},
{"random-blocks", no_argument, NULL, 'R'},
{"ignore-errors", no_argument, NULL, 'n'},
+ {"transport", no_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;
@@ -266,9 +268,10 @@ int main(int argc, char *argv[])

printf("iscsi-perf version %s - (c) 2014-2015 by Peter Lieven <pl@ĸamp.de>\n\n", PERF_VERSION);

- while ((c = getopt_long(argc, argv, "i:m:b:t:nrRx:", long_options,
+ while ((c = getopt_long(argc, argv, "i:m:b:t:nrRx:T:", long_options,
&option_index)) != -1) {
switch (c) {
+
case 'i':
initiator = optarg;
break;
@@ -293,12 +296,20 @@ int main(int argc, char *argv[])
case 'x':
client.max_reconnects = atoi(optarg);
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
usage();
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (optind != argc -1 ) usage();

if (argv[optind] != NULL) {
@@ -307,7 +318,7 @@ int main(int argc, char *argv[])

if (url == NULL) usage();

- client.iscsi = iscsi_create_context(initiator);
+ client.iscsi = iscsi_create_context(initiator, transport);
if (client.iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
exit(10);
diff --git a/utils/iscsi-readcapacity16.c b/utils/iscsi-readcapacity16.c
index 32f7a85..38b78e4 100644
--- a/utils/iscsi-readcapacity16.c
+++ b/utils/iscsi-readcapacity16.c
@@ -35,7 +35,7 @@ const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-readcapa

void print_usage(void)
{
- fprintf(stderr, "Usage: iscsi-readcapacity16 [-?] [-?|--help] [--usage] [-i|--initiator-name=iqn-name] [-s] <iscsi-url>\n");
+ fprintf(stderr, "Usage: iscsi-readcapacity16 [-?] [-?|--help] [--usage] [-i|--initiator-name=iqn-name] [-s] [-T|--transport] <iscsi-url>\n");
}

void print_help(void)
@@ -43,6 +43,7 @@ void print_help(void)
fprintf(stderr, "Usage: iscsi_readcapacity16 [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name Initiatorname to use\n");
fprintf(stderr, " -s, --size print target size only\n");
+ fprintf(stderr, " -T, --transport Transport type to use\n");
fprintf(stderr, " -d, --debug=integer debug level (0=disabled)\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
@@ -66,6 +67,7 @@ int main(int argc, char *argv[])
int c;
struct scsi_task *task;
struct scsi_readcapacity16 *rc16;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
@@ -75,11 +77,12 @@ int main(int argc, char *argv[])
{"initiator-name", required_argument, NULL, 'i'},
{"evpd", required_argument, NULL, 'e'},
{"pagecode", required_argument, NULL, 'c'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?udi:s", long_options,
+ while ((c = getopt_long(argc, argv, "h?udi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -98,6 +101,9 @@ int main(int argc, char *argv[])
case 'i':
initiator = optarg;
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -105,6 +111,10 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
if (show_help != 0) {
print_help();
exit(0);
@@ -115,7 +125,7 @@ int main(int argc, char *argv[])
exit(0);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
exit(10);
diff --git a/utils/iscsi-swp.c b/utils/iscsi-swp.c
index fc6f224..9a9994c 100644
--- a/utils/iscsi-swp.c
+++ b/utils/iscsi-swp.c
@@ -41,7 +41,7 @@ const char *initiator = "iqn.2007-10.com.github:sahlberg:libiscsi:iscsi-swp";
void print_usage(void)
{
fprintf(stderr, "Usage: iscsi-swp [-?] [-?|--help] [--usage] [-i|--initiator-name=iqn-name]\n"
- "\t\t[-s|--swp {on|off}] <iscsi-url>\n");
+ "\t\t[-s|--swp {on|off}] [-T|--transport] <iscsi-url>\n");
}

void print_help(void)
@@ -49,6 +49,7 @@ void print_help(void)
fprintf(stderr, "Usage: iscsi-swp [OPTION...] <iscsi-url>\n");
fprintf(stderr, " -i, --initiator-name=iqn-name Initiatorname to use\n");
fprintf(stderr, " -s, --swp={on|off} Turn software write protect on/off\n");
+ fprintf(stderr, " -T, --transport=transport Transport type to use\n");
fprintf(stderr, " -d, --debug=integer debug level (0=disabled)\n");
fprintf(stderr, "\n");
fprintf(stderr, "Help options:\n");
@@ -76,6 +77,7 @@ int main(int argc, char *argv[])
struct scsi_task *select_task = NULL;
struct scsi_mode_sense *ms;
struct scsi_mode_page *mp;
+ int transport = TCP_TRANSPORT;

static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
@@ -83,11 +85,12 @@ int main(int argc, char *argv[])
{"debug", no_argument, NULL, 'd'},
{"initiator-name", required_argument, NULL, 'i'},
{"swp", required_argument, NULL, 's'},
+ {"transport", required_argument, NULL, 'T'},
{0, 0, 0, 0}
};
int option_index;

- while ((c = getopt_long(argc, argv, "h?udi:s:", long_options,
+ while ((c = getopt_long(argc, argv, "h?udi:s:T:", long_options,
&option_index)) != -1) {
switch (c) {
case 'h':
@@ -111,6 +114,9 @@ int main(int argc, char *argv[])
swp = 2;
}
break;
+ case 'T':
+ transport = iscsi_string_to_transport(optarg);
+ break;
default:
fprintf(stderr, "Unrecognized option '%c'\n\n", c);
print_help();
@@ -118,6 +124,11 @@ int main(int argc, char *argv[])
}
}

+ if (transport == -1) {
+ fprintf(stderr, "Unrecognized transport\n\n");
+ exit(0);
+ }
+
if (show_help != 0) {
print_help();
exit(0);
@@ -128,7 +139,7 @@ int main(int argc, char *argv[])
exit(0);
}

- iscsi = iscsi_create_context(initiator);
+ iscsi = iscsi_create_context(initiator, transport);
if (iscsi == NULL) {
fprintf(stderr, "Failed to create context\n");
exit(10);
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:01 AM4/3/16
to libi...@googlegroups.com
socket: adding tcp_connect function and implement it
in the last common part of iSER and TCP in iscsi_connect_async

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
include/iscsi-private.h | 12 +++-
include/iscsi.h | 3 +
lib/socket.c | 168 +++++++++++++++++++++++------------------------
3 files changed, 96 insertions(+), 87 deletions(-)

diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index 654eb9e..820cdcf 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -40,6 +40,9 @@ extern "C" {
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif

+#include <sys/socket.h>
+#include <netinet/in.h>
+
#define ISCSI_RAW_HEADER_SIZE 48
#define ISCSI_DIGEST_SIZE 4

@@ -66,9 +69,15 @@ void iscsi_free_iscsi_inqueue(struct iscsi_context *iscsi, struct iscsi_in_pdu *
/* max length of chap challange */
#define MAX_CHAP_C_LENGTH 2048

+union socket_address {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct sockaddr sa;
+};
+
struct iscsi_transport {

- int temp;
+ int (*connect)(struct iscsi_context *iscsi, union socket_address *sa, int ai_family);
};

struct iscsi_tcp_transport {
@@ -76,7 +85,6 @@ struct iscsi_tcp_transport {
struct iscsi_transport t;

};
->>>>>>> Libiscsi: Adding transport layer into all library utilities

struct iscsi_context {

diff --git a/include/iscsi.h b/include/iscsi.h
index d2b6019..a6714df 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -33,6 +33,7 @@ extern "C" {

struct iscsi_context;
struct sockaddr;
+union socket_address;

/* API VERSION */
#define LIBISCSI_API_VERSION (20150621)
@@ -65,6 +66,8 @@ static inline int iscsi_string_to_transport(char *transport) {
return !strncmp(transport, "tcp", 3) ? TCP_TRANSPORT : ERR_TRANSPORT;
}

+EXTERN int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *sa, int ai_family);
+
EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca);

EXTERN void iscsi_init_tcp_transport(struct iscsi_context *iscsi);
diff --git a/lib/socket.c b/lib/socket.c
index d93a168..529949d 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -74,10 +74,9 @@
static uint32_t iface_rr = 0;
struct iscsi_transport;

-static struct iscsi_transport tcp_transport = {
-
- .temp = 1,
-
+static struct iscsi_transport tcp_transport =
+{
+ .connect = iscsi_tcp_connect,
};

void iscsi_init_tcp_transport(struct iscsi_context *iscsi)
@@ -202,11 +201,83 @@ static int set_tcp_syncnt(struct iscsi_context *iscsi)
return 0;
}

-union socket_address {
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- struct sockaddr sa;
-};
+int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *sa, int ai_family) {
+
+ int socksize;
+
+ iscsi->fd = socket(ai_family, SOCK_STREAM, 0);
+ if (iscsi->fd == -1) {
+ iscsi_set_error(iscsi, "Failed to open iscsi socket. "
+ "Errno:%s(%d).", strerror(errno), errno);
+ return -1;
+ }
+
+ if (iscsi->old_iscsi && iscsi->fd != iscsi->old_iscsi->fd) {
+ if (dup2(iscsi->fd, iscsi->old_iscsi->fd) == -1) {
+ return -1;
+ }
+ close(iscsi->fd);
+ iscsi->fd = iscsi->old_iscsi->fd;
+ }
+
+ set_nonblocking(iscsi->fd);
+
+ iscsi_set_tcp_keepalive(iscsi, iscsi->tcp_keepidle, iscsi->tcp_keepcnt, iscsi->tcp_keepintvl);
+
+ if (iscsi->tcp_user_timeout > 0) {
+ set_tcp_user_timeout(iscsi);
+ }
+
+ if (iscsi->tcp_syncnt > 0) {
+ set_tcp_syncnt(iscsi);
+ }
+
+#if __linux
+ if (iscsi->bind_interfaces[0]) {
+ char *pchr = iscsi->bind_interfaces, *pchr2;
+ int iface_n = iface_rr++%iscsi->bind_interfaces_cnt;
+ int iface_c = 0;
+ do {
+ pchr2 = strchr(pchr,',');
+ if (iface_c == iface_n) {
+ if (pchr2) pchr2[0]=0x00;
+ break;
+ }
+ if (pchr2) {pchr=pchr2+1;}
+ iface_c++;
+ } while (pchr2);
+
+ int res = setsockopt(iscsi->fd, SOL_SOCKET, SO_BINDTODEVICE, pchr, strlen(pchr));
+ if (res < 0) {
+ ISCSI_LOG(iscsi,1,"failed to bind to interface '%s': %s",pchr,strerror(errno));
+ } else {
+ ISCSI_LOG(iscsi,3,"successfully bound to interface '%s'",pchr);
+ }
+ if (pchr2) pchr2[0]=',';
+ }
+#endif
+
+ if (set_tcp_sockopt(iscsi->fd, TCP_NODELAY, 1) != 0) {
+ ISCSI_LOG(iscsi,1,"failed to set TCP_NODELAY sockopt: %s",strerror(errno));
+ } else {
+ ISCSI_LOG(iscsi,3,"TCP_NODELAY set to 1");
+ }
+
+ socksize = sizeof(struct sockaddr_in); // Work-around for now, need to fix it
+
+ if (connect(iscsi->fd, &sa->sa, socksize) != 0
+ && errno != EINPROGRESS) {
+ iscsi_set_error(iscsi, "Connect failed with errno : "
+ "%s(%d)", strerror(errno), errno);
+ close(iscsi->fd);
+ iscsi->fd = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+

int
iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
@@ -270,7 +341,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
iscsi_set_error(iscsi, "Invalid target:%s "
"Can not resolv into IPv4/v6.", portal);
return -1;
- }
+ }
iscsi_free(iscsi, addr);

memset(&sa, 0, sizeof(sa));
@@ -302,87 +373,14 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,

}

- iscsi->fd = socket(ai->ai_family, SOCK_STREAM, 0);
- if (iscsi->fd == -1) {
- freeaddrinfo(ai);
- iscsi_set_error(iscsi, "Failed to open iscsi socket. "
- "Errno:%s(%d).", strerror(errno), errno);
- return -1;
-
- }
-
- if (iscsi->old_iscsi && iscsi->fd != iscsi->old_iscsi->fd) {
- if (dup2(iscsi->fd, iscsi->old_iscsi->fd) == -1) {
- return -1;
- }
- close(iscsi->fd);
- iscsi->fd = iscsi->old_iscsi->fd;
- }
-
iscsi->socket_status_cb = cb;
iscsi->connect_data = private_data;

- set_nonblocking(iscsi->fd);
-
- iscsi_set_tcp_keepalive(iscsi, iscsi->tcp_keepidle, iscsi->tcp_keepcnt, iscsi->tcp_keepintvl);
-
- if (iscsi->tcp_user_timeout > 0) {
- set_tcp_user_timeout(iscsi);
- }
-
- if (iscsi->tcp_syncnt > 0) {
- set_tcp_syncnt(iscsi);
- }
-
-#if __linux
- if (iscsi->bind_interfaces[0]) {
- char *pchr = iscsi->bind_interfaces, *pchr2;
- int iface_n = iface_rr++%iscsi->bind_interfaces_cnt;
- int iface_c = 0;
- do {
- pchr2 = strchr(pchr,',');
- if (iface_c == iface_n) {
- if (pchr2) pchr2[0]=0x00;
- break;
- }
- if (pchr2) {pchr=pchr2+1;}
- iface_c++;
- } while (pchr2);
-
- int res = setsockopt(iscsi->fd, SOL_SOCKET, SO_BINDTODEVICE, pchr, strlen(pchr));
- if (res < 0) {
- ISCSI_LOG(iscsi,1,"failed to bind to interface '%s': %s",pchr,strerror(errno));
- } else {
- ISCSI_LOG(iscsi,3,"successfully bound to interface '%s'",pchr);
- }
- if (pchr2) pchr2[0]=',';
- }
-#endif
-
- if (set_tcp_sockopt(iscsi->fd, TCP_NODELAY, 1) != 0) {
- ISCSI_LOG(iscsi,1,"failed to set TCP_NODELAY sockopt: %s",strerror(errno));
- } else {
- ISCSI_LOG(iscsi,3,"TCP_NODELAY set to 1");
- }
-
- if (connect(iscsi->fd, &sa.sa, socksize) != 0
-#if defined(WIN32)
- && WSAGetLastError() != WSAEWOULDBLOCK) {
-#else
- && errno != EINPROGRESS) {
-#endif
- iscsi_set_error(iscsi, "Connect failed with errno : "
- "%s(%d)", strerror(errno), errno);
- close(iscsi->fd);
- iscsi->fd = -1;
- freeaddrinfo(ai);
+ if(iscsi->t->connect(iscsi, &sa, ai->ai_family) < 0) {
+ iscsi_set_error(iscsi, "Couldn't connect transport");
return -1;
}

- freeaddrinfo(ai);
-
- strncpy(iscsi->connected_portal,portal,MAX_STRING_SIZE);
-
return 0;
}

--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:06 AM4/3/16
to libi...@googlegroups.com
all library: change disconnect to iscsi->t->disconnect

1. In TCP we need only to put -1 in fd and we don't
have more transport resources. In future iSER we will need to
clean resources and destroy the rdma connection.

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
examples/iscsiclient.c | 3 ++-
include/iscsi-private.h | 1 +
include/iscsi.h | 2 ++
lib/connect.c | 2 +-
lib/init.c | 2 +-
lib/socket.c | 3 ++-
tests/prog_noop_reply.c | 2 +-
tests/prog_reconnect.c | 3 ++-
tests/prog_reconnect_timeout.c | 3 ++-
utils/iscsi-ls.c | 3 ++-
10 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c
index 8828359..cbbb3b1 100644
--- a/examples/iscsiclient.c
+++ b/examples/iscsiclient.c
@@ -48,6 +48,7 @@ WSADATA wsaData;
#include <unistd.h>
#include "iscsi.h"
#include "scsi-lowlevel.h"
+#include "iscsi-private.h"

/* This is the default host:port we connect to.*/
const char *target = "127.0.0.1:3260";
@@ -531,7 +532,7 @@ void discoverylogout_cb(struct iscsi_context *iscsi, int status, void *command_d
}

printf("disconnect socket\n");
- if (iscsi_disconnect(iscsi) != 0) {
+ if (iscsi->t->disconnect(iscsi) != 0) {
printf("Failed to disconnect old socket\n");
exit(10);
}
diff --git a/include/iscsi-private.h b/include/iscsi-private.h
index 69d2f3e..d4cde4b 100644
--- a/include/iscsi-private.h
+++ b/include/iscsi-private.h
@@ -80,6 +80,7 @@ struct iscsi_transport {
int (*connect)(struct iscsi_context *iscsi, union socket_address *sa, int ai_family);
int (*queue_pdu)(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
struct iscsi_pdu* (*new_pdu)(struct iscsi_context *iscsi, size_t size);
+ int (*disconnect)(struct iscsi_context *iscsi);
};

struct iscsi_tcp_transport {
diff --git a/include/iscsi.h b/include/iscsi.h
index b470232..00b8458 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -71,6 +71,8 @@ EXTERN int iscsi_tcp_connect(struct iscsi_context *iscsi, union socket_address *

EXTERN struct iscsi_pdu* iscsi_tcp_new_pdu(struct iscsi_context *iscsi, size_t size);

+EXTERN int iscsi_tcp_disconnect(struct iscsi_context *iscsi);
+
EXTERN int iscsi_tcp_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);

EXTERN void iscsi_set_cache_allocations(struct iscsi_context *iscsi, int ca);
diff --git a/lib/connect.c b/lib/connect.c
index c130129..b5e0ee4 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -143,7 +143,7 @@ iscsi_login_cb(struct iscsi_context *iscsi, int status, void *command_data _U_,
struct connect_task *ct = private_data;

if (status == SCSI_STATUS_REDIRECT && iscsi->target_address[0]) {
- iscsi_disconnect(iscsi);
+ iscsi->t->disconnect(iscsi);
if (iscsi->bind_interfaces[0]) iscsi_decrement_iface_rr();
if (iscsi_connect_async(iscsi, iscsi->target_address, iscsi_connect_cb, iscsi->connect_data) != 0) {
iscsi_free(iscsi, ct);
diff --git a/lib/init.c b/lib/init.c
index fdf5a04..81b0568 100644
--- a/lib/init.c
+++ b/lib/init.c
@@ -329,7 +329,7 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
}

if (iscsi->fd != -1) {
- iscsi_disconnect(iscsi);
+ iscsi->t->disconnect(iscsi);
}

while ((pdu = iscsi->outqueue)) {
diff --git a/lib/socket.c b/lib/socket.c
index 315e7ae..e329fc4 100644
--- a/lib/socket.c
+++ b/lib/socket.c
@@ -79,6 +79,7 @@ static struct iscsi_transport tcp_transport =
.connect = iscsi_tcp_connect,
.queue_pdu = iscsi_tcp_queue_pdu,
.new_pdu = iscsi_tcp_new_pdu,
+ .disconnect = iscsi_tcp_disconnect,
};

void iscsi_init_tcp_transport(struct iscsi_context *iscsi)
@@ -387,7 +388,7 @@ iscsi_connect_async(struct iscsi_context *iscsi, const char *portal,
}

int
-iscsi_disconnect(struct iscsi_context *iscsi)
+iscsi_tcp_disconnect(struct iscsi_context *iscsi)
{
if (iscsi->fd == -1) {
iscsi_set_error(iscsi, "Trying to disconnect "
diff --git a/tests/prog_noop_reply.c b/tests/prog_noop_reply.c
index 114ec29..c7c6e4e 100644
--- a/tests/prog_noop_reply.c
+++ b/tests/prog_noop_reply.c
@@ -259,7 +259,7 @@ int main(int argc, char *argv[])
event_loop(iscsi, &state, 3);

iscsi_destroy_url(iscsi_url);
- iscsi_disconnect(iscsi);
+ iscsi->t->disconnect(iscsi);
iscsi_destroy_context(iscsi);

if (state.status != 0) {
diff --git a/tests/prog_reconnect.c b/tests/prog_reconnect.c
index d13a58f..08b5f57 100644
--- a/tests/prog_reconnect.c
+++ b/tests/prog_reconnect.c
@@ -34,6 +34,7 @@
#include <getopt.h>
#include "iscsi.h"
#include "scsi-lowlevel.h"
+#include "iscsi-private.h"

#ifndef discard_const
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
@@ -88,7 +89,7 @@ void logout_cb(struct iscsi_context *iscsi, int status,
exit(10);
}

- if (iscsi_disconnect(iscsi) != 0) {
+ if (iscsi->t->disconnect(iscsi) != 0) {
fprintf(stderr, "Failed to disconnect old socket\n");
exit(10);
}
diff --git a/tests/prog_reconnect_timeout.c b/tests/prog_reconnect_timeout.c
index b50bc30..95dc9f6 100644
--- a/tests/prog_reconnect_timeout.c
+++ b/tests/prog_reconnect_timeout.c
@@ -34,6 +34,7 @@
#include <getopt.h>
#include "iscsi.h"
#include "scsi-lowlevel.h"
+#include "iscsi-private.h"

#ifndef discard_const
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
@@ -98,7 +99,7 @@ void logout_cb(struct iscsi_context *iscsi, int status,
exit(10);
}

- if (iscsi_disconnect(iscsi) != 0) {
+ if (iscsi->t->disconnect(iscsi) != 0) {
fprintf(stderr, "Failed to disconnect old socket\n");
exit(10);
}
diff --git a/utils/iscsi-ls.c b/utils/iscsi-ls.c
index e48c0d2..e82d961 100644
--- a/utils/iscsi-ls.c
+++ b/utils/iscsi-ls.c
@@ -35,6 +35,7 @@
#include <unistd.h>
#include "iscsi.h"
#include "scsi-lowlevel.h"
+#include "iscsi-private.h"

#ifndef discard_const
#define discard_const(ptr) ((void *)((intptr_t)(ptr)))
@@ -241,7 +242,7 @@ void discoverylogout_cb(struct iscsi_context *iscsi, int status, void *command_d
exit(10);
}

- if (iscsi_disconnect(iscsi) != 0) {
+ if (iscsi->t->disconnect(iscsi) != 0) {
fprintf(stderr, "Failed to disconnect old socket\n");
exit(10);
}
--
1.7.8.2

Roy Shterman

unread,
Apr 3, 2016, 9:59:06 AM4/3/16
to libi...@googlegroups.com
iscsi-command: Adding struct scsi_iovec and int niov into all
read function (READ6, READ10, etc') parameters.

In TCP adding pdu to out queue and writing it to the socket
are happening concurrently, so one can add io vectors to task after
adding the pdu of the same task to the outqueue.
In iSER adding the pdu to out queue is equivelent to sending the packet so
one must publish io vectors or buffers before putting the pdu on
the out queue.

By doing so, if an application wants to use it's own
buffers or iovectors, it's just need to inject the
address of the first scsi_iovec and expected number of
io vectors.

if don't want to use this (application don't has
buffers/iovectors), putting NULL and 0 will compete to
previous code.

Signed-off-by: Roy Shterman <ro...@mellanox.com>
---
examples/iscsi-dd.c | 4 ++--
examples/iscsiclient.c | 19 +++++++++++--------
include/iscsi.h | 10 ++++++----
lib/iscsi-command.c | 24 ++++++++++++++++++++----
lib/sync.c | 8 ++++----
tests/prog_reconnect.c | 4 ++--
tests/prog_reconnect_timeout.c | 4 ++--
utils/iscsi-perf.c | 4 ++--
8 files changed, 49 insertions(+), 28 deletions(-)

diff --git a/examples/iscsi-dd.c b/examples/iscsi-dd.c
index e9964d0..fadcafb 100644
--- a/examples/iscsi-dd.c
+++ b/examples/iscsi-dd.c
@@ -169,13 +169,13 @@ void fill_read_queue(struct client *client)
client->src_lun, client->pos,
num_blocks * client->src_blocksize,
client->src_blocksize, 0, 0, 0, 0, 0,
- read_cb, client);
+ read_cb, client, NULL, 0);
} else {
task = iscsi_read10_task(client->src_iscsi,
client->src_lun, client->pos,
num_blocks * client->src_blocksize,
client->src_blocksize, 0, 0, 0, 0, 0,
- read_cb, client);
+ read_cb, client, NULL, 0);
}
if (task == NULL) {
printf("failed to send read10/16 command\n");
diff --git a/examples/iscsiclient.c b/examples/iscsiclient.c
index cbbb3b1..8e6a5a8 100644
--- a/examples/iscsiclient.c
+++ b/examples/iscsiclient.c
@@ -243,12 +243,6 @@ void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void

memset(&small_buffer[0], 0, 512);

- if ((task = iscsi_read10_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, 0, 0, 0, 0, 0, read10_1_cb, private_data)) == NULL) {
- printf("failed to send read10 command\n");
- exit(10);
- }
- /* provide iovectors where to read the data.
- */
iov[0].iov_base = &small_buffer[0];
iov[0].iov_len = 7;
iov[1].iov_base = &small_buffer[7];
@@ -256,6 +250,13 @@ void read10_cb(struct iscsi_context *iscsi, int status, void *command_data, void
iov[2].iov_base = &small_buffer[15];
iov[2].iov_len = 512 - 15;
scsi_task_set_iov_in(task, &iov[0], 3);
+
+ if ((task = iscsi_read10_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, 0, 0, 0, 0, 0, read10_1_cb, private_data, &iov[0], 3)) == NULL) {
+ printf("failed to send read10 command\n");
+ exit(10);
+ }
+ /* provide iovectors where to read the data.
+ */
}

void read6_cb(struct iscsi_context *iscsi, int status, void *command_data, void *private_data)
@@ -282,7 +283,9 @@ void read6_cb(struct iscsi_context *iscsi, int status, void *command_data, void

scsi_free_scsi_task(task);

- if ((task = iscsi_read10_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, 0, 0, 0, 0, 0, read10_cb, private_data)) == NULL) {
+
+ /* for iSER need to provide buffer address already in the task creation */
+ if ((task = iscsi_read10_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, 0, 0, 0, 0, 0, read10_cb, private_data, NULL, 0)) == NULL) { // Need to Change it
printf("failed to send read10 command\n");
exit(10);
}
@@ -325,7 +328,7 @@ void readcapacity10_cb(struct iscsi_context *iscsi, int status, void *command_da
clnt->block_size = rc10->block_size;
printf("READCAPACITY10 successful. Size:%d blocks blocksize:%d. Read first block\n", rc10->lba, rc10->block_size);

- if (iscsi_read6_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, read6_cb, private_data) == NULL) {
+ if (iscsi_read6_task(iscsi, clnt->lun, 0, clnt->block_size, clnt->block_size, read6_cb, private_data, NULL, 0) == NULL) {
printf("failed to send read6 command\n");
scsi_free_scsi_task(task);
exit(10);
diff --git a/include/iscsi.h b/include/iscsi.h
index a2694b6..a5fad6d 100644
--- a/include/iscsi.h
+++ b/include/iscsi.h
@@ -31,6 +31,8 @@
extern "C" {
#endif

+#include "scsi-lowlevel.h"
+
struct iscsi_context;
struct sockaddr;
union socket_address;
@@ -851,13 +853,13 @@ iscsi_prefetch16_task(struct iscsi_context *iscsi, int lun,
EXTERN struct scsi_task *
iscsi_read6_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize, iscsi_command_cb cb,
- void *private_data);
+ void *private_data, struct scsi_iovec *iov, int niov);

EXTERN struct scsi_task *
iscsi_read10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize,
int rdprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_write10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
@@ -872,7 +874,7 @@ EXTERN struct scsi_task *
iscsi_read12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize,
int rdprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_write12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
@@ -887,7 +889,7 @@ EXTERN struct scsi_task *
iscsi_read16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
uint32_t datalen, int blocksize,
int rdprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data);
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov);
EXTERN struct scsi_task *
iscsi_write16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
unsigned char *data, uint32_t datalen, int blocksize,
diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c
index 8dacd08..0d25808 100644
--- a/lib/iscsi-command.c
+++ b/lib/iscsi-command.c
@@ -716,7 +716,7 @@ iscsi_get_lba_status_task(struct iscsi_context *iscsi, int lun,
struct scsi_task *
iscsi_read6_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;

@@ -732,6 +732,10 @@ iscsi_read6_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
"read6 cdb.");
return NULL;
}
+
+ if (iov != NULL)
+ scsi_task_set_iov_in(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
NULL, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -745,7 +749,7 @@ struct scsi_task *
iscsi_read10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize,
int rdprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;

@@ -762,6 +766,10 @@ iscsi_read10_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
"read10 cdb.");
return NULL;
}
+
+ if (iov != NULL)
+ scsi_task_set_iov_in(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
NULL, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -775,7 +783,7 @@ struct scsi_task *
iscsi_read12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
uint32_t datalen, int blocksize,
int rdprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;

@@ -792,6 +800,10 @@ iscsi_read12_task(struct iscsi_context *iscsi, int lun, uint32_t lba,
"read12 cdb.");
return NULL;
}
+
+ if (iov != NULL)
+ scsi_task_set_iov_in(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
NULL, private_data) != 0) {
scsi_free_scsi_task(task);
@@ -805,7 +817,7 @@ struct scsi_task *
iscsi_read16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
uint32_t datalen, int blocksize,
int rdprotect, int dpo, int fua, int fua_nv, int group_number,
- iscsi_command_cb cb, void *private_data)
+ iscsi_command_cb cb, void *private_data, struct scsi_iovec *iov, int niov)
{
struct scsi_task *task;

@@ -822,6 +834,10 @@ iscsi_read16_task(struct iscsi_context *iscsi, int lun, uint64_t lba,
"read16 cdb.");
return NULL;
}
+
+ if (iov != NULL)
+ scsi_task_set_iov_in(task, iov, niov);
+
if (iscsi_scsi_command_async(iscsi, lun, task, cb,
NULL, private_data) != 0) {
scsi_free_scsi_task(task);
diff --git a/lib/sync.c b/lib/sync.c
index 93f52ca..fcbf3da 100644
--- a/lib/sync.c
+++ b/lib/sync.c
@@ -409,7 +409,7 @@ iscsi_read6_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,
memset(&state, 0, sizeof(state));

if (iscsi_read6_task(iscsi, lun, lba, datalen, blocksize,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, NULL, 0) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Read6 command");
return NULL;
@@ -431,7 +431,7 @@ iscsi_read10_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,

if (iscsi_read10_task(iscsi, lun, lba, datalen, blocksize, rdprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, NULL, 0) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Read10 command");
return NULL;
@@ -453,7 +453,7 @@ iscsi_read12_sync(struct iscsi_context *iscsi, int lun, uint32_t lba,

if (iscsi_read12_task(iscsi, lun, lba, datalen, blocksize, rdprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, NULL, 0) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Read12 command");
return NULL;
@@ -475,7 +475,7 @@ iscsi_read16_sync(struct iscsi_context *iscsi, int lun, uint64_t lba,

if (iscsi_read16_task(iscsi, lun, lba, datalen, blocksize, rdprotect,
dpo, fua, fua_nv, group_number,
- scsi_sync_cb, &state) == NULL) {
+ scsi_sync_cb, &state, NULL, 0) == NULL) {
iscsi_set_error(iscsi,
"Failed to send Read16 command");
return NULL;
diff --git a/tests/prog_reconnect.c b/tests/prog_reconnect.c
index 08b5f57..320f9ce 100644
--- a/tests/prog_reconnect.c
+++ b/tests/prog_reconnect.c
@@ -141,7 +141,7 @@ void read_cb(struct iscsi_context *iscsi, int status,
state->lun, r16_state->lba,
state->block_size,
state->block_size, 0, 0, 0, 0, 0,
- read_cb, r16_state) == NULL) {
+ read_cb, r16_state, NULL, 0) == NULL) {
fprintf(stderr, "iscsi_read16_task failed : %s\n",
iscsi_get_error(iscsi));
exit(10);
@@ -336,7 +336,7 @@ int main(int argc, char *argv[])
r16_state->lba,
state.block_size,
state.block_size, 0, 0, 0, 0, 0,
- read_cb, r16_state) == NULL) {
+ read_cb, r16_state, NULL, 0) == NULL) {
fprintf(stderr, "iscsi_read16_task failed : %s\n",
iscsi_get_error(iscsi));
exit(10);
diff --git a/tests/prog_reconnect_timeout.c b/tests/prog_reconnect_timeout.c
index 95dc9f6..74820dc 100644
--- a/tests/prog_reconnect_timeout.c
+++ b/tests/prog_reconnect_timeout.c
@@ -163,7 +163,7 @@ void read_cb(struct iscsi_context *iscsi, int status,
state->lun, r16_state->lba,
state->block_size,
state->block_size, 0, 0, 0, 0, 0,
- read_cb, r16_state) == NULL) {
+ read_cb, r16_state, NULL, 0) == NULL) {
fprintf(stderr, "iscsi_read16_task failed : %s\n",
iscsi_get_error(iscsi));
exit(10);
@@ -360,7 +360,7 @@ int main(int argc, char *argv[])
r16_state->lba,
state.block_size,
state.block_size, 0, 0, 0, 0, 0,
- read_cb, r16_state) == NULL) {
+ read_cb, r16_state, NULL, 0) == NULL) {
fprintf(stderr, "iscsi_read16_task failed : %s\n",
iscsi_get_error(iscsi));
exit(10);
diff --git a/utils/iscsi-perf.c b/utils/iscsi-perf.c
index 2f63805..2c731f1 100644
--- a/utils/iscsi-perf.c
+++ b/utils/iscsi-perf.c
@@ -147,7 +147,7 @@ void cb(struct iscsi_context *iscsi _U_, int status, void *command_data, void *p
client->lun, read16_cdb->lba,
read16_cdb->transfer_length * client->blocksize,
client->blocksize, 0, 0, 0, 0, 0,
- cb, client);
+ cb, client, NULL, 0);
if (task2 == NULL) {
fprintf(stderr, "failed to send read16 command\n");
client->err_cnt++;
@@ -208,7 +208,7 @@ void fill_read_queue(struct client *client)
client->lun, client->pos,
num_blocks * client->blocksize,
client->blocksize, 0, 0, 0, 0, 0,
- cb, client);
+ cb, client, NULL, 0);
if (task == NULL) {
fprintf(stderr, "failed to send read16 command\n");
iscsi_destroy_context(client->iscsi);
--
1.7.8.2

ronnie sahlberg

unread,
Apr 3, 2016, 4:09:17 PM4/3/16
to libiscsi
Roy, this is awesome!

After a quick glanze I did not see anything major, but I will try
reviewing again, more carefully.

The things that I did notice we need some tweaks for are:

1, Do we really need a --transport argument?
Currently I support either iscs: urls or /dev/* nodes that support SG_IO.

Would it make sense to instead use a iser:-url ?
I.e. use iser:..... instead of iscsi:... for this ?
Then we dont need the --transport argument.

2, We need configure checks for this.
I think this will only ever be available for linux, so some configure
magic to only conditionally include this where available.
Maybe checking for the presence of'

+#include <infiniband/verbs.h>
+#include <rdma/rdma_cma.h>
+#include <rdma/rdma_verbs.h>

and then set HAVE_LINUX_ISER ?
> --
> You received this message because you are subscribed to the Google Groups "libiscsi" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to libiscsi+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

roy.sh...@gmail.com

unread,
Apr 21, 2016, 4:19:27 AM4/21/16
to libiscsi
Hi ronnie, 

I have small question about your comments,

In places that involves discovery there isn't url usage in the command line (like in iscsiclient example) how do you prefer to pass the transport type of the discovery session?
,the way I see it we can add url in the command line but then discovery is a bit wasted, or we can ass transport type just in case there is discovery session in the example/test

another question about including iser code, is it ok if I will do something like

ifdef HAVE_ISER

iser code

endif HAVE_ISER

 or you want me to implement something more sophisticated?

בתאריך יום ראשון, 3 באפריל 2016 בשעה 23:09:17 UTC+3, מאת ronnie sahlberg:
Reply all
Reply to author
Forward
0 new messages