@@ -4216,6 +4216,14 @@ out:
return ret;
}
+static void __netif_receive_skb_list_core(struct sk_buff_head *list, bool pfmemalloc)
+{
+ struct sk_buff *skb;
+
+ while ((skb = __skb_dequeue(list)) != NULL)
+ __netif_receive_skb_core(skb, pfmemalloc);
+}
+
static int __netif_receive_skb(struct sk_buff *skb)
{
int ret;
@@ -4243,10 +4251,34 @@ static int __netif_receive_skb(struct sk_buff *skb)
static void __netif_receive_skb_list(struct sk_buff_head *list)
{
+ struct sk_buff_head sublist;
+ bool pfmemalloc = false; /* Is current sublist PF_MEMALLOC? */
+ unsigned long pflags;
struct sk_buff *skb;
- while ((skb = __skb_dequeue(list)) != NULL)
- __netif_receive_skb(skb);
+ __skb_queue_head_init(&sublist);
+
+ while ((skb = __skb_dequeue(list)) != NULL) {
+ if ((sk_memalloc_socks() && skb_pfmemalloc(skb)) != pfmemalloc) {
+ /* Handle the previous sublist */
+ __netif_receive_skb_list_core(&sublist, pfmemalloc);
+ pfmemalloc = !pfmemalloc;
+ /* See comments in __netif_receive_skb */
+ if (pfmemalloc) {
+ pflags = current->flags;
+ current->flags |= PF_MEMALLOC;
+ } else {
+ tsk_restore_flags(current, pflags, PF_MEMALLOC);
+ }
+ __skb_queue_head_init(&sublist);
+ }
+ __skb_queue_tail(&sublist, skb);
+ }
+ /* Handle the last sublist */
+ __netif_receive_skb_list_core(&sublist, pfmemalloc);
+ /* Restore pflags */
+ if (pfmemalloc)
+ tsk_restore_flags(current, pflags, PF_MEMALLOC);
}
static int netif_receive_skb_internal(struct sk_buff *skb)
First example of a layer splitting the list (rather than merely taking individual packets off it). Again, trying to factor the common parts wouldn't make this any nicer. Signed-off-by: Edward Cree <ecree@solarflare.com> --- net/core/dev.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)