Commit 40b05497 authored by Nicholas Bellinger's avatar Nicholas Bellinger

iscsi-target: Fix sendpage breakage with proper padding+DataDigest iovec offsets

This patch fixes a bug in the iscsit_fe_sendpage_sg() transmit codepath that
was originally introduced with the v3.1 iscsi-target merge that incorrectly
uses hardcoded cmd->iov_data_count values to determine cmd->iov_data[] offsets
for extra outgoing padding and DataDigest payload vectors.

This code is obviously incorrect for the DataDigest enabled case with sendpage
offload, and this fix ensures correct operation for padding + DataDigest,
padding only, and DataDigest only cases.  The bug was introduced during a
pre-merge change in iscsit_fe_sendpage_sg() to natively use struct scatterlist
instead of the legacy v3.0 struct se_mem logic.

Cc: Andy Grover <agrover@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNicholas Bellinger <nab@linux-iscsi.org>
parent 2ff017f5
...@@ -1256,7 +1256,7 @@ int iscsit_fe_sendpage_sg( ...@@ -1256,7 +1256,7 @@ int iscsit_fe_sendpage_sg(
struct kvec iov; struct kvec iov;
u32 tx_hdr_size, data_len; u32 tx_hdr_size, data_len;
u32 offset = cmd->first_data_sg_off; u32 offset = cmd->first_data_sg_off;
int tx_sent; int tx_sent, iov_off;
send_hdr: send_hdr:
tx_hdr_size = ISCSI_HDR_LEN; tx_hdr_size = ISCSI_HDR_LEN;
...@@ -1276,9 +1276,19 @@ int iscsit_fe_sendpage_sg( ...@@ -1276,9 +1276,19 @@ int iscsit_fe_sendpage_sg(
} }
data_len = cmd->tx_size - tx_hdr_size - cmd->padding; data_len = cmd->tx_size - tx_hdr_size - cmd->padding;
if (conn->conn_ops->DataDigest) /*
* Set iov_off used by padding and data digest tx_data() calls below
* in order to determine proper offset into cmd->iov_data[]
*/
if (conn->conn_ops->DataDigest) {
data_len -= ISCSI_CRC_LEN; data_len -= ISCSI_CRC_LEN;
if (cmd->padding)
iov_off = (cmd->iov_data_count - 2);
else
iov_off = (cmd->iov_data_count - 1);
} else {
iov_off = (cmd->iov_data_count - 1);
}
/* /*
* Perform sendpage() for each page in the scatterlist * Perform sendpage() for each page in the scatterlist
*/ */
...@@ -1307,8 +1317,7 @@ int iscsit_fe_sendpage_sg( ...@@ -1307,8 +1317,7 @@ int iscsit_fe_sendpage_sg(
send_padding: send_padding:
if (cmd->padding) { if (cmd->padding) {
struct kvec *iov_p = struct kvec *iov_p = &cmd->iov_data[iov_off++];
&cmd->iov_data[cmd->iov_data_count-1];
tx_sent = tx_data(conn, iov_p, 1, cmd->padding); tx_sent = tx_data(conn, iov_p, 1, cmd->padding);
if (cmd->padding != tx_sent) { if (cmd->padding != tx_sent) {
...@@ -1322,8 +1331,7 @@ int iscsit_fe_sendpage_sg( ...@@ -1322,8 +1331,7 @@ int iscsit_fe_sendpage_sg(
send_datacrc: send_datacrc:
if (conn->conn_ops->DataDigest) { if (conn->conn_ops->DataDigest) {
struct kvec *iov_d = struct kvec *iov_d = &cmd->iov_data[iov_off];
&cmd->iov_data[cmd->iov_data_count];
tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN); tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN);
if (ISCSI_CRC_LEN != tx_sent) { if (ISCSI_CRC_LEN != tx_sent) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment