• Dean Nelson's avatar
    thunderx: eliminate extra calls to put_page() for pages held for recycling · cd35ef91
    Dean Nelson authored
    For the non-XDP case, commit 77322538 ("net: thunderx: Optimize
    page recycling for XDP") added code to nicvf_free_rbdr() that, when releasing
    the additional receive buffer page reference held for recycling, repeatedly
    calls put_page() until the page's _refcount goes to zero. Which results in
    the page being freed.
    
    This is not okay if the page's _refcount was greater than 1 (in the non-XDP
    case), because nicvf_free_rbdr() should not be subtracting more than what
    nicvf_alloc_page() had previously added to the page's _refcount, which was
    only 1 (in the non-XDP case).
    
    This can arise if a received packet is still being processed and the receive
    buffer (i.e., skb->head) has not yet been freed via skb_free_head() when
    nicvf_free_rbdr() is spinning through the aforementioned put_page() loop.
    
    If this should occur, when the received packet finishes processing and
    skb_free_head() is called, various problems can ensue. Exactly what, depends on
    whether the page has already been reallocated or not, anything from "BUG: Bad
    page state ... ", to "Unable to handle kernel NULL pointer dereference ..." or
    "Unable to handle kernel paging request...".
    
    So this patch changes nicvf_free_rbdr() to only call put_page() once for pages
    held for recycling (in the non-XDP case).
    
    Fixes: 77322538 ("net: thunderx: Optimize page recycling for XDP")
    Signed-off-by: default avatarDean Nelson <dnelson@redhat.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    cd35ef91
nicvf_queues.c 51.5 KB