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 <ec...@solarflare.com> --- net/core/dev.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 586807d..0f914bf 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -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)