[Devel] [PATCH rh7 07/11] net: core: another layer of lists, around PF_MEMALLOC skb handling
Andrey Ryabinin
aryabinin at virtuozzo.com
Mon Sep 10 18:39:36 MSK 2018
From: Edward Cree <ecree at solarflare.com>
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 at solarflare.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
https://jira.sw.ru/browse/PSBM-88420
(cherry picked from commit 4ce0017a373afaaa9ef17614d8fa4f6fde261d18)
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
include/linux/list.h | 30 ++++++++++++++++++++++++++++++
net/core/dev.c | 33 +++++++++++++++++++++++++++++++--
2 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/include/linux/list.h b/include/linux/list.h
index ac6aac04acce..c93c6d027fed 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -270,6 +270,36 @@ static inline void list_cut_position(struct list_head *list,
__list_cut_position(list, head, entry);
}
+/**
+ * list_cut_before - cut a list into two, before given entry
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ *
+ * This helper moves the initial part of @head, up to but
+ * excluding @entry, from @head to @list. You should pass
+ * in @entry an element you know is on @head. @list should
+ * be an empty list or a list you do not care about losing
+ * its data.
+ * If @entry == @head, all entries on @head are moved to
+ * @list.
+ */
+static inline void list_cut_before(struct list_head *list,
+ struct list_head *head,
+ struct list_head *entry)
+{
+ if (head->next == entry) {
+ INIT_LIST_HEAD(list);
+ return;
+ }
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry->prev;
+ list->prev->next = list;
+ head->next = entry;
+ entry->prev = head;
+}
+
static inline void __list_splice(const struct list_head *list,
struct list_head *prev,
struct list_head *next)
diff --git a/net/core/dev.c b/net/core/dev.c
index 270cae0fdb08..4fc5f1967ede 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -132,6 +132,7 @@
#include <trace/events/napi.h>
#include <trace/events/net.h>
#include <trace/events/skb.h>
+#include <linux/sched/mm.h>
#include <linux/pci.h>
#include <linux/inetdevice.h>
#include <linux/cpu_rmap.h>
@@ -4195,6 +4196,14 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
return ret;
}
+static void __netif_receive_skb_list_core(struct list_head *head, bool pfmemalloc)
+{
+ struct sk_buff *skb, *next;
+
+ list_for_each_entry_safe(skb, next, head, list)
+ __netif_receive_skb_core(skb, pfmemalloc);
+}
+
static int __netif_receive_skb(struct sk_buff *skb)
{
int ret;
@@ -4222,10 +4231,30 @@ static int __netif_receive_skb(struct sk_buff *skb)
static void __netif_receive_skb_list(struct list_head *head)
{
+ unsigned long noreclaim_flag = 0;
struct sk_buff *skb, *next;
+ bool pfmemalloc = false; /* Is current sublist PF_MEMALLOC? */
- list_for_each_entry_safe(skb, next, head, list)
- __netif_receive_skb(skb);
+ list_for_each_entry_safe(skb, next, head, list) {
+ if ((sk_memalloc_socks() && skb_pfmemalloc(skb)) != pfmemalloc) {
+ struct list_head sublist;
+
+ /* Handle the previous sublist */
+ list_cut_before(&sublist, head, &skb->list);
+ __netif_receive_skb_list_core(&sublist, pfmemalloc);
+ pfmemalloc = !pfmemalloc;
+ /* See comments in __netif_receive_skb */
+ if (pfmemalloc)
+ noreclaim_flag = memalloc_noreclaim_save();
+ else
+ memalloc_noreclaim_restore(noreclaim_flag);
+ }
+ }
+ /* Handle the remaining sublist */
+ __netif_receive_skb_list_core(head, pfmemalloc);
+ /* Restore pflags */
+ if (pfmemalloc)
+ memalloc_noreclaim_restore(noreclaim_flag);
}
static int netif_receive_skb_internal(struct sk_buff *skb)
--
2.16.4
More information about the Devel
mailing list