aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2009-06-15 23:11:08 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-06-21 11:52:39 -0400
commitd355e57d58193b89283b0c8153649f0427b0bdad (patch)
tree3b0abe01d5f384474b32d6606e1a4f57230a1f13 /drivers/scsi/libiscsi.c
parent9194c6264040d71f851236437a392594b26e5b91 (diff)
libiscsi: don't run scsi eh if iscsi task is making progress
If we are sending or receiving data for the task successfully do not run the scsi eh, because we know the task is making progress. 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.c62
1 files changed, 49 insertions, 13 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 59908aead531..b55b7991d5fa 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -954,6 +954,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
954 task = iscsi_itt_to_ctask(conn, hdr->itt); 954 task = iscsi_itt_to_ctask(conn, hdr->itt);
955 if (!task) 955 if (!task)
956 return ISCSI_ERR_BAD_ITT; 956 return ISCSI_ERR_BAD_ITT;
957 task->last_xfer = jiffies;
957 break; 958 break;
958 case ISCSI_OP_R2T: 959 case ISCSI_OP_R2T:
959 /* 960 /*
@@ -1192,10 +1193,12 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
1192 spin_unlock_bh(&conn->session->lock); 1193 spin_unlock_bh(&conn->session->lock);
1193 rc = conn->session->tt->xmit_task(task); 1194 rc = conn->session->tt->xmit_task(task);
1194 spin_lock_bh(&conn->session->lock); 1195 spin_lock_bh(&conn->session->lock);
1195 __iscsi_put_task(task); 1196 if (!rc) {
1196 if (!rc)
1197 /* done with this task */ 1197 /* done with this task */
1198 task->last_xfer = jiffies;
1198 conn->task = NULL; 1199 conn->task = NULL;
1200 }
1201 __iscsi_put_task(task);
1199 return rc; 1202 return rc;
1200} 1203}
1201 1204
@@ -1361,6 +1364,9 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn,
1361 task->state = ISCSI_TASK_PENDING; 1364 task->state = ISCSI_TASK_PENDING;
1362 task->conn = conn; 1365 task->conn = conn;
1363 task->sc = sc; 1366 task->sc = sc;
1367 task->have_checked_conn = false;
1368 task->last_timeout = jiffies;
1369 task->last_xfer = jiffies;
1364 INIT_LIST_HEAD(&task->running); 1370 INIT_LIST_HEAD(&task->running);
1365 return task; 1371 return task;
1366} 1372}
@@ -1716,17 +1722,18 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
1716 return 0; 1722 return 0;
1717} 1723}
1718 1724
1719static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) 1725static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
1720{ 1726{
1727 enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
1728 struct iscsi_task *task = NULL;
1721 struct iscsi_cls_session *cls_session; 1729 struct iscsi_cls_session *cls_session;
1722 struct iscsi_session *session; 1730 struct iscsi_session *session;
1723 struct iscsi_conn *conn; 1731 struct iscsi_conn *conn;
1724 enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
1725 1732
1726 cls_session = starget_to_session(scsi_target(scmd->device)); 1733 cls_session = starget_to_session(scsi_target(sc->device));
1727 session = cls_session->dd_data; 1734 session = cls_session->dd_data;
1728 1735
1729 ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd); 1736 ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", sc);
1730 1737
1731 spin_lock(&session->lock); 1738 spin_lock(&session->lock);
1732 if (session->state != ISCSI_STATE_LOGGED_IN) { 1739 if (session->state != ISCSI_STATE_LOGGED_IN) {
@@ -1745,6 +1752,26 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
1745 goto done; 1752 goto done;
1746 } 1753 }
1747 1754
1755 task = (struct iscsi_task *)sc->SCp.ptr;
1756 if (!task)
1757 goto done;
1758 /*
1759 * If we have sent (at least queued to the network layer) a pdu or
1760 * recvd one for the task since the last timeout ask for
1761 * more time. If on the next timeout we have not made progress
1762 * we can check if it is the task or connection when we send the
1763 * nop as a ping.
1764 */
1765 if (time_after_eq(task->last_xfer, task->last_timeout)) {
1766 ISCSI_DBG_CONN(conn, "Command making progress. Asking "
1767 "scsi-ml for more time to complete. "
1768 "Last data recv at %lu. Last timeout was at "
1769 "%lu\n.", task->last_xfer, task->last_timeout);
1770 task->have_checked_conn = false;
1771 rc = BLK_EH_RESET_TIMER;
1772 goto done;
1773 }
1774
1748 if (!conn->recv_timeout && !conn->ping_timeout) 1775 if (!conn->recv_timeout && !conn->ping_timeout)
1749 goto done; 1776 goto done;
1750 /* 1777 /*
@@ -1755,20 +1782,29 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
1755 rc = BLK_EH_RESET_TIMER; 1782 rc = BLK_EH_RESET_TIMER;
1756 goto done; 1783 goto done;
1757 } 1784 }
1785
1786 /* Assumes nop timeout is shorter than scsi cmd timeout */
1787 if (task->have_checked_conn)
1788 goto done;
1789
1758 /* 1790 /*
1759 * if we are about to check the transport then give the command 1791 * Checking the transport already or nop from a cmd timeout still
1760 * more time 1792 * running
1761 */ 1793 */
1762 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), 1794 if (conn->ping_task) {
1763 jiffies)) { 1795 task->have_checked_conn = true;
1764 rc = BLK_EH_RESET_TIMER; 1796 rc = BLK_EH_RESET_TIMER;
1765 goto done; 1797 goto done;
1766 } 1798 }
1767 1799
1768 /* if in the middle of checking the transport then give us more time */ 1800 /* Make sure there is a transport check done */
1769 if (conn->ping_task) 1801 iscsi_send_nopout(conn, NULL);
1770 rc = BLK_EH_RESET_TIMER; 1802 task->have_checked_conn = true;
1803 rc = BLK_EH_RESET_TIMER;
1804
1771done: 1805done:
1806 if (task)
1807 task->last_timeout = jiffies;
1772 spin_unlock(&session->lock); 1808 spin_unlock(&session->lock);
1773 ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? 1809 ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
1774 "timer reset" : "nh"); 1810 "timer reset" : "nh");