[NET] skbuff: Add skb_cow_head

This patch adds an optimised version of skb_cow that avoids the copy if
the header can be modified even if the rest of the payload is cloned.

This can be used in encapsulating paths where we only need to modify the
header. As it is, this can be used in PPPOE and bridging.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Herbert Xu and committed by David S. Miller d9cc2048 e081e1e3

+33 -11
+1 -1
drivers/net/pppoe.c
··· 860 /* Copy the data if there is no space for the header or if it's 861 * read-only. 862 */ 863 - if (skb_cow(skb, sizeof(*ph) + dev->hard_header_len)) 864 goto abort; 865 866 __skb_push(skb, sizeof(*ph));
··· 860 /* Copy the data if there is no space for the header or if it's 861 * read-only. 862 */ 863 + if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) 864 goto abort; 865 866 __skb_push(skb, sizeof(*ph));
+31 -9
include/linux/skbuff.h
··· 1352 skb_headroom(skb) + len <= skb->hdr_len; 1353 } 1354 1355 /** 1356 * skb_cow - copy header of skb when it is required 1357 * @skb: buffer to cow ··· 1382 */ 1383 static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) 1384 { 1385 - int delta = (headroom > NET_SKB_PAD ? headroom : NET_SKB_PAD) - 1386 - skb_headroom(skb); 1387 1388 - if (delta < 0) 1389 - delta = 0; 1390 - 1391 - if (delta || skb_cloned(skb)) 1392 - return pskb_expand_head(skb, (delta + (NET_SKB_PAD-1)) & 1393 - ~(NET_SKB_PAD-1), 0, GFP_ATOMIC); 1394 - return 0; 1395 } 1396 1397 /**
··· 1352 skb_headroom(skb) + len <= skb->hdr_len; 1353 } 1354 1355 + static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, 1356 + int cloned) 1357 + { 1358 + int delta = 0; 1359 + 1360 + if (headroom < NET_SKB_PAD) 1361 + headroom = NET_SKB_PAD; 1362 + if (headroom > skb_headroom(skb)) 1363 + delta = headroom - skb_headroom(skb); 1364 + 1365 + if (delta || cloned) 1366 + return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0, 1367 + GFP_ATOMIC); 1368 + return 0; 1369 + } 1370 + 1371 /** 1372 * skb_cow - copy header of skb when it is required 1373 * @skb: buffer to cow ··· 1366 */ 1367 static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) 1368 { 1369 + return __skb_cow(skb, headroom, skb_cloned(skb)); 1370 + } 1371 1372 + /** 1373 + * skb_cow_head - skb_cow but only making the head writable 1374 + * @skb: buffer to cow 1375 + * @headroom: needed headroom 1376 + * 1377 + * This function is identical to skb_cow except that we replace the 1378 + * skb_cloned check by skb_header_cloned. It should be used when 1379 + * you only need to push on some header and do not need to modify 1380 + * the data. 1381 + */ 1382 + static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom) 1383 + { 1384 + return __skb_cow(skb, headroom, skb_header_cloned(skb)); 1385 } 1386 1387 /**
+1 -1
net/bridge/br_netfilter.c
··· 183 int err; 184 int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); 185 186 - err = skb_cow(skb, header_size); 187 if (err) 188 return err; 189
··· 183 int err; 184 int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); 185 186 + err = skb_cow_head(skb, header_size); 187 if (err) 188 return err; 189