aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorSagi Grimberg <sagig@mellanox.com>2015-02-09 11:07:25 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2015-02-12 14:24:29 -0500
commite4f4e8016e6823475291eb0da7cc95d0fada2237 (patch)
treed9e1bb4da2c4d3ce8f80d055055482f89d490741 /drivers/target
parent11378cdbb69521530f69072a987f7f1280747c1a (diff)
iscsi/iser-target: Support multi-sequence sendtargets text response
In case sendtargets response is larger than initiator MRDSL, we send a partial sendtargets response (setting F=0, C=1, TTT!=0xffffffff), accept a consecutive empty text message and send the rest of the payload. In case we are done, we set F=1, C=0, TTT=0xffffffff. We do that by storing the sendtargets response bytes done under the session. This patch also makes iscsit_find_cmd_from_itt public for isert. (Re-add cmd->maxcmdsn_inc and clear in iscsit_build_text_rsp - nab) Signed-off-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target.c87
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_util.h1
3 files changed, 66 insertions, 23 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 75c29b687f35..f533a0dfa4de 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1994,6 +1994,7 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1994 cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); 1994 cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
1995 cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); 1995 cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
1996 cmd->data_direction = DMA_NONE; 1996 cmd->data_direction = DMA_NONE;
1997 cmd->text_in_ptr = NULL;
1997 1998
1998 return 0; 1999 return 0;
1999} 2000}
@@ -2007,9 +2008,13 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2007 int cmdsn_ret; 2008 int cmdsn_ret;
2008 2009
2009 if (!text_in) { 2010 if (!text_in) {
2010 pr_err("Unable to locate text_in buffer for sendtargets" 2011 cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
2011 " discovery\n"); 2012 if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
2012 goto reject; 2013 pr_err("Unable to locate text_in buffer for sendtargets"
2014 " discovery\n");
2015 goto reject;
2016 }
2017 goto empty_sendtargets;
2013 } 2018 }
2014 if (strncmp("SendTargets", text_in, 11) != 0) { 2019 if (strncmp("SendTargets", text_in, 11) != 0) {
2015 pr_err("Received Text Data that is not" 2020 pr_err("Received Text Data that is not"
@@ -2036,6 +2041,7 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2036 list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); 2041 list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
2037 spin_unlock_bh(&conn->cmd_lock); 2042 spin_unlock_bh(&conn->cmd_lock);
2038 2043
2044empty_sendtargets:
2039 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); 2045 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2040 2046
2041 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { 2047 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
@@ -3385,7 +3391,8 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
3385 3391
3386static int 3392static int
3387iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, 3393iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3388 enum iscsit_transport_type network_transport) 3394 enum iscsit_transport_type network_transport,
3395 int skip_bytes, bool *completed)
3389{ 3396{
3390 char *payload = NULL; 3397 char *payload = NULL;
3391 struct iscsi_conn *conn = cmd->conn; 3398 struct iscsi_conn *conn = cmd->conn;
@@ -3476,9 +3483,16 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3476 end_of_buf = 1; 3483 end_of_buf = 1;
3477 goto eob; 3484 goto eob;
3478 } 3485 }
3479 memcpy(payload + payload_len, buf, len); 3486
3480 payload_len += len; 3487 if (skip_bytes && len <= skip_bytes) {
3481 target_name_printed = 1; 3488 skip_bytes -= len;
3489 } else {
3490 memcpy(payload + payload_len, buf, len);
3491 payload_len += len;
3492 target_name_printed = 1;
3493 if (len > skip_bytes)
3494 skip_bytes = 0;
3495 }
3482 } 3496 }
3483 3497
3484 len = sprintf(buf, "TargetAddress=" 3498 len = sprintf(buf, "TargetAddress="
@@ -3494,15 +3508,24 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
3494 end_of_buf = 1; 3508 end_of_buf = 1;
3495 goto eob; 3509 goto eob;
3496 } 3510 }
3497 memcpy(payload + payload_len, buf, len); 3511
3498 payload_len += len; 3512 if (skip_bytes && len <= skip_bytes) {
3513 skip_bytes -= len;
3514 } else {
3515 memcpy(payload + payload_len, buf, len);
3516 payload_len += len;
3517 if (len > skip_bytes)
3518 skip_bytes = 0;
3519 }
3499 } 3520 }
3500 spin_unlock(&tpg->tpg_np_lock); 3521 spin_unlock(&tpg->tpg_np_lock);
3501 } 3522 }
3502 spin_unlock(&tiqn->tiqn_tpg_lock); 3523 spin_unlock(&tiqn->tiqn_tpg_lock);
3503eob: 3524eob:
3504 if (end_of_buf) 3525 if (end_of_buf) {
3526 *completed = false;
3505 break; 3527 break;
3528 }
3506 3529
3507 if (cmd->cmd_flags & IFC_SENDTARGETS_SINGLE) 3530 if (cmd->cmd_flags & IFC_SENDTARGETS_SINGLE)
3508 break; 3531 break;
@@ -3520,13 +3543,23 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
3520 enum iscsit_transport_type network_transport) 3543 enum iscsit_transport_type network_transport)
3521{ 3544{
3522 int text_length, padding; 3545 int text_length, padding;
3546 bool completed = true;
3523 3547
3524 text_length = iscsit_build_sendtargets_response(cmd, network_transport); 3548 text_length = iscsit_build_sendtargets_response(cmd, network_transport,
3549 cmd->read_data_done,
3550 &completed);
3525 if (text_length < 0) 3551 if (text_length < 0)
3526 return text_length; 3552 return text_length;
3527 3553
3554 if (completed) {
3555 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
3556 } else {
3557 hdr->flags |= ISCSI_FLAG_TEXT_CONTINUE;
3558 cmd->read_data_done += text_length;
3559 if (cmd->targ_xfer_tag == 0xFFFFFFFF)
3560 cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
3561 }
3528 hdr->opcode = ISCSI_OP_TEXT_RSP; 3562 hdr->opcode = ISCSI_OP_TEXT_RSP;
3529 hdr->flags |= ISCSI_FLAG_CMD_FINAL;
3530 padding = ((-text_length) & 3); 3563 padding = ((-text_length) & 3);
3531 hton24(hdr->dlength, text_length); 3564 hton24(hdr->dlength, text_length);
3532 hdr->itt = cmd->init_task_tag; 3565 hdr->itt = cmd->init_task_tag;
@@ -3535,21 +3568,25 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
3535 hdr->statsn = cpu_to_be32(cmd->stat_sn); 3568 hdr->statsn = cpu_to_be32(cmd->stat_sn);
3536 3569
3537 iscsit_increment_maxcmdsn(cmd, conn->sess); 3570 iscsit_increment_maxcmdsn(cmd, conn->sess);
3571 /*
3572 * Reset maxcmdsn_inc in multi-part text payload exchanges to
3573 * correctly increment MaxCmdSN for each response answering a
3574 * non immediate text request with a valid CmdSN.
3575 */
3576 cmd->maxcmdsn_inc = 0;
3538 hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); 3577 hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
3539 hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); 3578 hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
3540 3579
3541 pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x," 3580 pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
3542 " Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn, 3581 " Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
3543 text_length, conn->cid); 3582 cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
3583 !!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
3584 !!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
3544 3585
3545 return text_length + padding; 3586 return text_length + padding;
3546} 3587}
3547EXPORT_SYMBOL(iscsit_build_text_rsp); 3588EXPORT_SYMBOL(iscsit_build_text_rsp);
3548 3589
3549/*
3550 * FIXME: Add support for F_BIT and C_BIT when the length is longer than
3551 * MaxRecvDataSegmentLength.
3552 */
3553static int iscsit_send_text_rsp( 3590static int iscsit_send_text_rsp(
3554 struct iscsi_cmd *cmd, 3591 struct iscsi_cmd *cmd,
3555 struct iscsi_conn *conn) 3592 struct iscsi_conn *conn)
@@ -4013,9 +4050,15 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
4013 ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); 4050 ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
4014 break; 4051 break;
4015 case ISCSI_OP_TEXT: 4052 case ISCSI_OP_TEXT:
4016 cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); 4053 if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
4017 if (!cmd) 4054 cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
4018 goto reject; 4055 if (!cmd)
4056 goto reject;
4057 } else {
4058 cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
4059 if (!cmd)
4060 goto reject;
4061 }
4019 4062
4020 ret = iscsit_handle_text_cmd(conn, cmd, buf); 4063 ret = iscsit_handle_text_cmd(conn, cmd, buf);
4021 break; 4064 break;
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index c211d3f2726c..390df8ed72b2 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -390,6 +390,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
390 init_task_tag, conn->cid); 390 init_task_tag, conn->cid);
391 return NULL; 391 return NULL;
392} 392}
393EXPORT_SYMBOL(iscsit_find_cmd_from_itt);
393 394
394struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump( 395struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
395 struct iscsi_conn *conn, 396 struct iscsi_conn *conn,
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
index a68508c4fec8..1ab754a671ff 100644
--- a/drivers/target/iscsi/iscsi_target_util.h
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -16,7 +16,6 @@ extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
16extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, 16extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
17 unsigned char * ,__be32 cmdsn); 17 unsigned char * ,__be32 cmdsn);
18extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *); 18extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
19extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
20extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *, 19extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
21 itt_t, u32); 20 itt_t, u32);
22extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, u32); 21extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, u32);