aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c4
-rw-r--r--drivers/scsi/iscsi_tcp.c4
-rw-r--r--drivers/scsi/libiscsi.c153
-rw-r--r--include/scsi/libiscsi.h2
-rw-r--r--include/scsi/scsi_transport_iscsi.h1
5 files changed, 88 insertions, 76 deletions
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index a6f2303ed14a..47f716ca0026 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -621,9 +621,7 @@ void iser_snd_completion(struct iser_desc *tx_desc)
621 struct iscsi_session *session = conn->session; 621 struct iscsi_session *session = conn->session;
622 622
623 spin_lock(&conn->session->lock); 623 spin_lock(&conn->session->lock);
624 list_del(&mtask->running); 624 iscsi_free_mgmt_task(conn, mtask);
625 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
626 sizeof(void*));
627 spin_unlock(&session->lock); 625 spin_unlock(&session->lock);
628 } 626 }
629 } 627 }
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index f79a457099e6..90eae8e0d978 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -1349,9 +1349,7 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
1349 struct iscsi_session *session = conn->session; 1349 struct iscsi_session *session = conn->session;
1350 1350
1351 spin_lock_bh(&session->lock); 1351 spin_lock_bh(&session->lock);
1352 list_del(&conn->mtask->running); 1352 iscsi_free_mgmt_task(conn, mtask);
1353 __kfifo_put(session->mgmtpool.queue, (void*)&conn->mtask,
1354 sizeof(void*));
1355 spin_unlock_bh(&session->lock); 1353 spin_unlock_bh(&session->lock);
1356 } 1354 }
1357 return 0; 1355 return 0;
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index d43f909a022c..b7a2b9ad3a97 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -37,9 +37,6 @@
37#include <scsi/scsi_transport_iscsi.h> 37#include <scsi/scsi_transport_iscsi.h>
38#include <scsi/libiscsi.h> 38#include <scsi/libiscsi.h>
39 39
40static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
41 int err);
42
43struct iscsi_session * 40struct iscsi_session *
44class_to_transport_session(struct iscsi_cls_session *cls_session) 41class_to_transport_session(struct iscsi_cls_session *cls_session)
45{ 42{
@@ -274,6 +271,53 @@ static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
274 iscsi_complete_command(ctask); 271 iscsi_complete_command(ctask);
275} 272}
276 273
274/*
275 * session lock must be held
276 */
277static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
278 int err)
279{
280 struct scsi_cmnd *sc;
281
282 sc = ctask->sc;
283 if (!sc)
284 return;
285
286 if (ctask->state == ISCSI_TASK_PENDING)
287 /*
288 * cmd never made it to the xmit thread, so we should not count
289 * the cmd in the sequencing
290 */
291 conn->session->queued_cmdsn--;
292 else
293 conn->session->tt->cleanup_cmd_task(conn, ctask);
294
295 sc->result = err;
296 scsi_set_resid(sc, scsi_bufflen(sc));
297 if (conn->ctask == ctask)
298 conn->ctask = NULL;
299 /* release ref from queuecommand */
300 __iscsi_put_ctask(ctask);
301}
302
303/**
304 * iscsi_free_mgmt_task - return mgmt task back to pool
305 * @conn: iscsi connection
306 * @mtask: mtask
307 *
308 * Must be called with session lock.
309 */
310void iscsi_free_mgmt_task(struct iscsi_conn *conn,
311 struct iscsi_mgmt_task *mtask)
312{
313 list_del_init(&mtask->running);
314 if (conn->login_mtask == mtask)
315 return;
316 __kfifo_put(conn->session->mgmtpool.queue,
317 (void*)&mtask, sizeof(void*));
318}
319EXPORT_SYMBOL_GPL(iscsi_free_mgmt_task);
320
277/** 321/**
278 * iscsi_cmd_rsp - SCSI Command Response processing 322 * iscsi_cmd_rsp - SCSI Command Response processing
279 * @conn: iscsi connection 323 * @conn: iscsi connection
@@ -464,10 +508,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
464 */ 508 */
465 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) 509 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
466 rc = ISCSI_ERR_CONN_FAILED; 510 rc = ISCSI_ERR_CONN_FAILED;
467 list_del_init(&mtask->running); 511 iscsi_free_mgmt_task(conn, mtask);
468 if (conn->login_mtask != mtask)
469 __kfifo_put(session->mgmtpool.queue,
470 (void*)&mtask, sizeof(void*));
471 break; 512 break;
472 case ISCSI_OP_SCSI_TMFUNC_RSP: 513 case ISCSI_OP_SCSI_TMFUNC_RSP:
473 if (datalen) { 514 if (datalen) {
@@ -476,6 +517,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
476 } 517 }
477 518
478 iscsi_tmf_rsp(conn, hdr); 519 iscsi_tmf_rsp(conn, hdr);
520 iscsi_free_mgmt_task(conn, mtask);
479 break; 521 break;
480 case ISCSI_OP_NOOP_IN: 522 case ISCSI_OP_NOOP_IN:
481 if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) { 523 if (hdr->ttt != cpu_to_be32(ISCSI_RESERVED_TAG) || datalen) {
@@ -486,9 +528,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
486 528
487 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) 529 if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen))
488 rc = ISCSI_ERR_CONN_FAILED; 530 rc = ISCSI_ERR_CONN_FAILED;
489 list_del_init(&mtask->running); 531 iscsi_free_mgmt_task(conn, mtask);
490 __kfifo_put(session->mgmtpool.queue,
491 (void*)&mtask, sizeof(void*));
492 break; 532 break;
493 default: 533 default:
494 rc = ISCSI_ERR_BAD_OPCODE; 534 rc = ISCSI_ERR_BAD_OPCODE;
@@ -650,14 +690,12 @@ static void iscsi_prep_mtask(struct iscsi_conn *conn,
650static int iscsi_xmit_mtask(struct iscsi_conn *conn) 690static int iscsi_xmit_mtask(struct iscsi_conn *conn)
651{ 691{
652 struct iscsi_hdr *hdr = conn->mtask->hdr; 692 struct iscsi_hdr *hdr = conn->mtask->hdr;
653 int rc, was_logout = 0; 693 int rc;
654 694
695 if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT)
696 conn->session->state = ISCSI_STATE_LOGGING_OUT;
655 spin_unlock_bh(&conn->session->lock); 697 spin_unlock_bh(&conn->session->lock);
656 if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) { 698
657 conn->session->state = ISCSI_STATE_IN_RECOVERY;
658 iscsi_block_session(session_to_cls(conn->session));
659 was_logout = 1;
660 }
661 rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); 699 rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask);
662 spin_lock_bh(&conn->session->lock); 700 spin_lock_bh(&conn->session->lock);
663 if (rc) 701 if (rc)
@@ -665,11 +703,6 @@ static int iscsi_xmit_mtask(struct iscsi_conn *conn)
665 703
666 /* done with this in-progress mtask */ 704 /* done with this in-progress mtask */
667 conn->mtask = NULL; 705 conn->mtask = NULL;
668
669 if (was_logout) {
670 set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
671 return -ENODATA;
672 }
673 return 0; 706 return 0;
674} 707}
675 708
@@ -763,6 +796,12 @@ check_mgmt:
763 while (!list_empty(&conn->mgmtqueue)) { 796 while (!list_empty(&conn->mgmtqueue)) {
764 conn->mtask = list_entry(conn->mgmtqueue.next, 797 conn->mtask = list_entry(conn->mgmtqueue.next,
765 struct iscsi_mgmt_task, running); 798 struct iscsi_mgmt_task, running);
799 if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
800 iscsi_free_mgmt_task(conn, conn->mtask);
801 conn->mtask = NULL;
802 continue;
803 }
804
766 iscsi_prep_mtask(conn, conn->mtask); 805 iscsi_prep_mtask(conn, conn->mtask);
767 list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); 806 list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list);
768 rc = iscsi_xmit_mtask(conn); 807 rc = iscsi_xmit_mtask(conn);
@@ -777,6 +816,10 @@ check_mgmt:
777 816
778 conn->ctask = list_entry(conn->xmitqueue.next, 817 conn->ctask = list_entry(conn->xmitqueue.next,
779 struct iscsi_cmd_task, running); 818 struct iscsi_cmd_task, running);
819 if (conn->session->state == ISCSI_STATE_LOGGING_OUT) {
820 fail_command(conn, conn->ctask, DID_NO_CONNECT << 16);
821 continue;
822 }
780 if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) { 823 if (iscsi_prep_scsi_cmd_pdu(conn->ctask)) {
781 fail_command(conn, conn->ctask, DID_ABORT << 16); 824 fail_command(conn, conn->ctask, DID_ABORT << 16);
782 continue; 825 continue;
@@ -800,6 +843,12 @@ check_mgmt:
800 if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL) 843 if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL)
801 break; 844 break;
802 845
846 /*
847 * we always do fastlogout - conn stop code will clean up.
848 */
849 if (conn->session->state == ISCSI_STATE_LOGGING_OUT)
850 break;
851
803 conn->ctask = list_entry(conn->requeue.next, 852 conn->ctask = list_entry(conn->requeue.next,
804 struct iscsi_cmd_task, running); 853 struct iscsi_cmd_task, running);
805 conn->ctask->state = ISCSI_TASK_RUNNING; 854 conn->ctask->state = ISCSI_TASK_RUNNING;
@@ -842,6 +891,7 @@ enum {
842 FAILURE_SESSION_TERMINATE, 891 FAILURE_SESSION_TERMINATE,
843 FAILURE_SESSION_IN_RECOVERY, 892 FAILURE_SESSION_IN_RECOVERY,
844 FAILURE_SESSION_RECOVERY_TIMEOUT, 893 FAILURE_SESSION_RECOVERY_TIMEOUT,
894 FAILURE_SESSION_LOGGING_OUT,
845}; 895};
846 896
847int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) 897int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
@@ -879,12 +929,19 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
879 goto reject; 929 goto reject;
880 } 930 }
881 931
882 if (session->state == ISCSI_STATE_RECOVERY_FAILED) 932 switch (session->state) {
933 case ISCSI_STATE_RECOVERY_FAILED:
883 reason = FAILURE_SESSION_RECOVERY_TIMEOUT; 934 reason = FAILURE_SESSION_RECOVERY_TIMEOUT;
884 else if (session->state == ISCSI_STATE_TERMINATE) 935 break;
936 case ISCSI_STATE_TERMINATE:
885 reason = FAILURE_SESSION_TERMINATE; 937 reason = FAILURE_SESSION_TERMINATE;
886 else 938 break;
939 case ISCSI_STATE_LOGGING_OUT:
940 reason = FAILURE_SESSION_LOGGING_OUT;
941 break;
942 default:
887 reason = FAILURE_SESSION_FREED; 943 reason = FAILURE_SESSION_FREED;
944 }
888 goto fault; 945 goto fault;
889 } 946 }
890 947
@@ -1120,45 +1177,10 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
1120 if (age != session->age || 1177 if (age != session->age ||
1121 session->state != ISCSI_STATE_LOGGED_IN) 1178 session->state != ISCSI_STATE_LOGGED_IN)
1122 return -ENOTCONN; 1179 return -ENOTCONN;
1123
1124 if (!list_empty(&mtask->running)) {
1125 list_del_init(&mtask->running);
1126 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
1127 sizeof(void*));
1128 }
1129 return 0; 1180 return 0;
1130} 1181}
1131 1182
1132/* 1183/*
1133 * session lock must be held
1134 */
1135static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1136 int err)
1137{
1138 struct scsi_cmnd *sc;
1139
1140 sc = ctask->sc;
1141 if (!sc)
1142 return;
1143
1144 if (ctask->state == ISCSI_TASK_PENDING)
1145 /*
1146 * cmd never made it to the xmit thread, so we should not count
1147 * the cmd in the sequencing
1148 */
1149 conn->session->queued_cmdsn--;
1150 else
1151 conn->session->tt->cleanup_cmd_task(conn, ctask);
1152
1153 sc->result = err;
1154 scsi_set_resid(sc, scsi_bufflen(sc));
1155 if (conn->ctask == ctask)
1156 conn->ctask = NULL;
1157 /* release ref from queuecommand */
1158 __iscsi_put_ctask(ctask);
1159}
1160
1161/*
1162 * Fail commands. session lock held and recv side suspended and xmit 1184 * Fail commands. session lock held and recv side suspended and xmit
1163 * thread flushed 1185 * thread flushed
1164 */ 1186 */
@@ -1837,22 +1859,13 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
1837 /* handle pending */ 1859 /* handle pending */
1838 list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) { 1860 list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) {
1839 debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); 1861 debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt);
1840 list_del_init(&mtask->running); 1862 iscsi_free_mgmt_task(conn, mtask);
1841 if (mtask == conn->login_mtask)
1842 continue;
1843 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
1844 sizeof(void*));
1845 } 1863 }
1846 1864
1847 /* handle running */ 1865 /* handle running */
1848 list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { 1866 list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) {
1849 debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); 1867 debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt);
1850 list_del_init(&mtask->running); 1868 iscsi_free_mgmt_task(conn, mtask);
1851
1852 if (mtask == conn->login_mtask)
1853 continue;
1854 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
1855 sizeof(void*));
1856 } 1869 }
1857 1870
1858 conn->mtask = NULL; 1871 conn->mtask = NULL;
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 4b3e3c15121a..d68f74523f2e 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -346,6 +346,8 @@ extern int __iscsi_complete_pdu(struct iscsi_conn *, struct iscsi_hdr *,
346extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, 346extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *,
347 uint32_t *); 347 uint32_t *);
348extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); 348extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask);
349extern void iscsi_free_mgmt_task(struct iscsi_conn *conn,
350 struct iscsi_mgmt_task *mtask);
349 351
350/* 352/*
351 * generic helpers 353 * generic helpers
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 7ff6199cbd55..b8d97bd20f6e 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -176,6 +176,7 @@ struct iscsi_cls_conn {
176#define ISCSI_STATE_TERMINATE 4 176#define ISCSI_STATE_TERMINATE 4
177#define ISCSI_STATE_IN_RECOVERY 5 177#define ISCSI_STATE_IN_RECOVERY 5
178#define ISCSI_STATE_RECOVERY_FAILED 6 178#define ISCSI_STATE_RECOVERY_FAILED 6
179#define ISCSI_STATE_LOGGING_OUT 7
179 180
180struct iscsi_cls_session { 181struct iscsi_cls_session {
181 struct list_head sess_list; /* item in session_list */ 182 struct list_head sess_list; /* item in session_list */