net: Fix for dst_negative_advice
Krishna Kumar [Mon, 19 Oct 2009 23:46:45 +0000 (23:46 +0000)]
dst_negative_advice() should check for changed dst and reset
sk_tx_queue_mapping accordingly. Pass sock to the callers of
dst_negative_advice.

(sk_reset_txq is defined just for use by dst_negative_advice. The
only way I could find to get around this is to move dst_negative_()
from dst.h to dst.c, include sock.h in dst.c, etc)

Signed-off-by: Krishna Kumar <krkumar2@in.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

include/net/dst.h
net/core/sock.c
net/dccp/timer.c
net/decnet/af_decnet.c
net/ipv4/tcp_timer.c

index 5a900dd..720d906 100644 (file)
@@ -222,11 +222,19 @@ static inline void dst_confirm(struct dst_entry *dst)
                neigh_confirm(dst->neighbour);
 }
 
-static inline void dst_negative_advice(struct dst_entry **dst_p)
+static inline void dst_negative_advice(struct dst_entry **dst_p,
+                                      struct sock *sk)
 {
        struct dst_entry * dst = *dst_p;
-       if (dst && dst->ops->negative_advice)
+       if (dst && dst->ops->negative_advice) {
                *dst_p = dst->ops->negative_advice(dst);
+
+               if (dst != *dst_p) {
+                       extern void sk_reset_txq(struct sock *sk);
+
+                       sk_reset_txq(sk);
+               }
+       }
 }
 
 static inline void dst_link_failure(struct sk_buff *skb)
index 934d967..5a51512 100644 (file)
@@ -352,6 +352,12 @@ discard_and_relse:
 }
 EXPORT_SYMBOL(sk_receive_skb);
 
+void sk_reset_txq(struct sock *sk)
+{
+       sk_tx_queue_clear(sk);
+}
+EXPORT_SYMBOL(sk_reset_txq);
+
 struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie)
 {
        struct dst_entry *dst = sk->sk_dst_cache;
index 162d1e6..bbfeb5e 100644 (file)
@@ -38,7 +38,7 @@ static int dccp_write_timeout(struct sock *sk)
 
        if (sk->sk_state == DCCP_REQUESTING || sk->sk_state == DCCP_PARTOPEN) {
                if (icsk->icsk_retransmits != 0)
-                       dst_negative_advice(&sk->sk_dst_cache);
+                       dst_negative_advice(&sk->sk_dst_cache, sk);
                retry_until = icsk->icsk_syn_retries ?
                            : sysctl_dccp_request_retries;
        } else {
@@ -63,7 +63,7 @@ static int dccp_write_timeout(struct sock *sk)
                           Golden words :-).
                   */
 
-                       dst_negative_advice(&sk->sk_dst_cache);
+                       dst_negative_advice(&sk->sk_dst_cache, sk);
                }
 
                retry_until = sysctl_dccp_retries2;
index 4d30606..664965c 100644 (file)
@@ -1955,7 +1955,7 @@ static int dn_sendmsg(struct kiocb *iocb, struct socket *sock,
        }
 
        if ((flags & MSG_TRYHARD) && sk->sk_dst_cache)
-               dst_negative_advice(&sk->sk_dst_cache);
+               dst_negative_advice(&sk->sk_dst_cache, sk);
 
        mss = scp->segsize_rem;
        fctype = scp->services_rem & NSP_FC_MASK;
index 6e8996c..8353a53 100644 (file)
@@ -141,14 +141,14 @@ static int tcp_write_timeout(struct sock *sk)
 
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
                if (icsk->icsk_retransmits)
-                       dst_negative_advice(&sk->sk_dst_cache);
+                       dst_negative_advice(&sk->sk_dst_cache, sk);
                retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries;
        } else {
                if (retransmits_timed_out(sk, sysctl_tcp_retries1)) {
                        /* Black hole detection */
                        tcp_mtu_probing(icsk, sk);
 
-                       dst_negative_advice(&sk->sk_dst_cache);
+                       dst_negative_advice(&sk->sk_dst_cache, sk);
                }
 
                retry_until = sysctl_tcp_retries2;