aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-05-30 01:37:28 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-06-05 19:12:25 -0400
commit3219e5294150aee7d389e19029f49b44fb6b5c9f (patch)
tree44236fd9f2eb40d5622cadb126e9f2672b129486
parent040515f53c09047c76ad074dc6a280984dc84b04 (diff)
[SCSI] iscsi: fix writepsace race
We can race and misset the suspend bit if iscsi_write_space is called then iscsi_send returns with a failure indicating there is no space. To handle this this patch returns a error upwards allowing xmitworker to decide if we need to try and transmit again. For the no write space case xmitworker will not retry, and instead let iscsi_write_space queue it back up if needed (this relies on the work queue code to properly requeue us if needed). Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/iscsi_tcp.c182
-rw-r--r--drivers/scsi/libiscsi.c31
-rw-r--r--include/scsi/scsi_transport_iscsi.h8
3 files changed, 126 insertions, 95 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 2abda804a924..7fa85937a99f 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1006,7 +1006,6 @@ iscsi_write_space(struct sock *sk)
1006 1006
1007 tcp_conn->old_write_space(sk); 1007 tcp_conn->old_write_space(sk);
1008 debug_tcp("iscsi_write_space: cid %d\n", conn->id); 1008 debug_tcp("iscsi_write_space: cid %d\n", conn->id);
1009 clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1010 scsi_queue_work(conn->session->host, &conn->xmitwork); 1009 scsi_queue_work(conn->session->host, &conn->xmitwork);
1011} 1010}
1012 1011
@@ -1056,7 +1055,7 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
1056{ 1055{
1057 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1056 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1058 struct socket *sk = tcp_conn->sock; 1057 struct socket *sk = tcp_conn->sock;
1059 int offset = buf->sg.offset + buf->sent; 1058 int offset = buf->sg.offset + buf->sent, res;
1060 1059
1061 /* 1060 /*
1062 * if we got use_sg=0 or are sending something we kmallocd 1061 * if we got use_sg=0 or are sending something we kmallocd
@@ -1067,10 +1066,22 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
1067 * slab case. 1066 * slab case.
1068 */ 1067 */
1069 if (buf->use_sendmsg) 1068 if (buf->use_sendmsg)
1070 return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); 1069 res = sock_no_sendpage(sk, buf->sg.page, offset, size, flags);
1071 else 1070 else
1072 return tcp_conn->sendpage(sk, buf->sg.page, offset, size, 1071 res = tcp_conn->sendpage(sk, buf->sg.page, offset, size, flags);
1073 flags); 1072
1073 if (res >= 0) {
1074 conn->txdata_octets += res;
1075 buf->sent += res;
1076 return res;
1077 }
1078
1079 tcp_conn->sendpage_failures_cnt++;
1080 if (res == -EAGAIN)
1081 res = -ENOBUFS;
1082 else
1083 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1084 return res;
1074} 1085}
1075 1086
1076/** 1087/**
@@ -1085,7 +1096,6 @@ iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags)
1085static inline int 1096static inline int
1086iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) 1097iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
1087{ 1098{
1088 struct iscsi_tcp_conn *tcp_conn;
1089 int flags = 0; /* MSG_DONTWAIT; */ 1099 int flags = 0; /* MSG_DONTWAIT; */
1090 int res, size; 1100 int res, size;
1091 1101
@@ -1097,17 +1107,10 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen)
1097 res = iscsi_send(conn, buf, size, flags); 1107 res = iscsi_send(conn, buf, size, flags);
1098 debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); 1108 debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res);
1099 if (res >= 0) { 1109 if (res >= 0) {
1100 conn->txdata_octets += res;
1101 buf->sent += res;
1102 if (size != res) 1110 if (size != res)
1103 return -EAGAIN; 1111 return -EAGAIN;
1104 return 0; 1112 return 0;
1105 } else if (res == -EAGAIN) { 1113 }
1106 tcp_conn = conn->dd_data;
1107 tcp_conn->sendpage_failures_cnt++;
1108 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1109 } else if (res == -EPIPE)
1110 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1111 1114
1112 return res; 1115 return res;
1113} 1116}
@@ -1126,7 +1129,6 @@ static inline int
1126iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, 1129iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
1127 int *count, int *sent) 1130 int *count, int *sent)
1128{ 1131{
1129 struct iscsi_tcp_conn *tcp_conn;
1130 int flags = 0; /* MSG_DONTWAIT; */ 1132 int flags = 0; /* MSG_DONTWAIT; */
1131 int res, size; 1133 int res, size;
1132 1134
@@ -1141,19 +1143,12 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf,
1141 debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", 1143 debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n",
1142 size, buf->sent, *count, *sent, res); 1144 size, buf->sent, *count, *sent, res);
1143 if (res >= 0) { 1145 if (res >= 0) {
1144 conn->txdata_octets += res;
1145 buf->sent += res;
1146 *count -= res; 1146 *count -= res;
1147 *sent += res; 1147 *sent += res;
1148 if (size != res) 1148 if (size != res)
1149 return -EAGAIN; 1149 return -EAGAIN;
1150 return 0; 1150 return 0;
1151 } else if (res == -EAGAIN) { 1151 }
1152 tcp_conn = conn->dd_data;
1153 tcp_conn->sendpage_failures_cnt++;
1154 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
1155 } else if (res == -EPIPE)
1156 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1157 1152
1158 return res; 1153 return res;
1159} 1154}
@@ -1342,6 +1337,7 @@ static int
1342iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) 1337iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1343{ 1338{
1344 struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; 1339 struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
1340 int rc;
1345 1341
1346 debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", 1342 debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n",
1347 conn->id, tcp_mtask->xmstate, mtask->itt); 1343 conn->id, tcp_mtask->xmstate, mtask->itt);
@@ -1355,12 +1351,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1355 conn->hdrdgst_en) 1351 conn->hdrdgst_en)
1356 iscsi_hdr_digest(conn, &tcp_mtask->headbuf, 1352 iscsi_hdr_digest(conn, &tcp_mtask->headbuf,
1357 (u8*)tcp_mtask->hdrext); 1353 (u8*)tcp_mtask->hdrext);
1358 if (iscsi_sendhdr(conn, &tcp_mtask->headbuf, 1354 rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf,
1359 mtask->data_count)) { 1355 mtask->data_count);
1356 if (rc) {
1360 tcp_mtask->xmstate |= XMSTATE_IMM_HDR; 1357 tcp_mtask->xmstate |= XMSTATE_IMM_HDR;
1361 if (mtask->data_count) 1358 if (mtask->data_count)
1362 tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; 1359 tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA;
1363 return -EAGAIN; 1360 return rc;
1364 } 1361 }
1365 } 1362 }
1366 1363
@@ -1371,10 +1368,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1371 * Virtual buffer could be spreaded across multiple pages... 1368 * Virtual buffer could be spreaded across multiple pages...
1372 */ 1369 */
1373 do { 1370 do {
1374 if (iscsi_sendpage(conn, &tcp_mtask->sendbuf, 1371 int rc;
1375 &mtask->data_count, &tcp_mtask->sent)) { 1372
1373 rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf,
1374 &mtask->data_count, &tcp_mtask->sent);
1375 if (rc) {
1376 tcp_mtask->xmstate |= XMSTATE_IMM_DATA; 1376 tcp_mtask->xmstate |= XMSTATE_IMM_DATA;
1377 return -EAGAIN; 1377 return rc;
1378 } 1378 }
1379 } while (mtask->data_count); 1379 } while (mtask->data_count);
1380 } 1380 }
@@ -1396,16 +1396,19 @@ static inline int
1396handle_xmstate_r_hdr(struct iscsi_conn *conn, 1396handle_xmstate_r_hdr(struct iscsi_conn *conn,
1397 struct iscsi_tcp_cmd_task *tcp_ctask) 1397 struct iscsi_tcp_cmd_task *tcp_ctask)
1398{ 1398{
1399 int rc;
1400
1399 tcp_ctask->xmstate &= ~XMSTATE_R_HDR; 1401 tcp_ctask->xmstate &= ~XMSTATE_R_HDR;
1400 if (conn->hdrdgst_en) 1402 if (conn->hdrdgst_en)
1401 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1403 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1402 (u8*)tcp_ctask->hdrext); 1404 (u8*)tcp_ctask->hdrext);
1403 if (!iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0)) { 1405 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0);
1406 if (!rc) {
1404 BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); 1407 BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE);
1405 return 0; /* wait for Data-In */ 1408 return 0; /* wait for Data-In */
1406 } 1409 }
1407 tcp_ctask->xmstate |= XMSTATE_R_HDR; 1410 tcp_ctask->xmstate |= XMSTATE_R_HDR;
1408 return -EAGAIN; 1411 return rc;
1409} 1412}
1410 1413
1411static inline int 1414static inline int
@@ -1413,16 +1416,16 @@ handle_xmstate_w_hdr(struct iscsi_conn *conn,
1413 struct iscsi_cmd_task *ctask) 1416 struct iscsi_cmd_task *ctask)
1414{ 1417{
1415 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1418 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1419 int rc;
1416 1420
1417 tcp_ctask->xmstate &= ~XMSTATE_W_HDR; 1421 tcp_ctask->xmstate &= ~XMSTATE_W_HDR;
1418 if (conn->hdrdgst_en) 1422 if (conn->hdrdgst_en)
1419 iscsi_hdr_digest(conn, &tcp_ctask->headbuf, 1423 iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
1420 (u8*)tcp_ctask->hdrext); 1424 (u8*)tcp_ctask->hdrext);
1421 if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count)) { 1425 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
1426 if (rc)
1422 tcp_ctask->xmstate |= XMSTATE_W_HDR; 1427 tcp_ctask->xmstate |= XMSTATE_W_HDR;
1423 return -EAGAIN; 1428 return rc;
1424 }
1425 return 0;
1426} 1429}
1427 1430
1428static inline int 1431static inline int
@@ -1430,17 +1433,19 @@ handle_xmstate_data_digest(struct iscsi_conn *conn,
1430 struct iscsi_cmd_task *ctask) 1433 struct iscsi_cmd_task *ctask)
1431{ 1434{
1432 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1435 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1436 int rc;
1433 1437
1434 tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST; 1438 tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
1435 debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest); 1439 debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
1436 if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, 1440 rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
1437 &tcp_ctask->datadigest, 0)) { 1441 &tcp_ctask->datadigest, 0);
1442 if (rc) {
1438 tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST; 1443 tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
1439 debug_tcp("resent data digest 0x%x fail!\n", 1444 debug_tcp("resent data digest 0x%x fail!\n",
1440 tcp_ctask->datadigest); 1445 tcp_ctask->datadigest);
1441 return -EAGAIN;
1442 } 1446 }
1443 return 0; 1447
1448 return rc;
1444} 1449}
1445 1450
1446static inline int 1451static inline int
@@ -1448,6 +1453,7 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1448{ 1453{
1449 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1454 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1450 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1455 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1456 int rc;
1451 1457
1452 BUG_ON(!ctask->imm_count); 1458 BUG_ON(!ctask->imm_count);
1453 tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; 1459 tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
@@ -1458,8 +1464,9 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1458 } 1464 }
1459 1465
1460 for (;;) { 1466 for (;;) {
1461 if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &ctask->imm_count, 1467 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
1462 &tcp_ctask->sent)) { 1468 &ctask->imm_count, &tcp_ctask->sent);
1469 if (rc) {
1463 tcp_ctask->xmstate |= XMSTATE_IMM_DATA; 1470 tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
1464 if (conn->datadgst_en) { 1471 if (conn->datadgst_en) {
1465 crypto_digest_final(tcp_conn->data_tx_tfm, 1472 crypto_digest_final(tcp_conn->data_tx_tfm,
@@ -1467,7 +1474,7 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1467 debug_tcp("tx imm sendpage fail 0x%x\n", 1474 debug_tcp("tx imm sendpage fail 0x%x\n",
1468 tcp_ctask->datadigest); 1475 tcp_ctask->datadigest);
1469 } 1476 }
1470 return -EAGAIN; 1477 return rc;
1471 } 1478 }
1472 if (conn->datadgst_en) 1479 if (conn->datadgst_en)
1473 crypto_digest_update(tcp_conn->data_tx_tfm, 1480 crypto_digest_update(tcp_conn->data_tx_tfm,
@@ -1480,11 +1487,12 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1480 } 1487 }
1481 1488
1482 if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { 1489 if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
1483 if (iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf, 1490 rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
1484 &tcp_ctask->immdigest, 1)) { 1491 &tcp_ctask->immdigest, 1);
1492 if (rc) {
1485 debug_tcp("sending imm digest 0x%x fail!\n", 1493 debug_tcp("sending imm digest 0x%x fail!\n",
1486 tcp_ctask->immdigest); 1494 tcp_ctask->immdigest);
1487 return -EAGAIN; 1495 return rc;
1488 } 1496 }
1489 debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest); 1497 debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
1490 } 1498 }
@@ -1497,6 +1505,7 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1497{ 1505{
1498 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1506 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1499 struct iscsi_data_task *dtask; 1507 struct iscsi_data_task *dtask;
1508 int rc;
1500 1509
1501 tcp_ctask->xmstate |= XMSTATE_UNS_DATA; 1510 tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
1502 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { 1511 if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) {
@@ -1507,10 +1516,12 @@ handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1507 (u8*)dtask->hdrext); 1516 (u8*)dtask->hdrext);
1508 tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; 1517 tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT;
1509 } 1518 }
1510 if (iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count)) { 1519
1520 rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count);
1521 if (rc) {
1511 tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; 1522 tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
1512 tcp_ctask->xmstate |= XMSTATE_UNS_HDR; 1523 tcp_ctask->xmstate |= XMSTATE_UNS_HDR;
1513 return -EAGAIN; 1524 return rc;
1514 } 1525 }
1515 1526
1516 debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n", 1527 debug_scsi("uns dout [itt 0x%x dlen %d sent %d]\n",
@@ -1524,6 +1535,7 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1524 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1535 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1525 struct iscsi_data_task *dtask = tcp_ctask->dtask; 1536 struct iscsi_data_task *dtask = tcp_ctask->dtask;
1526 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1537 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1538 int rc;
1527 1539
1528 BUG_ON(!ctask->data_count); 1540 BUG_ON(!ctask->data_count);
1529 tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; 1541 tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA;
@@ -1536,8 +1548,9 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1536 for (;;) { 1548 for (;;) {
1537 int start = tcp_ctask->sent; 1549 int start = tcp_ctask->sent;
1538 1550
1539 if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, 1551 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
1540 &ctask->data_count, &tcp_ctask->sent)) { 1552 &ctask->data_count, &tcp_ctask->sent);
1553 if (rc) {
1541 ctask->unsol_count -= tcp_ctask->sent - start; 1554 ctask->unsol_count -= tcp_ctask->sent - start;
1542 tcp_ctask->xmstate |= XMSTATE_UNS_DATA; 1555 tcp_ctask->xmstate |= XMSTATE_UNS_DATA;
1543 /* will continue with this ctask later.. */ 1556 /* will continue with this ctask later.. */
@@ -1547,7 +1560,7 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1547 debug_tcp("tx uns data fail 0x%x\n", 1560 debug_tcp("tx uns data fail 0x%x\n",
1548 dtask->digest); 1561 dtask->digest);
1549 } 1562 }
1550 return -EAGAIN; 1563 return rc;
1551 } 1564 }
1552 1565
1553 BUG_ON(tcp_ctask->sent > ctask->total_length); 1566 BUG_ON(tcp_ctask->sent > ctask->total_length);
@@ -1574,12 +1587,13 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1574 */ 1587 */
1575 if (ctask->unsol_count) { 1588 if (ctask->unsol_count) {
1576 if (conn->datadgst_en) { 1589 if (conn->datadgst_en) {
1577 if (iscsi_digest_final_send(conn, ctask, 1590 rc = iscsi_digest_final_send(conn, ctask,
1578 &dtask->digestbuf, 1591 &dtask->digestbuf,
1579 &dtask->digest, 1)) { 1592 &dtask->digest, 1);
1593 if (rc) {
1580 debug_tcp("send uns digest 0x%x fail\n", 1594 debug_tcp("send uns digest 0x%x fail\n",
1581 dtask->digest); 1595 dtask->digest);
1582 return -EAGAIN; 1596 return rc;
1583 } 1597 }
1584 debug_tcp("sending uns digest 0x%x, more uns\n", 1598 debug_tcp("sending uns digest 0x%x, more uns\n",
1585 dtask->digest); 1599 dtask->digest);
@@ -1589,12 +1603,13 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1589 } 1603 }
1590 1604
1591 if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) { 1605 if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
1592 if (iscsi_digest_final_send(conn, ctask, 1606 rc = iscsi_digest_final_send(conn, ctask,
1593 &dtask->digestbuf, 1607 &dtask->digestbuf,
1594 &dtask->digest, 1)) { 1608 &dtask->digest, 1);
1609 if (rc) {
1595 debug_tcp("send last uns digest 0x%x fail\n", 1610 debug_tcp("send last uns digest 0x%x fail\n",
1596 dtask->digest); 1611 dtask->digest);
1597 return -EAGAIN; 1612 return rc;
1598 } 1613 }
1599 debug_tcp("sending uns digest 0x%x\n",dtask->digest); 1614 debug_tcp("sending uns digest 0x%x\n",dtask->digest);
1600 } 1615 }
@@ -1610,7 +1625,7 @@ handle_xmstate_sol_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1610 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1625 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1611 struct iscsi_r2t_info *r2t = tcp_ctask->r2t; 1626 struct iscsi_r2t_info *r2t = tcp_ctask->r2t;
1612 struct iscsi_data_task *dtask = &r2t->dtask; 1627 struct iscsi_data_task *dtask = &r2t->dtask;
1613 int left; 1628 int left, rc;
1614 1629
1615 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; 1630 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
1616 tcp_ctask->dtask = dtask; 1631 tcp_ctask->dtask = dtask;
@@ -1626,7 +1641,8 @@ solicit_again:
1626 if (!r2t->data_count) 1641 if (!r2t->data_count)
1627 goto data_out_done; 1642 goto data_out_done;
1628 1643
1629 if (iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent)) { 1644 rc = iscsi_sendpage(conn, &r2t->sendbuf, &r2t->data_count, &r2t->sent);
1645 if (rc) {
1630 tcp_ctask->xmstate |= XMSTATE_SOL_DATA; 1646 tcp_ctask->xmstate |= XMSTATE_SOL_DATA;
1631 /* will continue with this ctask later.. */ 1647 /* will continue with this ctask later.. */
1632 if (conn->datadgst_en) { 1648 if (conn->datadgst_en) {
@@ -1634,7 +1650,7 @@ solicit_again:
1634 (u8 *)&dtask->digest); 1650 (u8 *)&dtask->digest);
1635 debug_tcp("r2t data send fail 0x%x\n", dtask->digest); 1651 debug_tcp("r2t data send fail 0x%x\n", dtask->digest);
1636 } 1652 }
1637 return -EAGAIN; 1653 return rc;
1638 } 1654 }
1639 1655
1640 BUG_ON(r2t->data_count < 0); 1656 BUG_ON(r2t->data_count < 0);
@@ -1661,12 +1677,13 @@ data_out_done:
1661 left = r2t->data_length - r2t->sent; 1677 left = r2t->data_length - r2t->sent;
1662 if (left) { 1678 if (left) {
1663 if (conn->datadgst_en) { 1679 if (conn->datadgst_en) {
1664 if (iscsi_digest_final_send(conn, ctask, 1680 rc = iscsi_digest_final_send(conn, ctask,
1665 &dtask->digestbuf, 1681 &dtask->digestbuf,
1666 &dtask->digest, 1)) { 1682 &dtask->digest, 1);
1683 if (rc) {
1667 debug_tcp("send r2t data digest 0x%x" 1684 debug_tcp("send r2t data digest 0x%x"
1668 "fail\n", dtask->digest); 1685 "fail\n", dtask->digest);
1669 return -EAGAIN; 1686 return rc;
1670 } 1687 }
1671 debug_tcp("r2t data send digest 0x%x\n", 1688 debug_tcp("r2t data send digest 0x%x\n",
1672 dtask->digest); 1689 dtask->digest);
@@ -1683,11 +1700,12 @@ data_out_done:
1683 */ 1700 */
1684 BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0); 1701 BUG_ON(tcp_ctask->r2t_data_count - r2t->data_length < 0);
1685 if (conn->datadgst_en) { 1702 if (conn->datadgst_en) {
1686 if (iscsi_digest_final_send(conn, ctask, &dtask->digestbuf, 1703 rc = iscsi_digest_final_send(conn, ctask, &dtask->digestbuf,
1687 &dtask->digest, 1)) { 1704 &dtask->digest, 1);
1705 if (rc) {
1688 debug_tcp("send last r2t data digest 0x%x" 1706 debug_tcp("send last r2t data digest 0x%x"
1689 "fail\n", dtask->digest); 1707 "fail\n", dtask->digest);
1690 return -EAGAIN; 1708 return rc;
1691 } 1709 }
1692 debug_tcp("r2t done dout digest 0x%x\n", dtask->digest); 1710 debug_tcp("r2t done dout digest 0x%x\n", dtask->digest);
1693 } 1711 }
@@ -1713,15 +1731,16 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1713 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; 1731 struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
1714 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 1732 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
1715 struct iscsi_data_task *dtask = tcp_ctask->dtask; 1733 struct iscsi_data_task *dtask = tcp_ctask->dtask;
1716 int sent; 1734 int sent, rc;
1717 1735
1718 tcp_ctask->xmstate &= ~XMSTATE_W_PAD; 1736 tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
1719 iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, 1737 iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
1720 tcp_ctask->pad_count); 1738 tcp_ctask->pad_count);
1721 if (iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, 1739 rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
1722 &sent)) { 1740 &sent);
1741 if (rc) {
1723 tcp_ctask->xmstate |= XMSTATE_W_PAD; 1742 tcp_ctask->xmstate |= XMSTATE_W_PAD;
1724 return -EAGAIN; 1743 return rc;
1725 } 1744 }
1726 1745
1727 if (conn->datadgst_en) { 1746 if (conn->datadgst_en) {
@@ -1729,22 +1748,24 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1729 &tcp_ctask->sendbuf.sg, 1); 1748 &tcp_ctask->sendbuf.sg, 1);
1730 /* imm data? */ 1749 /* imm data? */
1731 if (!dtask) { 1750 if (!dtask) {
1732 if (iscsi_digest_final_send(conn, ctask, 1751 rc = iscsi_digest_final_send(conn, ctask,
1733 &tcp_ctask->immbuf, 1752 &tcp_ctask->immbuf,
1734 &tcp_ctask->immdigest, 1)) { 1753 &tcp_ctask->immdigest, 1);
1754 if (rc) {
1735 debug_tcp("send padding digest 0x%x" 1755 debug_tcp("send padding digest 0x%x"
1736 "fail!\n", tcp_ctask->immdigest); 1756 "fail!\n", tcp_ctask->immdigest);
1737 return -EAGAIN; 1757 return rc;
1738 } 1758 }
1739 debug_tcp("done with padding, digest 0x%x\n", 1759 debug_tcp("done with padding, digest 0x%x\n",
1740 tcp_ctask->datadigest); 1760 tcp_ctask->datadigest);
1741 } else { 1761 } else {
1742 if (iscsi_digest_final_send(conn, ctask, 1762 rc = iscsi_digest_final_send(conn, ctask,
1743 &dtask->digestbuf, 1763 &dtask->digestbuf,
1744 &dtask->digest, 1)) { 1764 &dtask->digest, 1);
1765 if (rc) {
1745 debug_tcp("send padding digest 0x%x" 1766 debug_tcp("send padding digest 0x%x"
1746 "fail\n", dtask->digest); 1767 "fail\n", dtask->digest);
1747 return -EAGAIN; 1768 return rc;
1748 } 1769 }
1749 debug_tcp("done with padding, digest 0x%x\n", 1770 debug_tcp("done with padding, digest 0x%x\n",
1750 dtask->digest); 1771 dtask->digest);
@@ -1769,10 +1790,8 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
1769 if (ctask->mtask) 1790 if (ctask->mtask)
1770 return rc; 1791 return rc;
1771 1792
1772 if (tcp_ctask->xmstate & XMSTATE_R_HDR) { 1793 if (tcp_ctask->xmstate & XMSTATE_R_HDR)
1773 rc = handle_xmstate_r_hdr(conn, tcp_ctask); 1794 return handle_xmstate_r_hdr(conn, tcp_ctask);
1774 return rc;
1775 }
1776 1795
1777 if (tcp_ctask->xmstate & XMSTATE_W_HDR) { 1796 if (tcp_ctask->xmstate & XMSTATE_W_HDR) {
1778 rc = handle_xmstate_w_hdr(conn, ctask); 1797 rc = handle_xmstate_w_hdr(conn, ctask);
@@ -1824,10 +1843,11 @@ solicit_head_again:
1824 if (conn->hdrdgst_en) 1843 if (conn->hdrdgst_en)
1825 iscsi_hdr_digest(conn, &r2t->headbuf, 1844 iscsi_hdr_digest(conn, &r2t->headbuf,
1826 (u8*)r2t->dtask.hdrext); 1845 (u8*)r2t->dtask.hdrext);
1827 if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { 1846 rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count);
1847 if (rc) {
1828 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; 1848 tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA;
1829 tcp_ctask->xmstate |= XMSTATE_SOL_HDR; 1849 tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
1830 return -EAGAIN; 1850 return rc;
1831 } 1851 }
1832 1852
1833 debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n", 1853 debug_scsi("sol dout [dsn %d itt 0x%x dlen %d sent %d]\n",
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 256b87a85978..2673a11a9495 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -513,10 +513,11 @@ EXPORT_SYMBOL_GPL(iscsi_conn_failure);
513static int iscsi_data_xmit(struct iscsi_conn *conn) 513static int iscsi_data_xmit(struct iscsi_conn *conn)
514{ 514{
515 struct iscsi_transport *tt; 515 struct iscsi_transport *tt;
516 int rc = 0;
516 517
517 if (unlikely(conn->suspend_tx)) { 518 if (unlikely(conn->suspend_tx)) {
518 debug_scsi("conn %d Tx suspended!\n", conn->id); 519 debug_scsi("conn %d Tx suspended!\n", conn->id);
519 return 0; 520 return -ENODATA;
520 } 521 }
521 tt = conn->session->tt; 522 tt = conn->session->tt;
522 523
@@ -536,13 +537,15 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
536 BUG_ON(conn->ctask && conn->mtask); 537 BUG_ON(conn->ctask && conn->mtask);
537 538
538 if (conn->ctask) { 539 if (conn->ctask) {
539 if (tt->xmit_cmd_task(conn, conn->ctask)) 540 rc = tt->xmit_cmd_task(conn, conn->ctask);
541 if (rc)
540 goto again; 542 goto again;
541 /* done with this in-progress ctask */ 543 /* done with this in-progress ctask */
542 conn->ctask = NULL; 544 conn->ctask = NULL;
543 } 545 }
544 if (conn->mtask) { 546 if (conn->mtask) {
545 if (tt->xmit_mgmt_task(conn, conn->mtask)) 547 rc = tt->xmit_mgmt_task(conn, conn->mtask);
548 if (rc)
546 goto again; 549 goto again;
547 /* done with this in-progress mtask */ 550 /* done with this in-progress mtask */
548 conn->mtask = NULL; 551 conn->mtask = NULL;
@@ -556,7 +559,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
556 list_add_tail(&conn->mtask->running, 559 list_add_tail(&conn->mtask->running,
557 &conn->mgmt_run_list); 560 &conn->mgmt_run_list);
558 spin_unlock_bh(&conn->session->lock); 561 spin_unlock_bh(&conn->session->lock);
559 if (tt->xmit_mgmt_task(conn, conn->mtask)) 562 rc = tt->xmit_mgmt_task(conn, conn->mtask);
563 if (rc)
560 goto again; 564 goto again;
561 } 565 }
562 /* done with this mtask */ 566 /* done with this mtask */
@@ -574,7 +578,8 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
574 if (list_empty(&conn->ctask->running)) 578 if (list_empty(&conn->ctask->running))
575 list_add_tail(&conn->ctask->running, &conn->run_list); 579 list_add_tail(&conn->ctask->running, &conn->run_list);
576 spin_unlock_bh(&conn->session->lock); 580 spin_unlock_bh(&conn->session->lock);
577 if (tt->xmit_cmd_task(conn, conn->ctask)) 581 rc = tt->xmit_cmd_task(conn, conn->ctask);
582 if (rc)
578 goto again; 583 goto again;
579 } 584 }
580 /* done with this ctask */ 585 /* done with this ctask */
@@ -588,32 +593,34 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
588 list_add_tail(&conn->mtask->running, 593 list_add_tail(&conn->mtask->running,
589 &conn->mgmt_run_list); 594 &conn->mgmt_run_list);
590 spin_unlock_bh(&conn->session->lock); 595 spin_unlock_bh(&conn->session->lock);
591 if (tt->xmit_mgmt_task(conn, conn->mtask)) 596 rc = tt->xmit_mgmt_task(conn, conn->mtask);
597 if (rc)
592 goto again; 598 goto again;
593 } 599 }
594 /* done with this mtask */ 600 /* done with this mtask */
595 conn->mtask = NULL; 601 conn->mtask = NULL;
596 } 602 }
597 603
598 return 0; 604 return -ENODATA;
599 605
600again: 606again:
601 if (unlikely(conn->suspend_tx)) 607 if (unlikely(conn->suspend_tx))
602 return 0; 608 return -ENODATA;
603 609
604 return -EAGAIN; 610 return rc;
605} 611}
606 612
607static void iscsi_xmitworker(void *data) 613static void iscsi_xmitworker(void *data)
608{ 614{
609 struct iscsi_conn *conn = data; 615 struct iscsi_conn *conn = data;
610 616 int rc;
611 /* 617 /*
612 * serialize Xmit worker on a per-connection basis. 618 * serialize Xmit worker on a per-connection basis.
613 */ 619 */
614 mutex_lock(&conn->xmitmutex); 620 mutex_lock(&conn->xmitmutex);
615 if (iscsi_data_xmit(conn)) 621 do {
616 scsi_queue_work(conn->session->host, &conn->xmitwork); 622 rc = iscsi_data_xmit(conn);
623 } while (rc >= 0 || rc == -EAGAIN);
617 mutex_unlock(&conn->xmitmutex); 624 mutex_unlock(&conn->xmitmutex);
618} 625}
619 626
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 92129b97d31e..b684426a5900 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -57,8 +57,12 @@ struct iscsi_mgmt_task;
57 * Called from queuecommand with session lock held. 57 * Called from queuecommand with session lock held.
58 * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs. 58 * @init_mgmt_task: Initialize a iscsi_mgmt_task and any internal structs.
59 * Called from iscsi_conn_send_generic with xmitmutex. 59 * Called from iscsi_conn_send_generic with xmitmutex.
60 * @xmit_cmd_task: requests LLD to transfer cmd task 60 * @xmit_cmd_task: Requests LLD to transfer cmd task. Returns 0 or the
61 * @xmit_mgmt_task: requests LLD to transfer mgmt task 61 * the number of bytes transferred on success, and -Exyz
62 * value on error.
63 * @xmit_mgmt_task: Requests LLD to transfer mgmt task. Returns 0 or the
64 * the number of bytes transferred on success, and -Exyz
65 * value on error.
62 * @cleanup_cmd_task: requests LLD to fail cmd task. Called with xmitmutex 66 * @cleanup_cmd_task: requests LLD to fail cmd task. Called with xmitmutex
63 * and session->lock after the connection has been 67 * and session->lock after the connection has been
64 * suspended and terminated during recovery. If called 68 * suspended and terminated during recovery. If called