diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-08-31 18:09:27 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-02 14:37:14 -0400 |
commit | 62f383003c22cd34920d0412465eddcb1223da0d (patch) | |
tree | ca5091110dbf19df3f8031a590cd11229e6081e1 /drivers/scsi/iscsi_tcp.c | |
parent | 98a9416af08385f8497e9c1595113a81aefa5d49 (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.c | 636 |
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 | ||
678 | static inline void | 678 | static inline void |
679 | partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn, | 679 | partial_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 | ||
690 | static void | 690 | static 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 | ||
1189 | static inline void | 1187 | static inline void |
1190 | iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn, | 1188 | iscsi_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 | ||
1200 | static int | ||
1201 | iscsi_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 | |||
1236 | iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 1209 | iscsi_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 | |||
1254 | static 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 | ||
1412 | static inline int | 1385 | static inline int |
1413 | handle_xmstate_r_hdr(struct iscsi_conn *conn, | 1386 | iscsi_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 | ||
1431 | static inline int | 1404 | static inline int |
1432 | handle_xmstate_w_hdr(struct iscsi_conn *conn, | 1405 | iscsi_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 | ||
1448 | static inline int | 1436 | static int |
1449 | handle_xmstate_data_digest(struct iscsi_conn *conn, | 1437 | iscsi_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 | ||
1468 | static inline int | 1465 | static int |
1469 | handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1466 | iscsi_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)) { | 1497 | static int |
1507 | rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, | 1498 | iscsi_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 | ||
1520 | static inline int | 1533 | static int |
1521 | handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1534 | iscsi_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 | ||
1551 | static inline int | 1571 | static int |
1552 | handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1572 | iscsi_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) { | 1580 | send_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 | ||
1639 | static inline int | 1610 | static int iscsi_send_sol_pdu(struct iscsi_conn *conn, |
1640 | handle_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 | } | ||
1656 | solicit_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); | 1625 | send_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 | ||
1690 | data_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 | ||
1745 | static inline int | 1655 | rc = iscsi_send_data(ctask, &r2t->sendbuf, &r2t->sg, |
1746 | handle_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; |
1835 | unsolicit_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*)); | ||
1858 | solicit_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 | ||
1883 | done: | 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 | } |