diff options
author | Tony Battersby <tonyb@cybernetics.com> | 2007-11-14 15:38:42 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2007-11-14 15:51:58 -0500 |
commit | 505f76b3061f6e74a50f378e45ac931abc1fe784 (patch) | |
tree | 55074ebf00aa0f7fc336d83392a01b20267978c6 /drivers | |
parent | 5f78e89b5f7041895c4820be5c000792243b634f (diff) |
[SCSI] iscsi_tcp: fix potential lockup with write commands
There is a race condition in iscsi_tcp.c that may cause it to forget
that it received a R2T from the target. This race may cause a data-out
command (such as a write) to lock up. The race occurs here:
static int
iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
int rc;
if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) {
BUG_ON(!ctask->unsol_count);
tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; <---- RACE
...
static int
iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
...
tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; <---- RACE
...
While iscsi_xmitworker() (called from scsi_queue_work()) is preparing to
send unsolicited data, iscsi_tcp_data_recv() (called from
tcp_read_sock()) interrupts it upon receipt of a R2T from the target.
Both contexts do read-modify-write of tcp_ctask->xmstate. Usually, gcc
on x86 will make &= and |= atomic on UP (not guaranteed of course), but
in this case iscsi_send_unsol_pdu() reads the value of xmstate before
clearing the bit, which causes gcc to read xmstate into a CPU register,
test it, clear the bit, and then store it back to memory. If the recv
interrupt happens during this sequence, then the XMSTATE_SOL_HDR_INIT
bit set by the recv interrupt will be lost, and the R2T will be
forgotten.
The patch below (against 2.6.24-rc1) converts accesses of xmstate to use
set_bit, clear_bit, and test_bit instead of |= and &=. I have tested
this patch and verified that it fixes the problem. Another possible
approach would be to hold a lock during most of the rx/tx setup and
post-processing, and drop the lock only for the actual rx/tx.
Signed-off-by: Tony Battersby <tonyb@cybernetics.com>
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 139 | ||||
-rw-r--r-- | drivers/scsi/iscsi_tcp.h | 34 |
2 files changed, 86 insertions, 87 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 4bcf916c21a7..57ce2251abc8 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -197,7 +197,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
197 | if (unlikely(!sc)) | 197 | if (unlikely(!sc)) |
198 | return; | 198 | return; |
199 | 199 | ||
200 | tcp_ctask->xmstate = XMSTATE_IDLE; | 200 | tcp_ctask->xmstate = XMSTATE_VALUE_IDLE; |
201 | tcp_ctask->r2t = NULL; | 201 | tcp_ctask->r2t = NULL; |
202 | } | 202 | } |
203 | 203 | ||
@@ -409,7 +409,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
409 | 409 | ||
410 | tcp_ctask->exp_datasn = r2tsn + 1; | 410 | tcp_ctask->exp_datasn = r2tsn + 1; |
411 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); | 411 | __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); |
412 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; | 412 | set_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); |
413 | list_move_tail(&ctask->running, &conn->xmitqueue); | 413 | list_move_tail(&ctask->running, &conn->xmitqueue); |
414 | 414 | ||
415 | scsi_queue_work(session->host, &conn->xmitwork); | 415 | scsi_queue_work(session->host, &conn->xmitwork); |
@@ -1254,7 +1254,7 @@ static void iscsi_set_padding(struct iscsi_tcp_cmd_task *tcp_ctask, | |||
1254 | 1254 | ||
1255 | tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; | 1255 | tcp_ctask->pad_count = ISCSI_PAD_LEN - tcp_ctask->pad_count; |
1256 | debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); | 1256 | debug_scsi("write padding %d bytes\n", tcp_ctask->pad_count); |
1257 | tcp_ctask->xmstate |= XMSTATE_W_PAD; | 1257 | set_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); |
1258 | } | 1258 | } |
1259 | 1259 | ||
1260 | /** | 1260 | /** |
@@ -1269,7 +1269,7 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) | |||
1269 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1269 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1270 | 1270 | ||
1271 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); | 1271 | BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); |
1272 | tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT; | 1272 | tcp_ctask->xmstate = 1 << XMSTATE_BIT_CMD_HDR_INIT; |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | /** | 1275 | /** |
@@ -1283,10 +1283,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) | |||
1283 | * xmit. | 1283 | * xmit. |
1284 | * | 1284 | * |
1285 | * Management xmit state machine consists of these states: | 1285 | * Management xmit state machine consists of these states: |
1286 | * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header | 1286 | * XMSTATE_BIT_IMM_HDR_INIT - calculate digest of PDU Header |
1287 | * XMSTATE_IMM_HDR - PDU Header xmit in progress | 1287 | * XMSTATE_BIT_IMM_HDR - PDU Header xmit in progress |
1288 | * XMSTATE_IMM_DATA - PDU Data xmit in progress | 1288 | * XMSTATE_BIT_IMM_DATA - PDU Data xmit in progress |
1289 | * XMSTATE_IDLE - management PDU is done | 1289 | * XMSTATE_VALUE_IDLE - management PDU is done |
1290 | **/ | 1290 | **/ |
1291 | static int | 1291 | static int |
1292 | iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | 1292 | iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) |
@@ -1297,12 +1297,12 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1297 | debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", | 1297 | debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", |
1298 | conn->id, tcp_mtask->xmstate, mtask->itt); | 1298 | conn->id, tcp_mtask->xmstate, mtask->itt); |
1299 | 1299 | ||
1300 | if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) { | 1300 | if (test_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate)) { |
1301 | iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, | 1301 | iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, |
1302 | sizeof(struct iscsi_hdr)); | 1302 | sizeof(struct iscsi_hdr)); |
1303 | 1303 | ||
1304 | if (mtask->data_count) { | 1304 | if (mtask->data_count) { |
1305 | tcp_mtask->xmstate |= XMSTATE_IMM_DATA; | 1305 | set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); |
1306 | iscsi_buf_init_iov(&tcp_mtask->sendbuf, | 1306 | iscsi_buf_init_iov(&tcp_mtask->sendbuf, |
1307 | (char*)mtask->data, | 1307 | (char*)mtask->data, |
1308 | mtask->data_count); | 1308 | mtask->data_count); |
@@ -1315,21 +1315,20 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1315 | (u8*)tcp_mtask->hdrext); | 1315 | (u8*)tcp_mtask->hdrext); |
1316 | 1316 | ||
1317 | tcp_mtask->sent = 0; | 1317 | tcp_mtask->sent = 0; |
1318 | tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT; | 1318 | clear_bit(XMSTATE_BIT_IMM_HDR_INIT, &tcp_mtask->xmstate); |
1319 | tcp_mtask->xmstate |= XMSTATE_IMM_HDR; | 1319 | set_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { | 1322 | if (test_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate)) { |
1323 | rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, | 1323 | rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, |
1324 | mtask->data_count); | 1324 | mtask->data_count); |
1325 | if (rc) | 1325 | if (rc) |
1326 | return rc; | 1326 | return rc; |
1327 | tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; | 1327 | clear_bit(XMSTATE_BIT_IMM_HDR, &tcp_mtask->xmstate); |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { | 1330 | if (test_and_clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate)) { |
1331 | BUG_ON(!mtask->data_count); | 1331 | BUG_ON(!mtask->data_count); |
1332 | tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; | ||
1333 | /* FIXME: implement. | 1332 | /* FIXME: implement. |
1334 | * Virtual buffer could be spreaded across multiple pages... | 1333 | * Virtual buffer could be spreaded across multiple pages... |
1335 | */ | 1334 | */ |
@@ -1339,13 +1338,13 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | |||
1339 | rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, | 1338 | rc = iscsi_sendpage(conn, &tcp_mtask->sendbuf, |
1340 | &mtask->data_count, &tcp_mtask->sent); | 1339 | &mtask->data_count, &tcp_mtask->sent); |
1341 | if (rc) { | 1340 | if (rc) { |
1342 | tcp_mtask->xmstate |= XMSTATE_IMM_DATA; | 1341 | set_bit(XMSTATE_BIT_IMM_DATA, &tcp_mtask->xmstate); |
1343 | return rc; | 1342 | return rc; |
1344 | } | 1343 | } |
1345 | } while (mtask->data_count); | 1344 | } while (mtask->data_count); |
1346 | } | 1345 | } |
1347 | 1346 | ||
1348 | BUG_ON(tcp_mtask->xmstate != XMSTATE_IDLE); | 1347 | BUG_ON(tcp_mtask->xmstate != XMSTATE_VALUE_IDLE); |
1349 | if (mtask->hdr->itt == RESERVED_ITT) { | 1348 | if (mtask->hdr->itt == RESERVED_ITT) { |
1350 | struct iscsi_session *session = conn->session; | 1349 | struct iscsi_session *session = conn->session; |
1351 | 1350 | ||
@@ -1365,7 +1364,7 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1365 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1364 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1366 | int rc = 0; | 1365 | int rc = 0; |
1367 | 1366 | ||
1368 | if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) { | 1367 | if (test_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate)) { |
1369 | tcp_ctask->sent = 0; | 1368 | tcp_ctask->sent = 0; |
1370 | tcp_ctask->sg_count = 0; | 1369 | tcp_ctask->sg_count = 0; |
1371 | tcp_ctask->exp_datasn = 0; | 1370 | tcp_ctask->exp_datasn = 0; |
@@ -1390,21 +1389,21 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1390 | if (conn->hdrdgst_en) | 1389 | if (conn->hdrdgst_en) |
1391 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1390 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
1392 | (u8*)tcp_ctask->hdrext); | 1391 | (u8*)tcp_ctask->hdrext); |
1393 | tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; | 1392 | clear_bit(XMSTATE_BIT_CMD_HDR_INIT, &tcp_ctask->xmstate); |
1394 | tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; | 1393 | set_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); |
1395 | } | 1394 | } |
1396 | 1395 | ||
1397 | if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) { | 1396 | if (test_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate)) { |
1398 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); | 1397 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); |
1399 | if (rc) | 1398 | if (rc) |
1400 | return rc; | 1399 | return rc; |
1401 | tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT; | 1400 | clear_bit(XMSTATE_BIT_CMD_HDR_XMIT, &tcp_ctask->xmstate); |
1402 | 1401 | ||
1403 | if (sc->sc_data_direction != DMA_TO_DEVICE) | 1402 | if (sc->sc_data_direction != DMA_TO_DEVICE) |
1404 | return 0; | 1403 | return 0; |
1405 | 1404 | ||
1406 | if (ctask->imm_count) { | 1405 | if (ctask->imm_count) { |
1407 | tcp_ctask->xmstate |= XMSTATE_IMM_DATA; | 1406 | set_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); |
1408 | iscsi_set_padding(tcp_ctask, ctask->imm_count); | 1407 | iscsi_set_padding(tcp_ctask, ctask->imm_count); |
1409 | 1408 | ||
1410 | if (ctask->conn->datadgst_en) { | 1409 | if (ctask->conn->datadgst_en) { |
@@ -1414,9 +1413,10 @@ iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1414 | } | 1413 | } |
1415 | } | 1414 | } |
1416 | 1415 | ||
1417 | if (ctask->unsol_count) | 1416 | if (ctask->unsol_count) { |
1418 | tcp_ctask->xmstate |= | 1417 | set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); |
1419 | XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; | 1418 | set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); |
1419 | } | ||
1420 | } | 1420 | } |
1421 | return rc; | 1421 | return rc; |
1422 | } | 1422 | } |
@@ -1428,25 +1428,25 @@ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1428 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; | 1428 | struct iscsi_tcp_conn *tcp_conn = conn->dd_data; |
1429 | int sent = 0, rc; | 1429 | int sent = 0, rc; |
1430 | 1430 | ||
1431 | if (tcp_ctask->xmstate & XMSTATE_W_PAD) { | 1431 | if (test_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate)) { |
1432 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, | 1432 | iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad, |
1433 | tcp_ctask->pad_count); | 1433 | tcp_ctask->pad_count); |
1434 | if (conn->datadgst_en) | 1434 | if (conn->datadgst_en) |
1435 | crypto_hash_update(&tcp_conn->tx_hash, | 1435 | crypto_hash_update(&tcp_conn->tx_hash, |
1436 | &tcp_ctask->sendbuf.sg, | 1436 | &tcp_ctask->sendbuf.sg, |
1437 | tcp_ctask->sendbuf.sg.length); | 1437 | tcp_ctask->sendbuf.sg.length); |
1438 | } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD)) | 1438 | } else if (!test_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate)) |
1439 | return 0; | 1439 | return 0; |
1440 | 1440 | ||
1441 | tcp_ctask->xmstate &= ~XMSTATE_W_PAD; | 1441 | clear_bit(XMSTATE_BIT_W_PAD, &tcp_ctask->xmstate); |
1442 | tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD; | 1442 | clear_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); |
1443 | debug_scsi("sending %d pad bytes for itt 0x%x\n", | 1443 | debug_scsi("sending %d pad bytes for itt 0x%x\n", |
1444 | tcp_ctask->pad_count, ctask->itt); | 1444 | tcp_ctask->pad_count, ctask->itt); |
1445 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, | 1445 | rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count, |
1446 | &sent); | 1446 | &sent); |
1447 | if (rc) { | 1447 | if (rc) { |
1448 | debug_scsi("padding send failed %d\n", rc); | 1448 | debug_scsi("padding send failed %d\n", rc); |
1449 | tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD; | 1449 | set_bit(XMSTATE_BIT_W_RESEND_PAD, &tcp_ctask->xmstate); |
1450 | } | 1450 | } |
1451 | return rc; | 1451 | return rc; |
1452 | } | 1452 | } |
@@ -1465,11 +1465,11 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1465 | tcp_ctask = ctask->dd_data; | 1465 | tcp_ctask = ctask->dd_data; |
1466 | tcp_conn = conn->dd_data; | 1466 | tcp_conn = conn->dd_data; |
1467 | 1467 | ||
1468 | if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) { | 1468 | if (!test_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate)) { |
1469 | crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); | 1469 | crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest); |
1470 | iscsi_buf_init_iov(buf, (char*)digest, 4); | 1470 | iscsi_buf_init_iov(buf, (char*)digest, 4); |
1471 | } | 1471 | } |
1472 | tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST; | 1472 | clear_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); |
1473 | 1473 | ||
1474 | rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); | 1474 | rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent); |
1475 | if (!rc) | 1475 | if (!rc) |
@@ -1478,7 +1478,7 @@ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1478 | else { | 1478 | else { |
1479 | debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", | 1479 | debug_scsi("sending digest 0x%x failed for itt 0x%x!\n", |
1480 | *digest, ctask->itt); | 1480 | *digest, ctask->itt); |
1481 | tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST; | 1481 | set_bit(XMSTATE_BIT_W_RESEND_DATA_DIGEST, &tcp_ctask->xmstate); |
1482 | } | 1482 | } |
1483 | return rc; | 1483 | return rc; |
1484 | } | 1484 | } |
@@ -1526,8 +1526,8 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1526 | struct iscsi_data_task *dtask; | 1526 | struct iscsi_data_task *dtask; |
1527 | int rc; | 1527 | int rc; |
1528 | 1528 | ||
1529 | tcp_ctask->xmstate |= XMSTATE_UNS_DATA; | 1529 | set_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); |
1530 | if (tcp_ctask->xmstate & XMSTATE_UNS_INIT) { | 1530 | if (test_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate)) { |
1531 | dtask = &tcp_ctask->unsol_dtask; | 1531 | dtask = &tcp_ctask->unsol_dtask; |
1532 | 1532 | ||
1533 | iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); | 1533 | iscsi_prep_unsolicit_data_pdu(ctask, &dtask->hdr); |
@@ -1537,14 +1537,14 @@ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1537 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, | 1537 | iscsi_hdr_digest(conn, &tcp_ctask->headbuf, |
1538 | (u8*)dtask->hdrext); | 1538 | (u8*)dtask->hdrext); |
1539 | 1539 | ||
1540 | tcp_ctask->xmstate &= ~XMSTATE_UNS_INIT; | 1540 | clear_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); |
1541 | iscsi_set_padding(tcp_ctask, ctask->data_count); | 1541 | iscsi_set_padding(tcp_ctask, ctask->data_count); |
1542 | } | 1542 | } |
1543 | 1543 | ||
1544 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); | 1544 | rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->data_count); |
1545 | if (rc) { | 1545 | if (rc) { |
1546 | tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; | 1546 | clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); |
1547 | tcp_ctask->xmstate |= XMSTATE_UNS_HDR; | 1547 | set_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate); |
1548 | return rc; | 1548 | return rc; |
1549 | } | 1549 | } |
1550 | 1550 | ||
@@ -1565,16 +1565,15 @@ iscsi_send_unsol_pdu(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1565 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; | 1565 | struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; |
1566 | int rc; | 1566 | int rc; |
1567 | 1567 | ||
1568 | if (tcp_ctask->xmstate & XMSTATE_UNS_HDR) { | 1568 | if (test_and_clear_bit(XMSTATE_BIT_UNS_HDR, &tcp_ctask->xmstate)) { |
1569 | BUG_ON(!ctask->unsol_count); | 1569 | BUG_ON(!ctask->unsol_count); |
1570 | tcp_ctask->xmstate &= ~XMSTATE_UNS_HDR; | ||
1571 | send_hdr: | 1570 | send_hdr: |
1572 | rc = iscsi_send_unsol_hdr(conn, ctask); | 1571 | rc = iscsi_send_unsol_hdr(conn, ctask); |
1573 | if (rc) | 1572 | if (rc) |
1574 | return rc; | 1573 | return rc; |
1575 | } | 1574 | } |
1576 | 1575 | ||
1577 | if (tcp_ctask->xmstate & XMSTATE_UNS_DATA) { | 1576 | if (test_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate)) { |
1578 | struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; | 1577 | struct iscsi_data_task *dtask = &tcp_ctask->unsol_dtask; |
1579 | int start = tcp_ctask->sent; | 1578 | int start = tcp_ctask->sent; |
1580 | 1579 | ||
@@ -1584,14 +1583,14 @@ send_hdr: | |||
1584 | ctask->unsol_count -= tcp_ctask->sent - start; | 1583 | ctask->unsol_count -= tcp_ctask->sent - start; |
1585 | if (rc) | 1584 | if (rc) |
1586 | return rc; | 1585 | return rc; |
1587 | tcp_ctask->xmstate &= ~XMSTATE_UNS_DATA; | 1586 | clear_bit(XMSTATE_BIT_UNS_DATA, &tcp_ctask->xmstate); |
1588 | /* | 1587 | /* |
1589 | * Done with the Data-Out. Next, check if we need | 1588 | * Done with the Data-Out. Next, check if we need |
1590 | * to send another unsolicited Data-Out. | 1589 | * to send another unsolicited Data-Out. |
1591 | */ | 1590 | */ |
1592 | if (ctask->unsol_count) { | 1591 | if (ctask->unsol_count) { |
1593 | debug_scsi("sending more uns\n"); | 1592 | debug_scsi("sending more uns\n"); |
1594 | tcp_ctask->xmstate |= XMSTATE_UNS_INIT; | 1593 | set_bit(XMSTATE_BIT_UNS_INIT, &tcp_ctask->xmstate); |
1595 | goto send_hdr; | 1594 | goto send_hdr; |
1596 | } | 1595 | } |
1597 | } | 1596 | } |
@@ -1607,7 +1606,7 @@ static int iscsi_send_sol_pdu(struct iscsi_conn *conn, | |||
1607 | struct iscsi_data_task *dtask; | 1606 | struct iscsi_data_task *dtask; |
1608 | int left, rc; | 1607 | int left, rc; |
1609 | 1608 | ||
1610 | if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) { | 1609 | if (test_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate)) { |
1611 | if (!tcp_ctask->r2t) { | 1610 | if (!tcp_ctask->r2t) { |
1612 | spin_lock_bh(&session->lock); | 1611 | spin_lock_bh(&session->lock); |
1613 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, | 1612 | __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, |
@@ -1621,19 +1620,19 @@ send_hdr: | |||
1621 | if (conn->hdrdgst_en) | 1620 | if (conn->hdrdgst_en) |
1622 | iscsi_hdr_digest(conn, &r2t->headbuf, | 1621 | iscsi_hdr_digest(conn, &r2t->headbuf, |
1623 | (u8*)dtask->hdrext); | 1622 | (u8*)dtask->hdrext); |
1624 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT; | 1623 | clear_bit(XMSTATE_BIT_SOL_HDR_INIT, &tcp_ctask->xmstate); |
1625 | tcp_ctask->xmstate |= XMSTATE_SOL_HDR; | 1624 | set_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); |
1626 | } | 1625 | } |
1627 | 1626 | ||
1628 | if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { | 1627 | if (test_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate)) { |
1629 | r2t = tcp_ctask->r2t; | 1628 | r2t = tcp_ctask->r2t; |
1630 | dtask = &r2t->dtask; | 1629 | dtask = &r2t->dtask; |
1631 | 1630 | ||
1632 | rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); | 1631 | rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); |
1633 | if (rc) | 1632 | if (rc) |
1634 | return rc; | 1633 | return rc; |
1635 | tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; | 1634 | clear_bit(XMSTATE_BIT_SOL_HDR, &tcp_ctask->xmstate); |
1636 | tcp_ctask->xmstate |= XMSTATE_SOL_DATA; | 1635 | set_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); |
1637 | 1636 | ||
1638 | if (conn->datadgst_en) { | 1637 | if (conn->datadgst_en) { |
1639 | iscsi_data_digest_init(conn->dd_data, tcp_ctask); | 1638 | iscsi_data_digest_init(conn->dd_data, tcp_ctask); |
@@ -1646,7 +1645,7 @@ send_hdr: | |||
1646 | r2t->sent); | 1645 | r2t->sent); |
1647 | } | 1646 | } |
1648 | 1647 | ||
1649 | if (tcp_ctask->xmstate & XMSTATE_SOL_DATA) { | 1648 | if (test_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate)) { |
1650 | r2t = tcp_ctask->r2t; | 1649 | r2t = tcp_ctask->r2t; |
1651 | dtask = &r2t->dtask; | 1650 | dtask = &r2t->dtask; |
1652 | 1651 | ||
@@ -1655,7 +1654,7 @@ send_hdr: | |||
1655 | &dtask->digestbuf, &dtask->digest); | 1654 | &dtask->digestbuf, &dtask->digest); |
1656 | if (rc) | 1655 | if (rc) |
1657 | return rc; | 1656 | return rc; |
1658 | tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; | 1657 | clear_bit(XMSTATE_BIT_SOL_DATA, &tcp_ctask->xmstate); |
1659 | 1658 | ||
1660 | /* | 1659 | /* |
1661 | * Done with this Data-Out. Next, check if we have | 1660 | * Done with this Data-Out. Next, check if we have |
@@ -1700,32 +1699,32 @@ send_hdr: | |||
1700 | * xmit stages. | 1699 | * xmit stages. |
1701 | * | 1700 | * |
1702 | *iscsi_send_cmd_hdr() | 1701 | *iscsi_send_cmd_hdr() |
1703 | * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate | 1702 | * XMSTATE_BIT_CMD_HDR_INIT - prepare Header and Data buffers Calculate |
1704 | * Header Digest | 1703 | * Header Digest |
1705 | * XMSTATE_CMD_HDR_XMIT - Transmit header in progress | 1704 | * XMSTATE_BIT_CMD_HDR_XMIT - Transmit header in progress |
1706 | * | 1705 | * |
1707 | *iscsi_send_padding | 1706 | *iscsi_send_padding |
1708 | * XMSTATE_W_PAD - Prepare and send pading | 1707 | * XMSTATE_BIT_W_PAD - Prepare and send pading |
1709 | * XMSTATE_W_RESEND_PAD - retry send pading | 1708 | * XMSTATE_BIT_W_RESEND_PAD - retry send pading |
1710 | * | 1709 | * |
1711 | *iscsi_send_digest | 1710 | *iscsi_send_digest |
1712 | * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest | 1711 | * XMSTATE_BIT_W_RESEND_DATA_DIGEST - Finalize and send Data Digest |
1713 | * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest | 1712 | * XMSTATE_BIT_W_RESEND_DATA_DIGEST - retry sending digest |
1714 | * | 1713 | * |
1715 | *iscsi_send_unsol_hdr | 1714 | *iscsi_send_unsol_hdr |
1716 | * XMSTATE_UNS_INIT - prepare un-solicit data header and digest | 1715 | * XMSTATE_BIT_UNS_INIT - prepare un-solicit data header and digest |
1717 | * XMSTATE_UNS_HDR - send un-solicit header | 1716 | * XMSTATE_BIT_UNS_HDR - send un-solicit header |
1718 | * | 1717 | * |
1719 | *iscsi_send_unsol_pdu | 1718 | *iscsi_send_unsol_pdu |
1720 | * XMSTATE_UNS_DATA - send un-solicit data in progress | 1719 | * XMSTATE_BIT_UNS_DATA - send un-solicit data in progress |
1721 | * | 1720 | * |
1722 | *iscsi_send_sol_pdu | 1721 | *iscsi_send_sol_pdu |
1723 | * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize | 1722 | * XMSTATE_BIT_SOL_HDR_INIT - solicit data header and digest initialize |
1724 | * XMSTATE_SOL_HDR - send solicit header | 1723 | * XMSTATE_BIT_SOL_HDR - send solicit header |
1725 | * XMSTATE_SOL_DATA - send solicit data | 1724 | * XMSTATE_BIT_SOL_DATA - send solicit data |
1726 | * | 1725 | * |
1727 | *iscsi_tcp_ctask_xmit | 1726 | *iscsi_tcp_ctask_xmit |
1728 | * XMSTATE_IMM_DATA - xmit managment data (??) | 1727 | * XMSTATE_BIT_IMM_DATA - xmit managment data (??) |
1729 | **/ | 1728 | **/ |
1730 | static int | 1729 | static int |
1731 | iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1730 | iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
@@ -1742,13 +1741,13 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1742 | if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) | 1741 | if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) |
1743 | return 0; | 1742 | return 0; |
1744 | 1743 | ||
1745 | if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { | 1744 | if (test_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate)) { |
1746 | rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, | 1745 | rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, |
1747 | &tcp_ctask->sent, &ctask->imm_count, | 1746 | &tcp_ctask->sent, &ctask->imm_count, |
1748 | &tcp_ctask->immbuf, &tcp_ctask->immdigest); | 1747 | &tcp_ctask->immbuf, &tcp_ctask->immdigest); |
1749 | if (rc) | 1748 | if (rc) |
1750 | return rc; | 1749 | return rc; |
1751 | tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA; | 1750 | clear_bit(XMSTATE_BIT_IMM_DATA, &tcp_ctask->xmstate); |
1752 | } | 1751 | } |
1753 | 1752 | ||
1754 | rc = iscsi_send_unsol_pdu(conn, ctask); | 1753 | rc = iscsi_send_unsol_pdu(conn, ctask); |
@@ -1981,7 +1980,7 @@ static void | |||
1981 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) | 1980 | iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) |
1982 | { | 1981 | { |
1983 | struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; | 1982 | struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; |
1984 | tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT; | 1983 | tcp_mtask->xmstate = 1 << XMSTATE_BIT_IMM_HDR_INIT; |
1985 | } | 1984 | } |
1986 | 1985 | ||
1987 | static int | 1986 | static int |
diff --git a/drivers/scsi/iscsi_tcp.h b/drivers/scsi/iscsi_tcp.h index 7eba44df0a7f..68c36cc8997e 100644 --- a/drivers/scsi/iscsi_tcp.h +++ b/drivers/scsi/iscsi_tcp.h | |||
@@ -32,21 +32,21 @@ | |||
32 | #define IN_PROGRESS_PAD_RECV 0x4 | 32 | #define IN_PROGRESS_PAD_RECV 0x4 |
33 | 33 | ||
34 | /* xmit state machine */ | 34 | /* xmit state machine */ |
35 | #define XMSTATE_IDLE 0x0 | 35 | #define XMSTATE_VALUE_IDLE 0 |
36 | #define XMSTATE_CMD_HDR_INIT 0x1 | 36 | #define XMSTATE_BIT_CMD_HDR_INIT 0 |
37 | #define XMSTATE_CMD_HDR_XMIT 0x2 | 37 | #define XMSTATE_BIT_CMD_HDR_XMIT 1 |
38 | #define XMSTATE_IMM_HDR 0x4 | 38 | #define XMSTATE_BIT_IMM_HDR 2 |
39 | #define XMSTATE_IMM_DATA 0x8 | 39 | #define XMSTATE_BIT_IMM_DATA 3 |
40 | #define XMSTATE_UNS_INIT 0x10 | 40 | #define XMSTATE_BIT_UNS_INIT 4 |
41 | #define XMSTATE_UNS_HDR 0x20 | 41 | #define XMSTATE_BIT_UNS_HDR 5 |
42 | #define XMSTATE_UNS_DATA 0x40 | 42 | #define XMSTATE_BIT_UNS_DATA 6 |
43 | #define XMSTATE_SOL_HDR 0x80 | 43 | #define XMSTATE_BIT_SOL_HDR 7 |
44 | #define XMSTATE_SOL_DATA 0x100 | 44 | #define XMSTATE_BIT_SOL_DATA 8 |
45 | #define XMSTATE_W_PAD 0x200 | 45 | #define XMSTATE_BIT_W_PAD 9 |
46 | #define XMSTATE_W_RESEND_PAD 0x400 | 46 | #define XMSTATE_BIT_W_RESEND_PAD 10 |
47 | #define XMSTATE_W_RESEND_DATA_DIGEST 0x800 | 47 | #define XMSTATE_BIT_W_RESEND_DATA_DIGEST 11 |
48 | #define XMSTATE_IMM_HDR_INIT 0x1000 | 48 | #define XMSTATE_BIT_IMM_HDR_INIT 12 |
49 | #define XMSTATE_SOL_HDR_INIT 0x2000 | 49 | #define XMSTATE_BIT_SOL_HDR_INIT 13 |
50 | 50 | ||
51 | #define ISCSI_PAD_LEN 4 | 51 | #define ISCSI_PAD_LEN 4 |
52 | #define ISCSI_SG_TABLESIZE SG_ALL | 52 | #define ISCSI_SG_TABLESIZE SG_ALL |
@@ -122,7 +122,7 @@ struct iscsi_data_task { | |||
122 | struct iscsi_tcp_mgmt_task { | 122 | struct iscsi_tcp_mgmt_task { |
123 | struct iscsi_hdr hdr; | 123 | struct iscsi_hdr hdr; |
124 | char hdrext[sizeof(__u32)]; /* Header-Digest */ | 124 | char hdrext[sizeof(__u32)]; /* Header-Digest */ |
125 | int xmstate; /* mgmt xmit progress */ | 125 | unsigned long xmstate; /* mgmt xmit progress */ |
126 | struct iscsi_buf headbuf; /* header buffer */ | 126 | struct iscsi_buf headbuf; /* header buffer */ |
127 | struct iscsi_buf sendbuf; /* in progress buffer */ | 127 | struct iscsi_buf sendbuf; /* in progress buffer */ |
128 | int sent; | 128 | int sent; |
@@ -150,7 +150,7 @@ struct iscsi_tcp_cmd_task { | |||
150 | int pad_count; /* padded bytes */ | 150 | int pad_count; /* padded bytes */ |
151 | struct iscsi_buf headbuf; /* header buf (xmit) */ | 151 | struct iscsi_buf headbuf; /* header buf (xmit) */ |
152 | struct iscsi_buf sendbuf; /* in progress buffer*/ | 152 | struct iscsi_buf sendbuf; /* in progress buffer*/ |
153 | int xmstate; /* xmit xtate machine */ | 153 | unsigned long xmstate; /* xmit xtate machine */ |
154 | int sent; | 154 | int sent; |
155 | struct scatterlist *sg; /* per-cmd SG list */ | 155 | struct scatterlist *sg; /* per-cmd SG list */ |
156 | struct scatterlist *bad_sg; /* assert statement */ | 156 | struct scatterlist *bad_sg; /* assert statement */ |