aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2007-12-13 13:43:26 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-11 19:28:28 -0500
commitb3a7ea8d50f6028964b468d13a095dfb2508b2fb (patch)
tree47cc070e1761208e7e6448a0eb8ca3567e27a462 /drivers/scsi/libiscsi.c
parent6320377fd94316e58f75d0be6f6e7a644950a4ee (diff)
[SCSI] libiscsi: do not block session during logout
There is not need to block the session during logout. Since we are going to fail the commands that were blocked just fail them immediately instead. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r--drivers/scsi/libiscsi.c153
1 files changed, 83 insertions, 70 deletions
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;