[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 860 /* Copy the data if there is no space for the header or if it's 861 861 * read-only. 862 862 */ 863 - if (skb_cow(skb, sizeof(*ph) + dev->hard_header_len)) 863 + if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) 864 864 goto abort; 865 865 866 866 __skb_push(skb, sizeof(*ph));
+31 -9
include/linux/skbuff.h
··· 1352 1352 skb_headroom(skb) + len <= skb->hdr_len; 1353 1353 } 1354 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 + 1355 1371 /** 1356 1372 * skb_cow - copy header of skb when it is required 1357 1373 * @skb: buffer to cow ··· 1382 1366 */ 1383 1367 static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) 1384 1368 { 1385 - int delta = (headroom > NET_SKB_PAD ? headroom : NET_SKB_PAD) - 1386 - skb_headroom(skb); 1369 + return __skb_cow(skb, headroom, skb_cloned(skb)); 1370 + } 1387 1371 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; 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)); 1395 1385 } 1396 1386 1397 1387 /**
+1 -1
net/bridge/br_netfilter.c
··· 183 183 int err; 184 184 int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); 185 185 186 - err = skb_cow(skb, header_size); 186 + err = skb_cow_head(skb, header_size); 187 187 if (err) 188 188 return err; 189 189