aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-08-31 18:09:27 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-02 14:37:14 -0400
commit62f383003c22cd34920d0412465eddcb1223da0d (patch)
treeca5091110dbf19df3f8031a590cd11229e6081e1 /drivers/scsi/iscsi_tcp.c
parent98a9416af08385f8497e9c1595113a81aefa5d49 (diff)
[SCSI] iscsi_tcp: fix padding, data digests, and IO at weird offsets
iscsi_tcp calculates padding by using the expected transfer length. This has the problem where if we have immediate data = no and initial R2T = yes, and the transfer length ended up needing padding then we send: 1. header 2. padding which should have gone after data 3. data Besides this bug, we also assume the target will always ask for nice transfer lengths and the first burst length will always be a nice value. As far as I can tell form the RFC this is not a requirement. It would be silly to do this, but if someone did it we will end doing bad things. Finally the last bug in that bit of code is in our handling of the recalculation of data digests when we do not send a whole iscsi_buf in one try. The bug here is that we call crypto_digest_final on a iscsi_sendpage error, then when we send the rest of the iscsi_buf, we doiscsi_data_digest_init and this causes the previous data digest to be lost. And to make matters worse, some of these bugs are replicated over and over and over again for immediate data, solicited data and unsolicited data. So the attached patch made over the iscsi git tree (see kernel.org/git for details) which I updated today to include the patches I said I merged, consolidates the sending of data, padding and digests and calculation of data digests and fixes the above bugs. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r--drivers/scsi/iscsi_tcp.c636
1 files changed, 241 insertions, 395 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index d6927f1a6b65..290c1d76cd40 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -281,7 +281,6 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
281{ 281{
282 struct iscsi_data *hdr; 282 struct iscsi_data *hdr;
283 struct scsi_cmnd *sc = ctask->sc; 283 struct scsi_cmnd *sc = ctask->sc;
284 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
285 284
286 hdr = &r2t->dtask.hdr; 285 hdr = &r2t->dtask.hdr;
287 memset(hdr, 0, sizeof(struct iscsi_data)); 286 memset(hdr, 0, sizeof(struct iscsi_data));
@@ -336,10 +335,12 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
336 sg_count += sg->length; 335 sg_count += sg->length;
337 } 336 }
338 BUG_ON(r2t->sg == NULL); 337 BUG_ON(r2t->sg == NULL);
339 } else 338 } else {
340 iscsi_buf_init_iov(&tcp_ctask->sendbuf, 339 iscsi_buf_init_iov(&r2t->sendbuf,
341 (char*)sc->request_buffer + r2t->data_offset, 340 (char*)sc->request_buffer + r2t->data_offset,
342 r2t->data_count); 341 r2t->data_count);
342 r2t->sg = NULL;
343 }
343} 344}
344 345
345/** 346/**
@@ -503,7 +504,6 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *conn)
503 goto copy_hdr; 504 goto copy_hdr;
504 505
505 spin_lock(&session->lock); 506 spin_lock(&session->lock);
506 iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
507 rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); 507 rc = __iscsi_complete_pdu(conn, hdr, NULL, 0);
508 spin_unlock(&session->lock); 508 spin_unlock(&session->lock);
509 break; 509 break;
@@ -676,15 +676,15 @@ iscsi_tcp_copy(struct iscsi_conn *conn)
676} 676}
677 677
678static inline void 678static inline void
679partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, 679partial_sg_digest_update(struct crypto_tfm *tfm, struct scatterlist *sg,
680 struct scatterlist *sg, int offset, int length) 680 int offset, int length)
681{ 681{
682 struct scatterlist temp; 682 struct scatterlist temp;
683 683
684 memcpy(&temp, sg, sizeof(struct scatterlist)); 684 memcpy(&temp, sg, sizeof(struct scatterlist));
685 temp.offset = offset; 685 temp.offset = offset;
686 temp.length = length; 686 temp.length = length;
687 crypto_digest_update(tcp_conn->data_rx_tfm, &temp, 1); 687 crypto_digest_update(tfm, &temp, 1);
688} 688}
689 689
690static void 690static void
@@ -751,7 +751,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
751 tcp_conn->data_rx_tfm, 751 tcp_conn->data_rx_tfm,
752 &sg[i], 1); 752 &sg[i], 1);
753 else 753 else
754 partial_sg_digest_update(tcp_conn, 754 partial_sg_digest_update(
755 tcp_conn->data_rx_tfm,
755 &sg[i], 756 &sg[i],
756 sg[i].offset + offset, 757 sg[i].offset + offset,
757 sg[i].length - offset); 758 sg[i].length - offset);
@@ -765,7 +766,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
765 /* 766 /*
766 * data-in is complete, but buffer not... 767 * data-in is complete, but buffer not...
767 */ 768 */
768 partial_sg_digest_update(tcp_conn, &sg[i], 769 partial_sg_digest_update(tcp_conn->data_rx_tfm,
770 &sg[i],
769 sg[i].offset, sg[i].length-rc); 771 sg[i].offset, sg[i].length-rc);
770 rc = 0; 772 rc = 0;
771 break; 773 break;
@@ -783,7 +785,6 @@ done:
783 (long)sc, sc->result, ctask->itt, 785 (long)sc, sc->result, ctask->itt,
784 tcp_conn->in.hdr->flags); 786 tcp_conn->in.hdr->flags);
785 spin_lock(&conn->session->lock); 787 spin_lock(&conn->session->lock);
786 iscsi_tcp_cleanup_ctask(conn, ctask);
787 __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0); 788 __iscsi_complete_pdu(conn, tcp_conn->in.hdr, NULL, 0);
788 spin_unlock(&conn->session->lock); 789 spin_unlock(&conn->session->lock);
789 } 790 }
@@ -803,9 +804,6 @@ iscsi_data_recv(struct iscsi_conn *conn)
803 rc = iscsi_scsi_data_in(conn); 804 rc = iscsi_scsi_data_in(conn);
804 break; 805 break;
805 case ISCSI_OP_SCSI_CMD_RSP: 806 case ISCSI_OP_SCSI_CMD_RSP:
806 spin_lock(&conn->session->lock);
807 iscsi_tcp_cleanup_ctask(conn, tcp_conn->in.ctask);
808 spin_unlock(&conn->session->lock);
809 case ISCSI_OP_TEXT_RSP: 807 case ISCSI_OP_TEXT_RSP:
810 case ISCSI_OP_LOGIN_RSP: 808 case ISCSI_OP_LOGIN_RSP:
811 case ISCSI_OP_ASYNC_EVENT: 809 case ISCSI_OP_ASYNC_EVENT:
@@ -1188,37 +1186,12 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
1188 1186
1189static inline void 1187static inline void
1190iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, 1188iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn,
1191 struct iscsi_cmd_task *ctask) 1189 struct iscsi_tcp_cmd_task *tcp_ctask)
1192{ 1190{
1193 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1194
1195 BUG_ON(!tcp_conn->data_tx_tfm);
1196 crypto_digest_init(tcp_conn->data_tx_tfm); 1191 crypto_digest_init(tcp_conn->data_tx_tfm);
1197 tcp_ctask->digest_count = 4; 1192 tcp_ctask->digest_count = 4;
1198} 1193}
1199 1194
1200static int
1201iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1202 struct iscsi_buf *buf, uint32_t *digest, int final)
1203{
1204 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1205 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1206 int rc = 0;
1207 int sent = 0;
1208
1209 if (final)
1210 crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
1211
1212 iscsi_buf_init_iov(buf, (char*)digest, 4);
1213 rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
1214 if (rc) {
1215 tcp_ctask->datadigest = *digest;
1216 tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
1217 } else
1218 tcp_ctask->digest_count = 4;
1219 return rc;
1220}
1221
1222/** 1195/**
1223 * iscsi_solicit_data_cont - initialize next Data-Out 1196 * iscsi_solicit_data_cont - initialize next Data-Out
1224 * @conn: iscsi connection 1197 * @conn: iscsi connection
@@ -1236,7 +1209,6 @@ static void
1236iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, 1209iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1237 struct iscsi_r2t_info *r2t, int left) 1210 struct iscsi_r2t_info *r2t, int left)
1238{ 1211{
1239 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1240 struct iscsi_data *hdr; 1212 struct iscsi_data *hdr;
1241 struct scsi_cmnd *sc = ctask->sc; 1213 struct scsi_cmnd *sc = ctask->sc;
1242 int new_offset; 1214 int new_offset;
@@ -1265,14 +1237,30 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1265 iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr, 1237 iscsi_buf_init_iov(&r2t->headbuf, (char*)hdr,
1266 sizeof(struct iscsi_hdr)); 1238 sizeof(struct iscsi_hdr));
1267 1239
1268 if (sc->use_sg && !iscsi_buf_left(&r2t->sendbuf)) { 1240 if (iscsi_buf_left(&r2t->sendbuf))
1269 BUG_ON(tcp_ctask->bad_sg == r2t->sg); 1241 return;
1242
1243 if (sc->use_sg) {
1270 iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg); 1244 iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
1271 r2t->sg += 1; 1245 r2t->sg += 1;
1272 } else 1246 } else {
1273 iscsi_buf_init_iov(&tcp_ctask->sendbuf, 1247 iscsi_buf_init_iov(&r2t->sendbuf,
1274 (char*)sc->request_buffer + new_offset, 1248 (char*)sc->request_buffer + new_offset,
1275 r2t->data_count); 1249 r2t->data_count);
1250 r2t->sg = NULL;
1251 }
1252}
1253
1254static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
1255 unsigned long len)
1256{
1257 tcp_ctask->pad_count = len & (ISCSI_PAD_LEN - 1);
1258 if (!tcp_ctask->pad_count)
1259 return;
1260
1261 tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count;
1262 debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count);
1263 tcp_ctask->xmstate |= XMSTATE_W_PAD;
1276} 1264}
1277 1265
1278/** 1266/**
@@ -1300,31 +1288,16 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
1300 if (sc->use_sg) { 1288 if (sc->use_sg) {
1301 struct scatterlist *sg = sc->request_buffer; 1289 struct scatterlist *sg = sc->request_buffer;
1302 1290
1303 iscsi_buf_init_sg(&tcp_ctask->sendbuf, 1291 iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
1304 &sg[tcp_ctask->sg_count++]); 1292 tcp_ctask->sg = sg + 1;
1305 tcp_ctask->sg = sg;
1306 tcp_ctask->bad_sg = sg + sc->use_sg; 1293 tcp_ctask->bad_sg = sg + sc->use_sg;
1307 } else 1294 } else {
1308 iscsi_buf_init_iov(&tcp_ctask->sendbuf, 1295 iscsi_buf_init_iov(&tcp_ctask->sendbuf,
1309 sc->request_buffer, 1296 sc->request_buffer,
1310 sc->request_bufflen); 1297 sc->request_bufflen);
1311 1298 tcp_ctask->sg = NULL;
1312 if (ctask->imm_count) 1299 tcp_ctask->bad_sg = NULL;
1313 tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
1314
1315 tcp_ctask->pad_count = ctask->total_length & (ISCSI_PAD_LEN-1);
1316 if (tcp_ctask->pad_count) {
1317 tcp_ctask->pad_count = ISCSI_PAD_LEN -
1318 tcp_ctask->pad_count;
1319 debug_scsi("write padding %d bytes\n",
1320 tcp_ctask->pad_count);
1321 tcp_ctask->xmstate |= XMSTATE_W_PAD;
1322 } 1300 }
1323
1324 if (ctask->unsol_count)
1325 tcp_ctask->xmstate |= XMSTATE_UNS_HDR |
1326 XMSTATE_UNS_INIT;
1327
1328 debug_scsi("cmd [itt 0x%x total %d imm_data %d " 1301 debug_scsi("cmd [itt 0x%x total %d imm_data %d "
1329 "unsol count %d, unsol offset %d]\n", 1302 "unsol count %d, unsol offset %d]\n",
1330 ctask->itt, ctask->total_length, ctask->imm_count, 1303 ctask->itt, ctask->total_length, ctask->imm_count,
@@ -1410,8 +1383,8 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1410} 1383}
1411 1384
1412static inline int 1385static inline int
1413handle_xmstate_r_hdr(struct iscsi_conn *conn, 1386iscsi_send_read_hdr(struct iscsi_conn *conn,
1414 struct iscsi_tcp_cmd_task *tcp_ctask) 1387 struct iscsi_tcp_cmd_task *tcp_ctask)
1415{ 1388{
1416 int rc; 1389 int rc;
1417 1390
@@ -1429,7 +1402,7 @@ handle_xmstate_r_hdr(struct iscsi_conn *conn,
1429} 1402}
1430 1403
1431static inline int 1404static inline int
1432handle_xmstate_w_hdr(struct iscsi_conn *conn, 1405iscsi_send_write_hdr(struct iscsi_conn *conn,
1433 struct iscsi_cmd_task *ctask) 1406 struct iscsi_cmd_task *ctask)
1434{ 1407{
1435 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1408 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
@@ -1440,85 +1413,125 @@ handle_xmstate_w_hdr(struct iscsi_conn *conn,
1440 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1413 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1441 (u8*)tcp_ctask->hdrext); 1414 (u8*)tcp_ctask->hdrext);
1442 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); 1415 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
1443 if (rc) 1416 if (rc) {
1444 tcp_ctask->xmstate |= XMSTATE_W_HDR; 1417 tcp_ctask->xmstate |= XMSTATE_W_HDR;
1445 return rc; 1418 return rc;
1419 }
1420
1421 if (ctask->imm_count) {
1422 tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
1423 iscsi_set_padding(tcp_ctask, ctask->imm_count);
1424
1425 if (ctask->conn->datadgst_en) {
1426 iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
1427 tcp_ctask->immdigest = 0;
1428 }
1429 }
1430
1431 if (ctask->unsol_count)
1432 tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
1433 return 0;
1446} 1434}
1447 1435
1448static inline int 1436static int
1449handle_xmstate_data_digest(struct iscsi_conn *conn, 1437iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1450 struct iscsi_cmd_task *ctask)
1451{ 1438{
1452 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1439 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1453 int rc; 1440 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1441 int sent = 0, rc;
1454 1442
1455 tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; 1443 if (tcp_ctask->xmstate & XMSTATE_W_PAD) {
1456 debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); 1444 iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
1457 rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, 1445 tcp_ctask->pad_count);
1458 &tcp_ctask->datadigest, 0); 1446 if (conn->datadgst_en)
1447 crypto_digest_update(tcp_conn->data_tx_tfm,
1448 &tcp_ctask->sendbuf.sg, 1);
1449 } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD))
1450 return 0;
1451
1452 tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
1453 tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD;
1454 debug_scsi("sending %d pad bytes for itt 0x%x\n",
1455 tcp_ctask->pad_count, ctask->itt);
1456 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
1457 &sent);
1459 if (rc) { 1458 if (rc) {
1460 tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; 1459 debug_scsi("padding send failed %d\n", rc);
1461 debug_tcp("resent data digest 0x%x fail!\n", 1460 tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD;
1462 tcp_ctask->datadigest);
1463 } 1461 }
1464
1465 return rc; 1462 return rc;
1466} 1463}
1467 1464
1468static inline int 1465static int
1469handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1466iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1467 struct iscsi_buf *buf, uint32_t *digest)
1470{ 1468{
1471 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1469 struct iscsi_tcp_cmd_task *tcp_ctask;
1472 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1470 struct iscsi_tcp_conn *tcp_conn;
1473 int rc; 1471 int rc, sent = 0;
1474 1472
1475 BUG_ON(!ctask->imm_count); 1473 if (!conn->datadgst_en)
1476 tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; 1474 return 0;
1477 1475
1478 if (conn->datadgst_en) { 1476 tcp_ctask = ctask->dd_data;
1479 iscsi_data_digest_init(tcp_conn, ctask); 1477 tcp_conn = conn->dd_data;
1480 tcp_ctask->immdigest = 0;
1481 }
1482 1478
1483 for (;;) { 1479 if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) {
1484 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, 1480 crypto_digest_final(tcp_conn->data_tx_tfm, (u8*)digest);
1485 &ctask->imm_count, &tcp_ctask->sent); 1481 iscsi_buf_init_iov(buf, (char*)digest, 4);
1486 if (rc) { 1482 }
1487 tcp_ctask->xmstate |= XMSTATE_IMM_DATA; 1483 tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST;
1488 if (conn->datadgst_en) {
1489 crypto_digest_final(tcp_conn->data_tx_tfm,
1490 (u8*)&tcp_ctask->immdigest);
1491 debug_tcp("tx imm sendpage fail 0x%x\n",
1492 tcp_ctask->datadigest);
1493 }
1494 return rc;
1495 }
1496 if (conn->datadgst_en)
1497 crypto_digest_update(tcp_conn->data_tx_tfm,
1498 &tcp_ctask->sendbuf.sg, 1);
1499 1484
1500 if (!ctask->imm_count) 1485 rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
1501 break; 1486 if (!rc)
1502 iscsi_buf_init_sg(&tcp_ctask->sendbuf, 1487 debug_scsi("sent digest 0x%x for itt 0x%x\n", *digest,
1503 &tcp_ctask->sg[tcp_ctask->sg_count++]); 1488 ctask->itt);
1489 else {
1490 debug_scsi("sending digest 0x%x failed for itt 0x%x!\n",
1491 *digest, ctask->itt);
1492 tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST;
1504 } 1493 }
1494 return rc;
1495}
1505 1496
1506 if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { 1497static int
1507 rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, 1498iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf,
1508 &tcp_ctask->immdigest, 1); 1499 struct scatterlist **sg, int *sent, int *count,
1509 if (rc) { 1500 struct iscsi_buf *digestbuf, uint32_t *digest)
1510 debug_tcp("sending imm digest 0x%x fail!\n", 1501{
1511 tcp_ctask->immdigest); 1502 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1512 return rc; 1503 struct iscsi_conn *conn = ctask->conn;
1504 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1505 int rc, buf_sent, offset;
1506
1507 while (*count) {
1508 buf_sent = 0;
1509 offset = sendbuf->sent;
1510
1511 rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent);
1512 *sent = *sent + buf_sent;
1513 if (buf_sent && conn->datadgst_en)
1514 partial_sg_digest_update(tcp_conn->data_tx_tfm,
1515 &sendbuf->sg, sendbuf->sg.offset + offset,
1516 buf_sent);
1517 if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) {
1518 iscsi_buf_init_sg(sendbuf, *sg);
1519 *sg = *sg + 1;
1513 } 1520 }
1514 debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); 1521
1522 if (rc)
1523 return rc;
1515 } 1524 }
1516 1525
1517 return 0; 1526 rc = iscsi_send_padding(conn, ctask);
1527 if (rc)
1528 return rc;
1529
1530 return iscsi_send_digest(conn, ctask, digestbuf, digest);
1518} 1531}
1519 1532
1520static inline int 1533static int
1521handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1534iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1522{ 1535{
1523 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1536 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1524 struct iscsi_data_task *dtask; 1537 struct iscsi_data_task *dtask;
@@ -1526,14 +1539,21 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1526 1539
1527 tcp_ctask->xmstate |= XMSTATE_UNS_DATA; 1540 tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
1528 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { 1541 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
1529 dtask = tcp_ctask->dtask = &tcp_ctask->unsol_dtask; 1542 dtask = &tcp_ctask->unsol_dtask;
1543
1530 iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); 1544 iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr);
1531 iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr, 1545 iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)&dtask->hdr,
1532 sizeof(struct iscsi_hdr)); 1546 sizeof(struct iscsi_hdr));
1533 if (conn->hdrdgst_en) 1547 if (conn->hdrdgst_en)
1534 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1548 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1535 (u8*)dtask->hdrext); 1549 (u8*)dtask->hdrext);
1550 if (conn->datadgst_en) {
1551 iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
1552 dtask->digest = 0;
1553 }
1554
1536 tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; 1555 tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
1556 iscsi_set_padding(tcp_ctask, ctask->data_count);
1537 } 1557 }
1538 1558
1539 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); 1559 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count);
@@ -1548,247 +1568,128 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1548 return 0; 1568 return 0;
1549} 1569}
1550 1570
1551static inline int 1571static int
1552handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1572iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1553{ 1573{
1554 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1574 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1555 struct iscsi_data_task *dtask = tcp_ctask->dtask;
1556 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1557 int rc; 1575 int rc;
1558 1576
1559 BUG_ON(!ctask->data_count); 1577 if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
1560 tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; 1578 BUG_ON(!ctask->unsol_count);
1561 1579 tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR;
1562 if (conn->datadgst_en) { 1580send_hdr:
1563 iscsi_data_digest_init(tcp_conn, ctask); 1581 rc = iscsi_send_unsol_hdr(conn, ctask);
1564 dtask->digest = 0; 1582 if (rc)
1583 return rc;
1565 } 1584 }
1566 1585
1567 for (;;) { 1586 if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
1587 struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask;
1568 int start = tcp_ctask->sent; 1588 int start = tcp_ctask->sent;
1569 1589
1570 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, 1590 rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
1571 &ctask->data_count, &tcp_ctask->sent); 1591 &tcp_ctask->sent, &ctask->data_count,
1572 if (rc) { 1592 &dtask->digestbuf, &dtask->digest);
1573 ctask->unsol_count -= tcp_ctask->sent - start;
1574 tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
1575 /* will continue with this ctask later.. */
1576 if (conn->datadgst_en) {
1577 crypto_digest_final(tcp_conn->data_tx_tfm,
1578 (u8 *)&dtask->digest);
1579 debug_tcp("tx uns data fail 0x%x\n",
1580 dtask->digest);
1581 }
1582 return rc;
1583 }
1584
1585 BUG_ON(tcp_ctask->sent > ctask->total_length);
1586 ctask->unsol_count -= tcp_ctask->sent - start; 1593 ctask->unsol_count -= tcp_ctask->sent - start;
1587 1594 if (rc)
1595 return rc;
1596 tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
1588 /* 1597 /*
1589 * XXX:we may run here with un-initial sendbuf. 1598 * Done with the Data-Out. Next, check if we need
1590 * so pass it 1599 * to send another unsolicited Data-Out.
1591 */ 1600 */
1592 if (conn->datadgst_en && tcp_ctask->sent - start > 0) 1601 if (ctask->unsol_count) {
1593 crypto_digest_update(tcp_conn->data_tx_tfm, 1602 debug_scsi("sending more uns\n");
1594 &tcp_ctask->sendbuf.sg, 1); 1603 tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
1595 1604 goto send_hdr;
1596 if (!ctask->data_count)
1597 break;
1598 iscsi_buf_init_sg(&tcp_ctask->sendbuf,
1599 &tcp_ctask->sg[tcp_ctask->sg_count++]);
1600 }
1601 BUG_ON(ctask->unsol_count < 0);
1602
1603 /*
1604 * Done with the Data-Out. Next, check if we need
1605 * to send another unsolicited Data-Out.
1606 */
1607 if (ctask->unsol_count) {
1608 if (conn->datadgst_en) {
1609 rc = iscsi_digest_final_send(conn, ctask,
1610 &dtask->digestbuf,
1611 &dtask->digest, 1);
1612 if (rc) {
1613 debug_tcp("send uns digest 0x%x fail\n",
1614 dtask->digest);
1615 return rc;
1616 }
1617 debug_tcp("sending uns digest 0x%x, more uns\n",
1618 dtask->digest);
1619 }
1620 tcp_ctask->xmstate |= XMSTATE_UNS_INIT;
1621 return 1;
1622 }
1623
1624 if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
1625 rc = iscsi_digest_final_send(conn, ctask,
1626 &dtask->digestbuf,
1627 &dtask->digest, 1);
1628 if (rc) {
1629 debug_tcp("send last uns digest 0x%x fail\n",
1630 dtask->digest);
1631 return rc;
1632 } 1605 }
1633 debug_tcp("sending uns digest 0x%x\n",dtask->digest);
1634 } 1606 }
1635
1636 return 0; 1607 return 0;
1637} 1608}
1638 1609
1639static inline int 1610static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
1640handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1611 struct iscsi_cmd_task *ctask)
1641{ 1612{
1642 struct iscsi_session *session = conn->session;
1643 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1644 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1613 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1645 struct iscsi_r2t_info *r2t = tcp_ctask->r2t; 1614 struct iscsi_session *session = conn->session;
1646 struct iscsi_data_task *dtask = &r2t->dtask; 1615 struct iscsi_r2t_info *r2t;
1616 struct iscsi_data_task *dtask;
1647 int left, rc; 1617 int left, rc;
1648 1618
1649 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; 1619 if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
1650 tcp_ctask->dtask = dtask; 1620 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1651
1652 if (conn->datadgst_en) {
1653 iscsi_data_digest_init(tcp_conn, ctask);
1654 dtask->digest = 0;
1655 }
1656solicit_again:
1657 /*
1658 * send Data-Out within this R2T sequence.
1659 */
1660 if (!r2t->data_count)
1661 goto data_out_done;
1662
1663 rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent);
1664 if (rc) {
1665 tcp_ctask->xmstate |= XMSTATE_SOL_DATA; 1621 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1666 /* will continue with this ctask later.. */ 1622 if (!tcp_ctask->r2t)
1667 if (conn->datadgst_en) { 1623 __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
1668 crypto_digest_final(tcp_conn->data_tx_tfm, 1624 sizeof(void*));
1669 (u8 *)&dtask->digest); 1625send_hdr:
1670 debug_tcp("r2t data send fail 0x%x\n", dtask->digest); 1626 r2t = tcp_ctask->r2t;
1671 } 1627 dtask = &r2t->dtask;
1672 return rc;
1673 }
1674 1628
1675 BUG_ON(r2t->data_count < 0); 1629 if (conn->hdrdgst_en)
1676 if (conn->datadgst_en) 1630 iscsi_hdr_digest(conn, &r2t->headbuf,
1677 crypto_digest_update(tcp_conn->data_tx_tfm, &r2t->sendbuf.sg, 1631 (u8*)dtask->hdrext);
1678 1);
1679
1680 if (r2t->data_count) {
1681 BUG_ON(ctask->sc->use_sg == 0);
1682 if (!iscsi_buf_left(&r2t->sendbuf)) {
1683 BUG_ON(tcp_ctask->bad_sg == r2t->sg);
1684 iscsi_buf_init_sg(&r2t->sendbuf, r2t->sg);
1685 r2t->sg += 1;
1686 }
1687 goto solicit_again;
1688 }
1689 1632
1690data_out_done:
1691 /*
1692 * Done with this Data-Out. Next, check if we have
1693 * to send another Data-Out for this R2T.
1694 */
1695 BUG_ON(r2t->data_length - r2t->sent < 0);
1696 left = r2t->data_length - r2t->sent;
1697 if (left) {
1698 if (conn->datadgst_en) { 1633 if (conn->datadgst_en) {
1699 rc = iscsi_digest_final_send(conn, ctask, 1634 iscsi_data_digest_init(conn->dd_data, tcp_ctask);
1700 &dtask->digestbuf, 1635 dtask->digest = 0;
1701 &dtask->digest, 1);
1702 if (rc) {
1703 debug_tcp("send r2t data digest 0x%x"
1704 "fail\n", dtask->digest);
1705 return rc;
1706 }
1707 debug_tcp("r2t data send digest 0x%x\n",
1708 dtask->digest);
1709 } 1636 }
1710 iscsi_solicit_data_cont(conn, ctask, r2t, left);
1711 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1712 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1713 return 1;
1714 }
1715 1637
1716 /* 1638 rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
1717 * Done with this R2T. Check if there are more
1718 * outstanding R2Ts ready to be processed.
1719 */
1720 if (conn->datadgst_en) {
1721 rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
1722 &dtask->digest, 1);
1723 if (rc) { 1639 if (rc) {
1724 debug_tcp("send last r2t data digest 0x%x" 1640 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
1725 "fail\n", dtask->digest); 1641 tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
1726 return rc; 1642 return rc;
1727 } 1643 }
1728 debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
1729 }
1730 1644
1731 tcp_ctask->r2t = NULL; 1645 iscsi_set_padding(tcp_ctask, r2t->data_count);
1732 spin_lock_bh(&session->lock); 1646 debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
1733 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, sizeof(void*)); 1647 r2t->solicit_datasn - 1, ctask->itt, r2t->data_count,
1734 spin_unlock_bh(&session->lock); 1648 r2t->sent);
1735 if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
1736 tcp_ctask->r2t = r2t;
1737 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1738 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1739 return 1;
1740 } 1649 }
1741 1650
1742 return 0; 1651 if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
1743} 1652 r2t = tcp_ctask->r2t;
1653 dtask = &r2t->dtask;
1744 1654
1745static inline int 1655 rc = iscsi_send_data(ctask, &r2t->sendbuf, &r2t->sg,
1746handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1656 &r2t->sent, &r2t->data_count,
1747{ 1657 &dtask->digestbuf, &dtask->digest);
1748 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1658 if (rc)
1749 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1659 return rc;
1750 struct iscsi_data_task *dtask = tcp_ctask->dtask; 1660 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
1751 int sent = 0, rc;
1752 1661
1753 tcp_ctask->xmstate &= ~XMSTATE_W_PAD; 1662 /*
1754 iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, 1663 * Done with this Data-Out. Next, check if we have
1755 tcp_ctask->pad_count); 1664 * to send another Data-Out for this R2T.
1756 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, 1665 */
1757 &sent); 1666 BUG_ON(r2t->data_length - r2t->sent < 0);
1758 if (rc) { 1667 left = r2t->data_length - r2t->sent;
1759 tcp_ctask->xmstate |= XMSTATE_W_PAD; 1668 if (left) {
1760 return rc; 1669 iscsi_solicit_data_cont(conn, ctask, r2t, left);
1761 } 1670 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1671 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1672 goto send_hdr;
1673 }
1762 1674
1763 if (conn->datadgst_en) { 1675 /*
1764 crypto_digest_update(tcp_conn->data_tx_tfm, 1676 * Done with this R2T. Check if there are more
1765 &tcp_ctask->sendbuf.sg, 1); 1677 * outstanding R2Ts ready to be processed.
1766 /* imm data? */ 1678 */
1767 if (!dtask) { 1679 spin_lock_bh(&session->lock);
1768 rc = iscsi_digest_final_send(conn, ctask, 1680 tcp_ctask->r2t = NULL;
1769 &tcp_ctask->immbuf, 1681 __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
1770 &tcp_ctask->immdigest, 1); 1682 sizeof(void*));
1771 if (rc) { 1683 if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
1772 debug_tcp("send padding digest 0x%x" 1684 sizeof(void*))) {
1773 "fail!\n", tcp_ctask->immdigest); 1685 tcp_ctask->r2t = r2t;
1774 return rc; 1686 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1775 } 1687 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1776 debug_tcp("done with padding, digest 0x%x\n", 1688 spin_unlock_bh(&session->lock);
1777 tcp_ctask->datadigest); 1689 goto send_hdr;
1778 } else {
1779 rc = iscsi_digest_final_send(conn, ctask,
1780 &dtask->digestbuf,
1781 &dtask->digest, 1);
1782 if (rc) {
1783 debug_tcp("send padding digest 0x%x"
1784 "fail\n", dtask->digest);
1785 return rc;
1786 }
1787 debug_tcp("done with padding, digest 0x%x\n",
1788 dtask->digest);
1789 } 1690 }
1691 spin_unlock_bh(&session->lock);
1790 } 1692 }
1791
1792 return 0; 1693 return 0;
1793} 1694}
1794 1695
@@ -1808,85 +1709,30 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1808 return rc; 1709 return rc;
1809 1710
1810 if (tcp_ctask->xmstate & XMSTATE_R_HDR) 1711 if (tcp_ctask->xmstate & XMSTATE_R_HDR)
1811 return handle_xmstate_r_hdr(conn, tcp_ctask); 1712 return iscsi_send_read_hdr(conn, tcp_ctask);
1812 1713
1813 if (tcp_ctask->xmstate & XMSTATE_W_HDR) { 1714 if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
1814 rc = handle_xmstate_w_hdr(conn, ctask); 1715 rc = iscsi_send_write_hdr(conn, ctask);
1815 if (rc)
1816 return rc;
1817 }
1818
1819 /* XXX: for data digest xmit recover */
1820 if (tcp_ctask->xmstate & XMSTATE_DATA_DIGEST) {
1821 rc = handle_xmstate_data_digest(conn, ctask);
1822 if (rc) 1716 if (rc)
1823 return rc; 1717 return rc;
1824 } 1718 }
1825 1719
1826 if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { 1720 if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
1827 rc = handle_xmstate_imm_data(conn, ctask); 1721 rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
1722 &tcp_ctask->sent, &ctask->imm_count,
1723 &tcp_ctask->immbuf, &tcp_ctask->immdigest);
1828 if (rc) 1724 if (rc)
1829 return rc; 1725 return rc;
1726 tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
1830 } 1727 }
1831 1728
1832 if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { 1729 rc = iscsi_send_unsol_pdu(conn, ctask);
1833 BUG_ON(!ctask->unsol_count); 1730 if (rc)
1834 tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; 1731 return rc;
1835unsolicit_head_again:
1836 rc = handle_xmstate_uns_hdr(conn, ctask);
1837 if (rc)
1838 return rc;
1839 }
1840
1841 if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) {
1842 rc = handle_xmstate_uns_data(conn, ctask);
1843 if (rc == 1)
1844 goto unsolicit_head_again;
1845 else if (rc)
1846 return rc;
1847 goto done;
1848 }
1849
1850 if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
1851 struct iscsi_r2t_info *r2t;
1852
1853 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1854 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1855 if (!tcp_ctask->r2t)
1856 __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
1857 sizeof(void*));
1858solicit_head_again:
1859 r2t = tcp_ctask->r2t;
1860 if (conn->hdrdgst_en)
1861 iscsi_hdr_digest(conn, &r2t->headbuf,
1862 (u8*)r2t->dtask.hdrext);
1863 rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
1864 if (rc) {
1865 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
1866 tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
1867 return rc;
1868 }
1869
1870 debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
1871 r2t->solicit_datasn - 1, ctask->itt, r2t->data_count,
1872 r2t->sent);
1873 }
1874
1875 if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) {
1876 rc = handle_xmstate_sol_data(conn, ctask);
1877 if (rc == 1)
1878 goto solicit_head_again;
1879 if (rc)
1880 return rc;
1881 }
1882 1732
1883done: 1733 rc = iscsi_send_sol_pdu(conn, ctask);
1884 /* 1734 if (rc)
1885 * Last thing to check is whether we need to send write 1735 return rc;
1886 * padding. Note that we check for xmstate equality, not just the bit.
1887 */
1888 if (tcp_ctask->xmstate == XMSTATE_W_PAD)
1889 rc = handle_xmstate_w_pad(conn, ctask);
1890 1736
1891 return rc; 1737 return rc;
1892} 1738}