aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/iscsi
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2011-09-16 19:55:47 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-09-16 19:47:07 -0400
commit40b054970afcf067896d62cd6f7e617c62665304 (patch)
tree5596f2b4fa1c1f41f599caf21bd5d10681ab152b /drivers/target/iscsi
parent2ff017f5b4299e24a7f22d9a336dd162bf52bb54 (diff)
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: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/iscsi')
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 1d1b4fe33e43..f00137f377b2 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -1256,7 +1256,7 @@ int iscsit_fe_sendpage_sg(
1256 struct kvec iov; 1256 struct kvec iov;
1257 u32 tx_hdr_size, data_len; 1257 u32 tx_hdr_size, data_len;
1258 u32 offset = cmd->first_data_sg_off; 1258 u32 offset = cmd->first_data_sg_off;
1259 int tx_sent; 1259 int tx_sent, iov_off;
1260 1260
1261send_hdr: 1261send_hdr:
1262 tx_hdr_size = ISCSI_HDR_LEN; 1262 tx_hdr_size = ISCSI_HDR_LEN;
@@ -1276,9 +1276,19 @@ send_hdr:
1276 } 1276 }
1277 1277
1278 data_len = cmd->tx_size - tx_hdr_size - cmd->padding; 1278 data_len = cmd->tx_size - tx_hdr_size - cmd->padding;
1279 if (conn->conn_ops->DataDigest) 1279 /*
1280 * Set iov_off used by padding and data digest tx_data() calls below
1281 * in order to determine proper offset into cmd->iov_data[]
1282 */
1283 if (conn->conn_ops->DataDigest) {
1280 data_len -= ISCSI_CRC_LEN; 1284 data_len -= ISCSI_CRC_LEN;
1281 1285 if (cmd->padding)
1286 iov_off = (cmd->iov_data_count - 2);
1287 else
1288 iov_off = (cmd->iov_data_count - 1);
1289 } else {
1290 iov_off = (cmd->iov_data_count - 1);
1291 }
1282 /* 1292 /*
1283 * Perform sendpage() for each page in the scatterlist 1293 * Perform sendpage() for each page in the scatterlist
1284 */ 1294 */
@@ -1307,8 +1317,7 @@ send_pg:
1307 1317
1308send_padding: 1318send_padding:
1309 if (cmd->padding) { 1319 if (cmd->padding) {
1310 struct kvec *iov_p = 1320 struct kvec *iov_p = &cmd->iov_data[iov_off++];
1311 &cmd->iov_data[cmd->iov_data_count-1];
1312 1321
1313 tx_sent = tx_data(conn, iov_p, 1, cmd->padding); 1322 tx_sent = tx_data(conn, iov_p, 1, cmd->padding);
1314 if (cmd->padding != tx_sent) { 1323 if (cmd->padding != tx_sent) {
@@ -1322,8 +1331,7 @@ send_padding:
1322 1331
1323send_datacrc: 1332send_datacrc:
1324 if (conn->conn_ops->DataDigest) { 1333 if (conn->conn_ops->DataDigest) {
1325 struct kvec *iov_d = 1334 struct kvec *iov_d = &cmd->iov_data[iov_off];
1326 &cmd->iov_data[cmd->iov_data_count];
1327 1335
1328 tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN); 1336 tx_sent = tx_data(conn, iov_d, 1, ISCSI_CRC_LEN);
1329 if (ISCSI_CRC_LEN != tx_sent) { 1337 if (ISCSI_CRC_LEN != tx_sent) {