summaryrefslogtreecommitdiffstats
path: root/net/sctp/outqueue.c
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2011-07-23 21:09:03 +0400
committerJames Bottomley <JBottomley@Parallels.com>2011-07-23 21:09:03 +0400
commit87045b033a62777337ae4aa62834876da09b5fb5 (patch)
tree26aefd28e436668ff906e42b1e0d75c056e33e01 /net/sctp/outqueue.c
parent0d83ab65ff1b54ce8b6cd172285cf71a38c4cceb (diff)
parentbfe159a51203c15d23cb3158fffdc25ec4b4dda1 (diff)
Merge branch 'scsi-fixes'
Diffstat (limited to 'net/sctp/outqueue.c')
-rw-r--r--net/sctp/outqueue.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1c88c8911dc..d03682109b7 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1582,6 +1582,8 @@ static void sctp_check_transmitted(struct sctp_outq *q,
#endif /* SCTP_DEBUG */
if (transport) {
if (bytes_acked) {
+ struct sctp_association *asoc = transport->asoc;
+
/* We may have counted DATA that was migrated
* to this transport due to DEL-IP operation.
* Subtract those bytes, since the were never
@@ -1600,6 +1602,17 @@ static void sctp_check_transmitted(struct sctp_outq *q,
transport->error_count = 0;
transport->asoc->overall_error_count = 0;
+ /*
+ * While in SHUTDOWN PENDING, we may have started
+ * the T5 shutdown guard timer after reaching the
+ * retransmission limit. Stop that timer as soon
+ * as the receiver acknowledged any data.
+ */
+ if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING &&
+ del_timer(&asoc->timers
+ [SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]))
+ sctp_association_put(asoc);
+
/* Mark the destination transport address as
* active if it is not so marked.
*/
@@ -1629,10 +1642,15 @@ static void sctp_check_transmitted(struct sctp_outq *q,
* A sender is doing zero window probing when the
* receiver's advertised window is zero, and there is
* only one data chunk in flight to the receiver.
+ *
+ * Allow the association to timeout while in SHUTDOWN
+ * PENDING or SHUTDOWN RECEIVED in case the receiver
+ * stays in zero window mode forever.
*/
if (!q->asoc->peer.rwnd &&
!list_empty(&tlist) &&
- (sack_ctsn+2 == q->asoc->next_tsn)) {
+ (sack_ctsn+2 == q->asoc->next_tsn) &&
+ q->asoc->state < SCTP_STATE_SHUTDOWN_PENDING) {
SCTP_DEBUG_PRINTK("%s: SACK received for zero "
"window probe: %u\n",
__func__, sack_ctsn);