Commit bad93e9d authored by Octavian Purdila's avatar Octavian Purdila Committed by David S. Miller

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: default avatarChristoph Paasch <christoph.paasch@uclouvain.be>
Signed-off-by: default avatarOctavian Purdila <octavian.purdila@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1a0b20b2
...@@ -744,7 +744,13 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); ...@@ -744,7 +744,13 @@ struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask); int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority); struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority);
struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority); struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t priority);
struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask); struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
gfp_t gfp_mask, bool fclone);
static inline struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom,
gfp_t gfp_mask)
{
return __pskb_copy_fclone(skb, headroom, gfp_mask, false);
}
int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask); int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail, gfp_t gfp_mask);
struct sk_buff *skb_realloc_headroom(struct sk_buff *skb, 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,6 +2244,14 @@ static inline struct sk_buff *pskb_copy(struct sk_buff *skb,
return __pskb_copy(skb, skb_headroom(skb), gfp_mask); return __pskb_copy(skb, skb_headroom(skb), gfp_mask);
} }
static inline struct sk_buff *pskb_copy_for_clone(struct sk_buff *skb,
gfp_t gfp_mask)
{
return __pskb_copy_fclone(skb, skb_headroom(skb), gfp_mask, true);
}
/** /**
* skb_clone_writable - is the header of a clone writable * skb_clone_writable - is the header of a clone writable
* @skb: buffer to check * @skb: buffer to check
......
...@@ -594,7 +594,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, ...@@ -594,7 +594,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
if (!neigh_node) if (!neigh_node)
goto free_orig; goto free_orig;
tmp_skb = pskb_copy(skb, GFP_ATOMIC); tmp_skb = pskb_copy_for_clone(skb, GFP_ATOMIC);
if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb, if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, tmp_skb,
cand[i].orig_node, cand[i].orig_node,
packet_subtype)) { packet_subtype)) {
......
...@@ -1344,7 +1344,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, ...@@ -1344,7 +1344,7 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv,
struct ethhdr *ethhdr; struct ethhdr *ethhdr;
/* Copy skb header to change the mac header */ /* Copy skb header to change the mac header */
skb = pskb_copy(skb, GFP_ATOMIC); skb = pskb_copy_for_clone(skb, GFP_ATOMIC);
if (!skb) if (!skb)
return; return;
......
...@@ -143,7 +143,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -143,7 +143,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (!skb_copy) { if (!skb_copy) {
/* Create a private copy with headroom */ /* Create a private copy with headroom */
skb_copy = __pskb_copy(skb, 1, GFP_ATOMIC); skb_copy = __pskb_copy_fclone(skb, 1, GFP_ATOMIC, true);
if (!skb_copy) if (!skb_copy)
continue; continue;
...@@ -247,8 +247,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -247,8 +247,8 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
struct hci_mon_hdr *hdr; struct hci_mon_hdr *hdr;
/* Create a private copy with headroom */ /* Create a private copy with headroom */
skb_copy = __pskb_copy(skb, HCI_MON_HDR_SIZE, skb_copy = __pskb_copy_fclone(skb, HCI_MON_HDR_SIZE,
GFP_ATOMIC); GFP_ATOMIC, true);
if (!skb_copy) if (!skb_copy)
continue; continue;
......
...@@ -951,10 +951,13 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask) ...@@ -951,10 +951,13 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, gfp_t gfp_mask)
EXPORT_SYMBOL(skb_copy); EXPORT_SYMBOL(skb_copy);
/** /**
* __pskb_copy - create copy of an sk_buff with private head. * __pskb_copy_fclone - create copy of an sk_buff with private head.
* @skb: buffer to copy * @skb: buffer to copy
* @headroom: headroom of new skb * @headroom: headroom of new skb
* @gfp_mask: allocation priority * @gfp_mask: allocation priority
* @fclone: if true allocate the copy of the skb from the fclone
* cache instead of the head cache; it is recommended to set this
* to true for the cases where the copy will likely be cloned
* *
* Make a copy of both an &sk_buff and part of its data, located * Make a copy of both an &sk_buff and part of its data, located
* in header. Fragmented data remain shared. This is used when * in header. Fragmented data remain shared. This is used when
...@@ -964,11 +967,12 @@ EXPORT_SYMBOL(skb_copy); ...@@ -964,11 +967,12 @@ EXPORT_SYMBOL(skb_copy);
* The returned buffer has a reference count of 1. * The returned buffer has a reference count of 1.
*/ */
struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask) struct sk_buff *__pskb_copy_fclone(struct sk_buff *skb, int headroom,
gfp_t gfp_mask, bool fclone)
{ {
unsigned int size = skb_headlen(skb) + headroom; unsigned int size = skb_headlen(skb) + headroom;
struct sk_buff *n = __alloc_skb(size, gfp_mask, int flags = skb_alloc_rx_flag(skb) | (fclone ? SKB_ALLOC_FCLONE : 0);
skb_alloc_rx_flag(skb), NUMA_NO_NODE); struct sk_buff *n = __alloc_skb(size, gfp_mask, flags, NUMA_NO_NODE);
if (!n) if (!n)
goto out; goto out;
...@@ -1008,7 +1012,7 @@ struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask) ...@@ -1008,7 +1012,7 @@ struct sk_buff *__pskb_copy(struct sk_buff *skb, int headroom, gfp_t gfp_mask)
out: out:
return n; return n;
} }
EXPORT_SYMBOL(__pskb_copy); EXPORT_SYMBOL(__pskb_copy_fclone);
/** /**
* pskb_expand_head - reallocate header of &sk_buff * pskb_expand_head - reallocate header of &sk_buff
......
...@@ -680,8 +680,8 @@ void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local, ...@@ -680,8 +680,8 @@ void nfc_llcp_send_to_raw_sock(struct nfc_llcp_local *local,
continue; continue;
if (skb_copy == NULL) { if (skb_copy == NULL) {
skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE, skb_copy = __pskb_copy_fclone(skb, NFC_RAW_HEADER_SIZE,
GFP_ATOMIC); GFP_ATOMIC, true);
if (skb_copy == NULL) if (skb_copy == NULL)
continue; continue;
......
...@@ -378,8 +378,8 @@ void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb, ...@@ -378,8 +378,8 @@ void nfc_send_to_raw_sock(struct nfc_dev *dev, struct sk_buff *skb,
sk_for_each(sk, &raw_sk_list.head) { sk_for_each(sk, &raw_sk_list.head) {
if (!skb_copy) { if (!skb_copy) {
skb_copy = __pskb_copy(skb, NFC_RAW_HEADER_SIZE, skb_copy = __pskb_copy_fclone(skb, NFC_RAW_HEADER_SIZE,
GFP_ATOMIC); GFP_ATOMIC, true);
if (!skb_copy) if (!skb_copy)
continue; continue;
......
...@@ -653,7 +653,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, ...@@ -653,7 +653,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1,
tipc_bearer_send(b->identity, buf, &b->bcast_addr); tipc_bearer_send(b->identity, buf, &b->bcast_addr);
} else { } else {
/* Avoid concurrent buffer access */ /* Avoid concurrent buffer access */
tbuf = pskb_copy(buf, GFP_ATOMIC); tbuf = pskb_copy_for_clone(buf, GFP_ATOMIC);
if (!tbuf) if (!tbuf)
break; break;
tipc_bearer_send(b->identity, tbuf, &b->bcast_addr); tipc_bearer_send(b->identity, tbuf, &b->bcast_addr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment