.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /******************************************************************************* |
---|
2 | 3 | * This file contains main functions related to the iSCSI Target Core Driver. |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * |
---|
6 | 7 | * Author: Nicholas A. Bellinger <nab@linux-iscsi.org> |
---|
7 | 8 | * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
11 | | - * (at your option) any later version. |
---|
12 | | - * |
---|
13 | | - * This program is distributed in the hope that it will be useful, |
---|
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
16 | | - * GNU General Public License for more details. |
---|
17 | 9 | ******************************************************************************/ |
---|
18 | 10 | |
---|
19 | 11 | #include <crypto/hash.h> |
---|
.. | .. |
---|
308 | 300 | return false; |
---|
309 | 301 | } |
---|
310 | 302 | |
---|
311 | | -/* |
---|
312 | | - * Called with mutex np_lock held |
---|
313 | | - */ |
---|
314 | 303 | static struct iscsi_np *iscsit_get_np( |
---|
315 | 304 | struct sockaddr_storage *sockaddr, |
---|
316 | 305 | int network_transport) |
---|
317 | 306 | { |
---|
318 | 307 | struct iscsi_np *np; |
---|
319 | 308 | bool match; |
---|
| 309 | + |
---|
| 310 | + lockdep_assert_held(&np_lock); |
---|
320 | 311 | |
---|
321 | 312 | list_for_each_entry(np, &g_np_list, np_list) { |
---|
322 | 313 | spin_lock_bh(&np->np_thread_lock); |
---|
.. | .. |
---|
573 | 564 | return 0; |
---|
574 | 565 | } |
---|
575 | 566 | |
---|
576 | | -static int iscsit_map_iovec(struct iscsi_cmd *, struct kvec *, u32, u32); |
---|
| 567 | +static int iscsit_map_iovec(struct iscsi_cmd *cmd, struct kvec *iov, int nvec, |
---|
| 568 | + u32 data_offset, u32 data_length); |
---|
577 | 569 | static void iscsit_unmap_iovec(struct iscsi_cmd *); |
---|
578 | 570 | static u32 iscsit_do_crypto_hash_sg(struct ahash_request *, struct iscsi_cmd *, |
---|
579 | 571 | u32, u32, u32, u8 *); |
---|
.. | .. |
---|
604 | 596 | *header_digest); |
---|
605 | 597 | } |
---|
606 | 598 | |
---|
607 | | - iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1], |
---|
| 599 | + iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[iov_count], |
---|
| 600 | + cmd->orig_iov_data_count - (iov_count + 2), |
---|
608 | 601 | datain->offset, datain->length); |
---|
609 | 602 | if (iov_ret < 0) |
---|
610 | 603 | return -1; |
---|
.. | .. |
---|
713 | 706 | sizeof(struct iscsi_queue_req), |
---|
714 | 707 | __alignof__(struct iscsi_queue_req), 0, NULL); |
---|
715 | 708 | if (!lio_qr_cache) { |
---|
716 | | - pr_err("nable to kmem_cache_create() for" |
---|
| 709 | + pr_err("Unable to kmem_cache_create() for" |
---|
717 | 710 | " lio_qr_cache\n"); |
---|
718 | 711 | goto bitmap_out; |
---|
719 | 712 | } |
---|
.. | .. |
---|
886 | 879 | * Map some portion of the allocated scatterlist to an iovec, suitable for |
---|
887 | 880 | * kernel sockets to copy data in/out. |
---|
888 | 881 | */ |
---|
889 | | -static int iscsit_map_iovec( |
---|
890 | | - struct iscsi_cmd *cmd, |
---|
891 | | - struct kvec *iov, |
---|
892 | | - u32 data_offset, |
---|
893 | | - u32 data_length) |
---|
| 882 | +static int iscsit_map_iovec(struct iscsi_cmd *cmd, struct kvec *iov, int nvec, |
---|
| 883 | + u32 data_offset, u32 data_length) |
---|
894 | 884 | { |
---|
895 | | - u32 i = 0; |
---|
| 885 | + u32 i = 0, orig_data_length = data_length; |
---|
896 | 886 | struct scatterlist *sg; |
---|
897 | 887 | unsigned int page_off; |
---|
898 | 888 | |
---|
.. | .. |
---|
901 | 891 | */ |
---|
902 | 892 | u32 ent = data_offset / PAGE_SIZE; |
---|
903 | 893 | |
---|
| 894 | + if (!data_length) |
---|
| 895 | + return 0; |
---|
| 896 | + |
---|
904 | 897 | if (ent >= cmd->se_cmd.t_data_nents) { |
---|
905 | 898 | pr_err("Initial page entry out-of-bounds\n"); |
---|
906 | | - return -1; |
---|
| 899 | + goto overflow; |
---|
907 | 900 | } |
---|
908 | 901 | |
---|
909 | 902 | sg = &cmd->se_cmd.t_data_sg[ent]; |
---|
.. | .. |
---|
913 | 906 | cmd->first_data_sg_off = page_off; |
---|
914 | 907 | |
---|
915 | 908 | while (data_length) { |
---|
916 | | - u32 cur_len = min_t(u32, data_length, sg->length - page_off); |
---|
| 909 | + u32 cur_len; |
---|
| 910 | + |
---|
| 911 | + if (WARN_ON_ONCE(!sg || i >= nvec)) |
---|
| 912 | + goto overflow; |
---|
| 913 | + |
---|
| 914 | + cur_len = min_t(u32, data_length, sg->length - page_off); |
---|
917 | 915 | |
---|
918 | 916 | iov[i].iov_base = kmap(sg_page(sg)) + sg->offset + page_off; |
---|
919 | 917 | iov[i].iov_len = cur_len; |
---|
.. | .. |
---|
927 | 925 | cmd->kmapped_nents = i; |
---|
928 | 926 | |
---|
929 | 927 | return i; |
---|
| 928 | + |
---|
| 929 | +overflow: |
---|
| 930 | + pr_err("offset %d + length %d overflow; %d/%d; sg-list:\n", |
---|
| 931 | + data_offset, orig_data_length, i, nvec); |
---|
| 932 | + for_each_sg(cmd->se_cmd.t_data_sg, sg, |
---|
| 933 | + cmd->se_cmd.t_data_nents, i) { |
---|
| 934 | + pr_err("[%d] off %d len %d\n", |
---|
| 935 | + i, sg->offset, sg->length); |
---|
| 936 | + } |
---|
| 937 | + return -1; |
---|
930 | 938 | } |
---|
931 | 939 | |
---|
932 | 940 | static void iscsit_unmap_iovec(struct iscsi_cmd *cmd) |
---|
.. | .. |
---|
1149 | 1157 | transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops, |
---|
1150 | 1158 | conn->sess->se_sess, be32_to_cpu(hdr->data_length), |
---|
1151 | 1159 | cmd->data_direction, sam_task_attr, |
---|
1152 | | - cmd->sense_buffer + 2); |
---|
| 1160 | + cmd->sense_buffer + 2, scsilun_to_int(&hdr->lun)); |
---|
1153 | 1161 | |
---|
1154 | 1162 | pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x," |
---|
1155 | 1163 | " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, |
---|
.. | .. |
---|
1158 | 1166 | |
---|
1159 | 1167 | target_get_sess_cmd(&cmd->se_cmd, true); |
---|
1160 | 1168 | |
---|
1161 | | - cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, |
---|
1162 | | - scsilun_to_int(&hdr->lun)); |
---|
1163 | | - if (cmd->sense_reason) |
---|
1164 | | - goto attach_cmd; |
---|
1165 | | - |
---|
1166 | | - /* only used for printks or comparing with ->ref_task_tag */ |
---|
1167 | 1169 | cmd->se_cmd.tag = (__force u32)cmd->init_task_tag; |
---|
1168 | | - cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); |
---|
| 1170 | + cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, hdr->cdb); |
---|
1169 | 1171 | if (cmd->sense_reason) { |
---|
1170 | 1172 | if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { |
---|
1171 | 1173 | return iscsit_add_reject_cmd(cmd, |
---|
1172 | | - ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
---|
| 1174 | + ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
---|
1173 | 1175 | } |
---|
1174 | 1176 | |
---|
1175 | 1177 | goto attach_cmd; |
---|
1176 | 1178 | } |
---|
| 1179 | + |
---|
| 1180 | + cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd); |
---|
| 1181 | + if (cmd->sense_reason) |
---|
| 1182 | + goto attach_cmd; |
---|
| 1183 | + |
---|
| 1184 | + cmd->sense_reason = target_cmd_parse_cdb(&cmd->se_cmd); |
---|
| 1185 | + if (cmd->sense_reason) |
---|
| 1186 | + goto attach_cmd; |
---|
1177 | 1187 | |
---|
1178 | 1188 | if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { |
---|
1179 | 1189 | return iscsit_add_reject_cmd(cmd, |
---|
.. | .. |
---|
1194 | 1204 | } |
---|
1195 | 1205 | EXPORT_SYMBOL(iscsit_setup_scsi_cmd); |
---|
1196 | 1206 | |
---|
1197 | | -void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd) |
---|
| 1207 | +void iscsit_set_unsolicited_dataout(struct iscsi_cmd *cmd) |
---|
1198 | 1208 | { |
---|
1199 | 1209 | iscsit_set_dataout_sequence_values(cmd); |
---|
1200 | 1210 | |
---|
.. | .. |
---|
1202 | 1212 | iscsit_start_dataout_timer(cmd, cmd->conn); |
---|
1203 | 1213 | spin_unlock_bh(&cmd->dataout_timeout_lock); |
---|
1204 | 1214 | } |
---|
1205 | | -EXPORT_SYMBOL(iscsit_set_unsoliticed_dataout); |
---|
| 1215 | +EXPORT_SYMBOL(iscsit_set_unsolicited_dataout); |
---|
1206 | 1216 | |
---|
1207 | 1217 | int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, |
---|
1208 | 1218 | struct iscsi_scsi_req *hdr) |
---|
.. | .. |
---|
1236 | 1246 | */ |
---|
1237 | 1247 | if (!cmd->immediate_data) { |
---|
1238 | 1248 | if (!cmd->sense_reason && cmd->unsolicited_data) |
---|
1239 | | - iscsit_set_unsoliticed_dataout(cmd); |
---|
| 1249 | + iscsit_set_unsolicited_dataout(cmd); |
---|
1240 | 1250 | if (!cmd->sense_reason) |
---|
1241 | 1251 | return 0; |
---|
1242 | 1252 | |
---|
.. | .. |
---|
1268 | 1278 | bool dump_payload) |
---|
1269 | 1279 | { |
---|
1270 | 1280 | int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; |
---|
| 1281 | + int rc; |
---|
| 1282 | + |
---|
1271 | 1283 | /* |
---|
1272 | 1284 | * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. |
---|
1273 | 1285 | */ |
---|
1274 | | - if (dump_payload) |
---|
1275 | | - goto after_immediate_data; |
---|
1276 | | - /* |
---|
1277 | | - * Check for underflow case where both EDTL and immediate data payload |
---|
1278 | | - * exceeds what is presented by CDB's TRANSFER LENGTH, and what has |
---|
1279 | | - * already been set in target_cmd_size_check() as se_cmd->data_length. |
---|
1280 | | - * |
---|
1281 | | - * For this special case, fail the command and dump the immediate data |
---|
1282 | | - * payload. |
---|
1283 | | - */ |
---|
1284 | | - if (cmd->first_burst_len > cmd->se_cmd.data_length) { |
---|
1285 | | - cmd->sense_reason = TCM_INVALID_CDB_FIELD; |
---|
1286 | | - goto after_immediate_data; |
---|
| 1286 | + if (dump_payload) { |
---|
| 1287 | + u32 length = min(cmd->se_cmd.data_length - cmd->write_data_done, |
---|
| 1288 | + cmd->first_burst_len); |
---|
| 1289 | + |
---|
| 1290 | + pr_debug("Dumping min(%d - %d, %d) = %d bytes of immediate data\n", |
---|
| 1291 | + cmd->se_cmd.data_length, cmd->write_data_done, |
---|
| 1292 | + cmd->first_burst_len, length); |
---|
| 1293 | + rc = iscsit_dump_data_payload(cmd->conn, length, 1); |
---|
| 1294 | + pr_debug("Finished dumping immediate data\n"); |
---|
| 1295 | + if (rc < 0) |
---|
| 1296 | + immed_ret = IMMEDIATE_DATA_CANNOT_RECOVER; |
---|
| 1297 | + } else { |
---|
| 1298 | + immed_ret = iscsit_handle_immediate_data(cmd, hdr, |
---|
| 1299 | + cmd->first_burst_len); |
---|
1287 | 1300 | } |
---|
1288 | 1301 | |
---|
1289 | | - immed_ret = iscsit_handle_immediate_data(cmd, hdr, |
---|
1290 | | - cmd->first_burst_len); |
---|
1291 | | -after_immediate_data: |
---|
1292 | 1302 | if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) { |
---|
1293 | 1303 | /* |
---|
1294 | 1304 | * A PDU/CmdSN carrying Immediate Data passed |
---|
.. | .. |
---|
1301 | 1311 | return -1; |
---|
1302 | 1312 | |
---|
1303 | 1313 | if (cmd->sense_reason || cmdsn_ret == CMDSN_LOWER_THAN_EXP) { |
---|
1304 | | - int rc; |
---|
1305 | | - |
---|
1306 | | - rc = iscsit_dump_data_payload(cmd->conn, |
---|
1307 | | - cmd->first_burst_len, 1); |
---|
1308 | 1314 | target_put_sess_cmd(&cmd->se_cmd); |
---|
1309 | | - return rc; |
---|
| 1315 | + |
---|
| 1316 | + return 0; |
---|
1310 | 1317 | } else if (cmd->unsolicited_data) |
---|
1311 | | - iscsit_set_unsoliticed_dataout(cmd); |
---|
| 1318 | + iscsit_set_unsolicited_dataout(cmd); |
---|
1312 | 1319 | |
---|
1313 | 1320 | } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { |
---|
1314 | 1321 | /* |
---|
.. | .. |
---|
1505 | 1512 | if (hdr->flags & ISCSI_FLAG_CMD_FINAL) |
---|
1506 | 1513 | iscsit_stop_dataout_timer(cmd); |
---|
1507 | 1514 | |
---|
1508 | | - transport_check_aborted_status(se_cmd, |
---|
1509 | | - (hdr->flags & ISCSI_FLAG_CMD_FINAL)); |
---|
1510 | 1515 | return iscsit_dump_data_payload(conn, payload_length, 1); |
---|
1511 | 1516 | } |
---|
1512 | 1517 | } else { |
---|
.. | .. |
---|
1521 | 1526 | * TASK_ABORTED status. |
---|
1522 | 1527 | */ |
---|
1523 | 1528 | if (se_cmd->transport_state & CMD_T_ABORTED) { |
---|
1524 | | - if (hdr->flags & ISCSI_FLAG_CMD_FINAL) |
---|
1525 | | - if (--cmd->outstanding_r2ts < 1) { |
---|
1526 | | - iscsit_stop_dataout_timer(cmd); |
---|
1527 | | - transport_check_aborted_status( |
---|
1528 | | - se_cmd, 1); |
---|
1529 | | - } |
---|
| 1529 | + if (hdr->flags & ISCSI_FLAG_CMD_FINAL && |
---|
| 1530 | + --cmd->outstanding_r2ts < 1) |
---|
| 1531 | + iscsit_stop_dataout_timer(cmd); |
---|
1530 | 1532 | |
---|
1531 | 1533 | return iscsit_dump_data_payload(conn, payload_length, 1); |
---|
1532 | 1534 | } |
---|
.. | .. |
---|
1586 | 1588 | { |
---|
1587 | 1589 | struct kvec *iov; |
---|
1588 | 1590 | u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0; |
---|
1589 | | - u32 payload_length = ntoh24(hdr->dlength); |
---|
| 1591 | + u32 payload_length; |
---|
1590 | 1592 | int iov_ret, data_crc_failed = 0; |
---|
1591 | 1593 | |
---|
| 1594 | + payload_length = min_t(u32, cmd->se_cmd.data_length, |
---|
| 1595 | + ntoh24(hdr->dlength)); |
---|
1592 | 1596 | rx_size += payload_length; |
---|
1593 | 1597 | iov = &cmd->iov_data[0]; |
---|
1594 | 1598 | |
---|
1595 | | - iov_ret = iscsit_map_iovec(cmd, iov, be32_to_cpu(hdr->offset), |
---|
1596 | | - payload_length); |
---|
| 1599 | + iov_ret = iscsit_map_iovec(cmd, iov, cmd->orig_iov_data_count - 2, |
---|
| 1600 | + be32_to_cpu(hdr->offset), payload_length); |
---|
1597 | 1601 | if (iov_ret < 0) |
---|
1598 | 1602 | return -1; |
---|
1599 | 1603 | |
---|
.. | .. |
---|
1613 | 1617 | rx_size += ISCSI_CRC_LEN; |
---|
1614 | 1618 | } |
---|
1615 | 1619 | |
---|
| 1620 | + WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count); |
---|
1616 | 1621 | rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size); |
---|
1617 | 1622 | |
---|
1618 | 1623 | iscsit_unmap_iovec(cmd); |
---|
.. | .. |
---|
1878 | 1883 | rx_size += ISCSI_CRC_LEN; |
---|
1879 | 1884 | } |
---|
1880 | 1885 | |
---|
| 1886 | + WARN_ON_ONCE(niov > ARRAY_SIZE(cmd->iov_misc)); |
---|
1881 | 1887 | rx_got = rx_data(conn, &cmd->iov_misc[0], niov, rx_size); |
---|
1882 | 1888 | if (rx_got != rx_size) { |
---|
1883 | 1889 | ret = -1; |
---|
.. | .. |
---|
2008 | 2014 | |
---|
2009 | 2015 | transport_init_se_cmd(&cmd->se_cmd, &iscsi_ops, |
---|
2010 | 2016 | conn->sess->se_sess, 0, DMA_NONE, |
---|
2011 | | - TCM_SIMPLE_TAG, cmd->sense_buffer + 2); |
---|
| 2017 | + TCM_SIMPLE_TAG, cmd->sense_buffer + 2, |
---|
| 2018 | + scsilun_to_int(&hdr->lun)); |
---|
2012 | 2019 | |
---|
2013 | 2020 | target_get_sess_cmd(&cmd->se_cmd, true); |
---|
2014 | 2021 | |
---|
.. | .. |
---|
2046 | 2053 | * Locate the struct se_lun for all TMRs not related to ERL=2 TASK_REASSIGN |
---|
2047 | 2054 | */ |
---|
2048 | 2055 | if (function != ISCSI_TM_FUNC_TASK_REASSIGN) { |
---|
2049 | | - ret = transport_lookup_tmr_lun(&cmd->se_cmd, |
---|
2050 | | - scsilun_to_int(&hdr->lun)); |
---|
| 2056 | + ret = transport_lookup_tmr_lun(&cmd->se_cmd); |
---|
2051 | 2057 | if (ret < 0) { |
---|
2052 | 2058 | se_tmr->response = ISCSI_TMF_RSP_NO_LUN; |
---|
2053 | 2059 | goto attach; |
---|
.. | .. |
---|
2197 | 2203 | } |
---|
2198 | 2204 | goto empty_sendtargets; |
---|
2199 | 2205 | } |
---|
2200 | | - if (strncmp("SendTargets", text_in, 11) != 0) { |
---|
| 2206 | + if (strncmp("SendTargets=", text_in, 12) != 0) { |
---|
2201 | 2207 | pr_err("Received Text Data that is not" |
---|
2202 | 2208 | " SendTargets, cannot continue.\n"); |
---|
2203 | 2209 | goto reject; |
---|
2204 | 2210 | } |
---|
| 2211 | + /* '=' confirmed in strncmp */ |
---|
2205 | 2212 | text_ptr = strchr(text_in, '='); |
---|
2206 | | - if (!text_ptr) { |
---|
2207 | | - pr_err("No \"=\" separator found in Text Data," |
---|
2208 | | - " cannot continue.\n"); |
---|
2209 | | - goto reject; |
---|
2210 | | - } |
---|
2211 | | - if (!strncmp("=All", text_ptr, 4)) { |
---|
| 2213 | + BUG_ON(!text_ptr); |
---|
| 2214 | + if (!strncmp("=All", text_ptr, 5)) { |
---|
2212 | 2215 | cmd->cmd_flags |= ICF_SENDTARGETS_ALL; |
---|
2213 | 2216 | } else if (!strncmp("=iqn.", text_ptr, 5) || |
---|
2214 | 2217 | !strncmp("=eui.", text_ptr, 5)) { |
---|
2215 | 2218 | cmd->cmd_flags |= ICF_SENDTARGETS_SINGLE; |
---|
2216 | 2219 | } else { |
---|
2217 | | - pr_err("Unable to locate valid SendTargets=%s value\n", text_ptr); |
---|
| 2220 | + pr_err("Unable to locate valid SendTargets%s value\n", |
---|
| 2221 | + text_ptr); |
---|
2218 | 2222 | goto reject; |
---|
2219 | 2223 | } |
---|
2220 | 2224 | |
---|
.. | .. |
---|
2258 | 2262 | rx_size = payload_length; |
---|
2259 | 2263 | if (payload_length) { |
---|
2260 | 2264 | u32 checksum = 0, data_crc = 0; |
---|
2261 | | - u32 padding = 0, pad_bytes = 0; |
---|
| 2265 | + u32 padding = 0; |
---|
2262 | 2266 | int niov = 0, rx_got; |
---|
2263 | | - struct kvec iov[3]; |
---|
| 2267 | + struct kvec iov[2]; |
---|
2264 | 2268 | |
---|
2265 | | - text_in = kzalloc(payload_length, GFP_KERNEL); |
---|
| 2269 | + rx_size = ALIGN(payload_length, 4); |
---|
| 2270 | + text_in = kzalloc(rx_size, GFP_KERNEL); |
---|
2266 | 2271 | if (!text_in) |
---|
2267 | 2272 | goto reject; |
---|
2268 | 2273 | |
---|
2269 | 2274 | cmd->text_in_ptr = text_in; |
---|
2270 | 2275 | |
---|
2271 | | - memset(iov, 0, 3 * sizeof(struct kvec)); |
---|
| 2276 | + memset(iov, 0, sizeof(iov)); |
---|
2272 | 2277 | iov[niov].iov_base = text_in; |
---|
2273 | | - iov[niov++].iov_len = payload_length; |
---|
| 2278 | + iov[niov++].iov_len = rx_size; |
---|
2274 | 2279 | |
---|
2275 | | - padding = ((-payload_length) & 3); |
---|
2276 | | - if (padding != 0) { |
---|
2277 | | - iov[niov].iov_base = &pad_bytes; |
---|
2278 | | - iov[niov++].iov_len = padding; |
---|
2279 | | - rx_size += padding; |
---|
| 2280 | + padding = rx_size - payload_length; |
---|
| 2281 | + if (padding) |
---|
2280 | 2282 | pr_debug("Receiving %u additional bytes" |
---|
2281 | 2283 | " for padding.\n", padding); |
---|
2282 | | - } |
---|
2283 | 2284 | if (conn->conn_ops->DataDigest) { |
---|
2284 | 2285 | iov[niov].iov_base = &checksum; |
---|
2285 | 2286 | iov[niov++].iov_len = ISCSI_CRC_LEN; |
---|
2286 | 2287 | rx_size += ISCSI_CRC_LEN; |
---|
2287 | 2288 | } |
---|
2288 | 2289 | |
---|
| 2290 | + WARN_ON_ONCE(niov > ARRAY_SIZE(iov)); |
---|
2289 | 2291 | rx_got = rx_data(conn, &iov[0], niov, rx_size); |
---|
2290 | 2292 | if (rx_got != rx_size) |
---|
2291 | 2293 | goto reject; |
---|
2292 | 2294 | |
---|
2293 | 2295 | if (conn->conn_ops->DataDigest) { |
---|
2294 | | - iscsit_do_crypto_hash_buf(conn->conn_rx_hash, text_in, |
---|
2295 | | - payload_length, padding, |
---|
2296 | | - &pad_bytes, &data_crc); |
---|
| 2296 | + iscsit_do_crypto_hash_buf(conn->conn_rx_hash, |
---|
| 2297 | + text_in, rx_size, 0, NULL, |
---|
| 2298 | + &data_crc); |
---|
2297 | 2299 | |
---|
2298 | 2300 | if (checksum != data_crc) { |
---|
2299 | 2301 | pr_err("Text data CRC32C DataDigest" |
---|
.. | .. |
---|
2596 | 2598 | u32 checksum, iov_count = 0, padding = 0; |
---|
2597 | 2599 | struct iscsi_conn *conn = cmd->conn; |
---|
2598 | 2600 | struct kvec *iov; |
---|
| 2601 | + void *overflow_buf = NULL; |
---|
2599 | 2602 | |
---|
2600 | | - iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done, length); |
---|
| 2603 | + BUG_ON(cmd->write_data_done > cmd->se_cmd.data_length); |
---|
| 2604 | + rx_size = min(cmd->se_cmd.data_length - cmd->write_data_done, length); |
---|
| 2605 | + iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, |
---|
| 2606 | + cmd->orig_iov_data_count - 2, |
---|
| 2607 | + cmd->write_data_done, rx_size); |
---|
2601 | 2608 | if (iov_ret < 0) |
---|
2602 | 2609 | return IMMEDIATE_DATA_CANNOT_RECOVER; |
---|
2603 | 2610 | |
---|
2604 | | - rx_size = length; |
---|
2605 | 2611 | iov_count = iov_ret; |
---|
2606 | 2612 | iov = &cmd->iov_data[0]; |
---|
| 2613 | + if (rx_size < length) { |
---|
| 2614 | + /* |
---|
| 2615 | + * Special case: length of immediate data exceeds the data |
---|
| 2616 | + * buffer size derived from the CDB. |
---|
| 2617 | + */ |
---|
| 2618 | + overflow_buf = kmalloc(length - rx_size, GFP_KERNEL); |
---|
| 2619 | + if (!overflow_buf) { |
---|
| 2620 | + iscsit_unmap_iovec(cmd); |
---|
| 2621 | + return IMMEDIATE_DATA_CANNOT_RECOVER; |
---|
| 2622 | + } |
---|
| 2623 | + cmd->overflow_buf = overflow_buf; |
---|
| 2624 | + iov[iov_count].iov_base = overflow_buf; |
---|
| 2625 | + iov[iov_count].iov_len = length - rx_size; |
---|
| 2626 | + iov_count++; |
---|
| 2627 | + rx_size = length; |
---|
| 2628 | + } |
---|
2607 | 2629 | |
---|
2608 | 2630 | padding = ((-length) & 3); |
---|
2609 | 2631 | if (padding != 0) { |
---|
.. | .. |
---|
2618 | 2640 | rx_size += ISCSI_CRC_LEN; |
---|
2619 | 2641 | } |
---|
2620 | 2642 | |
---|
| 2643 | + WARN_ON_ONCE(iov_count > cmd->orig_iov_data_count); |
---|
2621 | 2644 | rx_got = rx_data(conn, &cmd->iov_data[0], iov_count, rx_size); |
---|
2622 | 2645 | |
---|
2623 | 2646 | iscsit_unmap_iovec(cmd); |
---|
.. | .. |
---|
2672 | 2695 | return IMMEDIATE_DATA_NORMAL_OPERATION; |
---|
2673 | 2696 | } |
---|
2674 | 2697 | |
---|
2675 | | -/* |
---|
2676 | | - * Called with sess->conn_lock held. |
---|
2677 | | - */ |
---|
2678 | 2698 | /* #warning iscsi_build_conn_drop_async_message() only sends out on connections |
---|
2679 | 2699 | with active network interface */ |
---|
2680 | 2700 | static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) |
---|
.. | .. |
---|
2682 | 2702 | struct iscsi_cmd *cmd; |
---|
2683 | 2703 | struct iscsi_conn *conn_p; |
---|
2684 | 2704 | bool found = false; |
---|
| 2705 | + |
---|
| 2706 | + lockdep_assert_held(&conn->sess->conn_lock); |
---|
2685 | 2707 | |
---|
2686 | 2708 | /* |
---|
2687 | 2709 | * Only send a Asynchronous Message on connections whos network |
---|
.. | .. |
---|
3143 | 3165 | else |
---|
3144 | 3166 | xfer_len = conn->sess->sess_ops->MaxBurstLength; |
---|
3145 | 3167 | } |
---|
| 3168 | + |
---|
| 3169 | + if ((s32)xfer_len < 0) { |
---|
| 3170 | + cmd->cmd_flags |= ICF_SENT_LAST_R2T; |
---|
| 3171 | + break; |
---|
| 3172 | + } |
---|
| 3173 | + |
---|
3146 | 3174 | cmd->r2t_offset += xfer_len; |
---|
3147 | 3175 | |
---|
3148 | 3176 | if (cmd->r2t_offset == cmd->se_cmd.data_length) |
---|
.. | .. |
---|
3723 | 3751 | case ISTATE_SEND_LOGOUTRSP: |
---|
3724 | 3752 | if (!iscsit_logout_post_handler(cmd, conn)) |
---|
3725 | 3753 | return -ECONNRESET; |
---|
3726 | | - /* fall through */ |
---|
| 3754 | + fallthrough; |
---|
3727 | 3755 | case ISTATE_SEND_STATUS: |
---|
3728 | 3756 | case ISTATE_SEND_ASYNCMSG: |
---|
3729 | 3757 | case ISTATE_SEND_NOPIN: |
---|
.. | .. |
---|
4056 | 4084 | list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { |
---|
4057 | 4085 | struct se_cmd *se_cmd = &cmd->se_cmd; |
---|
4058 | 4086 | |
---|
4059 | | - if (se_cmd->se_tfo != NULL) { |
---|
4060 | | - spin_lock_irq(&se_cmd->t_state_lock); |
---|
4061 | | - if (se_cmd->transport_state & CMD_T_ABORTED) { |
---|
| 4087 | + if (!se_cmd->se_tfo) |
---|
| 4088 | + continue; |
---|
| 4089 | + |
---|
| 4090 | + spin_lock_irq(&se_cmd->t_state_lock); |
---|
| 4091 | + if (se_cmd->transport_state & CMD_T_ABORTED) { |
---|
| 4092 | + if (!(se_cmd->transport_state & CMD_T_TAS)) |
---|
4062 | 4093 | /* |
---|
4063 | 4094 | * LIO's abort path owns the cleanup for this, |
---|
4064 | 4095 | * so put it back on the list and let |
---|
.. | .. |
---|
4066 | 4097 | */ |
---|
4067 | 4098 | list_move_tail(&cmd->i_conn_node, |
---|
4068 | 4099 | &conn->conn_cmd_list); |
---|
4069 | | - } else { |
---|
4070 | | - se_cmd->transport_state |= CMD_T_FABRIC_STOP; |
---|
4071 | | - } |
---|
4072 | | - spin_unlock_irq(&se_cmd->t_state_lock); |
---|
| 4100 | + } else { |
---|
| 4101 | + se_cmd->transport_state |= CMD_T_FABRIC_STOP; |
---|
4073 | 4102 | } |
---|
| 4103 | + spin_unlock_irq(&se_cmd->t_state_lock); |
---|
4074 | 4104 | } |
---|
4075 | 4105 | spin_unlock_bh(&conn->cmd_lock); |
---|
4076 | 4106 | |
---|
.. | .. |
---|
4355 | 4385 | iscsit_stop_time2retain_timer(sess); |
---|
4356 | 4386 | spin_unlock_bh(&se_tpg->session_lock); |
---|
4357 | 4387 | |
---|
| 4388 | + if (sess->sess_ops->ErrorRecoveryLevel == 2) |
---|
| 4389 | + iscsit_free_connection_recovery_entries(sess); |
---|
| 4390 | + |
---|
4358 | 4391 | /* |
---|
4359 | 4392 | * transport_deregister_session_configfs() will clear the |
---|
4360 | 4393 | * struct se_node_acl->nacl_sess pointer now as a iscsi_np process context |
---|
.. | .. |
---|
4371 | 4404 | * restart the timer and exit. |
---|
4372 | 4405 | */ |
---|
4373 | 4406 | if (!in_interrupt()) { |
---|
4374 | | - if (iscsit_check_session_usage_count(sess) == 1) |
---|
4375 | | - iscsit_stop_session(sess, 1, 1); |
---|
| 4407 | + iscsit_check_session_usage_count(sess); |
---|
4376 | 4408 | } else { |
---|
4377 | 4409 | if (iscsit_check_session_usage_count(sess) == 2) { |
---|
4378 | 4410 | atomic_set(&sess->session_logout, 0); |
---|
.. | .. |
---|
4382 | 4414 | } |
---|
4383 | 4415 | |
---|
4384 | 4416 | transport_deregister_session(sess->se_sess); |
---|
4385 | | - |
---|
4386 | | - if (sess->sess_ops->ErrorRecoveryLevel == 2) |
---|
4387 | | - iscsit_free_connection_recovery_entires(sess); |
---|
4388 | 4417 | |
---|
4389 | 4418 | iscsit_free_all_ooo_cmdsns(sess); |
---|
4390 | 4419 | |
---|
.. | .. |
---|
4510 | 4539 | iscsit_logout_post_handler_closesession(conn); |
---|
4511 | 4540 | break; |
---|
4512 | 4541 | } |
---|
4513 | | - ret = 0; |
---|
4514 | 4542 | break; |
---|
4515 | 4543 | case ISCSI_LOGOUT_REASON_CLOSE_CONNECTION: |
---|
4516 | 4544 | if (conn->cid == cmd->logout_cid) { |
---|
.. | .. |
---|
4521 | 4549 | iscsit_logout_post_handler_samecid(conn); |
---|
4522 | 4550 | break; |
---|
4523 | 4551 | } |
---|
4524 | | - ret = 0; |
---|
4525 | 4552 | } else { |
---|
4526 | 4553 | switch (cmd->logout_response) { |
---|
4527 | 4554 | case ISCSI_LOGOUT_SUCCESS: |
---|