diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-06-09 19:10:40 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-18 00:30:16 -0400 |
commit | 364c6badde0dd62a0a38e5ed67f85d87d6665780 (patch) | |
tree | 56c8ad3e3f45fafec010da4f5858825db5dbc86c /net | |
parent | 932ff279a43ab7257942cddff2595acd541cc49b (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.c | 63 | ||||
-rw-r--r-- | net/decnet/dn_nsp_in.c | 3 | ||||
-rw-r--r-- | net/decnet/dn_route.c | 3 | ||||
-rw-r--r-- | net/ipv4/ipcomp.c | 11 | ||||
-rw-r--r-- | net/ipv6/ipcomp6.c | 11 |
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 */ | ||
1226 | int __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); | |||
3473 | EXPORT_SYMBOL(__dev_get_by_index); | 3415 | EXPORT_SYMBOL(__dev_get_by_index); |
3474 | EXPORT_SYMBOL(__dev_get_by_name); | 3416 | EXPORT_SYMBOL(__dev_get_by_name); |
3475 | EXPORT_SYMBOL(__dev_remove_pack); | 3417 | EXPORT_SYMBOL(__dev_remove_pack); |
3476 | EXPORT_SYMBOL(__skb_linearize); | ||
3477 | EXPORT_SYMBOL(dev_valid_name); | 3418 | EXPORT_SYMBOL(dev_valid_name); |
3478 | EXPORT_SYMBOL(dev_add_pack); | 3419 | EXPORT_SYMBOL(dev_add_pack); |
3479 | EXPORT_SYMBOL(dev_alloc_name); | 3420 | EXPORT_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 | ||
81 | static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb) | 81 | static 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 | ||
66 | static int ipcomp6_input(struct xfrm_state *x, struct sk_buff *skb) | 66 | static 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; |