diff options
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 636 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.h | 33 | ||||
-rw-r--r-- | drivers/scsi/libiscsi.c | 37 |
3 files changed, 286 insertions, 420 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 | } |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index aace8f70dfd7..7e40e94d9fdc 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
@@ -31,23 +31,21 @@ | |||
31 | #define IN_PROGRESS_DDIGEST_RECV 0x3 | 31 | #define IN_PROGRESS_DDIGEST_RECV 0x3 |
32 | 32 | ||
33 | /* xmit state machine */ | 33 | /* xmit state machine */ |
34 | #define XMSTATE_IDLE 0x0 | 34 | #define XMSTATE_IDLE 0x0 |
35 | #define XMSTATE_R_HDR 0x1 | 35 | #define XMSTATE_R_HDR 0x1 |
36 | #define XMSTATE_W_HDR 0x2 | 36 | #define XMSTATE_W_HDR 0x2 |
37 | #define XMSTATE_IMM_HDR 0x4 | 37 | #define XMSTATE_IMM_HDR 0x4 |
38 | #define XMSTATE_IMM_DATA 0x8 | 38 | #define XMSTATE_IMM_DATA 0x8 |
39 | #define XMSTATE_UNS_INIT 0x10 | 39 | #define XMSTATE_UNS_INIT 0x10 |
40 | #define XMSTATE_UNS_HDR 0x20 | 40 | #define XMSTATE_UNS_HDR 0x20 |
41 | #define XMSTATE_UNS_DATA 0x40 | 41 | #define XMSTATE_UNS_DATA 0x40 |
42 | #define XMSTATE_SOL_HDR 0x80 | 42 | #define XMSTATE_SOL_HDR 0x80 |
43 | #define XMSTATE_SOL_DATA 0x100 | 43 | #define XMSTATE_SOL_DATA 0x100 |
44 | #define XMSTATE_W_PAD 0x200 | 44 | #define XMSTATE_W_PAD 0x200 |
45 | #define XMSTATE_DATA_DIGEST 0x400 | 45 | #define XMSTATE_W_RESEND_PAD 0x400 |
46 | 46 | #define XMSTATE_W_RESEND_DATA_DIGEST 0x800 | |
47 | #define ISCSI_CONN_RCVBUF_MIN 262144 | 47 | |
48 | #define ISCSI_CONN_SNDBUF_MIN 262144 | ||
49 | #define ISCSI_PAD_LEN 4 | 48 | #define ISCSI_PAD_LEN 4 |
50 | #define ISCSI_R2T_MAX 16 | ||
51 | #define ISCSI_SG_TABLESIZE SG_ALL | 49 | #define ISCSI_SG_TABLESIZE SG_ALL |
52 | #define ISCSI_TCP_MAX_CMD_LEN 16 | 50 | #define ISCSI_TCP_MAX_CMD_LEN 16 |
53 | 51 | ||
@@ -162,13 +160,10 @@ struct iscsi_tcp_cmd_task { | |||
162 | struct iscsi_queue r2tpool; | 160 | struct iscsi_queue r2tpool; |
163 | struct kfifo *r2tqueue; | 161 | struct kfifo *r2tqueue; |
164 | struct iscsi_r2t_info **r2ts; | 162 | struct iscsi_r2t_info **r2ts; |
165 | uint32_t datadigest; /* for recover digest */ | ||
166 | int digest_count; | 163 | int digest_count; |
167 | uint32_t immdigest; /* for imm data */ | 164 | uint32_t immdigest; /* for imm data */ |
168 | struct iscsi_buf immbuf; /* for imm data digest */ | 165 | struct iscsi_buf immbuf; /* for imm data digest */ |
169 | struct iscsi_data_task *dtask; /* data task in progress*/ | ||
170 | struct iscsi_data_task unsol_dtask; /* unsol data task */ | 166 | struct iscsi_data_task unsol_dtask; /* unsol data task */ |
171 | int digest_offset; /* for partial buff digest */ | ||
172 | }; | 167 | }; |
173 | 168 | ||
174 | #endif /* ISCSI_H */ | 169 | #endif /* ISCSI_H */ |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 9584cbc082fe..fb65311c81dd 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -325,6 +325,30 @@ static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) | |||
325 | wake_up(&conn->ehwait); | 325 | wake_up(&conn->ehwait); |
326 | } | 326 | } |
327 | 327 | ||
328 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | ||
329 | char *data, int datalen) | ||
330 | { | ||
331 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; | ||
332 | struct iscsi_hdr rejected_pdu; | ||
333 | uint32_t itt; | ||
334 | |||
335 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; | ||
336 | |||
337 | if (reject->reason == ISCSI_REASON_DATA_DIGEST_ERROR) { | ||
338 | if (ntoh24(reject->dlength) > datalen) | ||
339 | return ISCSI_ERR_PROTO; | ||
340 | |||
341 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { | ||
342 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); | ||
343 | itt = rejected_pdu.itt & ISCSI_ITT_MASK; | ||
344 | printk(KERN_ERR "itt 0x%x had pdu (op 0x%x) rejected " | ||
345 | "due to DataDigest error.\n", itt, | ||
346 | rejected_pdu.opcode); | ||
347 | } | ||
348 | } | ||
349 | return 0; | ||
350 | } | ||
351 | |||
328 | /** | 352 | /** |
329 | * __iscsi_complete_pdu - complete pdu | 353 | * __iscsi_complete_pdu - complete pdu |
330 | * @conn: iscsi conn | 354 | * @conn: iscsi conn |
@@ -436,6 +460,11 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
436 | break; | 460 | break; |
437 | } | 461 | } |
438 | } else if (itt == ISCSI_RESERVED_TAG) { | 462 | } else if (itt == ISCSI_RESERVED_TAG) { |
463 | rc = iscsi_check_assign_cmdsn(session, | ||
464 | (struct iscsi_nopin*)hdr); | ||
465 | if (rc) | ||
466 | goto done; | ||
467 | |||
439 | switch(opcode) { | 468 | switch(opcode) { |
440 | case ISCSI_OP_NOOP_IN: | 469 | case ISCSI_OP_NOOP_IN: |
441 | if (datalen) { | 470 | if (datalen) { |
@@ -443,11 +472,6 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
443 | break; | 472 | break; |
444 | } | 473 | } |
445 | 474 | ||
446 | rc = iscsi_check_assign_cmdsn(session, | ||
447 | (struct iscsi_nopin*)hdr); | ||
448 | if (rc) | ||
449 | break; | ||
450 | |||
451 | if (hdr->ttt == ISCSI_RESERVED_TAG) | 475 | if (hdr->ttt == ISCSI_RESERVED_TAG) |
452 | break; | 476 | break; |
453 | 477 | ||
@@ -455,7 +479,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
455 | rc = ISCSI_ERR_CONN_FAILED; | 479 | rc = ISCSI_ERR_CONN_FAILED; |
456 | break; | 480 | break; |
457 | case ISCSI_OP_REJECT: | 481 | case ISCSI_OP_REJECT: |
458 | /* we need sth like iscsi_reject_rsp()*/ | 482 | rc = iscsi_handle_reject(conn, hdr, data, datalen); |
483 | break; | ||
459 | case ISCSI_OP_ASYNC_EVENT: | 484 | case ISCSI_OP_ASYNC_EVENT: |
460 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 485 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
461 | /* we need sth like iscsi_async_event_rsp() */ | 486 | /* we need sth like iscsi_async_event_rsp() */ |