diff options
Diffstat (limited to 'drivers/scsi/libiscsi.c')
-rw-r--r-- | drivers/scsi/libiscsi.c | 38 |
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 | */ | ||
1686 | static 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 | |||
1680 | static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) | 1696 | static 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; |