aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libiscsi.c59
-rw-r--r--include/scsi/libiscsi.h1
2 files changed, 51 insertions, 9 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index a7c6e70f4ef8..9584cbc082fe 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -179,16 +179,15 @@ EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu);
179 179
180/** 180/**
181 * iscsi_complete_command - return command back to scsi-ml 181 * iscsi_complete_command - return command back to scsi-ml
182 * @session: iscsi session
183 * @ctask: iscsi cmd task 182 * @ctask: iscsi cmd task
184 * 183 *
185 * Must be called with session lock. 184 * Must be called with session lock.
186 * This function returns the scsi command to scsi-ml and returns 185 * This function returns the scsi command to scsi-ml and returns
187 * the cmd task to the pool of available cmd tasks. 186 * the cmd task to the pool of available cmd tasks.
188 */ 187 */
189static void iscsi_complete_command(struct iscsi_session *session, 188static void iscsi_complete_command(struct iscsi_cmd_task *ctask)
190 struct iscsi_cmd_task *ctask)
191{ 189{
190 struct iscsi_session *session = ctask->conn->session;
192 struct scsi_cmnd *sc = ctask->sc; 191 struct scsi_cmnd *sc = ctask->sc;
193 192
194 ctask->state = ISCSI_TASK_COMPLETED; 193 ctask->state = ISCSI_TASK_COMPLETED;
@@ -198,6 +197,35 @@ static void iscsi_complete_command(struct iscsi_session *session,
198 sc->scsi_done(sc); 197 sc->scsi_done(sc);
199} 198}
200 199
200static void __iscsi_get_ctask(struct iscsi_cmd_task *ctask)
201{
202 atomic_inc(&ctask->refcount);
203}
204
205static void iscsi_get_ctask(struct iscsi_cmd_task *ctask)
206{
207 spin_lock_bh(&ctask->conn->session->lock);
208 __iscsi_get_ctask(ctask);
209 spin_unlock_bh(&ctask->conn->session->lock);
210}
211
212static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask)
213{
214 struct iscsi_conn *conn = ctask->conn;
215
216 if (atomic_dec_and_test(&ctask->refcount)) {
217 conn->session->tt->cleanup_cmd_task(conn, ctask);
218 iscsi_complete_command(ctask);
219 }
220}
221
222static void iscsi_put_ctask(struct iscsi_cmd_task *ctask)
223{
224 spin_lock_bh(&ctask->conn->session->lock);
225 __iscsi_put_ctask(ctask);
226 spin_unlock_bh(&ctask->conn->session->lock);
227}
228
201/** 229/**
202 * iscsi_cmd_rsp - SCSI Command Response processing 230 * iscsi_cmd_rsp - SCSI Command Response processing
203 * @conn: iscsi connection 231 * @conn: iscsi connection
@@ -274,7 +302,7 @@ out:
274 (long)sc, sc->result, ctask->itt); 302 (long)sc, sc->result, ctask->itt);
275 conn->scsirsp_pdus_cnt++; 303 conn->scsirsp_pdus_cnt++;
276 304
277 iscsi_complete_command(conn->session, ctask); 305 __iscsi_put_ctask(ctask);
278 return rc; 306 return rc;
279} 307}
280 308
@@ -338,7 +366,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
338 BUG_ON((void*)ctask != ctask->sc->SCp.ptr); 366 BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
339 if (hdr->flags & ISCSI_FLAG_DATA_STATUS) { 367 if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
340 conn->scsirsp_pdus_cnt++; 368 conn->scsirsp_pdus_cnt++;
341 iscsi_complete_command(session, ctask); 369 __iscsi_put_ctask(ctask);
342 } 370 }
343 break; 371 break;
344 case ISCSI_OP_R2T: 372 case ISCSI_OP_R2T:
@@ -563,7 +591,9 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
563 BUG_ON(conn->ctask && conn->mtask); 591 BUG_ON(conn->ctask && conn->mtask);
564 592
565 if (conn->ctask) { 593 if (conn->ctask) {
594 iscsi_get_ctask(conn->ctask);
566 rc = tt->xmit_cmd_task(conn, conn->ctask); 595 rc = tt->xmit_cmd_task(conn, conn->ctask);
596 iscsi_put_ctask(conn->ctask);
567 if (rc) 597 if (rc)
568 goto again; 598 goto again;
569 /* done with this in-progress ctask */ 599 /* done with this in-progress ctask */
@@ -604,12 +634,19 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
604 struct iscsi_cmd_task, running); 634 struct iscsi_cmd_task, running);
605 conn->ctask->state = ISCSI_TASK_RUNNING; 635 conn->ctask->state = ISCSI_TASK_RUNNING;
606 list_move_tail(conn->xmitqueue.next, &conn->run_list); 636 list_move_tail(conn->xmitqueue.next, &conn->run_list);
637 __iscsi_get_ctask(conn->ctask);
607 spin_unlock_bh(&conn->session->lock); 638 spin_unlock_bh(&conn->session->lock);
608 639
609 rc = tt->xmit_cmd_task(conn, conn->ctask); 640 rc = tt->xmit_cmd_task(conn, conn->ctask);
610 if (rc) 641 if (rc)
611 goto again; 642 goto again;
643
612 spin_lock_bh(&conn->session->lock); 644 spin_lock_bh(&conn->session->lock);
645 __iscsi_put_ctask(conn->ctask);
646 if (rc) {
647 spin_unlock_bh(&conn->session->lock);
648 goto again;
649 }
613 } 650 }
614 spin_unlock_bh(&conn->session->lock); 651 spin_unlock_bh(&conn->session->lock);
615 /* done with this ctask */ 652 /* done with this ctask */
@@ -659,6 +696,7 @@ enum {
659 FAILURE_SESSION_FAILED, 696 FAILURE_SESSION_FAILED,
660 FAILURE_SESSION_FREED, 697 FAILURE_SESSION_FREED,
661 FAILURE_WINDOW_CLOSED, 698 FAILURE_WINDOW_CLOSED,
699 FAILURE_OOM,
662 FAILURE_SESSION_TERMINATE, 700 FAILURE_SESSION_TERMINATE,
663 FAILURE_SESSION_IN_RECOVERY, 701 FAILURE_SESSION_IN_RECOVERY,
664 FAILURE_SESSION_RECOVERY_TIMEOUT, 702 FAILURE_SESSION_RECOVERY_TIMEOUT,
@@ -717,10 +755,15 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
717 755
718 conn = session->leadconn; 756 conn = session->leadconn;
719 757
720 __kfifo_get(session->cmdpool.queue, (void*)&ctask, sizeof(void*)); 758 if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask,
759 sizeof(void*))) {
760 reason = FAILURE_OOM;
761 goto reject;
762 }
721 sc->SCp.phase = session->age; 763 sc->SCp.phase = session->age;
722 sc->SCp.ptr = (char *)ctask; 764 sc->SCp.ptr = (char *)ctask;
723 765
766 atomic_set(&ctask->refcount, 1);
724 ctask->state = ISCSI_TASK_PENDING; 767 ctask->state = ISCSI_TASK_PENDING;
725 ctask->mtask = NULL; 768 ctask->mtask = NULL;
726 ctask->conn = conn; 769 ctask->conn = conn;
@@ -1057,13 +1100,11 @@ static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
1057 sc = ctask->sc; 1100 sc = ctask->sc;
1058 if (!sc) 1101 if (!sc)
1059 return; 1102 return;
1060
1061 conn->session->tt->cleanup_cmd_task(conn, ctask);
1062 iscsi_ctask_mtask_cleanup(ctask); 1103 iscsi_ctask_mtask_cleanup(ctask);
1063 1104
1064 sc->result = err; 1105 sc->result = err;
1065 sc->resid = sc->request_bufflen; 1106 sc->resid = sc->request_bufflen;
1066 iscsi_complete_command(conn->session, ctask); 1107 __iscsi_put_ctask(ctask);
1067} 1108}
1068 1109
1069int iscsi_eh_abort(struct scsi_cmnd *sc) 1110int iscsi_eh_abort(struct scsi_cmnd *sc)
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index 4900650bd081..401192e56e50 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -112,6 +112,7 @@ struct iscsi_cmd_task {
112 112
113 /* state set/tested under session->lock */ 113 /* state set/tested under session->lock */
114 int state; 114 int state;
115 atomic_t refcount;
115 struct list_head running; /* running cmd list */ 116 struct list_head running; /* running cmd list */
116 void *dd_data; /* driver/transport data */ 117 void *dd_data; /* driver/transport data */
117}; 118};