tcp: tcp_make_synack() consumes dst parameter
authorEric Dumazet <edumazet@google.com>
Sun, 3 Jun 2012 20:33:21 +0000 (20:33 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 4 Jun 2012 15:27:39 +0000 (11:27 -0400)
tcp_make_synack() clones the dst, and callers release it.

We can avoid two atomic operations per SYNACK if tcp_make_synack()
consumes dst instead of cloning it.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/tcp_ipv6.c

index c8d28c433b2b0dc958f7bdebaa77f2b899dfd22e..3d9c1a4b88193fd42f3a84b25223809a95e3e495 100644 (file)
@@ -848,7 +848,6 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
                err = net_xmit_eval(err);
        }
 
-       dst_release(dst);
        return err;
 }
 
index f0b0e4414b00c0371402cd180d5fa1e7f266c4ee..c465d3e51e28f66fb16bb5a5adb3dafd082eb7dc 100644 (file)
@@ -2442,7 +2442,16 @@ int tcp_send_synack(struct sock *sk)
        return tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
 }
 
-/* Prepare a SYN-ACK. */
+/**
+ * tcp_make_synack - Prepare a SYN-ACK.
+ * sk: listener socket
+ * dst: dst entry attached to the SYNACK
+ * req: request_sock pointer
+ * rvp: request_values pointer
+ *
+ * Allocate one skb and build a SYNACK packet.
+ * @dst is consumed : Caller should not use it again.
+ */
 struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
                                struct request_sock *req,
                                struct request_values *rvp)
@@ -2462,13 +2471,14 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
        if (cvp != NULL && cvp->s_data_constant && cvp->s_data_desired)
                s_data_desired = cvp->s_data_desired;
        skb = alloc_skb(MAX_TCP_HEADER + 15 + s_data_desired, GFP_ATOMIC);
-       if (skb == NULL)
+       if (unlikely(!skb)) {
+               dst_release(dst);
                return NULL;
-
+       }
        /* Reserve space for headers. */
        skb_reserve(skb, MAX_TCP_HEADER);
 
-       skb_dst_set(skb, dst_clone(dst));
+       skb_dst_set(skb, dst);
 
        mss = dst_metric_advmss(dst);
        if (tp->rx_opt.user_mss && tp->rx_opt.user_mss < mss)
index 3a9aec29581a14cb88f4948ec32737026bfd22ce..80758255556c26aa4fe875770534545671826753 100644 (file)
@@ -522,7 +522,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 done:
        if (opt && opt != np->opt)
                sock_kfree_s(sk, opt, opt->tot_len);
-       dst_release(dst);
        return err;
 }