Re: [PATCH v1 1/3] mm/huge_memory: buddy allocator like folio_split()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Zi,

kernel test robot noticed the following build warnings:

[auto build test WARNING on akpm-mm/mm-everything]
[also build test WARNING on next-20241029]
[cannot apply to linus/master v6.12-rc5]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Zi-Yan/mm-huge_memory-buddy-allocator-like-folio_split/20241029-021200
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link:    https://lore.kernel.org/r/20241028180932.1319265-2-ziy%40nvidia.com
patch subject: [PATCH v1 1/3] mm/huge_memory: buddy allocator like folio_split()
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20241029/202410291853.lBOeTPTK-lkp@xxxxxxxxx/config)
compiler: clang version 19.1.2 (https://github.com/llvm/llvm-project 7ba7d8e2f7b6445b60679da826210cdde29eaf8b)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241029/202410291853.lBOeTPTK-lkp@xxxxxxxxx/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@xxxxxxxxx>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410291853.lBOeTPTK-lkp@xxxxxxxxx/

All warnings (new ones prefixed by >>):

   In file included from mm/huge_memory.c:8:
   In file included from include/linux/mm.h:2213:
   include/linux/vmstat.h:504:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     504 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     505 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:511:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     511 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     512 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:518:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     518 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:524:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     524 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     525 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/huge_memory.c:18:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>> mm/huge_memory.c:3342:6: warning: variable 'nr_dropped' set but not used [-Wunused-but-set-variable]
    3342 |         int nr_dropped = 0;
         |             ^
   mm/huge_memory.c:3806:12: warning: unused function 'folio_split' [-Wunused-function]
    3806 | static int folio_split(struct folio *folio, unsigned int new_order,
         |            ^~~~~~~~~~~
   8 warnings generated.


vim +/nr_dropped +3342 mm/huge_memory.c

  3292	
  3293	#define for_each_folio_until_end_safe(iter, iter2, start, end)	\
  3294		for (iter = start, iter2 = folio_next(start);		\
  3295		     iter != end;					\
  3296		     iter = iter2, iter2 = folio_next(iter2))
  3297	
  3298	/*
  3299	 * It splits a @folio (without mapping) to lower order smaller folios in two
  3300	 * ways.
  3301	 * 1. uniform split: the given @folio into multiple @new_order small folios,
  3302	 *    where all small folios have the same order. This is done when
  3303	 *    uniform_split is true.
  3304	 * 2. buddy allocator like split: the given @folio is split into half and one
  3305	 *    of the half (containing the given page) is split into half until the
  3306	 *    given @page's order becomes @new_order. This is done when uniform_split is
  3307	 *    false.
  3308	 *
  3309	 * The high level flow for these two methods are:
  3310	 * 1. uniform split: a single __split_folio_to_order() is called to split the
  3311	 *    @folio into @new_order, then we traverse all the resulting folios one by
  3312	 *    one in PFN ascending order and perform stats, unfreeze, adding to list,
  3313	 *    and file mapping index operations.
  3314	 * 2. buddy allocator like split: in general, folio_order - @new_order calls to
  3315	 *    __split_folio_to_order() are called in the for loop to split the @folio
  3316	 *    to one lower order at a time. The resulting small folios are processed
  3317	 *    like what is done during the traversal in 1, except the one containing
  3318	 *    @page, which is split in next for loop.
  3319	 *
  3320	 * After splitting, the caller's folio reference will be transferred to the
  3321	 * folio containing @page. The other folios may be freed if they are not mapped.
  3322	 *
  3323	 * In terms of locking, after splitting,
  3324	 * 1. uniform split leaves @page (or the folio contains it) locked;
  3325	 * 2. buddy allocator like split leaves @folio locked.
  3326	 *
  3327	 * If @list is null, tail pages will be added to LRU list, otherwise, to @list.
  3328	 */
  3329	static int __folio_split_without_mapping(struct folio *folio, int new_order,
  3330			struct page *page, struct list_head *list, pgoff_t end,
  3331			struct xa_state *xas, struct address_space *mapping,
  3332			bool uniform_split)
  3333	{
  3334		struct lruvec *lruvec;
  3335		struct address_space *swap_cache = NULL;
  3336		struct folio *origin_folio = folio;
  3337		struct folio *next_folio = folio_next(folio);
  3338		struct folio *new_folio;
  3339		struct folio *next;
  3340		int order = folio_order(folio);
  3341		int split_order = order - 1;
> 3342		int nr_dropped = 0;
  3343	
  3344		if (folio_test_anon(folio) && folio_test_swapcache(folio)) {
  3345			if (!uniform_split)
  3346				return -EINVAL;
  3347	
  3348			swap_cache = swap_address_space(folio->swap);
  3349			xa_lock(&swap_cache->i_pages);
  3350		}
  3351	
  3352		if (folio_test_anon(folio))
  3353			mod_mthp_stat(order, MTHP_STAT_NR_ANON, -1);
  3354	
  3355		/* lock lru list/PageCompound, ref frozen by page_ref_freeze */
  3356		lruvec = folio_lruvec_lock(folio);
  3357	
  3358		/*
  3359		 * split to new_order one order at a time. For uniform split,
  3360		 * intermediate orders are skipped
  3361		 */
  3362		for (split_order = order - 1; split_order >= new_order; split_order--) {
  3363			int old_order = folio_order(folio);
  3364			struct folio *release;
  3365			struct folio *end_folio = folio_next(folio);
  3366			int status;
  3367	
  3368			if (folio_test_anon(folio) && split_order == 1)
  3369				continue;
  3370			if (uniform_split && split_order != new_order)
  3371				continue;
  3372	
  3373			if (mapping) {
  3374				/*
  3375				 * uniform split has xas_split_alloc() called before
  3376				 * irq is disabled, since xas_nomem() might not be
  3377				 * able to allocate enough memory.
  3378				 */
  3379				if (uniform_split)
  3380					xas_split(xas, folio, old_order);
  3381				else {
  3382					xas_set_order(xas, folio->index, split_order);
  3383					xas_set_err(xas, -ENOMEM);
  3384					if (xas_nomem(xas, 0))
  3385						xas_split(xas, folio, old_order);
  3386					else
  3387						return -ENOMEM;
  3388				}
  3389			}
  3390	
  3391			split_page_memcg(&folio->page, old_order, split_order);
  3392			split_page_owner(&folio->page, old_order, split_order);
  3393			pgalloc_tag_split(folio, old_order, split_order);
  3394	
  3395			status = __split_folio_to_order(folio, split_order);
  3396	
  3397			if (status < 0)
  3398				return status;
  3399	
  3400			/*
  3401			 * Iterate through after-split folios and perform related
  3402			 * operations. But in buddy allocator like split, the folio
  3403			 * containing the specified page is skipped until its order
  3404			 * is new_order, since the folio will be worked on in next
  3405			 * iteration.
  3406			 */
  3407			for_each_folio_until_end_safe(release, next, folio, end_folio) {
  3408				if (page_in_folio_offset(page, release) >= 0) {
  3409					folio = release;
  3410					if (split_order != new_order)
  3411						continue;
  3412				}
  3413				if (folio_test_anon(release))
  3414					mod_mthp_stat(folio_order(release),
  3415							MTHP_STAT_NR_ANON, 1);
  3416	
  3417				/*
  3418				 * Unfreeze refcount first. Additional reference from
  3419				 * page cache.
  3420				 */
  3421				folio_ref_unfreeze(release,
  3422					1 + ((!folio_test_anon(origin_folio) ||
  3423					     folio_test_swapcache(origin_folio)) ?
  3424						     folio_nr_pages(release) : 0));
  3425	
  3426				if (release != origin_folio)
  3427					lru_add_page_tail(origin_folio, &release->page,
  3428							lruvec, list);
  3429	
  3430				/* Some pages can be beyond EOF: drop them from page cache */
  3431				if (release->index >= end) {
  3432					if (shmem_mapping(origin_folio->mapping))
  3433						nr_dropped++;
  3434					else if (folio_test_clear_dirty(release))
  3435						folio_account_cleaned(release,
  3436							inode_to_wb(origin_folio->mapping->host));
  3437					__filemap_remove_folio(release, NULL);
  3438					folio_put(release);
  3439				} else if (!folio_test_anon(release)) {
  3440					__xa_store(&origin_folio->mapping->i_pages,
  3441							release->index, &release->page, 0);
  3442				} else if (swap_cache) {
  3443					__xa_store(&swap_cache->i_pages,
  3444							swap_cache_index(release->swap),
  3445							&release->page, 0);
  3446				}
  3447			}
  3448		}
  3449	
  3450		unlock_page_lruvec(lruvec);
  3451	
  3452		if (folio_test_anon(origin_folio)) {
  3453			if (folio_test_swapcache(origin_folio))
  3454				xa_unlock(&swap_cache->i_pages);
  3455		} else
  3456			xa_unlock(&mapping->i_pages);
  3457	
  3458		/* Caller disabled irqs, so they are still disabled here */
  3459		local_irq_enable();
  3460	
  3461		remap_page(origin_folio, 1 << order,
  3462				folio_test_anon(origin_folio) ?
  3463					RMP_USE_SHARED_ZEROPAGE : 0);
  3464	
  3465		/*
  3466		 * At this point, folio should contain the specified page, so that it
  3467		 * will be left to the caller to unlock it.
  3468		 */
  3469		for_each_folio_until_end_safe(new_folio, next, origin_folio, next_folio) {
  3470			if (uniform_split && new_folio == folio)
  3471				continue;
  3472			if (!uniform_split && new_folio == origin_folio)
  3473				continue;
  3474	
  3475			folio_unlock(new_folio);
  3476			/*
  3477			 * Subpages may be freed if there wasn't any mapping
  3478			 * like if add_to_swap() is running on a lru page that
  3479			 * had its mapping zapped. And freeing these pages
  3480			 * requires taking the lru_lock so we do the put_page
  3481			 * of the tail pages after the split is complete.
  3482			 */
  3483			free_page_and_swap_cache(&new_folio->page);
  3484		}
  3485		return 0;
  3486	}
  3487	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux