diff options
| author | Octavian Purdila <octavian.purdila@intel.com> | 2014-06-11 18:36:26 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-06-11 18:38:02 -0400 |
| commit | bad93e9d4eeb0d2d6b79204d6cedc7f2e7b256f1 (patch) | |
| tree | 816931467196e2a89ac47919bfb2b2fc45969209 | |
| parent | 1a0b20b257326523ec2a6cb51dd6f26ef179eb84 (diff) | |
net: add __pskb_copy_fclone and pskb_copy_for_clone
There are several instances where a pskb_copy or __pskb_copy is
immediately followed by an skb_clone.
Add a couple of new functions to allow the copy skb to be allocated
from the fclone cache and thus speed up subsequent skb_clone calls.
Cc: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Cc: Marek Lindner <mareklindner@neomailbox.ch>
Cc: Simon Wunderlich <sw@simonwunderlich.de>
Cc: Antonio Quartulli <antonio@meshcoding.com>
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Gustavo Padovan <gustavo@padovan.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: Arvid Brodin <arvid.brodin@alten.se>
Cc: Patrick McHardy <kaber@trash.net>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>
Cc: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Cc: Lauro Ramos Venancio <lauro.venancio@openbossa.org>
Cc: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Jon Maloy <jon.maloy@ericsson.com>
Cc: Allan Stephens <allan.stephens@windriver.com>
Cc: Andrew Hendry <andrew.hendry@gmail.com>
Cc: Eric Dumazet <edumazet@google.com>
Reviewed-by: Christoph Paasch <christoph.paasch@uclouvain.be>
Signed-off-by: Octavian Purdila <octavian.purdila@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/skbuff.h | 16 | ||||
| -rw-r--r-- | net/batman-adv/distributed-arp-table.c | 2 | ||||
| -rw-r--r-- | net/batman-adv/network-coding.c | 2 | ||||
| -rw-r--r-- | net/bluetooth/hci_sock.c | 6 | ||||
| -rw-r--r-- | net/core/skbuff.c | 14 | ||||
| -rw-r--r-- | net/nfc/llcp_core.c | 4 | ||||
| -rw-r--r-- | net/nfc/rawsock.c | 4 | ||||
| -rw-r--r-- | net/tipc/bcast.c | 2 |
8 files changed, 34 insertions, 16 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c705808bef9c..1f50bfe2243d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
| @@ -744,7 +744,13 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); | |||
| 744 | int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); | 744 | int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); |
| 745 | struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); | 745 | struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); |
| 746 | struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority); | 746 | struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority); |
| 747 | struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask); | 747 | struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom, |
| 748 | gfp_t gfp_mask, bool fclone); | ||
| 749 | static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, | ||
| 750 | gfp_t gfp_mask) | ||
| 751 | { | ||
| 752 | return __pskb_copy_fclone(skb, headroom, gfp_mask, false); | ||
| 753 | } | ||
| 748 | 754 | ||
| 749 | int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask); | 755 | int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask); |
| 750 | struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, | 756 | struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, |
| @@ -2238,6 +2244,14 @@ static inline struct sk_buff *pskb_copy(struct sk_buff *skb, | |||
| 2238 | return __pskb_copy(skb, skb_headroom(skb), gfp_mask); | 2244 | return __pskb_copy(skb, skb_headroom(skb), gfp_mask); |
| 2239 | } | 2245 | } |
| 2240 | 2246 | ||
| 2247 | |||
| 2248 | static inline struct sk_buff *pskb_copy_for_clone(struct sk_buff *skb, | ||
| 2249 | gfp_t gfp_mask) | ||
| 2250 | { | ||
| 2251 | return __pskb_copy_fclone(skb, skb_headroom(skb), gfp_mask, true); | ||
| 2252 | } | ||
| 2253 | |||
| 2254 | |||
| 2241 | /** | 2255 | /** |
| 2242 | * skb_clone_writable - is the header of a clone writable | 2256 | * skb_clone_writable - is the header of a clone writable |
| 2243 | * @skb: buffer to check | 2257 | * @skb: buffer to check |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index dcd99b2bea3c..f2c066b21716 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
| @@ -594,7 +594,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, | |||
| 594 | if (!neigh_node) | 594 | if (!neigh_node) |
| 595 | goto free_orig; | 595 | goto free_orig; |
| 596 | 596 | ||
| 597 | tmp_skb = pskb_copy(skb, GFP_ATOMIC); | 597 | tmp_skb = pskb_copy_for_clone(skb, GFP_ATOMIC); |
| 598 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb, | 598 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb, |
| 599 | cand[i].orig_node, | 599 | cand[i].orig_node, |
| 600 | packet_subtype)) { | 600 | packet_subtype)) { |
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index 40a2fc4bcf4c..8d04d174669e 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
| @@ -1344,7 +1344,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, | |||
| 1344 | struct ethhdr *ethhdr; | 1344 | struct ethhdr *ethhdr; |
| 1345 | 1345 | ||
| 1346 | /* Copy skb header to change the mac header */ | 1346 | /* Copy skb header to change the mac header */ |
| 1347 | skb = pskb_copy(skb, GFP_ATOMIC); | 1347 | skb = pskb_copy_for_clone(skb, GFP_ATOMIC); |
| 1348 | if (!skb) | 1348 | if (!skb) |
| 1349 | return; | 1349 | return; |
| 1350 | 1350 | ||
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index f608bffdb8b9..80d25c150a65 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
| @@ -143,7 +143,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 143 | 143 | ||
| 144 | if (!skb_copy) { | 144 | if (!skb_copy) { |
| 145 | /* Create a private copy with headroom */ | 145 | /* Create a private copy with headroom */ |
| 146 | skb_copy = __pskb_copy(skb, 1, GFP_ATOMIC); | 146 | skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true); |
| 147 | if (!skb_copy) | 147 | if (!skb_copy) |
| 148 | continue; | 148 | continue; |
| 149 | 149 | ||
| @@ -247,8 +247,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 247 | struct hci_mon_hdr *hdr; | 247 | struct hci_mon_hdr *hdr; |
| 248 | 248 | ||
| 249 | /* Create a private copy with headroom */ | 249 | /* Create a private copy with headroom */ |
| 250 | skb_copy = __pskb_copy(skb, HCI_MON_HDR_SIZE, | 250 | skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE, |
| 251 | GFP_ATOMIC); | 251 | GFP_ATOMIC, true); |
| 252 | if (!skb_copy) | 252 | if (!skb_copy) |
| 253 | continue; | 253 | continue; |
| 254 | 254 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 05f4bef2ce12..b9e85e6cb26a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -951,10 +951,13 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) | |||
| 951 | EXPORT_SYMBOL(skb_copy); | 951 | EXPORT_SYMBOL(skb_copy); |
| 952 | 952 | ||
| 953 | /** | 953 | /** |
| 954 | * __pskb_copy - create copy of an sk_buff with private head. | 954 | * __pskb_copy_fclone - create copy of an sk_buff with private head. |
| 955 | * @skb: buffer to copy | 955 | * @skb: buffer to copy |
| 956 | * @headroom: headroom of new skb | 956 | * @headroom: headroom of new skb |
| 957 | * @gfp_mask: allocation priority | 957 | * @gfp_mask: allocation priority |
| 958 | * @fclone: if true allocate the copy of the skb from the fclone | ||
| 959 | * cache instead of the head cache; it is recommended to set this | ||
| 960 | * to true for the cases where the copy will likely be cloned | ||
| 958 | * | 961 | * |
| 959 | * Make a copy of both an &sk_buff and part of its data, located | 962 | * Make a copy of both an &sk_buff and part of its data, located |
| 960 | * in header. Fragmented data remain shared. This is used when | 963 | * in header. Fragmented data remain shared. This is used when |
| @@ -964,11 +967,12 @@ EXPORT_SYMBOL(skb_copy); | |||
| 964 | * The returned buffer has a reference count of 1. | 967 | * The returned buffer has a reference count of 1. |
| 965 | */ | 968 | */ |
| 966 | 969 | ||
| 967 | struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask) | 970 | struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom, |
| 971 | gfp_t gfp_mask, bool fclone) | ||
| 968 | { | 972 | { |
| 969 | unsigned int size = skb_headlen(skb) + headroom; | 973 | unsigned int size = skb_headlen(skb) + headroom; |
| 970 | struct sk_buff *n = __alloc_skb(size, gfp_mask, | 974 | int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0); |
| 971 | skb_alloc_rx_flag(skb), NUMA_NO_NODE); | 975 | struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE); |
| 972 | 976 | ||
| 973 | if (!n) | 977 | if (!n) |
| 974 | goto out; | 978 | goto out; |
| @@ -1008,7 +1012,7 @@ struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask) | |||
| 1008 | out: | 1012 | out: |
| 1009 | return n; | 1013 | return n; |
| 1010 | } | 1014 | } |
| 1011 | EXPORT_SYMBOL(__pskb_copy); | 1015 | EXPORT_SYMBOL(__pskb_copy_fclone); |
| 1012 | 1016 | ||
| 1013 | /** | 1017 | /** |
| 1014 | * pskb_expand_head - reallocate header of &sk_buff | 1018 | * pskb_expand_head - reallocate header of &sk_buff |
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index f6278da68763..51e788797317 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c | |||
| @@ -680,8 +680,8 @@ void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, | |||
| 680 | continue; | 680 | continue; |
| 681 | 681 | ||
| 682 | if (skb_copy == NULL) { | 682 | if (skb_copy == NULL) { |
| 683 | skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE, | 683 | skb_copy = __pskb_copy_fclone(skb, NFC_RAW_HEADER_SIZE, |
| 684 | GFP_ATOMIC); | 684 | GFP_ATOMIC, true); |
| 685 | 685 | ||
| 686 | if (skb_copy == NULL) | 686 | if (skb_copy == NULL) |
| 687 | continue; | 687 | continue; |
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 55eefee311eb..11c3544ea546 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
| @@ -378,8 +378,8 @@ void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb, | |||
| 378 | 378 | ||
| 379 | sk_for_each(sk, &raw_sk_list.head) { | 379 | sk_for_each(sk, &raw_sk_list.head) { |
| 380 | if (!skb_copy) { | 380 | if (!skb_copy) { |
| 381 | skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE, | 381 | skb_copy = __pskb_copy_fclone(skb, NFC_RAW_HEADER_SIZE, |
| 382 | GFP_ATOMIC); | 382 | GFP_ATOMIC, true); |
| 383 | if (!skb_copy) | 383 | if (!skb_copy) |
| 384 | continue; | 384 | continue; |
| 385 | 385 | ||
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 671f9817b4f4..26631679a1fa 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
| @@ -653,7 +653,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, | |||
| 653 | tipc_bearer_send(b->identity, buf, &b->bcast_addr); | 653 | tipc_bearer_send(b->identity, buf, &b->bcast_addr); |
| 654 | } else { | 654 | } else { |
| 655 | /* Avoid concurrent buffer access */ | 655 | /* Avoid concurrent buffer access */ |
| 656 | tbuf = pskb_copy(buf, GFP_ATOMIC); | 656 | tbuf = pskb_copy_for_clone(buf, GFP_ATOMIC); |
| 657 | if (!tbuf) | 657 | if (!tbuf) |
| 658 | break; | 658 | break; |
| 659 | tipc_bearer_send(b->identity, tbuf, &b->bcast_addr); | 659 | tipc_bearer_send(b->identity, tbuf, &b->bcast_addr); |
