aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-06-09 19:10:40 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-18 00:30:16 -0400
commit364c6badde0dd62a0a38e5ed67f85d87d6665780 (patch)
tree56c8ad3e3f45fafec010da4f5858825db5dbc86c /net
parent932ff279a43ab7257942cddff2595acd541cc49b (diff)
[NET]: Clean up skb_linearize
The linearisation operation doesn't need to be super-optimised. So we can replace __skb_linearize with __pskb_pull_tail which does the same thing but is more general. Also, most users of skb_linearize end up testing whether the skb is linear or not so it helps to make skb_linearize do just that. Some callers of skb_linearize also use it to copy cloned data, so it's useful to have a new function skb_linearize_cow to copy the data if it's either non-linear or cloned. Last but not least, I've removed the gfp argument since nobody uses it anymore. If it's ever needed we can easily add it back. Misc bugs fixed by this patch: * via-velocity error handling (also, no SG => no frags) Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c63
-rw-r--r--net/decnet/dn_nsp_in.c3
-rw-r--r--net/decnet/dn_route.c3
-rw-r--r--net/ipv4/ipcomp.c11
-rw-r--r--net/ipv6/ipcomp6.c11
5 files changed, 10 insertions, 81 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 1b09f1cae46e..91361bc2b682 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1222,64 +1222,6 @@ static inline int illegal_highdma(struct net_device *dev, struct sk_buff *skb)
1222#define illegal_highdma(dev, skb) (0) 1222#define illegal_highdma(dev, skb) (0)
1223#endif 1223#endif
1224 1224
1225/* Keep head the same: replace data */
1226int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
1227{
1228 unsigned int size;
1229 u8 *data;
1230 long offset;
1231 struct skb_shared_info *ninfo;
1232 int headerlen = skb->data - skb->head;
1233 int expand = (skb->tail + skb->data_len) - skb->end;
1234
1235 if (skb_shared(skb))
1236 BUG();
1237
1238 if (expand <= 0)
1239 expand = 0;
1240
1241 size = skb->end - skb->head + expand;
1242 size = SKB_DATA_ALIGN(size);
1243 data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
1244 if (!data)
1245 return -ENOMEM;
1246
1247 /* Copy entire thing */
1248 if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
1249 BUG();
1250
1251 /* Set up shinfo */
1252 ninfo = (struct skb_shared_info*)(data + size);
1253 atomic_set(&ninfo->dataref, 1);
1254 ninfo->tso_size = skb_shinfo(skb)->tso_size;
1255 ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
1256 ninfo->nr_frags = 0;
1257 ninfo->frag_list = NULL;
1258
1259 /* Offset between the two in bytes */
1260 offset = data - skb->head;
1261
1262 /* Free old data. */
1263 skb_release_data(skb);
1264
1265 skb->head = data;
1266 skb->end = data + size;
1267
1268 /* Set up new pointers */
1269 skb->h.raw += offset;
1270 skb->nh.raw += offset;
1271 skb->mac.raw += offset;
1272 skb->tail += offset;
1273 skb->data += offset;
1274
1275 /* We are no longer a clone, even if we were. */
1276 skb->cloned = 0;
1277
1278 skb->tail += skb->data_len;
1279 skb->data_len = 0;
1280 return 0;
1281}
1282
1283#define HARD_TX_LOCK(dev, cpu) { \ 1225#define HARD_TX_LOCK(dev, cpu) { \
1284 if ((dev->features & NETIF_F_LLTX) == 0) { \ 1226 if ((dev->features & NETIF_F_LLTX) == 0) { \
1285 netif_tx_lock(dev); \ 1227 netif_tx_lock(dev); \
@@ -1326,7 +1268,7 @@ int dev_queue_xmit(struct sk_buff *skb)
1326 1268
1327 if (skb_shinfo(skb)->frag_list && 1269 if (skb_shinfo(skb)->frag_list &&
1328 !(dev->features & NETIF_F_FRAGLIST) && 1270 !(dev->features & NETIF_F_FRAGLIST) &&
1329 __skb_linearize(skb, GFP_ATOMIC)) 1271 __skb_linearize(skb))
1330 goto out_kfree_skb; 1272 goto out_kfree_skb;
1331 1273
1332 /* Fragmented skb is linearized if device does not support SG, 1274 /* Fragmented skb is linearized if device does not support SG,
@@ -1335,7 +1277,7 @@ int dev_queue_xmit(struct sk_buff *skb)
1335 */ 1277 */
1336 if (skb_shinfo(skb)->nr_frags && 1278 if (skb_shinfo(skb)->nr_frags &&
1337 (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) && 1279 (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
1338 __skb_linearize(skb, GFP_ATOMIC)) 1280 __skb_linearize(skb))
1339 goto out_kfree_skb; 1281 goto out_kfree_skb;
1340 1282
1341 /* If packet is not checksummed and device does not support 1283 /* If packet is not checksummed and device does not support
@@ -3473,7 +3415,6 @@ subsys_initcall(net_dev_init);
3473EXPORT_SYMBOL(__dev_get_by_index); 3415EXPORT_SYMBOL(__dev_get_by_index);
3474EXPORT_SYMBOL(__dev_get_by_name); 3416EXPORT_SYMBOL(__dev_get_by_name);
3475EXPORT_SYMBOL(__dev_remove_pack); 3417EXPORT_SYMBOL(__dev_remove_pack);
3476EXPORT_SYMBOL(__skb_linearize);
3477EXPORT_SYMBOL(dev_valid_name); 3418EXPORT_SYMBOL(dev_valid_name);
3478EXPORT_SYMBOL(dev_add_pack); 3419EXPORT_SYMBOL(dev_add_pack);
3479EXPORT_SYMBOL(dev_alloc_name); 3420EXPORT_SYMBOL(dev_alloc_name);
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
index 547523b41c81..a2ba9db1c376 100644
--- a/net/decnet/dn_nsp_in.c
+++ b/net/decnet/dn_nsp_in.c
@@ -801,8 +801,7 @@ got_it:
801 * We linearize everything except data segments here. 801 * We linearize everything except data segments here.
802 */ 802 */
803 if (cb->nsp_flags & ~0x60) { 803 if (cb->nsp_flags & ~0x60) {
804 if (unlikely(skb_is_nonlinear(skb)) && 804 if (unlikely(skb_linearize(skb)))
805 skb_linearize(skb, GFP_ATOMIC) != 0)
806 goto free_out; 805 goto free_out;
807 } 806 }
808 807
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index e172cf98d7fc..5abf7057af00 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -629,8 +629,7 @@ int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type
629 padlen); 629 padlen);
630 630
631 if (flags & DN_RT_PKT_CNTL) { 631 if (flags & DN_RT_PKT_CNTL) {
632 if (unlikely(skb_is_nonlinear(skb)) && 632 if (unlikely(skb_linearize(skb)))
633 skb_linearize(skb, GFP_ATOMIC) != 0)
634 goto dump_it; 633 goto dump_it;
635 634
636 switch(flags & DN_RT_CNTL_MSK) { 635 switch(flags & DN_RT_CNTL_MSK) {
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 8e243589045f..3ed8b57a1002 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -80,15 +80,12 @@ out:
80 80
81static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) 81static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
82{ 82{
83 int err = 0; 83 int err = -ENOMEM;
84 struct iphdr *iph; 84 struct iphdr *iph;
85 struct ip_comp_hdr *ipch; 85 struct ip_comp_hdr *ipch;
86 86
87 if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && 87 if (skb_linearize_cow(skb))
88 skb_linearize(skb, GFP_ATOMIC) != 0) {
89 err = -ENOMEM;
90 goto out; 88 goto out;
91 }
92 89
93 skb->ip_summed = CHECKSUM_NONE; 90 skb->ip_summed = CHECKSUM_NONE;
94 91
@@ -158,10 +155,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
158 goto out_ok; 155 goto out_ok;
159 } 156 }
160 157
161 if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && 158 if (skb_linearize_cow(skb))
162 skb_linearize(skb, GFP_ATOMIC) != 0) {
163 goto out_ok; 159 goto out_ok;
164 }
165 160
166 err = ipcomp_compress(x, skb); 161 err = ipcomp_compress(x, skb);
167 iph = skb->nh.iph; 162 iph = skb->nh.iph;
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index cec3be544b69..f28cd37feed3 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -65,7 +65,7 @@ static LIST_HEAD(ipcomp6_tfms_list);
65 65
66static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) 66static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
67{ 67{
68 int err = 0; 68 int err = -ENOMEM;
69 struct ipv6hdr *iph; 69 struct ipv6hdr *iph;
70 struct ipv6_comp_hdr *ipch; 70 struct ipv6_comp_hdr *ipch;
71 int plen, dlen; 71 int plen, dlen;
@@ -74,11 +74,8 @@ static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb)
74 struct crypto_tfm *tfm; 74 struct crypto_tfm *tfm;
75 int cpu; 75 int cpu;
76 76
77 if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && 77 if (skb_linearize_cow(skb))
78 skb_linearize(skb, GFP_ATOMIC) != 0) {
79 err = -ENOMEM;
80 goto out; 78 goto out;
81 }
82 79
83 skb->ip_summed = CHECKSUM_NONE; 80 skb->ip_summed = CHECKSUM_NONE;
84 81
@@ -142,10 +139,8 @@ static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
142 goto out_ok; 139 goto out_ok;
143 } 140 }
144 141
145 if ((skb_is_nonlinear(skb) || skb_cloned(skb)) && 142 if (skb_linearize_cow(skb))
146 skb_linearize(skb, GFP_ATOMIC) != 0) {
147 goto out_ok; 143 goto out_ok;
148 }
149 144
150 /* compression */ 145 /* compression */
151 plen = skb->len - hdr_len; 146 plen = skb->len - hdr_len;