On Sun, 15 Nov 2020 12:10:29 -0800 Dongli Zhang wrote: > The ethernet driver may allocate skb (and skb->data) via napi_alloc_skb(). > This ends up to page_frag_alloc() to allocate skb->data from > page_frag_cache->va. > > During the memory pressure, page_frag_cache->va may be allocated as > pfmemalloc page. As a result, the skb->pfmemalloc is always true as > skb->data is from page_frag_cache->va. The skb will be dropped if the > sock (receiver) does not have SOCK_MEMALLOC. This is expected behaviour > under memory pressure. > > However, once kernel is not under memory pressure any longer (suppose large > amount of memory pages are just reclaimed), the page_frag_alloc() may still > re-use the prior pfmemalloc page_frag_cache->va to allocate skb->data. As a > result, the skb->pfmemalloc is always true unless page_frag_cache->va is > re-allocated, even if the kernel is not under memory pressure any longer. > > Here is how kernel runs into issue. > > 1. The kernel is under memory pressure and allocation of > PAGE_FRAG_CACHE_MAX_ORDER in __page_frag_cache_refill() will fail. Instead, > the pfmemalloc page is allocated for page_frag_cache->va. > > 2: All skb->data from page_frag_cache->va (pfmemalloc) will have > skb->pfmemalloc=true. The skb will always be dropped by sock without > SOCK_MEMALLOC. This is an expected behaviour. > > 3. Suppose a large amount of pages are reclaimed and kernel is not under > memory pressure any longer. We expect skb->pfmemalloc drop will not happen. > > 4. Unfortunately, page_frag_alloc() does not proactively re-allocate > page_frag_alloc->va and will always re-use the prior pfmemalloc page. The > skb->pfmemalloc is always true even kernel is not under memory pressure any > longer. > > Fix this by freeing and re-allocating the page instead of recycling it.
Andrew, are you taking this via -mm or should I put it in net? I'm sending a PR to Linus tomorrow.