[PATCH 0/8] iscsi-target: ISCSI_OP_NOOP + ISCSI_OP_TEXT refactoring for v3.11

8 views
Skip to first unread message

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:49:57 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

Hi folks,

This series contains the necessary refactoring for ISCSI_OP_NOOP RX
and ISCSI_OP_TEXT RX/TX handling within patch #1 -> #3 to allow these
PDU payloads to function in a transport dependent manner across
traditional iscsi and iser code.

Patch #4 contains initial support for ISCSI_OP_TEXT handling within
iser-target for native in-band sendtargets discovery, and patch #5
is a login parameter negotiation change specific to this case.

Also included in patch #6 are cleanups for handling SendTargets payload
parsing, and patch #7 adds support for explicit SendTargets=[iqn.,eui.]
discovery. Patch #8 contains iser-target specific setup for saving the
incoming ISCSI_OP_TEXT payload.

Or is still tracking down a bug to allow ISCSI_OP_TEXT payloads to
function properly over iser using open-iscsi, but that bit should be
resolved shortly.

Please review.

--nab

Nicholas Bellinger (8):
iscsi/isert-target: Refactor ISCSI_OP_NOOP RX handling
iscsi-target: Refactor ISCSI_OP_TEXT RX handling
iscsi-target: Refactor ISCSI_OP_TEXT_RSP TX handling
iser-target: Initial support for ISCSI_OP_TEXT opcode
iscsi-target: Allow IRDSL and TRDSL to be exchanged during iser
discovery
iscsi-target: Move sendtargets parsing into iscsit_process_text_cmd
iscsi-target: Add IFC_SENDTARGETS_SINGLE support
iser-target: Setup incoming ISCSI_OP_TEXT buffer

drivers/infiniband/ulp/isert/ib_isert.c | 116 ++++++-
drivers/target/iscsi/iscsi_target.c | 459 ++++++++++++++----------
drivers/target/iscsi/iscsi_target_core.h | 4 +
drivers/target/iscsi/iscsi_target_login.c | 2 +-
drivers/target/iscsi/iscsi_target_parameters.c | 12 +-
drivers/target/iscsi/iscsi_target_parameters.h | 2 +-
drivers/target/iscsi/iscsi_target_util.c | 1 +
include/target/iscsi/iscsi_transport.h | 12 +-
8 files changed, 411 insertions(+), 197 deletions(-)

--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:49:58 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch refactors ISCSI_OP_NOOP handling within iscsi-target in
order to handle iscsi_nopout payloads in a transport specific manner.

This includes splitting existing iscsit_handle_nop_out() into
iscsit_setup_nop_out() and iscsit_process_nop_out() calls, and
makes iscsit_handle_nop_out() be only used internally by traditional
iscsi socket calls.

Next update iser-target code to use new callers and add FIXME for
the handling iscsi_nopout payloads. Also fix reject response handling
in iscsit_setup_nop_out() to use proper iscsit_add_reject_from_cmd().

v2: Fix uninitialized iscsit_handle_nop_out() payload_length usage (Fengguang)

Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/infiniband/ulp/isert/ib_isert.c | 23 ++++-
drivers/target/iscsi/iscsi_target.c | 173 ++++++++++++++++---------------
include/target/iscsi/iscsi_transport.h | 6 +-
3 files changed, 117 insertions(+), 85 deletions(-)

diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 41712f0..c48c948 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1001,6 +1001,25 @@ isert_handle_iscsi_dataout(struct isert_conn *isert_conn,
}

static int
+isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
+ struct iser_rx_desc *rx_desc, unsigned char *buf)
+{
+ struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
+ struct iscsi_conn *conn = isert_conn->conn;
+ struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
+ int rc;
+
+ rc = iscsit_setup_nop_out(conn, cmd, hdr);
+ if (rc < 0)
+ return rc;
+ /*
+ * FIXME: Add support for NOPOUT payload using unsolicited RDMA payload
+ */
+
+ return iscsit_process_nop_out(conn, cmd, hdr);
+}
+
+static int
isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
uint32_t read_stag, uint64_t read_va,
uint32_t write_stag, uint64_t write_va)
@@ -1032,7 +1051,9 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
if (!cmd)
break;

- ret = iscsit_handle_nop_out(conn, cmd, (unsigned char *)hdr);
+ isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd);
+ ret = isert_handle_nop_out(isert_conn, isert_cmd,
+ rx_desc, (unsigned char *)hdr);
break;
case ISCSI_OP_SCSI_DATA_OUT:
ret = isert_handle_iscsi_dataout(isert_conn, rx_desc,
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index cc43d41..e50f49a 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1535,24 +1535,16 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
}

-int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
- unsigned char *buf)
+int iscsit_setup_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ struct iscsi_nopout *hdr)
{
- unsigned char *ping_data = NULL;
- int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size;
- u32 checksum, data_crc, padding = 0, payload_length;
- struct iscsi_cmd *cmd_p = NULL;
- struct kvec *iov = NULL;
- struct iscsi_nopout *hdr;
-
- hdr = (struct iscsi_nopout *) buf;
- payload_length = ntoh24(hdr->dlength);
+ u32 payload_length = ntoh24(hdr->dlength);

if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
pr_err("NOPOUT ITT is reserved, but Immediate Bit is"
" not set, protocol error.\n");
- return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
- buf, conn);
+ return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+ 1, 0, (unsigned char *)hdr, cmd);
}

if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
@@ -1560,8 +1552,8 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
" greater than MaxXmitDataSegmentLength: %u, protocol"
" error.\n", payload_length,
conn->conn_ops->MaxXmitDataSegmentLength);
- return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
- buf, conn);
+ return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+ 1, 0, (unsigned char *)hdr, cmd);
}

pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
@@ -1578,9 +1570,9 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
*/
if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
if (!cmd)
- return iscsit_add_reject(
+ return iscsit_add_reject_from_cmd(
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
- 1, buf, conn);
+ 1, 0, (unsigned char *)hdr, cmd);

cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT;
cmd->i_state = ISTATE_SEND_NOPIN;
@@ -1593,8 +1585,87 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
cmd->data_direction = DMA_NONE;
}

+ return 0;
+}
+EXPORT_SYMBOL(iscsit_setup_nop_out);
+
+int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ struct iscsi_nopout *hdr)
+{
+ struct iscsi_cmd *cmd_p = NULL;
+ int cmdsn_ret = 0;
+ /*
+ * Initiator is expecting a NopIN ping reply..
+ */
+ if (hdr->itt != RESERVED_ITT) {
+ BUG_ON(!cmd);
+
+ spin_lock_bh(&conn->cmd_lock);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
+ spin_unlock_bh(&conn->cmd_lock);
+
+ iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
+
+ if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
+ iscsit_add_cmd_to_response_queue(cmd, conn,
+ cmd->i_state);
+ return 0;
+ }
+
+ cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+ if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
+ return 0;
+
+ if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+ return iscsit_add_reject_from_cmd(
+ ISCSI_REASON_PROTOCOL_ERROR,
+ 1, 0, (unsigned char *)hdr, cmd);
+
+ return 0;
+ }
+ /*
+ * This was a response to a unsolicited NOPIN ping.
+ */
+ if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
+ cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
+ if (!cmd_p)
+ return -EINVAL;
+
+ iscsit_stop_nopin_response_timer(conn);
+
+ cmd_p->i_state = ISTATE_REMOVE;
+ iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
+
+ iscsit_start_nopin_timer(conn);
+ return 0;
+ }
+ /*
+ * Otherwise, initiator is not expecting a NOPIN is response.
+ * Just ignore for now.
+ */
+ return 0;
+}
+EXPORT_SYMBOL(iscsit_process_nop_out);
+
+static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ unsigned char *buf)
+{
+ unsigned char *ping_data = NULL;
+ struct iscsi_nopout *hdr = (struct iscsi_nopout *)buf;
+ struct kvec *iov = NULL;
+ u32 payload_length = ntoh24(hdr->dlength);
+ int ret;
+
+ ret = iscsit_setup_nop_out(conn, cmd, hdr);
+ if (ret < 0)
+ return ret;
+ /*
+ * Handle NOP-OUT payload for traditional iSCSI sockets
+ */
if (payload_length && hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
- rx_size = payload_length;
+ u32 checksum, data_crc, padding = 0;
+ int niov = 0, rx_got, rx_size = payload_length;
+
ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
if (!ping_data) {
pr_err("Unable to allocate memory for"
@@ -1673,76 +1744,14 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
pr_debug("Ping Data: \"%s\"\n", ping_data);
}

- if (hdr->itt != RESERVED_ITT) {
- if (!cmd) {
- pr_err("Checking CmdSN for NOPOUT,"
- " but cmd is NULL!\n");
- return -1;
- }
- /*
- * Initiator is expecting a NopIN ping reply,
- */
- spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
- spin_unlock_bh(&conn->cmd_lock);
-
- iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
-
- if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
- iscsit_add_cmd_to_response_queue(cmd, conn,
- cmd->i_state);
- return 0;
- }
-
- cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
- if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
- ret = 0;
- goto ping_out;
- }
- if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
- return iscsit_add_reject_from_cmd(
- ISCSI_REASON_PROTOCOL_ERROR,
- 1, 0, buf, cmd);
-
- return 0;
- }
-
- if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
- /*
- * This was a response to a unsolicited NOPIN ping.
- */
- cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
- if (!cmd_p)
- return -1;
-
- iscsit_stop_nopin_response_timer(conn);
-
- cmd_p->i_state = ISTATE_REMOVE;
- iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
- iscsit_start_nopin_timer(conn);
- } else {
- /*
- * Initiator is not expecting a NOPIN is response.
- * Just ignore for now.
- *
- * iSCSI v19-91 10.18
- * "A NOP-OUT may also be used to confirm a changed
- * ExpStatSN if another PDU will not be available
- * for a long time."
- */
- ret = 0;
- goto out;
- }
-
- return 0;
+ return iscsit_process_nop_out(conn, cmd, hdr);
out:
if (cmd)
iscsit_free_cmd(cmd, false);
-ping_out:
+
kfree(ping_data);
return ret;
}
-EXPORT_SYMBOL(iscsit_handle_nop_out);

int
iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
index 23a87d0..ecb53ea 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -45,8 +45,10 @@ extern int iscsit_check_dataout_hdr(struct iscsi_conn *, unsigned char *,
struct iscsi_cmd **);
extern int iscsit_check_dataout_payload(struct iscsi_cmd *, struct iscsi_data *,
bool);
-extern int iscsit_handle_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
- unsigned char *);
+extern int iscsit_setup_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
+ struct iscsi_nopout *);
+extern int iscsit_process_nop_out(struct iscsi_conn *, struct iscsi_cmd *,
+ struct iscsi_nopout *);
extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *,
unsigned char *);
extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *,
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:49:59 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch refactors ISCSI_OP_TEXT handling within iscsi-target in
order to handle iscsi_text payloads in a transport specific manner.

This includes splitting current iscsit_handle_text_cmd() into
iscsit_setup_text_cmd() and iscsit_process_text_cmd() calls, and
makes iscsit_handle_text_cmd be only used internally by traditional
iscsi socket calls.

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/target/iscsi/iscsi_target.c | 158 ++++++++++++++++++--------------
include/target/iscsi/iscsi_transport.h | 4 +
2 files changed, 94 insertions(+), 68 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index e50f49a..0ff30cf 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1965,45 +1965,93 @@ attach:
EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);

/* #warning FIXME: Support Text Command parameters besides SendTargets */
-static int iscsit_handle_text_cmd(
- struct iscsi_conn *conn,
- unsigned char *buf)
+int
+iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ struct iscsi_text *hdr)
{
- char *text_ptr, *text_in;
- int cmdsn_ret, niov = 0, rx_got, rx_size;
- u32 checksum = 0, data_crc = 0, payload_length;
- u32 padding = 0, pad_bytes = 0, text_length = 0;
- struct iscsi_cmd *cmd;
- struct kvec iov[3];
- struct iscsi_text *hdr;
-
- hdr = (struct iscsi_text *) buf;
- payload_length = ntoh24(hdr->dlength);
+ u32 payload_length = ntoh24(hdr->dlength);

if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
pr_err("Unable to accept text parameter length: %u"
"greater than MaxXmitDataSegmentLength %u.\n",
payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
- return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1,
- buf, conn);
+ return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+ 1, 0, (unsigned char *)hdr, cmd);
}

pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x,"
" ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn,
hdr->exp_statsn, payload_length);

- rx_size = text_length = payload_length;
- if (text_length) {
- text_in = kzalloc(text_length, GFP_KERNEL);
+ cmd->iscsi_opcode = ISCSI_OP_TEXT;
+ cmd->i_state = ISTATE_SEND_TEXTRSP;
+ cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
+ conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
+ cmd->targ_xfer_tag = 0xFFFFFFFF;
+ cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
+ cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
+ cmd->data_direction = DMA_NONE;
+
+ return 0;
+}
+EXPORT_SYMBOL(iscsit_setup_text_cmd);
+
+int
+iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ struct iscsi_text *hdr)
+{
+ int cmdsn_ret;
+
+ spin_lock_bh(&conn->cmd_lock);
+ list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
+ spin_unlock_bh(&conn->cmd_lock);
+
+ iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
+
+ if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
+ cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
+ if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
+ return iscsit_add_reject_from_cmd(
+ ISCSI_REASON_PROTOCOL_ERROR,
+ 1, 0, (unsigned char *)hdr, cmd);
+ return 0;
+ }
+
+ return iscsit_execute_cmd(cmd, 0);
+}
+EXPORT_SYMBOL(iscsit_process_text_cmd);
+
+static int
+iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
+ unsigned char *buf)
+{
+ struct iscsi_text *hdr = (struct iscsi_text *)buf;
+ char *text_in = NULL;
+ u32 payload_length = ntoh24(hdr->dlength);
+ int rx_size, rc;
+
+ rc = iscsit_setup_text_cmd(conn, cmd, hdr);
+ if (rc < 0)
+ return rc;
+
+ rx_size = payload_length;
+ if (payload_length) {
+ char *text_ptr;
+ u32 checksum = 0, data_crc = 0;
+ u32 padding = 0, pad_bytes = 0;
+ int niov = 0, rx_got;
+ struct kvec iov[3];
+
+ text_in = kzalloc(payload_length, GFP_KERNEL);
if (!text_in) {
pr_err("Unable to allocate memory for"
" incoming text parameters\n");
- return -1;
+ goto reject;
}

memset(iov, 0, 3 * sizeof(struct kvec));
iov[niov].iov_base = text_in;
- iov[niov++].iov_len = text_length;
+ iov[niov++].iov_len = payload_length;

padding = ((-payload_length) & 3);
if (padding != 0) {
@@ -2020,14 +2068,12 @@ static int iscsit_handle_text_cmd(
}

rx_got = rx_data(conn, &iov[0], niov, rx_size);
- if (rx_got != rx_size) {
- kfree(text_in);
- return -1;
- }
+ if (rx_got != rx_size)
+ goto reject;

if (conn->conn_ops->DataDigest) {
iscsit_do_crypto_hash_buf(&conn->conn_rx_hash,
- text_in, text_length,
+ text_in, payload_length,
padding, (u8 *)&pad_bytes,
(u8 *)&data_crc);

@@ -2039,8 +2085,7 @@ static int iscsit_handle_text_cmd(
pr_err("Unable to recover from"
" Text Data digest failure while in"
" ERL=0.\n");
- kfree(text_in);
- return -1;
+ goto reject;
} else {
/*
* Silently drop this PDU and let the
@@ -2055,68 +2100,40 @@ static int iscsit_handle_text_cmd(
} else {
pr_debug("Got CRC32C DataDigest"
" 0x%08x for %u bytes of text data.\n",
- checksum, text_length);
+ checksum, payload_length);
}
}
- text_in[text_length - 1] = '\0';
+ text_in[payload_length - 1] = '\0';
pr_debug("Successfully read %d bytes of text"
- " data.\n", text_length);
+ " data.\n", payload_length);

if (strncmp("SendTargets", text_in, 11) != 0) {
pr_err("Received Text Data that is not"
" SendTargets, cannot continue.\n");
- kfree(text_in);
- return -1;
+ goto reject;
}
text_ptr = strchr(text_in, '=');
if (!text_ptr) {
pr_err("No \"=\" separator found in Text Data,"
" cannot continue.\n");
- kfree(text_in);
- return -1;
+ goto reject;
}
if (strncmp("=All", text_ptr, 4) != 0) {
pr_err("Unable to locate All value for"
" SendTargets key, cannot continue.\n");
- kfree(text_in);
- return -1;
+ goto reject;
}
-/*#warning Support SendTargets=(iSCSI Target Name/Nothing) values. */
kfree(text_in);
}

- cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
- if (!cmd)
- return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
- 1, buf, conn);
-
- cmd->iscsi_opcode = ISCSI_OP_TEXT;
- cmd->i_state = ISTATE_SEND_TEXTRSP;
- cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
- conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
- cmd->targ_xfer_tag = 0xFFFFFFFF;
- cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
- cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
- cmd->data_direction = DMA_NONE;
-
- spin_lock_bh(&conn->cmd_lock);
- list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
- spin_unlock_bh(&conn->cmd_lock);
-
- iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
+ return iscsit_process_text_cmd(conn, cmd, hdr);

- if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
- cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
- if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
- return iscsit_add_reject_from_cmd(
- ISCSI_REASON_PROTOCOL_ERROR,
- 1, 0, buf, cmd);
-
- return 0;
- }
-
- return iscsit_execute_cmd(cmd, 0);
+reject:
+ kfree(text_in);
+ return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+ 0, 0, buf, cmd);
}
+EXPORT_SYMBOL(iscsit_handle_text_cmd);

int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
{
@@ -3952,7 +3969,12 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
break;
case ISCSI_OP_TEXT:
- ret = iscsit_handle_text_cmd(conn, buf);
+ cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+ if (!cmd)
+ return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
+ 1, buf, conn);
+
+ ret = iscsit_handle_text_cmd(conn, cmd, buf);
break;
case ISCSI_OP_LOGOUT:
cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
index ecb53ea..90f3b60 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -53,6 +53,10 @@ extern int iscsit_handle_logout_cmd(struct iscsi_conn *, struct iscsi_cmd *,
unsigned char *);
extern int iscsit_handle_task_mgt_cmd(struct iscsi_conn *, struct iscsi_cmd *,
unsigned char *);
+extern int iscsit_setup_text_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+ struct iscsi_text *);
+extern int iscsit_process_text_cmd(struct iscsi_conn *, struct iscsi_cmd *,
+ struct iscsi_text *);
extern void iscsit_build_rsp_pdu(struct iscsi_cmd *, struct iscsi_conn *,
bool, struct iscsi_scsi_rsp *);
extern void iscsit_build_nopin_rsp(struct iscsi_cmd *, struct iscsi_conn *,
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:50:00 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch refactoring existing iscsit_send_text_rsp() in order
to handle iscsi_text_rsp payloads in a transport specific manner.

This includes the addition of iscsit_build_text_rsp() to build
the response payload and initialize ISCSI_OP_TEXT_RSP.

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/target/iscsi/iscsi_target.c | 59 +++++++++++++++++++------------
include/target/iscsi/iscsi_transport.h | 2 +
2 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 0ff30cf..e173b49 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -3466,6 +3466,36 @@ eob:
return payload_len;
}

+int
+iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
+ struct iscsi_text_rsp *hdr)
+{
+ int text_length;
+
+ text_length = iscsit_build_sendtargets_response(cmd);
+ if (text_length < 0)
+ return text_length;
+
+ hdr->opcode = ISCSI_OP_TEXT_RSP;
+ hdr->flags |= ISCSI_FLAG_CMD_FINAL;
+ hton24(hdr->dlength, text_length);
+ hdr->itt = cmd->init_task_tag;
+ hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
+ cmd->stat_sn = conn->stat_sn++;
+ hdr->statsn = cpu_to_be32(cmd->stat_sn);
+
+ iscsit_increment_maxcmdsn(cmd, conn->sess);
+ hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
+ hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
+
+ pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x,"
+ " Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn,
+ text_length, conn->cid);
+
+ return text_length;
+}
+EXPORT_SYMBOL(iscsit_build_text_rsp);
+
/*
* FIXME: Add support for F_BIT and C_BIT when the length is longer than
* MaxRecvDataSegmentLength.
@@ -3474,15 +3504,16 @@ static int iscsit_send_text_rsp(
struct iscsi_cmd *cmd,
struct iscsi_conn *conn)
{
- struct iscsi_text_rsp *hdr;
+ struct iscsi_text_rsp *hdr = (struct iscsi_text_rsp *)cmd->pdu;
struct kvec *iov;
u32 padding = 0, tx_size = 0;
- int text_length, iov_count = 0;
+ int text_length, iov_count = 0, rc;

- text_length = iscsit_build_sendtargets_response(cmd);
- if (text_length < 0)
- return text_length;
+ rc = iscsit_build_text_rsp(cmd, conn, hdr);
+ if (rc < 0)
+ return rc;

+ text_length = rc;
padding = ((-text_length) & 3);
if (padding != 0) {
memset(cmd->buf_ptr + text_length, 0, padding);
@@ -3490,22 +3521,7 @@ static int iscsit_send_text_rsp(
" padding.\n", padding);
}

- hdr = (struct iscsi_text_rsp *) cmd->pdu;
- memset(hdr, 0, ISCSI_HDR_LEN);
- hdr->opcode = ISCSI_OP_TEXT_RSP;
- hdr->flags |= ISCSI_FLAG_CMD_FINAL;
- hton24(hdr->dlength, text_length);
- hdr->itt = cmd->init_task_tag;
- hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
- cmd->stat_sn = conn->stat_sn++;
- hdr->statsn = cpu_to_be32(cmd->stat_sn);
-
- iscsit_increment_maxcmdsn(cmd, conn->sess);
- hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
- hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
-
iov = &cmd->iov_misc[0];
-
iov[iov_count].iov_base = cmd->pdu;
iov[iov_count++].iov_len = ISCSI_HDR_LEN;
iov[iov_count].iov_base = cmd->buf_ptr;
@@ -3542,9 +3558,6 @@ static int iscsit_send_text_rsp(
cmd->iov_misc_count = iov_count;
cmd->tx_size = tx_size;

- pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x,"
- " Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn,
- text_length, conn->cid);
return 0;
}

diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
index 90f3b60..ce991ba 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -63,6 +63,8 @@ extern void iscsit_build_nopin_rsp(struct iscsi_cmd *, struct iscsi_conn *,
struct iscsi_nopin *, bool);
extern void iscsit_build_task_mgt_rsp(struct iscsi_cmd *, struct iscsi_conn *,
struct iscsi_tm_rsp *);
+extern int iscsit_build_text_rsp(struct iscsi_cmd *, struct iscsi_conn *,
+ struct iscsi_text_rsp *);
extern void iscsit_build_reject(struct iscsi_cmd *, struct iscsi_conn *,
struct iscsi_reject *);
extern int iscsit_build_logout_rsp(struct iscsi_cmd *, struct iscsi_conn *,
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:50:01 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch adds isert_handle_text_cmd() to handle incoming
ISCSI_OP_TEXT PDU processing, along with isert_put_text_rsp()
for posting ISCSI_OP_TEXT_RSP ib_send_wr response.

Note this uses cmd->buf_ptr -> isert_cmd->sense_buf_[dma,len]
for the outgoing response payload.

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/infiniband/ulp/isert/ib_isert.c | 84 ++++++++++++++++++++++++++++++-
1 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index c48c948..c3b4e6e 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1020,6 +1020,24 @@ isert_handle_nop_out(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
}

static int
+isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
+ struct iser_rx_desc *rx_desc, struct iscsi_text *hdr)
+{
+ struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
+ struct iscsi_conn *conn = isert_conn->conn;
+ int rc;
+
+ rc = iscsit_setup_text_cmd(conn, cmd, hdr);
+ if (rc < 0)
+ return rc;
+
+ /*
+ * FIXME: Add support for TEXT payload parsing
+ */
+ return iscsit_process_text_cmd(conn, cmd, hdr);
+}
+
+static int
isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
uint32_t read_stag, uint64_t read_va,
uint32_t write_stag, uint64_t write_va)
@@ -1078,6 +1096,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
SECONDS_FOR_LOGOUT_COMP *
HZ);
break;
+ case ISCSI_OP_TEXT:
+ cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
+ if (!cmd)
+ break;
+
+ isert_cmd = container_of(cmd, struct isert_cmd, iscsi_cmd);
+ ret = isert_handle_text_cmd(isert_conn, isert_cmd,
+ rx_desc, (struct iscsi_text *)hdr);
+ break;
default:
pr_err("Got unknown iSCSI OpCode: 0x%02x\n", opcode);
dump_stack();
@@ -1230,6 +1257,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd)
break;
case ISCSI_OP_REJECT:
case ISCSI_OP_NOOP_OUT:
+ case ISTATE_SEND_TEXTRSP:
conn = isert_conn->conn;

spin_lock_bh(&conn->cmd_lock);
@@ -1350,6 +1378,11 @@ isert_do_control_comp(struct work_struct *work)
isert_conn->logout_posted = true;
iscsit_logout_post_handler(cmd, cmd->conn);
break;
+ case ISTATE_SEND_TEXTRSP:
+ atomic_dec(&isert_conn->post_send_buf_count);
+ cmd->i_state = ISTATE_SENT_STATUS;
+ isert_completion_put(&isert_cmd->tx_desc, isert_cmd, ib_dev);
+ break;
default:
pr_err("Unknown do_control_comp i_state %d\n", cmd->i_state);
dump_stack();
@@ -1366,7 +1399,8 @@ isert_response_completion(struct iser_tx_desc *tx_desc,
struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;

if (cmd->i_state == ISTATE_SEND_TASKMGTRSP ||
- cmd->i_state == ISTATE_SEND_LOGOUTRSP) {
+ cmd->i_state == ISTATE_SEND_LOGOUTRSP ||
+ cmd->i_state == ISTATE_SEND_TEXTRSP) {
isert_unmap_tx_desc(tx_desc, ib_dev);

INIT_WORK(&isert_cmd->comp_work, isert_do_control_comp);
@@ -1671,6 +1705,51 @@ isert_put_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
}

static int
+isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
+{
+ struct isert_cmd *isert_cmd = container_of(cmd,
+ struct isert_cmd, iscsi_cmd);
+ struct isert_conn *isert_conn = (struct isert_conn *)conn->context;
+ struct ib_send_wr *send_wr = &isert_cmd->tx_desc.send_wr;
+ struct iscsi_text_rsp *hdr =
+ (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header;
+ int rc, text_length;
+
+ isert_create_send_desc(isert_conn, isert_cmd, &isert_cmd->tx_desc);
+ rc = iscsit_build_text_rsp(cmd, conn, hdr);
+ if (rc < 0)
+ return rc;
+
+ text_length = rc;
+ if (text_length) {
+ struct ib_device *ib_dev = isert_conn->conn_cm_id->device;
+ struct ib_sge *tx_dsg = &isert_cmd->tx_desc.tx_sg[1];
+ void *txt_rsp_buf = cmd->buf_ptr;
+ u32 padding, txt_rsp_len;
+
+ padding = -(text_length) & 3;
+ hton24(hdr->dlength, text_length);
+ txt_rsp_len = text_length + padding;
+
+ isert_cmd->sense_buf_dma = ib_dma_map_single(ib_dev,
+ txt_rsp_buf, txt_rsp_len, DMA_TO_DEVICE);
+
+ isert_cmd->sense_buf_len = txt_rsp_len;
+ tx_dsg->addr = isert_cmd->sense_buf_dma;
+ tx_dsg->length = txt_rsp_len;
+ tx_dsg->lkey = isert_conn->conn_mr->lkey;
+ isert_cmd->tx_desc.num_sge = 2;
+ }
+
+ isert_init_tx_hdrs(isert_conn, &isert_cmd->tx_desc);
+ isert_init_send_wr(isert_cmd, send_wr);
+
+ pr_debug("Posting Text Response IB_WR_SEND >>>>>>>>>>>>>>>>>>>>>>\n");
+
+ return isert_post_response(isert_conn, isert_cmd);
+}
+
+static int
isert_build_rdma_wr(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd,
struct ib_sge *ib_sge, struct ib_send_wr *send_wr,
u32 data_left, u32 offset)
@@ -1968,6 +2047,9 @@ isert_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
case ISTATE_SEND_REJECT:
ret = isert_put_reject(cmd, conn);
break;
+ case ISTATE_SEND_TEXTRSP:
+ ret = isert_put_text_rsp(cmd, conn);
+ break;
case ISTATE_SEND_STATUS:
/*
* Special case for sending non GOOD SCSI status from TX thread
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:50:02 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch changes iscsi_set_keys_irrelevant_for_discovery() parameter
usage to allow INITIATORRECVDATASEGMENTLENGTH + TARGETRECVDATASEGMENTLENGTH
keys to be negotiated during in-band iser send-targets discovery.

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/target/iscsi/iscsi_target_login.c | 2 +-
drivers/target/iscsi/iscsi_target_parameters.c | 12 +++++++++---
drivers/target/iscsi/iscsi_target_parameters.h | 2 +-
3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index bb5d5c5..f42eb84 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -369,7 +369,7 @@ static int iscsi_login_zero_tsih_s2(

if (sess->sess_ops->SessionType)
return iscsi_set_keys_irrelevant_for_discovery(
- conn->param_list);
+ conn->param_list, iser);

na = iscsit_tpg_get_node_attrib(sess);

diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index e382221..0b8c819 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -545,7 +545,8 @@ int iscsi_set_keys_to_negotiate(
}

int iscsi_set_keys_irrelevant_for_discovery(
- struct iscsi_param_list *param_list)
+ struct iscsi_param_list *param_list,
+ bool iser)
{
struct iscsi_param *param;

@@ -582,10 +583,15 @@ int iscsi_set_keys_irrelevant_for_discovery(
param->state &= ~PSTATE_NEGOTIATE;
else if (!strcmp(param->name, RDMAEXTENSIONS))
param->state &= ~PSTATE_NEGOTIATE;
- else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH))
+ else if (!strcmp(param->name, INITIATORRECVDATASEGMENTLENGTH)) {
+ if (!iser)
+ continue;
param->state &= ~PSTATE_NEGOTIATE;
- else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH))
+ } else if (!strcmp(param->name, TARGETRECVDATASEGMENTLENGTH)) {
+ if (!iser)
+ continue;
param->state &= ~PSTATE_NEGOTIATE;
+ }
}

return 0;
diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h
index a47046a..76d2fdf 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.h
+++ b/drivers/target/iscsi/iscsi_target_parameters.h
@@ -30,7 +30,7 @@ extern void iscsi_dump_sess_ops(struct iscsi_sess_ops *);
extern void iscsi_print_params(struct iscsi_param_list *);
extern int iscsi_create_default_params(struct iscsi_param_list **);
extern int iscsi_set_keys_to_negotiate(struct iscsi_param_list *, bool);
-extern int iscsi_set_keys_irrelevant_for_discovery(struct iscsi_param_list *);
+extern int iscsi_set_keys_irrelevant_for_discovery(struct iscsi_param_list *, bool);
extern int iscsi_copy_param_list(struct iscsi_param_list **,
struct iscsi_param_list *, int);
extern int iscsi_change_param_value(char *, struct iscsi_param_list *, int);
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:50:03 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch moves ISCSI_OP_TEXT PDU buffer sanity checks to
iscsit_process_text_cmd() code, so that it can be shared
with iser-target code.

It adds IFC_SENDTARGETS_ALL + iscsi_cmd->text_in_ptr in order
to save text payload for ISCSI_OP_TEXT_RSP, and updates
iscsit_release_cmd() to assigned memory.

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/target/iscsi/iscsi_target.c | 51 ++++++++++++++++++------------
drivers/target/iscsi/iscsi_target_core.h | 3 ++
drivers/target/iscsi/iscsi_target_util.c | 1 +
3 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index e173b49..0ce7a61 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -2000,8 +2000,32 @@ int
iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
struct iscsi_text *hdr)
{
+ unsigned char *text_in = cmd->text_in_ptr, *text_ptr;
int cmdsn_ret;

+ if (!text_in) {
+ pr_err("Unable to locate text_in buffer for sendtargets"
+ " discovery\n");
+ goto reject;
+ }
+ if (strncmp("SendTargets", text_in, 11) != 0) {
+ pr_err("Received Text Data that is not"
+ " SendTargets, cannot continue.\n");
+ goto reject;
+ }
+ text_ptr = strchr(text_in, '=');
+ if (!text_ptr) {
+ pr_err("No \"=\" separator found in Text Data,"
+ " cannot continue.\n");
+ goto reject;
+ }
+ if (!strncmp("=All", text_ptr, 4)) {
+ cmd->cmd_flags |= IFC_SENDTARGETS_ALL;
+ } else {
+ pr_err("Unable to locate valid SendTargets=%s value\n", text_ptr);
+ goto reject;
+ }
+
spin_lock_bh(&conn->cmd_lock);
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock);
@@ -2018,6 +2042,10 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
}

return iscsit_execute_cmd(cmd, 0);
+
+reject:
+ return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
+ 0, 0, (unsigned char *)hdr, cmd);
}
EXPORT_SYMBOL(iscsit_process_text_cmd);

@@ -2036,7 +2064,6 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,

rx_size = payload_length;
if (payload_length) {
- char *text_ptr;
u32 checksum = 0, data_crc = 0;
u32 padding = 0, pad_bytes = 0;
int niov = 0, rx_got;
@@ -2048,6 +2075,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
" incoming text parameters\n");
goto reject;
}
+ cmd->text_in_ptr = text_in;

memset(iov, 0, 3 * sizeof(struct kvec));
iov[niov].iov_base = text_in;
@@ -2106,30 +2134,13 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
text_in[payload_length - 1] = '\0';
pr_debug("Successfully read %d bytes of text"
" data.\n", payload_length);
-
- if (strncmp("SendTargets", text_in, 11) != 0) {
- pr_err("Received Text Data that is not"
- " SendTargets, cannot continue.\n");
- goto reject;
- }
- text_ptr = strchr(text_in, '=');
- if (!text_ptr) {
- pr_err("No \"=\" separator found in Text Data,"
- " cannot continue.\n");
- goto reject;
- }
- if (strncmp("=All", text_ptr, 4) != 0) {
- pr_err("Unable to locate All value for"
- " SendTargets key, cannot continue.\n");
- goto reject;
- }
- kfree(text_in);
}

return iscsit_process_text_cmd(conn, cmd, hdr);

reject:
- kfree(text_in);
+ kfree(cmd->text_in_ptr);
+ cmd->text_in_ptr = NULL;
return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
0, 0, buf, cmd);
}
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index 60ec4b9..ad46e73 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -133,6 +133,7 @@ enum cmd_flags_table {
ICF_ATTACHED_TO_RQUEUE = 0x00000040,
ICF_OOO_CMDSN = 0x00000080,
ICF_REJECT_FAIL_CONN = 0x00000100,
+ IFC_SENDTARGETS_ALL = 0x00000200,
};

/* struct iscsi_cmd->i_state */
@@ -427,6 +428,8 @@ struct iscsi_cmd {
u32 tx_size;
/* Buffer used for various purposes */
void *buf_ptr;
+ /* Used by SendTargets=[iqn.,eui.] discovery */
+ void *text_in_ptr;
/* See include/linux/dma-mapping.h */
enum dma_data_direction data_direction;
/* iSCSI PDU Header + CRC */
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 08a3bac..fe712d6 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -681,6 +681,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
kfree(cmd->seq_list);
kfree(cmd->tmr_req);
kfree(cmd->iov_data);
+ kfree(cmd->text_in_ptr);

kmem_cache_free(lio_cmd_cache, cmd);
}
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:50:04 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch changes ISCSI_OP_TEXT handling of SendTargets=[iqn.,eui.]
payloads to return explicit discovery information.

It adds checks to iscsit_process_text_cmd() and adds the special single
$TARGETNAME discovery case in iscsit_build_sendtargets_response() code.

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/target/iscsi/iscsi_target.c | 28 ++++++++++++++++++++++++++++
drivers/target/iscsi/iscsi_target_core.h | 1 +
2 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 0ce7a61..c1106bb 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -2021,6 +2021,9 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
}
if (!strncmp("=All", text_ptr, 4)) {
cmd->cmd_flags |= IFC_SENDTARGETS_ALL;
+ } else if (!strncmp("=iqn.", text_ptr, 5) ||
+ !strncmp("=eui.", text_ptr, 5)) {
+ cmd->cmd_flags |= IFC_SENDTARGETS_SINGLE;
} else {
pr_err("Unable to locate valid SendTargets=%s value\n", text_ptr);
goto reject;
@@ -3403,6 +3406,7 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
struct iscsi_tpg_np *tpg_np;
int buffer_len, end_of_buf = 0, len = 0, payload_len = 0;
unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
+ unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;

buffer_len = max(conn->conn_ops->MaxRecvDataSegmentLength,
SENDTARGETS_BUF_LIMIT);
@@ -3413,9 +3417,30 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
" response.\n");
return -ENOMEM;
}
+ /*
+ * Locate pointer to iqn./eui. string for IFC_SENDTARGETS_SINGLE
+ * explicit case..
+ */
+ if (cmd->cmd_flags & IFC_SENDTARGETS_SINGLE) {
+ text_ptr = strchr(text_in, '=');
+ if (!text_ptr) {
+ pr_err("Unable to locate '=' string in text_in:"
+ " %s\n", text_in);
+ return -EINVAL;
+ }
+ /*
+ * Skip over '=' character..
+ */
+ text_ptr += 1;
+ }

spin_lock(&tiqn_lock);
list_for_each_entry(tiqn, &g_tiqn_list, tiqn_list) {
+ if ((cmd->cmd_flags & IFC_SENDTARGETS_SINGLE) &&
+ strcmp(tiqn->tiqn, text_ptr)) {
+ continue;
+ }
+
len = sprintf(buf, "TargetName=%s", tiqn->tiqn);
len += 1;

@@ -3469,6 +3494,9 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
eob:
if (end_of_buf)
break;
+
+ if (cmd->cmd_flags & IFC_SENDTARGETS_SINGLE)
+ break;
}
spin_unlock(&tiqn_lock);

diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h
index ad46e73..3436a2c 100644
--- a/drivers/target/iscsi/iscsi_target_core.h
+++ b/drivers/target/iscsi/iscsi_target_core.h
@@ -134,6 +134,7 @@ enum cmd_flags_table {
ICF_OOO_CMDSN = 0x00000080,
ICF_REJECT_FAIL_CONN = 0x00000100,
IFC_SENDTARGETS_ALL = 0x00000200,
+ IFC_SENDTARGETS_SINGLE = 0x00000400,
};

/* struct iscsi_cmd->i_state */
--
1.7.2.5

Nicholas A. Bellinger

unread,
Jun 20, 2013, 4:50:05 PM6/20/13
to target-devel, Or Gerlitz, Alexander Nezhinsky, Mike Christie, Nicholas Bellinger
From: Nicholas Bellinger <n...@linux-iscsi.org>

This patch copies ISCSI_OP_TEXT payload using unsolicited payload
at &iser_rx_desc->data[0] into iscsi_cmd->text_in_ptr for usage with
outgoing isert_put_text_rsp() -> iscsit_build_text_rsp()

Cc: Or Gerlitz <oger...@mellanox.com>
Cc: Mike Christie <mich...@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <n...@linux-iscsi.org>
---
drivers/infiniband/ulp/isert/ib_isert.c | 15 ++++++++++++---
1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index c3b4e6e..dace896 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -1025,15 +1025,24 @@ isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd
{
struct iscsi_cmd *cmd = &isert_cmd->iscsi_cmd;
struct iscsi_conn *conn = isert_conn->conn;
+ u32 payload_length = ntoh24(hdr->dlength);
int rc;
+ unsigned char *text_in;

rc = iscsit_setup_text_cmd(conn, cmd, hdr);
if (rc < 0)
return rc;

- /*
- * FIXME: Add support for TEXT payload parsing
- */
+ text_in = kzalloc(payload_length, GFP_KERNEL);
+ if (!text_in) {
+ pr_err("Unable to allocate text_in of payload_length: %u\n",
+ payload_length);
+ return -ENOMEM;
+ }
+ cmd->text_in_ptr = text_in;
+
+ memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length);
+
return iscsit_process_text_cmd(conn, cmd, hdr);
}

--
1.7.2.5

Reply all
Reply to author
Forward
0 new messages