aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-05-06 18:02:07 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-06 18:37:57 -0400
commitbdc712b4c2baf9515887de3a52e7ecd89fafc0c7 (patch)
tree3ce09227fb75593256403eaa459d178a2668db25 /net
parentad638bd16d91012a512979327b5c17c867d260c6 (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')
-rw-r--r--net/ipv4/ip_output.c22
-rw-r--r--net/ipv6/ip6_output.c34
-rw-r--r--net/ipv6/raw.c4
3 files changed, 32 insertions, 28 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
1247error: 1249error:
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
1397void ip_flush_pending_frames(struct sock *sk) 1399void 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
1402struct sk_buff *ip_make_skb(struct sock *sk, 1404struct sk_buff *ip_make_skb(struct sock *sk,
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 4cfbb24b9e04..9d4b165837d6 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1150,6 +1150,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1150{ 1150{
1151 struct inet_sock *inet = inet_sk(sk); 1151 struct inet_sock *inet = inet_sk(sk);
1152 struct ipv6_pinfo *np = inet6_sk(sk); 1152 struct ipv6_pinfo *np = inet6_sk(sk);
1153 struct inet_cork *cork;
1153 struct sk_buff *skb; 1154 struct sk_buff *skb;
1154 unsigned int maxfraglen, fragheaderlen; 1155 unsigned int maxfraglen, fragheaderlen;
1155 int exthdrlen; 1156 int exthdrlen;
@@ -1163,6 +1164,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1163 1164
1164 if (flags&MSG_PROBE) 1165 if (flags&MSG_PROBE)
1165 return 0; 1166 return 0;
1167 cork = &inet->cork.base;
1166 if (skb_queue_empty(&sk->sk_write_queue)) { 1168 if (skb_queue_empty(&sk->sk_write_queue)) {
1167 /* 1169 /*
1168 * setup for corking 1170 * setup for corking
@@ -1202,7 +1204,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1202 /* need source address above miyazawa*/ 1204 /* need source address above miyazawa*/
1203 } 1205 }
1204 dst_hold(&rt->dst); 1206 dst_hold(&rt->dst);
1205 inet->cork.dst = &rt->dst; 1207 cork->dst = &rt->dst;
1206 inet->cork.fl.u.ip6 = *fl6; 1208 inet->cork.fl.u.ip6 = *fl6;
1207 np->cork.hop_limit = hlimit; 1209 np->cork.hop_limit = hlimit;
1208 np->cork.tclass = tclass; 1210 np->cork.tclass = tclass;
@@ -1212,10 +1214,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1212 if (np->frag_size) 1214 if (np->frag_size)
1213 mtu = np->frag_size; 1215 mtu = np->frag_size;
1214 } 1216 }
1215 inet->cork.fragsize = mtu; 1217 cork->fragsize = mtu;
1216 if (dst_allfrag(rt->dst.path)) 1218 if (dst_allfrag(rt->dst.path))
1217 inet->cork.flags |= IPCORK_ALLFRAG; 1219 cork->flags |= IPCORK_ALLFRAG;
1218 inet->cork.length = 0; 1220 cork->length = 0;
1219 sk->sk_sndmsg_page = NULL; 1221 sk->sk_sndmsg_page = NULL;
1220 sk->sk_sndmsg_off = 0; 1222 sk->sk_sndmsg_off = 0;
1221 exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - 1223 exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) -
@@ -1223,12 +1225,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1223 length += exthdrlen; 1225 length += exthdrlen;
1224 transhdrlen += exthdrlen; 1226 transhdrlen += exthdrlen;
1225 } else { 1227 } else {
1226 rt = (struct rt6_info *)inet->cork.dst; 1228 rt = (struct rt6_info *)cork->dst;
1227 fl6 = &inet->cork.fl.u.ip6; 1229 fl6 = &inet->cork.fl.u.ip6;
1228 opt = np->cork.opt; 1230 opt = np->cork.opt;
1229 transhdrlen = 0; 1231 transhdrlen = 0;
1230 exthdrlen = 0; 1232 exthdrlen = 0;
1231 mtu = inet->cork.fragsize; 1233 mtu = cork->fragsize;
1232 } 1234 }
1233 1235
1234 hh_len = LL_RESERVED_SPACE(rt->dst.dev); 1236 hh_len = LL_RESERVED_SPACE(rt->dst.dev);
@@ -1238,7 +1240,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1238 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); 1240 maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr);
1239 1241
1240 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { 1242 if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) {
1241 if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { 1243 if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) {
1242 ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); 1244 ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen);
1243 return -EMSGSIZE; 1245 return -EMSGSIZE;
1244 } 1246 }
@@ -1267,7 +1269,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1267 * --yoshfuji 1269 * --yoshfuji
1268 */ 1270 */
1269 1271
1270 inet->cork.length += length; 1272 cork->length += length;
1271 if (length > mtu) { 1273 if (length > mtu) {
1272 int proto = sk->sk_protocol; 1274 int proto = sk->sk_protocol;
1273 if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ 1275 if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){
@@ -1292,7 +1294,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
1292 1294
1293 while (length > 0) { 1295 while (length > 0) {
1294 /* Check if the remaining data fits into current packet. */ 1296 /* Check if the remaining data fits into current packet. */
1295 copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len; 1297 copy = (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
1296 if (copy < length) 1298 if (copy < length)
1297 copy = maxfraglen - skb->len; 1299 copy = maxfraglen - skb->len;
1298 1300
@@ -1317,7 +1319,7 @@ alloc_new_skb:
1317 * we know we need more fragment(s). 1319 * we know we need more fragment(s).
1318 */ 1320 */
1319 datalen = length + fraggap; 1321 datalen = length + fraggap;
1320 if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) 1322 if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
1321 datalen = maxfraglen - fragheaderlen; 1323 datalen = maxfraglen - fragheaderlen;
1322 1324
1323 fraglen = datalen + fragheaderlen; 1325 fraglen = datalen + fragheaderlen;
@@ -1481,7 +1483,7 @@ alloc_new_skb:
1481 } 1483 }
1482 return 0; 1484 return 0;
1483error: 1485error:
1484 inet->cork.length -= length; 1486 cork->length -= length;
1485 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); 1487 IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS);
1486 return err; 1488 return err;
1487} 1489}
@@ -1497,10 +1499,10 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np)
1497 np->cork.opt = NULL; 1499 np->cork.opt = NULL;
1498 } 1500 }
1499 1501
1500 if (inet->cork.dst) { 1502 if (inet->cork.base.dst) {
1501 dst_release(inet->cork.dst); 1503 dst_release(inet->cork.base.dst);
1502 inet->cork.dst = NULL; 1504 inet->cork.base.dst = NULL;
1503 inet->cork.flags &= ~IPCORK_ALLFRAG; 1505 inet->cork.base.flags &= ~IPCORK_ALLFRAG;
1504 } 1506 }
1505 memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); 1507 memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
1506} 1508}
@@ -1515,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk)
1515 struct net *net = sock_net(sk); 1517 struct net *net = sock_net(sk);
1516 struct ipv6hdr *hdr; 1518 struct ipv6hdr *hdr;
1517 struct ipv6_txoptions *opt = np->cork.opt; 1519 struct ipv6_txoptions *opt = np->cork.opt;
1518 struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; 1520 struct rt6_info *rt = (struct rt6_info *)inet->cork.base.dst;
1519 struct flowi6 *fl6 = &inet->cork.fl.u.ip6; 1521 struct flowi6 *fl6 = &inet->cork.fl.u.ip6;
1520 unsigned char proto = fl6->flowi6_proto; 1522 unsigned char proto = fl6->flowi6_proto;
1521 int err = 0; 1523 int err = 0;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index e5e5425fe7d0..ae64984f81aa 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -542,8 +542,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
542 goto out; 542 goto out;
543 543
544 offset = rp->offset; 544 offset = rp->offset;
545 total_len = inet_sk(sk)->cork.length - (skb_network_header(skb) - 545 total_len = inet_sk(sk)->cork.base.length - (skb_network_header(skb) -
546 skb->data); 546 skb->data);
547 if (offset >= total_len - 1) { 547 if (offset >= total_len - 1) {
548 err = -EINVAL; 548 err = -EINVAL;
549 ip6_flush_pending_frames(sk); 549 ip6_flush_pending_frames(sk);