aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2007-05-30 13:57:17 -0400
committerJames Bottomley <jejb@mulgrave.(none)>2007-06-01 12:59:26 -0400
commit218432c68085d6c2b04df57daaf105d2ffa2aa61 (patch)
treecdc4646cc1d20f16bea893fb366f24c3ea50f0af /drivers/scsi/iscsi_tcp.c
parentb2c6416736b847b91950bd43cc5153e11a1f83ee (diff)
[SCSI] iscsi tcp: fix iscsi xmit state machine
If iscsi_tcp partially sends a header, it would recalculate the header size and readd the size of the digest (if header digests are used).This would cause us to send sizeof(digest) extra bytes when we sent the rest of the header. 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.c258
1 files changed, 145 insertions, 113 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 1e722f5aabd4..0afdca2224c2 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -109,7 +109,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn, struct iscsi_buf *buf,
109 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 109 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
110 110
111 crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc); 111 crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
112 buf->sg.length = tcp_conn->hdr_size; 112 buf->sg.length += sizeof(u32);
113} 113}
114 114
115static inline int 115static inline int
@@ -423,7 +423,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
423 423
424 tcp_ctask->exp_datasn = r2tsn + 1; 424 tcp_ctask->exp_datasn = r2tsn + 1;
425 __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); 425 __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
426 tcp_ctask->xmstate |= XMSTATE_SOL_HDR; 426 tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT;
427 list_move_tail(&ctask->running, &conn->xmitqueue); 427 list_move_tail(&ctask->running, &conn->xmitqueue);
428 428
429 scsi_queue_work(session->host, &conn->xmitwork); 429 scsi_queue_work(session->host, &conn->xmitwork);
@@ -1284,41 +1284,10 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask,
1284static void 1284static void
1285iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) 1285iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
1286{ 1286{
1287 struct scsi_cmnd *sc = ctask->sc;
1288 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1287 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1289 1288
1290 BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); 1289 BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
1291 1290 tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT;
1292 tcp_ctask->sent = 0;
1293 tcp_ctask->sg_count = 0;
1294 tcp_ctask->exp_datasn = 0;
1295
1296 if (sc->sc_data_direction == DMA_TO_DEVICE) {
1297 tcp_ctask->xmstate = XMSTATE_W_HDR;
1298 BUG_ON(sc->request_bufflen == 0);
1299
1300 if (sc->use_sg) {
1301 struct scatterlist *sg = sc->request_buffer;
1302
1303 iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
1304 tcp_ctask->sg = sg + 1;
1305 tcp_ctask->bad_sg = sg + sc->use_sg;
1306 } else {
1307 iscsi_buf_init_iov(&tcp_ctask->sendbuf,
1308 sc->request_buffer,
1309 sc->request_bufflen);
1310 tcp_ctask->sg = NULL;
1311 tcp_ctask->bad_sg = NULL;
1312 }
1313 debug_scsi("cmd [itt 0x%x total %d imm_data %d "
1314 "unsol count %d, unsol offset %d]\n",
1315 ctask->itt, sc->request_bufflen, ctask->imm_count,
1316 ctask->unsol_count, ctask->unsol_offset);
1317 } else
1318 tcp_ctask->xmstate = XMSTATE_R_HDR;
1319
1320 iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
1321 sizeof(struct iscsi_hdr));
1322} 1291}
1323 1292
1324/** 1293/**
@@ -1331,9 +1300,11 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
1331 * call it again later, or recover. '0' return code means successful 1300 * call it again later, or recover. '0' return code means successful
1332 * xmit. 1301 * xmit.
1333 * 1302 *
1334 * Management xmit state machine consists of two states: 1303 * Management xmit state machine consists of these states:
1335 * IN_PROGRESS_IMM_HEAD - PDU Header xmit in progress 1304 * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header
1336 * IN_PROGRESS_IMM_DATA - PDU Data xmit in progress 1305 * XMSTATE_IMM_HDR - PDU Header xmit in progress
1306 * XMSTATE_IMM_DATA - PDU Data xmit in progress
1307 * XMSTATE_IDLE - management PDU is done
1337 **/ 1308 **/
1338static int 1309static int
1339iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) 1310iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
@@ -1344,23 +1315,34 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1344 debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", 1315 debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
1345 conn->id, tcp_mtask->xmstate, mtask->itt); 1316 conn->id, tcp_mtask->xmstate, mtask->itt);
1346 1317
1347 if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { 1318 if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) {
1348 tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; 1319 iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
1349 if (mtask->data_count) 1320 sizeof(struct iscsi_hdr));
1321
1322 if (mtask->data_count) {
1350 tcp_mtask->xmstate |= XMSTATE_IMM_DATA; 1323 tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
1324 iscsi_buf_init_iov(&tcp_mtask->sendbuf,
1325 (char*)mtask->data,
1326 mtask->data_count);
1327 }
1328
1351 if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && 1329 if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE &&
1352 conn->stop_stage != STOP_CONN_RECOVER && 1330 conn->stop_stage != STOP_CONN_RECOVER &&
1353 conn->hdrdgst_en) 1331 conn->hdrdgst_en)
1354 iscsi_hdr_digest(conn, &tcp_mtask->headbuf, 1332 iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
1355 (u8*)tcp_mtask->hdrext); 1333 (u8*)tcp_mtask->hdrext);
1334
1335 tcp_mtask->sent = 0;
1336 tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT;
1337 tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
1338 }
1339
1340 if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) {
1356 rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, 1341 rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
1357 mtask->data_count); 1342 mtask->data_count);
1358 if (rc) { 1343 if (rc)
1359 tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
1360 if (mtask->data_count)
1361 tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
1362 return rc; 1344 return rc;
1363 } 1345 tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR;
1364 } 1346 }
1365 1347
1366 if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { 1348 if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) {
@@ -1394,55 +1376,75 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1394 return 0; 1376 return 0;
1395} 1377}
1396 1378
1397static inline int 1379static int
1398iscsi_send_read_hdr(struct iscsi_conn *conn, 1380iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1399 struct iscsi_tcp_cmd_task *tcp_ctask)
1400{ 1381{
1401 int rc; 1382 struct scsi_cmnd *sc = ctask->sc;
1383 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1384 int rc = 0;
1402 1385
1403 tcp_ctask->xmstate &= ~XMSTATE_R_HDR; 1386 if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) {
1404 if (conn->hdrdgst_en) 1387 tcp_ctask->sent = 0;
1405 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1388 tcp_ctask->sg_count = 0;
1406 (u8*)tcp_ctask->hdrext); 1389 tcp_ctask->exp_datasn = 0;
1407 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0); 1390
1408 if (!rc) { 1391 if (sc->sc_data_direction == DMA_TO_DEVICE) {
1409 BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); 1392 if (sc->use_sg) {
1410 return 0; /* wait for Data-In */ 1393 struct scatterlist *sg = sc->request_buffer;
1411 } 1394
1412 tcp_ctask->xmstate |= XMSTATE_R_HDR; 1395 iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg);
1413 return rc; 1396 tcp_ctask->sg = sg + 1;
1414} 1397 tcp_ctask->bad_sg = sg + sc->use_sg;
1398 } else {
1399 iscsi_buf_init_iov(&tcp_ctask->sendbuf,
1400 sc->request_buffer,
1401 sc->request_bufflen);
1402 tcp_ctask->sg = NULL;
1403 tcp_ctask->bad_sg = NULL;
1404 }
1415 1405
1416static inline int 1406 debug_scsi("cmd [itt 0x%x total %d imm_data %d "
1417iscsi_send_write_hdr(struct iscsi_conn *conn, 1407 "unsol count %d, unsol offset %d]\n",
1418 struct iscsi_cmd_task *ctask) 1408 ctask->itt, sc->request_bufflen,
1419{ 1409 ctask->imm_count, ctask->unsol_count,
1420 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1410 ctask->unsol_offset);
1421 int rc; 1411 }
1422 1412
1423 tcp_ctask->xmstate &= ~XMSTATE_W_HDR; 1413 iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr,
1424 if (conn->hdrdgst_en) 1414 sizeof(struct iscsi_hdr));
1425 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1415
1426 (u8*)tcp_ctask->hdrext); 1416 if (conn->hdrdgst_en)
1427 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); 1417 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1428 if (rc) { 1418 (u8*)tcp_ctask->hdrext);
1429 tcp_ctask->xmstate |= XMSTATE_W_HDR; 1419 tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT;
1430 return rc; 1420 tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT;
1431 } 1421 }
1432 1422
1433 if (ctask->imm_count) { 1423 if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) {
1434 tcp_ctask->xmstate |= XMSTATE_IMM_DATA; 1424 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
1435 iscsi_set_padding(tcp_ctask, ctask->imm_count); 1425 if (rc)
1426 return rc;
1427 tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT;
1428
1429 if (sc->sc_data_direction != DMA_TO_DEVICE)
1430 return 0;
1431
1432 if (ctask->imm_count) {
1433 tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
1434 iscsi_set_padding(tcp_ctask, ctask->imm_count);
1436 1435
1437 if (ctask->conn->datadgst_en) { 1436 if (ctask->conn->datadgst_en) {
1438 iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask); 1437 iscsi_data_digest_init(ctask->conn->dd_data,
1439 tcp_ctask->immdigest = 0; 1438 tcp_ctask);
1439 tcp_ctask->immdigest = 0;
1440 }
1440 } 1441 }
1441 }
1442 1442
1443 if (ctask->unsol_count) 1443 if (ctask->unsol_count)
1444 tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; 1444 tcp_ctask->xmstate |=
1445 return 0; 1445 XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
1446 }
1447 return rc;
1446} 1448}
1447 1449
1448static int 1450static int
@@ -1631,9 +1633,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn,
1631 struct iscsi_data_task *dtask; 1633 struct iscsi_data_task *dtask;
1632 int left, rc; 1634 int left, rc;
1633 1635
1634 if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { 1636 if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) {
1635 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1636 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1637 if (!tcp_ctask->r2t) { 1637 if (!tcp_ctask->r2t) {
1638 spin_lock_bh(&session->lock); 1638 spin_lock_bh(&session->lock);
1639 __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, 1639 __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t,
@@ -1647,12 +1647,19 @@ send_hdr:
1647 if (conn->hdrdgst_en) 1647 if (conn->hdrdgst_en)
1648 iscsi_hdr_digest(conn, &r2t->headbuf, 1648 iscsi_hdr_digest(conn, &r2t->headbuf,
1649 (u8*)dtask->hdrext); 1649 (u8*)dtask->hdrext);
1650 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT;
1651 tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
1652 }
1653
1654 if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) {
1655 r2t = tcp_ctask->r2t;
1656 dtask = &r2t->dtask;
1657
1650 rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); 1658 rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
1651 if (rc) { 1659 if (rc)
1652 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
1653 tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
1654 return rc; 1660 return rc;
1655 } 1661 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1662 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1656 1663
1657 if (conn->datadgst_en) { 1664 if (conn->datadgst_en) {
1658 iscsi_data_digest_init(conn->dd_data, tcp_ctask); 1665 iscsi_data_digest_init(conn->dd_data, tcp_ctask);
@@ -1684,8 +1691,6 @@ send_hdr:
1684 left = r2t->data_length - r2t->sent; 1691 left = r2t->data_length - r2t->sent;
1685 if (left) { 1692 if (left) {
1686 iscsi_solicit_data_cont(conn, ctask, r2t, left); 1693 iscsi_solicit_data_cont(conn, ctask, r2t, left);
1687 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1688 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1689 goto send_hdr; 1694 goto send_hdr;
1690 } 1695 }
1691 1696
@@ -1700,8 +1705,6 @@ send_hdr:
1700 if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, 1705 if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t,
1701 sizeof(void*))) { 1706 sizeof(void*))) {
1702 tcp_ctask->r2t = r2t; 1707 tcp_ctask->r2t = r2t;
1703 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1704 tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR;
1705 spin_unlock_bh(&session->lock); 1708 spin_unlock_bh(&session->lock);
1706 goto send_hdr; 1709 goto send_hdr;
1707 } 1710 }
@@ -1710,6 +1713,46 @@ send_hdr:
1710 return 0; 1713 return 0;
1711} 1714}
1712 1715
1716/**
1717 * iscsi_tcp_ctask_xmit - xmit normal PDU task
1718 * @conn: iscsi connection
1719 * @ctask: iscsi command task
1720 *
1721 * Notes:
1722 * The function can return -EAGAIN in which case caller must
1723 * call it again later, or recover. '0' return code means successful
1724 * xmit.
1725 * The function is devided to logical helpers (above) for the different
1726 * xmit stages.
1727 *
1728 *iscsi_send_cmd_hdr()
1729 * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate
1730 * Header Digest
1731 * XMSTATE_CMD_HDR_XMIT - Transmit header in progress
1732 *
1733 *iscsi_send_padding
1734 * XMSTATE_W_PAD - Prepare and send pading
1735 * XMSTATE_W_RESEND_PAD - retry send pading
1736 *
1737 *iscsi_send_digest
1738 * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest
1739 * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest
1740 *
1741 *iscsi_send_unsol_hdr
1742 * XMSTATE_UNS_INIT - prepare un-solicit data header and digest
1743 * XMSTATE_UNS_HDR - send un-solicit header
1744 *
1745 *iscsi_send_unsol_pdu
1746 * XMSTATE_UNS_DATA - send un-solicit data in progress
1747 *
1748 *iscsi_send_sol_pdu
1749 * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize
1750 * XMSTATE_SOL_HDR - send solicit header
1751 * XMSTATE_SOL_DATA - send solicit data
1752 *
1753 *iscsi_tcp_ctask_xmit
1754 * XMSTATE_IMM_DATA - xmit managment data (??)
1755 **/
1713static int 1756static int
1714iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) 1757iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1715{ 1758{
@@ -1725,14 +1768,11 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1725 if (ctask->mtask) 1768 if (ctask->mtask)
1726 return rc; 1769 return rc;
1727 1770
1728 if (tcp_ctask->xmstate & XMSTATE_R_HDR) 1771 rc = iscsi_send_cmd_hdr(conn, ctask);
1729 return iscsi_send_read_hdr(conn, tcp_ctask); 1772 if (rc)
1730 1773 return rc;
1731 if (tcp_ctask->xmstate & XMSTATE_W_HDR) { 1774 if (ctask->sc->sc_data_direction != DMA_TO_DEVICE)
1732 rc = iscsi_send_write_hdr(conn, ctask); 1775 return 0;
1733 if (rc)
1734 return rc;
1735 }
1736 1776
1737 if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { 1777 if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) {
1738 rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, 1778 rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg,
@@ -1913,15 +1953,7 @@ iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask,
1913 char *data, uint32_t data_size) 1953 char *data, uint32_t data_size)
1914{ 1954{
1915 struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; 1955 struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
1916 1956 tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT;
1917 iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr,
1918 sizeof(struct iscsi_hdr));
1919 tcp_mtask->xmstate = XMSTATE_IMM_HDR;
1920 tcp_mtask->sent = 0;
1921
1922 if (mtask->data_count)
1923 iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data,
1924 mtask->data_count);
1925} 1957}
1926 1958
1927static int 1959static int