diff options
author | David S. Miller <davem@davemloft.net> | 2011-05-06 18:02:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-06 18:37:57 -0400 |
commit | bdc712b4c2baf9515887de3a52e7ecd89fafc0c7 (patch) | |
tree | 3ce09227fb75593256403eaa459d178a2668db25 /net/ipv4/ip_output.c | |
parent | ad638bd16d91012a512979327b5c17c867d260c6 (diff) |
inet: Decrease overhead of on-stack inet_cork.
When we fast path datagram sends to avoid locking by putting
the inet_cork on the stack we use up lots of space that isn't
necessary.
This is because inet_cork contains a "struct flowi" which isn't
used in these code paths.
Split inet_cork to two parts, "inet_cork" and "inet_cork_full".
Only the latter of which has the "struct flowi" and is what is
stored in inet_sock.
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
Diffstat (limited to 'net/ipv4/ip_output.c')
-rw-r--r-- | net/ipv4/ip_output.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index db38c1822de8..eb0647a2f073 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -1096,14 +1096,14 @@ int ip_append_data(struct sock *sk, | |||
1096 | return 0; | 1096 | return 0; |
1097 | 1097 | ||
1098 | if (skb_queue_empty(&sk->sk_write_queue)) { | 1098 | if (skb_queue_empty(&sk->sk_write_queue)) { |
1099 | err = ip_setup_cork(sk, &inet->cork, ipc, rtp); | 1099 | err = ip_setup_cork(sk, &inet->cork.base, ipc, rtp); |
1100 | if (err) | 1100 | if (err) |
1101 | return err; | 1101 | return err; |
1102 | } else { | 1102 | } else { |
1103 | transhdrlen = 0; | 1103 | transhdrlen = 0; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork, getfrag, | 1106 | return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork.base, getfrag, |
1107 | from, length, transhdrlen, flags); | 1107 | from, length, transhdrlen, flags); |
1108 | } | 1108 | } |
1109 | 1109 | ||
@@ -1114,6 +1114,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1114 | struct sk_buff *skb; | 1114 | struct sk_buff *skb; |
1115 | struct rtable *rt; | 1115 | struct rtable *rt; |
1116 | struct ip_options *opt = NULL; | 1116 | struct ip_options *opt = NULL; |
1117 | struct inet_cork *cork; | ||
1117 | int hh_len; | 1118 | int hh_len; |
1118 | int mtu; | 1119 | int mtu; |
1119 | int len; | 1120 | int len; |
@@ -1129,20 +1130,21 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1129 | if (skb_queue_empty(&sk->sk_write_queue)) | 1130 | if (skb_queue_empty(&sk->sk_write_queue)) |
1130 | return -EINVAL; | 1131 | return -EINVAL; |
1131 | 1132 | ||
1132 | rt = (struct rtable *)inet->cork.dst; | 1133 | cork = &inet->cork.base; |
1133 | if (inet->cork.flags & IPCORK_OPT) | 1134 | rt = (struct rtable *)cork->dst; |
1134 | opt = inet->cork.opt; | 1135 | if (cork->flags & IPCORK_OPT) |
1136 | opt = cork->opt; | ||
1135 | 1137 | ||
1136 | if (!(rt->dst.dev->features&NETIF_F_SG)) | 1138 | if (!(rt->dst.dev->features&NETIF_F_SG)) |
1137 | return -EOPNOTSUPP; | 1139 | return -EOPNOTSUPP; |
1138 | 1140 | ||
1139 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 1141 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
1140 | mtu = inet->cork.fragsize; | 1142 | mtu = cork->fragsize; |
1141 | 1143 | ||
1142 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 1144 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
1143 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 1145 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
1144 | 1146 | ||
1145 | if (inet->cork.length + size > 0xFFFF - fragheaderlen) { | 1147 | if (cork->length + size > 0xFFFF - fragheaderlen) { |
1146 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, mtu); | 1148 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, mtu); |
1147 | return -EMSGSIZE; | 1149 | return -EMSGSIZE; |
1148 | } | 1150 | } |
@@ -1150,7 +1152,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1150 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1152 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
1151 | return -EINVAL; | 1153 | return -EINVAL; |
1152 | 1154 | ||
1153 | inet->cork.length += size; | 1155 | cork->length += size; |
1154 | if ((size + skb->len > mtu) && | 1156 | if ((size + skb->len > mtu) && |
1155 | (sk->sk_protocol == IPPROTO_UDP) && | 1157 | (sk->sk_protocol == IPPROTO_UDP) && |
1156 | (rt->dst.dev->features & NETIF_F_UFO)) { | 1158 | (rt->dst.dev->features & NETIF_F_UFO)) { |
@@ -1245,7 +1247,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1245 | return 0; | 1247 | return 0; |
1246 | 1248 | ||
1247 | error: | 1249 | error: |
1248 | inet->cork.length -= size; | 1250 | cork->length -= size; |
1249 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); | 1251 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); |
1250 | return err; | 1252 | return err; |
1251 | } | 1253 | } |
@@ -1396,7 +1398,7 @@ static void __ip_flush_pending_frames(struct sock *sk, | |||
1396 | 1398 | ||
1397 | void ip_flush_pending_frames(struct sock *sk) | 1399 | void ip_flush_pending_frames(struct sock *sk) |
1398 | { | 1400 | { |
1399 | __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork); | 1401 | __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); |
1400 | } | 1402 | } |
1401 | 1403 | ||
1402 | struct sk_buff *ip_make_skb(struct sock *sk, | 1404 | struct sk_buff *ip_make_skb(struct sock *sk, |