Skip to content

Commit 4ce0017

Browse files
ecree-solarflaredavem330
authored andcommitted
net: core: another layer of lists, around PF_MEMALLOC skb handling
First example of a layer splitting the list (rather than merely taking individual packets off it). Involves new list.h function, list_cut_before(), like list_cut_position() but cuts on the other side of the given entry. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7da517a commit 4ce0017

File tree

2 files changed

+66
-8
lines changed

2 files changed

+66
-8
lines changed

include/linux/list.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,36 @@ static inline void list_cut_position(struct list_head *list,
285285
__list_cut_position(list, head, entry);
286286
}
287287

288+
/**
289+
* list_cut_before - cut a list into two, before given entry
290+
* @list: a new list to add all removed entries
291+
* @head: a list with entries
292+
* @entry: an entry within head, could be the head itself
293+
*
294+
* This helper moves the initial part of @head, up to but
295+
* excluding @entry, from @head to @list. You should pass
296+
* in @entry an element you know is on @head. @list should
297+
* be an empty list or a list you do not care about losing
298+
* its data.
299+
* If @entry == @head, all entries on @head are moved to
300+
* @list.
301+
*/
302+
static inline void list_cut_before(struct list_head *list,
303+
struct list_head *head,
304+
struct list_head *entry)
305+
{
306+
if (head->next == entry) {
307+
INIT_LIST_HEAD(list);
308+
return;
309+
}
310+
list->next = head->next;
311+
list->next->prev = list;
312+
list->prev = entry->prev;
313+
list->prev->next = list;
314+
head->next = entry;
315+
entry->prev = head;
316+
}
317+
288318
static inline void __list_splice(const struct list_head *list,
289319
struct list_head *prev,
290320
struct list_head *next)

net/core/dev.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4784,6 +4784,14 @@ int netif_receive_skb_core(struct sk_buff *skb)
47844784
}
47854785
EXPORT_SYMBOL(netif_receive_skb_core);
47864786

4787+
static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc)
4788+
{
4789+
struct sk_buff *skb, *next;
4790+
4791+
list_for_each_entry_safe(skb, next, head, list)
4792+
__netif_receive_skb_core(skb, pfmemalloc);
4793+
}
4794+
47874795
static int __netif_receive_skb(struct sk_buff *skb)
47884796
{
47894797
int ret;
@@ -4809,6 +4817,34 @@ static int __netif_receive_skb(struct sk_buff *skb)
48094817
return ret;
48104818
}
48114819

4820+
static void __netif_receive_skb_list(struct list_head *head)
4821+
{
4822+
unsigned long noreclaim_flag = 0;
4823+
struct sk_buff *skb, *next;
4824+
bool pfmemalloc = false; /* Is current sublist PF_MEMALLOC? */
4825+
4826+
list_for_each_entry_safe(skb, next, head, list) {
4827+
if ((sk_memalloc_socks() && skb_pfmemalloc(skb)) != pfmemalloc) {
4828+
struct list_head sublist;
4829+
4830+
/* Handle the previous sublist */
4831+
list_cut_before(&sublist, head, &skb->list);
4832+
__netif_receive_skb_list_core(&sublist, pfmemalloc);
4833+
pfmemalloc = !pfmemalloc;
4834+
/* See comments in __netif_receive_skb */
4835+
if (pfmemalloc)
4836+
noreclaim_flag = memalloc_noreclaim_save();
4837+
else
4838+
memalloc_noreclaim_restore(noreclaim_flag);
4839+
}
4840+
}
4841+
/* Handle the remaining sublist */
4842+
__netif_receive_skb_list_core(head, pfmemalloc);
4843+
/* Restore pflags */
4844+
if (pfmemalloc)
4845+
memalloc_noreclaim_restore(noreclaim_flag);
4846+
}
4847+
48124848
static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp)
48134849
{
48144850
struct bpf_prog *old = rtnl_dereference(dev->xdp_prog);
@@ -4843,14 +4879,6 @@ static int generic_xdp_install(struct net_device *dev, struct netdev_bpf *xdp)
48434879
return ret;
48444880
}
48454881

4846-
static void __netif_receive_skb_list(struct list_head *head)
4847-
{
4848-
struct sk_buff *skb, *next;
4849-
4850-
list_for_each_entry_safe(skb, next, head, list)
4851-
__netif_receive_skb(skb);
4852-
}
4853-
48544882
static int netif_receive_skb_internal(struct sk_buff *skb)
48554883
{
48564884
int ret;

0 commit comments

Comments
 (0)