diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-06-14 19:46:16 -0400 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-06-25 01:36:29 -0400 |
commit | 64534aa79496a3bc4f750a695fe9e978ab46e91d (patch) | |
tree | 6e3bf0ab5bb001c541e76bd425742802c8c8c8b1 /drivers/target/iscsi | |
parent | 778de368964c5b7e8100cde9f549992d521e9c89 (diff) |
iscsi-target: Refactor ISCSI_OP_TEXT RX handling
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>
Diffstat (limited to 'drivers/target/iscsi')
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 158 |
1 files changed, 90 insertions, 68 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index f684627244bf..ae312c5d8a45 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -1960,45 +1960,93 @@ attach: | |||
1960 | EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd); | 1960 | EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd); |
1961 | 1961 | ||
1962 | /* #warning FIXME: Support Text Command parameters besides SendTargets */ | 1962 | /* #warning FIXME: Support Text Command parameters besides SendTargets */ |
1963 | static int iscsit_handle_text_cmd( | 1963 | int |
1964 | struct iscsi_conn *conn, | 1964 | iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, |
1965 | unsigned char *buf) | 1965 | struct iscsi_text *hdr) |
1966 | { | 1966 | { |
1967 | char *text_ptr, *text_in; | 1967 | u32 payload_length = ntoh24(hdr->dlength); |
1968 | int cmdsn_ret, niov = 0, rx_got, rx_size; | ||
1969 | u32 checksum = 0, data_crc = 0, payload_length; | ||
1970 | u32 padding = 0, pad_bytes = 0, text_length = 0; | ||
1971 | struct iscsi_cmd *cmd; | ||
1972 | struct kvec iov[3]; | ||
1973 | struct iscsi_text *hdr; | ||
1974 | |||
1975 | hdr = (struct iscsi_text *) buf; | ||
1976 | payload_length = ntoh24(hdr->dlength); | ||
1977 | 1968 | ||
1978 | if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { | 1969 | if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { |
1979 | pr_err("Unable to accept text parameter length: %u" | 1970 | pr_err("Unable to accept text parameter length: %u" |
1980 | "greater than MaxXmitDataSegmentLength %u.\n", | 1971 | "greater than MaxXmitDataSegmentLength %u.\n", |
1981 | payload_length, conn->conn_ops->MaxXmitDataSegmentLength); | 1972 | payload_length, conn->conn_ops->MaxXmitDataSegmentLength); |
1982 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 1973 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, |
1983 | buf, conn); | 1974 | 1, 0, (unsigned char *)hdr, cmd); |
1984 | } | 1975 | } |
1985 | 1976 | ||
1986 | pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," | 1977 | pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," |
1987 | " ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn, | 1978 | " ExpStatSN: 0x%08x, Length: %u\n", hdr->itt, hdr->cmdsn, |
1988 | hdr->exp_statsn, payload_length); | 1979 | hdr->exp_statsn, payload_length); |
1989 | 1980 | ||
1990 | rx_size = text_length = payload_length; | 1981 | cmd->iscsi_opcode = ISCSI_OP_TEXT; |
1991 | if (text_length) { | 1982 | cmd->i_state = ISTATE_SEND_TEXTRSP; |
1992 | text_in = kzalloc(text_length, GFP_KERNEL); | 1983 | cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); |
1984 | conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt; | ||
1985 | cmd->targ_xfer_tag = 0xFFFFFFFF; | ||
1986 | cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); | ||
1987 | cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); | ||
1988 | cmd->data_direction = DMA_NONE; | ||
1989 | |||
1990 | return 0; | ||
1991 | } | ||
1992 | EXPORT_SYMBOL(iscsit_setup_text_cmd); | ||
1993 | |||
1994 | int | ||
1995 | iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | ||
1996 | struct iscsi_text *hdr) | ||
1997 | { | ||
1998 | int cmdsn_ret; | ||
1999 | |||
2000 | spin_lock_bh(&conn->cmd_lock); | ||
2001 | list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); | ||
2002 | spin_unlock_bh(&conn->cmd_lock); | ||
2003 | |||
2004 | iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); | ||
2005 | |||
2006 | if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | ||
2007 | cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); | ||
2008 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | ||
2009 | return iscsit_add_reject_from_cmd( | ||
2010 | ISCSI_REASON_PROTOCOL_ERROR, | ||
2011 | 1, 0, (unsigned char *)hdr, cmd); | ||
2012 | return 0; | ||
2013 | } | ||
2014 | |||
2015 | return iscsit_execute_cmd(cmd, 0); | ||
2016 | } | ||
2017 | EXPORT_SYMBOL(iscsit_process_text_cmd); | ||
2018 | |||
2019 | static int | ||
2020 | iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | ||
2021 | unsigned char *buf) | ||
2022 | { | ||
2023 | struct iscsi_text *hdr = (struct iscsi_text *)buf; | ||
2024 | char *text_in = NULL; | ||
2025 | u32 payload_length = ntoh24(hdr->dlength); | ||
2026 | int rx_size, rc; | ||
2027 | |||
2028 | rc = iscsit_setup_text_cmd(conn, cmd, hdr); | ||
2029 | if (rc < 0) | ||
2030 | return rc; | ||
2031 | |||
2032 | rx_size = payload_length; | ||
2033 | if (payload_length) { | ||
2034 | char *text_ptr; | ||
2035 | u32 checksum = 0, data_crc = 0; | ||
2036 | u32 padding = 0, pad_bytes = 0; | ||
2037 | int niov = 0, rx_got; | ||
2038 | struct kvec iov[3]; | ||
2039 | |||
2040 | text_in = kzalloc(payload_length, GFP_KERNEL); | ||
1993 | if (!text_in) { | 2041 | if (!text_in) { |
1994 | pr_err("Unable to allocate memory for" | 2042 | pr_err("Unable to allocate memory for" |
1995 | " incoming text parameters\n"); | 2043 | " incoming text parameters\n"); |
1996 | return -1; | 2044 | goto reject; |
1997 | } | 2045 | } |
1998 | 2046 | ||
1999 | memset(iov, 0, 3 * sizeof(struct kvec)); | 2047 | memset(iov, 0, 3 * sizeof(struct kvec)); |
2000 | iov[niov].iov_base = text_in; | 2048 | iov[niov].iov_base = text_in; |
2001 | iov[niov++].iov_len = text_length; | 2049 | iov[niov++].iov_len = payload_length; |
2002 | 2050 | ||
2003 | padding = ((-payload_length) & 3); | 2051 | padding = ((-payload_length) & 3); |
2004 | if (padding != 0) { | 2052 | if (padding != 0) { |
@@ -2015,14 +2063,12 @@ static int iscsit_handle_text_cmd( | |||
2015 | } | 2063 | } |
2016 | 2064 | ||
2017 | rx_got = rx_data(conn, &iov[0], niov, rx_size); | 2065 | rx_got = rx_data(conn, &iov[0], niov, rx_size); |
2018 | if (rx_got != rx_size) { | 2066 | if (rx_got != rx_size) |
2019 | kfree(text_in); | 2067 | goto reject; |
2020 | return -1; | ||
2021 | } | ||
2022 | 2068 | ||
2023 | if (conn->conn_ops->DataDigest) { | 2069 | if (conn->conn_ops->DataDigest) { |
2024 | iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, | 2070 | iscsit_do_crypto_hash_buf(&conn->conn_rx_hash, |
2025 | text_in, text_length, | 2071 | text_in, payload_length, |
2026 | padding, (u8 *)&pad_bytes, | 2072 | padding, (u8 *)&pad_bytes, |
2027 | (u8 *)&data_crc); | 2073 | (u8 *)&data_crc); |
2028 | 2074 | ||
@@ -2034,8 +2080,7 @@ static int iscsit_handle_text_cmd( | |||
2034 | pr_err("Unable to recover from" | 2080 | pr_err("Unable to recover from" |
2035 | " Text Data digest failure while in" | 2081 | " Text Data digest failure while in" |
2036 | " ERL=0.\n"); | 2082 | " ERL=0.\n"); |
2037 | kfree(text_in); | 2083 | goto reject; |
2038 | return -1; | ||
2039 | } else { | 2084 | } else { |
2040 | /* | 2085 | /* |
2041 | * Silently drop this PDU and let the | 2086 | * Silently drop this PDU and let the |
@@ -2050,68 +2095,40 @@ static int iscsit_handle_text_cmd( | |||
2050 | } else { | 2095 | } else { |
2051 | pr_debug("Got CRC32C DataDigest" | 2096 | pr_debug("Got CRC32C DataDigest" |
2052 | " 0x%08x for %u bytes of text data.\n", | 2097 | " 0x%08x for %u bytes of text data.\n", |
2053 | checksum, text_length); | 2098 | checksum, payload_length); |
2054 | } | 2099 | } |
2055 | } | 2100 | } |
2056 | text_in[text_length - 1] = '\0'; | 2101 | text_in[payload_length - 1] = '\0'; |
2057 | pr_debug("Successfully read %d bytes of text" | 2102 | pr_debug("Successfully read %d bytes of text" |
2058 | " data.\n", text_length); | 2103 | " data.\n", payload_length); |
2059 | 2104 | ||
2060 | if (strncmp("SendTargets", text_in, 11) != 0) { | 2105 | if (strncmp("SendTargets", text_in, 11) != 0) { |
2061 | pr_err("Received Text Data that is not" | 2106 | pr_err("Received Text Data that is not" |
2062 | " SendTargets, cannot continue.\n"); | 2107 | " SendTargets, cannot continue.\n"); |
2063 | kfree(text_in); | 2108 | goto reject; |
2064 | return -1; | ||
2065 | } | 2109 | } |
2066 | text_ptr = strchr(text_in, '='); | 2110 | text_ptr = strchr(text_in, '='); |
2067 | if (!text_ptr) { | 2111 | if (!text_ptr) { |
2068 | pr_err("No \"=\" separator found in Text Data," | 2112 | pr_err("No \"=\" separator found in Text Data," |
2069 | " cannot continue.\n"); | 2113 | " cannot continue.\n"); |
2070 | kfree(text_in); | 2114 | goto reject; |
2071 | return -1; | ||
2072 | } | 2115 | } |
2073 | if (strncmp("=All", text_ptr, 4) != 0) { | 2116 | if (strncmp("=All", text_ptr, 4) != 0) { |
2074 | pr_err("Unable to locate All value for" | 2117 | pr_err("Unable to locate All value for" |
2075 | " SendTargets key, cannot continue.\n"); | 2118 | " SendTargets key, cannot continue.\n"); |
2076 | kfree(text_in); | 2119 | goto reject; |
2077 | return -1; | ||
2078 | } | 2120 | } |
2079 | /*#warning Support SendTargets=(iSCSI Target Name/Nothing) values. */ | ||
2080 | kfree(text_in); | 2121 | kfree(text_in); |
2081 | } | 2122 | } |
2082 | 2123 | ||
2083 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 2124 | return iscsit_process_text_cmd(conn, cmd, hdr); |
2084 | if (!cmd) | ||
2085 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | ||
2086 | 1, buf, conn); | ||
2087 | |||
2088 | cmd->iscsi_opcode = ISCSI_OP_TEXT; | ||
2089 | cmd->i_state = ISTATE_SEND_TEXTRSP; | ||
2090 | cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); | ||
2091 | conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt; | ||
2092 | cmd->targ_xfer_tag = 0xFFFFFFFF; | ||
2093 | cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); | ||
2094 | cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); | ||
2095 | cmd->data_direction = DMA_NONE; | ||
2096 | |||
2097 | spin_lock_bh(&conn->cmd_lock); | ||
2098 | list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); | ||
2099 | spin_unlock_bh(&conn->cmd_lock); | ||
2100 | |||
2101 | iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); | ||
2102 | 2125 | ||
2103 | if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | 2126 | reject: |
2104 | cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); | 2127 | kfree(text_in); |
2105 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | 2128 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, |
2106 | return iscsit_add_reject_from_cmd( | 2129 | 0, 0, buf, cmd); |
2107 | ISCSI_REASON_PROTOCOL_ERROR, | ||
2108 | 1, 0, buf, cmd); | ||
2109 | |||
2110 | return 0; | ||
2111 | } | ||
2112 | |||
2113 | return iscsit_execute_cmd(cmd, 0); | ||
2114 | } | 2130 | } |
2131 | EXPORT_SYMBOL(iscsit_handle_text_cmd); | ||
2115 | 2132 | ||
2116 | int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn) | 2133 | int iscsit_logout_closesession(struct iscsi_cmd *cmd, struct iscsi_conn *conn) |
2117 | { | 2134 | { |
@@ -3947,7 +3964,12 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3947 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); | 3964 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); |
3948 | break; | 3965 | break; |
3949 | case ISCSI_OP_TEXT: | 3966 | case ISCSI_OP_TEXT: |
3950 | ret = iscsit_handle_text_cmd(conn, buf); | 3967 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
3968 | if (!cmd) | ||
3969 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | ||
3970 | 1, buf, conn); | ||
3971 | |||
3972 | ret = iscsit_handle_text_cmd(conn, cmd, buf); | ||
3951 | break; | 3973 | break; |
3952 | case ISCSI_OP_LOGOUT: | 3974 | case ISCSI_OP_LOGOUT: |
3953 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3975 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |