Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[sfrench/cifs-2.6.git] / net / sctp / sm_sideeffect.c
index 2bc29463e1dcf15b99a81ffa24c9a2d727e670dc..9f36fe911d082e9fa3e3de7096d56323a93d4ba6 100644 (file)
@@ -1523,9 +1523,17 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        timeout = asoc->timeouts[cmd->obj.to];
                        BUG_ON(!timeout);
 
-                       timer->expires = jiffies + timeout;
-                       sctp_association_hold(asoc);
-                       add_timer(timer);
+                       /*
+                        * SCTP has a hard time with timer starts.  Because we process
+                        * timer starts as side effects, it can be hard to tell if we
+                        * have already started a timer or not, which leads to BUG
+                        * halts when we call add_timer. So here, instead of just starting
+                        * a timer, if the timer is already started, and just mod
+                        * the timer with the shorter of the two expiration times
+                        */
+                       if (!timer_pending(timer))
+                               sctp_association_hold(asoc);
+                       timer_reduce(timer, jiffies + timeout);
                        break;
 
                case SCTP_CMD_TIMER_RESTART: