From 8cb8c8ae0e97e722df26eb2600602bd90604baa3 Mon Sep 17 00:00:00 2001 From: Jim Ma Date: Wed, 23 Nov 2022 01:19:36 +0800 Subject: [PATCH] fix page refcount not decrease when free page Signed-off-by: Jim Ma --- backport.h | 19 +++++++++++++++++++ igc_main.c | 4 ++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/backport.h b/backport.h index a92ede2..bfebd84 100644 --- a/backport.h +++ b/backport.h @@ -200,4 +200,23 @@ static inline bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, } *legacy_u32 = src[0]; return retval; +} + +static inline int page_ref_sub_and_test(struct page *page, int nr) +{ + int ret = atomic_sub_and_test(nr, &page->_count); + return ret; +} + +static inline void __page_frag_cache_drain(struct page *page, unsigned int count) +{ + if (page_ref_sub_and_test(page, count)) { + unsigned int order = compound_order(page); + + // TODO optimize with free_unref_page + // if (order == 0) + // free_unref_page(page); + // else + __free_pages(page, order); + } } \ No newline at end of file diff --git a/igc_main.c b/igc_main.c index df2de6c..d6d9cf0 100644 --- a/igc_main.c +++ b/igc_main.c @@ -374,7 +374,7 @@ static void igc_clean_rx_ring(struct igc_ring *rx_ring) buffer_info->dma, igc_rx_pg_size(rx_ring), DMA_FROM_DEVICE); - __free_pages(buffer_info->page, igc_rx_pg_order(rx_ring)); + __page_frag_cache_drain(buffer_info->page, buffer_info->pagecnt_bias); i++; if (i == rx_ring->count) @@ -1763,7 +1763,7 @@ static void igc_put_rx_buffer(struct igc_ring *rx_ring, dma_unmap_page(rx_ring->dev, rx_buffer->dma, igc_rx_pg_size(rx_ring), DMA_FROM_DEVICE); - __free_pages(rx_buffer->page, igc_rx_pg_order(rx_ring)); + __page_frag_cache_drain(rx_buffer->page, rx_buffer->pagecnt_bias); } /* clear contents of rx_buffer */