1. 24 Oct, 2023 1 commit
    • Yunsheng Lin's avatar
      page_pool: unify frag_count handling in page_pool_is_last_frag() · 58d53d8f
      Yunsheng Lin authored
      Currently when page_pool_create() is called with
      PP_FLAG_PAGE_FRAG flag, page_pool_alloc_pages() is only
      allowed to be called under the below constraints:
      1. page_pool_fragment_page() need to be called to setup
         page->pp_frag_count immediately.
      2. page_pool_defrag_page() often need to be called to drain
         the page->pp_frag_count when there is no more user will
         be holding on to that page.
      
      Those constraints exist in order to support a page to be
      split into multi fragments.
      
      And those constraints have some overhead because of the
      cache line dirtying/bouncing and atomic update.
      
      Those constraints are unavoidable for case when we need a
      page to be split into more than one fragment, but there is
      also case that we want to avoid the above constraints and
      their overhead when a page can't be split as it can only
      hold a fragment as requested by user, depending on different
      use cases:
      use case 1: allocate page without page splitting.
      use case 2: allocate page with page splitting.
      use case 3: allocate page with or without page splitting
                  depending on the fragment size.
      
      Currently page pool only provide page_pool_alloc_pages() and
      page_pool_alloc_frag() API to enable the 1 & 2 separately,
      so we can not use a combination of 1 & 2 to enable 3, it is
      not possible yet because of the per page_pool flag
      PP_FLAG_PAGE_FRAG.
      
      So in order to allow allocating unsplit page without the
      overhead of split page while still allow allocating split
      page we need to remove the per page_pool flag in
      page_pool_is_last_frag(), as best as I can think of, it seems
      there are two methods as below:
      1. Add per page flag/bit to indicate a page is split or
         not, which means we might need to update that flag/bit
         everytime the page is recycled, dirtying the cache line
         of 'struct page' for use case 1.
      2. Unify the page->pp_frag_count handling for both split and
         unsplit page by assuming all pages in the page pool is split
         into a big fragment initially.
      
      As page pool already supports use case 1 without dirtying the
      cache line of 'struct page' whenever a page is recyclable, we
      need to support the above use case 3 with minimal overhead,
      especially not adding any noticeable overhead for use case 1,
      and we are already doing an optimization by not updating
      pp_frag_count in page_pool_defrag_page() for the last fragment
      user, this patch chooses to unify the pp_frag_count handling
      to support the above use case 3.
      
      There is no noticeable performance degradation and some
      justification for unifying the frag_count handling with this
      patch applied using a micro-benchmark testing in [1].
      
      1. https://lore.kernel.org/all/bf2591f8-7b3c-4480-bb2c-31dc9da1d6ac@huawei.com/Signed-off-by: default avatarYunsheng Lin <linyunsheng@huawei.com>
      CC: Lorenzo Bianconi <lorenzo@kernel.org>
      CC: Alexander Duyck <alexander.duyck@gmail.com>
      CC: Liang Chen <liangchen.linux@gmail.com>
      CC: Alexander Lobakin <aleksander.lobakin@intel.com>
      Link: https://lore.kernel.org/r/20231020095952.11055-2-linyunsheng@huawei.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
      58d53d8f
  2. 23 Oct, 2023 39 commits