diff options
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 27 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 1 | ||||
-rw-r--r-- | include/target/iscsi/iscsi_target_core.h | 1 |
3 files changed, 26 insertions, 3 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 828697015759..8cdea25f1377 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -1568,9 +1568,11 @@ iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1568 | { | 1568 | { |
1569 | struct kvec *iov; | 1569 | struct kvec *iov; |
1570 | u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0; | 1570 | u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0; |
1571 | u32 payload_length = ntoh24(hdr->dlength); | 1571 | u32 payload_length; |
1572 | int iov_ret, data_crc_failed = 0; | 1572 | int iov_ret, data_crc_failed = 0; |
1573 | 1573 | ||
1574 | payload_length = min_t(u32, cmd->se_cmd.data_length, | ||
1575 | ntoh24(hdr->dlength)); | ||
1574 | rx_size += payload_length; | 1576 | rx_size += payload_length; |
1575 | iov = &cmd->iov_data[0]; | 1577 | iov = &cmd->iov_data[0]; |
1576 | 1578 | ||
@@ -2575,14 +2577,33 @@ static int iscsit_handle_immediate_data( | |||
2575 | u32 checksum, iov_count = 0, padding = 0; | 2577 | u32 checksum, iov_count = 0, padding = 0; |
2576 | struct iscsi_conn *conn = cmd->conn; | 2578 | struct iscsi_conn *conn = cmd->conn; |
2577 | struct kvec *iov; | 2579 | struct kvec *iov; |
2580 | void *overflow_buf = NULL; | ||
2578 | 2581 | ||
2579 | iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done, length); | 2582 | BUG_ON(cmd->write_data_done > cmd->se_cmd.data_length); |
2583 | rx_size = min(cmd->se_cmd.data_length - cmd->write_data_done, length); | ||
2584 | iov_ret = iscsit_map_iovec(cmd, cmd->iov_data, cmd->write_data_done, | ||
2585 | rx_size); | ||
2580 | if (iov_ret < 0) | 2586 | if (iov_ret < 0) |
2581 | return IMMEDIATE_DATA_CANNOT_RECOVER; | 2587 | return IMMEDIATE_DATA_CANNOT_RECOVER; |
2582 | 2588 | ||
2583 | rx_size = length; | ||
2584 | iov_count = iov_ret; | 2589 | iov_count = iov_ret; |
2585 | iov = &cmd->iov_data[0]; | 2590 | iov = &cmd->iov_data[0]; |
2591 | if (rx_size < length) { | ||
2592 | /* | ||
2593 | * Special case: length of immediate data exceeds the data | ||
2594 | * buffer size derived from the CDB. | ||
2595 | */ | ||
2596 | overflow_buf = kmalloc(length - rx_size, GFP_KERNEL); | ||
2597 | if (!overflow_buf) { | ||
2598 | iscsit_unmap_iovec(cmd); | ||
2599 | return IMMEDIATE_DATA_CANNOT_RECOVER; | ||
2600 | } | ||
2601 | cmd->overflow_buf = overflow_buf; | ||
2602 | iov[iov_count].iov_base = overflow_buf; | ||
2603 | iov[iov_count].iov_len = length - rx_size; | ||
2604 | iov_count++; | ||
2605 | rx_size = length; | ||
2606 | } | ||
2586 | 2607 | ||
2587 | padding = ((-length) & 3); | 2608 | padding = ((-length) & 3); |
2588 | if (padding != 0) { | 2609 | if (padding != 0) { |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 5b26bc23016a..fae85bfd790e 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -737,6 +737,7 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd) | |||
737 | kfree(cmd->pdu_list); | 737 | kfree(cmd->pdu_list); |
738 | kfree(cmd->seq_list); | 738 | kfree(cmd->seq_list); |
739 | kfree(cmd->tmr_req); | 739 | kfree(cmd->tmr_req); |
740 | kfree(cmd->overflow_buf); | ||
740 | kfree(cmd->iov_data); | 741 | kfree(cmd->iov_data); |
741 | kfree(cmd->text_in_ptr); | 742 | kfree(cmd->text_in_ptr); |
742 | 743 | ||
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h index 24c398f4a68f..a49d37140a64 100644 --- a/include/target/iscsi/iscsi_target_core.h +++ b/include/target/iscsi/iscsi_target_core.h | |||
@@ -473,6 +473,7 @@ struct iscsi_cmd { | |||
473 | struct timer_list dataout_timer; | 473 | struct timer_list dataout_timer; |
474 | /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */ | 474 | /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */ |
475 | struct kvec *iov_data; | 475 | struct kvec *iov_data; |
476 | void *overflow_buf; | ||
476 | /* Iovecs for miscellaneous purposes */ | 477 | /* Iovecs for miscellaneous purposes */ |
477 | #define ISCSI_MISC_IOVECS 5 | 478 | #define ISCSI_MISC_IOVECS 5 |
478 | struct kvec iov_misc[ISCSI_MISC_IOVECS]; | 479 | struct kvec iov_misc[ISCSI_MISC_IOVECS]; |