iscsi-target: Refactor ISCSI_OP_TEXT RX handling
authorNicholas Bellinger <nab@linux-iscsi.org>
Fri, 14 Jun 2013 23:46:16 +0000 (16:46 -0700)
committerNicholas Bellinger <nab@linux-iscsi.org>
Tue, 25 Jun 2013 05:36:29 +0000 (22:36 -0700)
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 <ogerlitz@mellanox.com>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
drivers/target/iscsi/iscsi_target.c
include/target/iscsi/iscsi_transport.h

index f684627244bfc27f62e1c9439847cc07a3fbdc1d..ae312c5d8a450ebac4169825f4121ab1a3b7390d 100644 (file)
@@ -1960,45 +1960,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) {
@@ -2015,14 +2063,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);
 
@@ -2034,8 +2080,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
@@ -2050,68 +2095,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)
 {
@@ -3947,7 +3964,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);
index ecb53ea6d1c7b8da15dba2cfb3fdf8df8a1cad6e..90f3b60d30c42c10e809a468dd12eb6cd151bd69 100644 (file)
@@ -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 *,