diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 201 |
1 files changed, 166 insertions, 35 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index a751f6230c22..8dc73c489a17 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -109,12 +109,9 @@ inline void iscsi_conn_queue_work(struct iscsi_conn *conn) | |||
109 | } | 109 | } |
110 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); | 110 | EXPORT_SYMBOL_GPL(iscsi_conn_queue_work); |
111 | 111 | ||
112 | void | 112 | static void __iscsi_update_cmdsn(struct iscsi_session *session, |
113 | iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | 113 | uint32_t exp_cmdsn, uint32_t max_cmdsn) |
114 | { | 114 | { |
115 | uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); | ||
116 | uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); | ||
117 | |||
118 | /* | 115 | /* |
119 | * standard specifies this check for when to update expected and | 116 | * standard specifies this check for when to update expected and |
120 | * max sequence numbers | 117 | * max sequence numbers |
@@ -138,6 +135,12 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | |||
138 | iscsi_conn_queue_work(session->leadconn); | 135 | iscsi_conn_queue_work(session->leadconn); |
139 | } | 136 | } |
140 | } | 137 | } |
138 | |||
139 | void iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) | ||
140 | { | ||
141 | __iscsi_update_cmdsn(session, be32_to_cpu(hdr->exp_cmdsn), | ||
142 | be32_to_cpu(hdr->max_cmdsn)); | ||
143 | } | ||
141 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); | 144 | EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); |
142 | 145 | ||
143 | /** | 146 | /** |
@@ -301,8 +304,6 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
301 | hdr->flags = ISCSI_ATTR_SIMPLE; | 304 | hdr->flags = ISCSI_ATTR_SIMPLE; |
302 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); | 305 | int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); |
303 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); | 306 | memcpy(task->lun, hdr->lun, sizeof(task->lun)); |
304 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | ||
305 | session->cmdsn++; | ||
306 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); | 307 | hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); |
307 | cmd_len = sc->cmd_len; | 308 | cmd_len = sc->cmd_len; |
308 | if (cmd_len < ISCSI_CDB_SIZE) | 309 | if (cmd_len < ISCSI_CDB_SIZE) |
@@ -388,6 +389,8 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
388 | return -EIO; | 389 | return -EIO; |
389 | 390 | ||
390 | task->state = ISCSI_TASK_RUNNING; | 391 | task->state = ISCSI_TASK_RUNNING; |
392 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | ||
393 | session->cmdsn++; | ||
391 | 394 | ||
392 | conn->scsicmd_pdus_cnt++; | 395 | conn->scsicmd_pdus_cnt++; |
393 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " | 396 | ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x " |
@@ -499,6 +502,31 @@ static void iscsi_complete_task(struct iscsi_task *task, int state) | |||
499 | __iscsi_put_task(task); | 502 | __iscsi_put_task(task); |
500 | } | 503 | } |
501 | 504 | ||
505 | /** | ||
506 | * iscsi_complete_scsi_task - finish scsi task normally | ||
507 | * @task: iscsi task for scsi cmd | ||
508 | * @exp_cmdsn: expected cmd sn in cpu format | ||
509 | * @max_cmdsn: max cmd sn in cpu format | ||
510 | * | ||
511 | * This is used when drivers do not need or cannot perform | ||
512 | * lower level pdu processing. | ||
513 | * | ||
514 | * Called with session lock | ||
515 | */ | ||
516 | void iscsi_complete_scsi_task(struct iscsi_task *task, | ||
517 | uint32_t exp_cmdsn, uint32_t max_cmdsn) | ||
518 | { | ||
519 | struct iscsi_conn *conn = task->conn; | ||
520 | |||
521 | ISCSI_DBG_SESSION(conn->session, "[itt 0x%x]\n", task->itt); | ||
522 | |||
523 | conn->last_recv = jiffies; | ||
524 | __iscsi_update_cmdsn(conn->session, exp_cmdsn, max_cmdsn); | ||
525 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | ||
526 | } | ||
527 | EXPORT_SYMBOL_GPL(iscsi_complete_scsi_task); | ||
528 | |||
529 | |||
502 | /* | 530 | /* |
503 | * session lock must be held and if not called for a task that is | 531 | * session lock must be held and if not called for a task that is |
504 | * still pending or from the xmit thread, then xmit thread must | 532 | * still pending or from the xmit thread, then xmit thread must |
@@ -857,27 +885,102 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | |||
857 | } | 885 | } |
858 | } | 886 | } |
859 | 887 | ||
888 | static int iscsi_nop_out_rsp(struct iscsi_task *task, | ||
889 | struct iscsi_nopin *nop, char *data, int datalen) | ||
890 | { | ||
891 | struct iscsi_conn *conn = task->conn; | ||
892 | int rc = 0; | ||
893 | |||
894 | if (conn->ping_task != task) { | ||
895 | /* | ||
896 | * If this is not in response to one of our | ||
897 | * nops then it must be from userspace. | ||
898 | */ | ||
899 | if (iscsi_recv_pdu(conn->cls_conn, (struct iscsi_hdr *)nop, | ||
900 | data, datalen)) | ||
901 | rc = ISCSI_ERR_CONN_FAILED; | ||
902 | } else | ||
903 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); | ||
904 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | ||
905 | return rc; | ||
906 | } | ||
907 | |||
860 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 908 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
861 | char *data, int datalen) | 909 | char *data, int datalen) |
862 | { | 910 | { |
863 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; | 911 | struct iscsi_reject *reject = (struct iscsi_reject *)hdr; |
864 | struct iscsi_hdr rejected_pdu; | 912 | struct iscsi_hdr rejected_pdu; |
913 | int opcode, rc = 0; | ||
865 | 914 | ||
866 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; | 915 | conn->exp_statsn = be32_to_cpu(reject->statsn) + 1; |
867 | 916 | ||
868 | if (reject->reason == ISCSI_REASON_DATA_DIGEST_ERROR) { | 917 | if (ntoh24(reject->dlength) > datalen || |
869 | if (ntoh24(reject->dlength) > datalen) | 918 | ntoh24(reject->dlength) < sizeof(struct iscsi_hdr)) { |
870 | return ISCSI_ERR_PROTO; | 919 | iscsi_conn_printk(KERN_ERR, conn, "Cannot handle rejected " |
920 | "pdu. Invalid data length (pdu dlength " | ||
921 | "%u, datalen %d\n", ntoh24(reject->dlength), | ||
922 | datalen); | ||
923 | return ISCSI_ERR_PROTO; | ||
924 | } | ||
925 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); | ||
926 | opcode = rejected_pdu.opcode & ISCSI_OPCODE_MASK; | ||
927 | |||
928 | switch (reject->reason) { | ||
929 | case ISCSI_REASON_DATA_DIGEST_ERROR: | ||
930 | iscsi_conn_printk(KERN_ERR, conn, | ||
931 | "pdu (op 0x%x itt 0x%x) rejected " | ||
932 | "due to DataDigest error.\n", | ||
933 | rejected_pdu.itt, opcode); | ||
934 | break; | ||
935 | case ISCSI_REASON_IMM_CMD_REJECT: | ||
936 | iscsi_conn_printk(KERN_ERR, conn, | ||
937 | "pdu (op 0x%x itt 0x%x) rejected. Too many " | ||
938 | "immediate commands.\n", | ||
939 | rejected_pdu.itt, opcode); | ||
940 | /* | ||
941 | * We only send one TMF at a time so if the target could not | ||
942 | * handle it, then it should get fixed (RFC mandates that | ||
943 | * a target can handle one immediate TMF per conn). | ||
944 | * | ||
945 | * For nops-outs, we could have sent more than one if | ||
946 | * the target is sending us lots of nop-ins | ||
947 | */ | ||
948 | if (opcode != ISCSI_OP_NOOP_OUT) | ||
949 | return 0; | ||
871 | 950 | ||
872 | if (ntoh24(reject->dlength) >= sizeof(struct iscsi_hdr)) { | 951 | if (rejected_pdu.itt == cpu_to_be32(ISCSI_RESERVED_TAG)) |
873 | memcpy(&rejected_pdu, data, sizeof(struct iscsi_hdr)); | 952 | /* |
874 | iscsi_conn_printk(KERN_ERR, conn, | 953 | * nop-out in response to target's nop-out rejected. |
875 | "pdu (op 0x%x) rejected " | 954 | * Just resend. |
876 | "due to DataDigest error.\n", | 955 | */ |
877 | rejected_pdu.opcode); | 956 | iscsi_send_nopout(conn, |
957 | (struct iscsi_nopin*)&rejected_pdu); | ||
958 | else { | ||
959 | struct iscsi_task *task; | ||
960 | /* | ||
961 | * Our nop as ping got dropped. We know the target | ||
962 | * and transport are ok so just clean up | ||
963 | */ | ||
964 | task = iscsi_itt_to_task(conn, rejected_pdu.itt); | ||
965 | if (!task) { | ||
966 | iscsi_conn_printk(KERN_ERR, conn, | ||
967 | "Invalid pdu reject. Could " | ||
968 | "not lookup rejected task.\n"); | ||
969 | rc = ISCSI_ERR_BAD_ITT; | ||
970 | } else | ||
971 | rc = iscsi_nop_out_rsp(task, | ||
972 | (struct iscsi_nopin*)&rejected_pdu, | ||
973 | NULL, 0); | ||
878 | } | 974 | } |
975 | break; | ||
976 | default: | ||
977 | iscsi_conn_printk(KERN_ERR, conn, | ||
978 | "pdu (op 0x%x itt 0x%x) rejected. Reason " | ||
979 | "code 0x%x\n", rejected_pdu.itt, | ||
980 | rejected_pdu.opcode, reject->reason); | ||
981 | break; | ||
879 | } | 982 | } |
880 | return 0; | 983 | return rc; |
881 | } | 984 | } |
882 | 985 | ||
883 | /** | 986 | /** |
@@ -1038,15 +1141,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
1038 | } | 1141 | } |
1039 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; | 1142 | conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; |
1040 | 1143 | ||
1041 | if (conn->ping_task != task) | 1144 | rc = iscsi_nop_out_rsp(task, (struct iscsi_nopin*)hdr, |
1042 | /* | 1145 | data, datalen); |
1043 | * If this is not in response to one of our | ||
1044 | * nops then it must be from userspace. | ||
1045 | */ | ||
1046 | goto recv_pdu; | ||
1047 | |||
1048 | mod_timer(&conn->transport_timer, jiffies + conn->recv_timeout); | ||
1049 | iscsi_complete_task(task, ISCSI_TASK_COMPLETED); | ||
1050 | break; | 1146 | break; |
1051 | default: | 1147 | default: |
1052 | rc = ISCSI_ERR_BAD_OPCODE; | 1148 | rc = ISCSI_ERR_BAD_OPCODE; |
@@ -1212,6 +1308,9 @@ static int iscsi_xmit_task(struct iscsi_conn *conn) | |||
1212 | struct iscsi_task *task = conn->task; | 1308 | struct iscsi_task *task = conn->task; |
1213 | int rc; | 1309 | int rc; |
1214 | 1310 | ||
1311 | if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) | ||
1312 | return -ENODATA; | ||
1313 | |||
1215 | __iscsi_get_task(task); | 1314 | __iscsi_get_task(task); |
1216 | spin_unlock_bh(&conn->session->lock); | 1315 | spin_unlock_bh(&conn->session->lock); |
1217 | rc = conn->session->tt->xmit_task(task); | 1316 | rc = conn->session->tt->xmit_task(task); |
@@ -1261,7 +1360,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
1261 | int rc = 0; | 1360 | int rc = 0; |
1262 | 1361 | ||
1263 | spin_lock_bh(&conn->session->lock); | 1362 | spin_lock_bh(&conn->session->lock); |
1264 | if (unlikely(conn->suspend_tx)) { | 1363 | if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { |
1265 | ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n"); | 1364 | ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n"); |
1266 | spin_unlock_bh(&conn->session->lock); | 1365 | spin_unlock_bh(&conn->session->lock); |
1267 | return -ENODATA; | 1366 | return -ENODATA; |
@@ -1270,7 +1369,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn) | |||
1270 | if (conn->task) { | 1369 | if (conn->task) { |
1271 | rc = iscsi_xmit_task(conn); | 1370 | rc = iscsi_xmit_task(conn); |
1272 | if (rc) | 1371 | if (rc) |
1273 | goto again; | 1372 | goto done; |
1274 | } | 1373 | } |
1275 | 1374 | ||
1276 | /* | 1375 | /* |
@@ -1290,7 +1389,7 @@ check_mgmt: | |||
1290 | } | 1389 | } |
1291 | rc = iscsi_xmit_task(conn); | 1390 | rc = iscsi_xmit_task(conn); |
1292 | if (rc) | 1391 | if (rc) |
1293 | goto again; | 1392 | goto done; |
1294 | } | 1393 | } |
1295 | 1394 | ||
1296 | /* process pending command queue */ | 1395 | /* process pending command queue */ |
@@ -1311,14 +1410,14 @@ check_mgmt: | |||
1311 | list_add_tail(&conn->task->running, | 1410 | list_add_tail(&conn->task->running, |
1312 | &conn->cmdqueue); | 1411 | &conn->cmdqueue); |
1313 | conn->task = NULL; | 1412 | conn->task = NULL; |
1314 | goto again; | 1413 | goto done; |
1315 | } else | 1414 | } else |
1316 | fail_scsi_task(conn->task, DID_ABORT); | 1415 | fail_scsi_task(conn->task, DID_ABORT); |
1317 | continue; | 1416 | continue; |
1318 | } | 1417 | } |
1319 | rc = iscsi_xmit_task(conn); | 1418 | rc = iscsi_xmit_task(conn); |
1320 | if (rc) | 1419 | if (rc) |
1321 | goto again; | 1420 | goto done; |
1322 | /* | 1421 | /* |
1323 | * we could continuously get new task requests so | 1422 | * we could continuously get new task requests so |
1324 | * we need to check the mgmt queue for nops that need to | 1423 | * we need to check the mgmt queue for nops that need to |
@@ -1344,16 +1443,14 @@ check_mgmt: | |||
1344 | conn->task->state = ISCSI_TASK_RUNNING; | 1443 | conn->task->state = ISCSI_TASK_RUNNING; |
1345 | rc = iscsi_xmit_task(conn); | 1444 | rc = iscsi_xmit_task(conn); |
1346 | if (rc) | 1445 | if (rc) |
1347 | goto again; | 1446 | goto done; |
1348 | if (!list_empty(&conn->mgmtqueue)) | 1447 | if (!list_empty(&conn->mgmtqueue)) |
1349 | goto check_mgmt; | 1448 | goto check_mgmt; |
1350 | } | 1449 | } |
1351 | spin_unlock_bh(&conn->session->lock); | 1450 | spin_unlock_bh(&conn->session->lock); |
1352 | return -ENODATA; | 1451 | return -ENODATA; |
1353 | 1452 | ||
1354 | again: | 1453 | done: |
1355 | if (unlikely(conn->suspend_tx)) | ||
1356 | rc = -ENODATA; | ||
1357 | spin_unlock_bh(&conn->session->lock); | 1454 | spin_unlock_bh(&conn->session->lock); |
1358 | return rc; | 1455 | return rc; |
1359 | } | 1456 | } |
@@ -1474,6 +1571,12 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1474 | goto fault; | 1571 | goto fault; |
1475 | } | 1572 | } |
1476 | 1573 | ||
1574 | if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { | ||
1575 | reason = FAILURE_SESSION_IN_RECOVERY; | ||
1576 | sc->result = DID_REQUEUE; | ||
1577 | goto fault; | ||
1578 | } | ||
1579 | |||
1477 | if (iscsi_check_cmdsn_window_closed(conn)) { | 1580 | if (iscsi_check_cmdsn_window_closed(conn)) { |
1478 | reason = FAILURE_WINDOW_CLOSED; | 1581 | reason = FAILURE_WINDOW_CLOSED; |
1479 | goto reject; | 1582 | goto reject; |
@@ -1497,6 +1600,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
1497 | } | 1600 | } |
1498 | } | 1601 | } |
1499 | if (session->tt->xmit_task(task)) { | 1602 | if (session->tt->xmit_task(task)) { |
1603 | session->cmdsn--; | ||
1500 | reason = FAILURE_SESSION_NOT_READY; | 1604 | reason = FAILURE_SESSION_NOT_READY; |
1501 | goto prepd_reject; | 1605 | goto prepd_reject; |
1502 | } | 1606 | } |
@@ -1712,6 +1816,33 @@ static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, | |||
1712 | } | 1816 | } |
1713 | } | 1817 | } |
1714 | 1818 | ||
1819 | /** | ||
1820 | * iscsi_suspend_queue - suspend iscsi_queuecommand | ||
1821 | * @conn: iscsi conn to stop queueing IO on | ||
1822 | * | ||
1823 | * This grabs the session lock to make sure no one is in | ||
1824 | * xmit_task/queuecommand, and then sets suspend to prevent | ||
1825 | * new commands from being queued. This only needs to be called | ||
1826 | * by offload drivers that need to sync a path like ep disconnect | ||
1827 | * with the iscsi_queuecommand/xmit_task. To start IO again libiscsi | ||
1828 | * will call iscsi_start_tx and iscsi_unblock_session when in FFP. | ||
1829 | */ | ||
1830 | void iscsi_suspend_queue(struct iscsi_conn *conn) | ||
1831 | { | ||
1832 | spin_lock_bh(&conn->session->lock); | ||
1833 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); | ||
1834 | spin_unlock_bh(&conn->session->lock); | ||
1835 | } | ||
1836 | EXPORT_SYMBOL_GPL(iscsi_suspend_queue); | ||
1837 | |||
1838 | /** | ||
1839 | * iscsi_suspend_tx - suspend iscsi_data_xmit | ||
1840 | * @conn: iscsi conn tp stop processing IO on. | ||
1841 | * | ||
1842 | * This function sets the suspend bit to prevent iscsi_data_xmit | ||
1843 | * from sending new IO, and if work is queued on the xmit thread | ||
1844 | * it will wait for it to be completed. | ||
1845 | */ | ||
1715 | void iscsi_suspend_tx(struct iscsi_conn *conn) | 1846 | void iscsi_suspend_tx(struct iscsi_conn *conn) |
1716 | { | 1847 | { |
1717 | struct Scsi_Host *shost = conn->session->host; | 1848 | struct Scsi_Host *shost = conn->session->host; |