aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libiscsi.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2009-05-13 18:57:45 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-05-23 16:44:11 -0400
commit4c48a82935f833d94fcf44c2b0c5d2922acfc77a (patch)
treecc735d1d55feacc515155be528380cc60ce8f1a8 /drivers/scsi/libiscsi.c
parentd1acfae514425d680912907c6554852f1e258551 (diff)
[SCSI] libiscsi: fix iscsi transport checks to account for slower links
If we have not got any pdus for recv_timeout seconds, then we will send a iscsi ping/nop to make sure the target is still around. The problem is if this is a slow link, and the ping got queued after the data for a data_out (read), then the transport code could think the ping has failed when it is just slowly making its way through the network. This patch has us check if we are making progress while the nop is outstanding. If we are still reading in data, then we do not fail the session at that time. 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.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 212fe2027a8c..c648bd328a21 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1677,6 +1677,22 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
1677 iscsi_conn_queue_work(conn); 1677 iscsi_conn_queue_work(conn);
1678} 1678}
1679 1679
1680/*
1681 * We want to make sure a ping is in flight. It has timed out.
1682 * And we are not busy processing a pdu that is making
1683 * progress but got started before the ping and is taking a while
1684 * to complete so the ping is just stuck behind it in a queue.
1685 */
1686static int iscsi_has_ping_timed_out(struct iscsi_conn *conn)
1687{
1688 if (conn->ping_task &&
1689 time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) +
1690 (conn->ping_timeout * HZ), jiffies))
1691 return 1;
1692 else
1693 return 0;
1694}
1695
1680static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) 1696static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
1681{ 1697{
1682 struct iscsi_cls_session *cls_session; 1698 struct iscsi_cls_session *cls_session;
@@ -1712,16 +1728,20 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
1712 * if the ping timedout then we are in the middle of cleaning up 1728 * if the ping timedout then we are in the middle of cleaning up
1713 * and can let the iscsi eh handle it 1729 * and can let the iscsi eh handle it
1714 */ 1730 */
1715 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ) + 1731 if (iscsi_has_ping_timed_out(conn)) {
1716 (conn->ping_timeout * HZ), jiffies))
1717 rc = BLK_EH_RESET_TIMER; 1732 rc = BLK_EH_RESET_TIMER;
1733 goto done;
1734 }
1718 /* 1735 /*
1719 * if we are about to check the transport then give the command 1736 * if we are about to check the transport then give the command
1720 * more time 1737 * more time
1721 */ 1738 */
1722 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), 1739 if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ),
1723 jiffies)) 1740 jiffies)) {
1724 rc = BLK_EH_RESET_TIMER; 1741 rc = BLK_EH_RESET_TIMER;
1742 goto done;
1743 }
1744
1725 /* if in the middle of checking the transport then give us more time */ 1745 /* if in the middle of checking the transport then give us more time */
1726 if (conn->ping_task) 1746 if (conn->ping_task)
1727 rc = BLK_EH_RESET_TIMER; 1747 rc = BLK_EH_RESET_TIMER;
@@ -1748,13 +1768,13 @@ static void iscsi_check_transport_timeouts(unsigned long data)
1748 1768
1749 recv_timeout *= HZ; 1769 recv_timeout *= HZ;
1750 last_recv = conn->last_recv; 1770 last_recv = conn->last_recv;
1751 if (conn->ping_task && 1771
1752 time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), 1772 if (iscsi_has_ping_timed_out(conn)) {
1753 jiffies)) {
1754 iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " 1773 iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs "
1755 "expired, last rx %lu, last ping %lu, " 1774 "expired, recv timeout %d, last rx %lu, "
1756 "now %lu\n", conn->ping_timeout, last_recv, 1775 "last ping %lu, now %lu\n",
1757 conn->last_ping, jiffies); 1776 conn->ping_timeout, conn->recv_timeout,
1777 last_recv, conn->last_ping, jiffies);
1758 spin_unlock(&session->lock); 1778 spin_unlock(&session->lock);
1759 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); 1779 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1760 return; 1780 return;