include/linux/huge_mm.h | 5 +- mm/huge_memory.c | 332 ++++++++++++++++++++++------------------ mm/migrate_device.c | 3 +- 3 files changed, 191 insertions(+), 149 deletions(-)
Unmapped was added as a parameter to __folio_split() and related
call sites to support splitting of folios already in the midst
of a migration. This special case arose for device private folio
migration since during migration there could be a disconnect between
source and destination on the folio size.
Introduce folio_split_unmapped() to handle this special case. Also
refactor code and add __folio_freeze_and_split_unmapped() helper that
is common to both __folio_split() and folio_split_unmapped().
This in turn removes the special casing introduced by the unmapped
parameter in __folio_split().
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Rakie Kim <rakie.kim@sk.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ying Huang <ying.huang@linux.alibaba.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>
Cc: Nico Pache <npache@redhat.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Lyude Paul <lyude@redhat.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Ralph Campbell <rcampbell@nvidia.com>
Cc: Mika Penttilä <mpenttil@redhat.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Francois Dugast <francois.dugast@intel.com>
Suggested-by: Zi Yan <ziy@nvidia.com>
Signed-off-by: Balbir Singh <balbirs@nvidia.com>
---
include/linux/huge_mm.h | 5 +-
mm/huge_memory.c | 332 ++++++++++++++++++++++------------------
mm/migrate_device.c | 3 +-
3 files changed, 191 insertions(+), 149 deletions(-)
diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h
index e2e91aa1a042..1d439de1ca2c 100644
--- a/include/linux/huge_mm.h
+++ b/include/linux/huge_mm.h
@@ -371,7 +371,8 @@ enum split_type {
bool can_split_folio(struct folio *folio, int caller_pins, int *pextra_pins);
int __split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
- unsigned int new_order, bool unmapped);
+ unsigned int new_order);
+int folio_split_unmapped(struct folio *folio, unsigned int new_order);
int min_order_for_split(struct folio *folio);
int split_folio_to_list(struct folio *folio, struct list_head *list);
bool folio_split_supported(struct folio *folio, unsigned int new_order,
@@ -382,7 +383,7 @@ int folio_split(struct folio *folio, unsigned int new_order, struct page *page,
static inline int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
unsigned int new_order)
{
- return __split_huge_page_to_list_to_order(page, list, new_order, false);
+ return __split_huge_page_to_list_to_order(page, list, new_order);
}
static inline int split_huge_page_to_order(struct page *page, unsigned int new_order)
{
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index e4dadcb9e90b..afc10079724c 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -3739,6 +3739,151 @@ bool folio_split_supported(struct folio *folio, unsigned int new_order,
return true;
}
+static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int new_order,
+ struct page *split_at, struct xa_state *xas,
+ struct address_space *mapping, bool do_lru,
+ struct list_head *list, enum split_type split_type,
+ pgoff_t end, int extra_pins)
+{
+ struct folio *end_folio = folio_next(folio);
+ struct folio *new_folio, *next;
+ int old_order = folio_order(folio);
+ int nr_shmem_dropped = 0;
+ int ret = 0;
+ struct deferred_split *ds_queue;
+
+ /* Prevent deferred_split_scan() touching ->_refcount */
+ ds_queue = folio_split_queue_lock(folio);
+ if (folio_ref_freeze(folio, 1 + extra_pins)) {
+ struct swap_cluster_info *ci = NULL;
+ struct lruvec *lruvec;
+ int expected_refs;
+
+ if (old_order > 1) {
+ if (!list_empty(&folio->_deferred_list)) {
+ ds_queue->split_queue_len--;
+ /*
+ * Reinitialize page_deferred_list after removing the
+ * page from the split_queue, otherwise a subsequent
+ * split will see list corruption when checking the
+ * page_deferred_list.
+ */
+ list_del_init(&folio->_deferred_list);
+ }
+ if (folio_test_partially_mapped(folio)) {
+ folio_clear_partially_mapped(folio);
+ mod_mthp_stat(old_order,
+ MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
+ }
+ }
+ split_queue_unlock(ds_queue);
+ if (mapping) {
+ int nr = folio_nr_pages(folio);
+
+ if (folio_test_pmd_mappable(folio) &&
+ new_order < HPAGE_PMD_ORDER) {
+ if (folio_test_swapbacked(folio)) {
+ __lruvec_stat_mod_folio(folio,
+ NR_SHMEM_THPS, -nr);
+ } else {
+ __lruvec_stat_mod_folio(folio,
+ NR_FILE_THPS, -nr);
+ filemap_nr_thps_dec(mapping);
+ }
+ }
+ }
+
+ if (folio_test_swapcache(folio)) {
+ if (mapping) {
+ VM_WARN_ON_ONCE_FOLIO(mapping, folio);
+ return -EINVAL;
+ }
+
+ ci = swap_cluster_get_and_lock(folio);
+ }
+
+ /* lock lru list/PageCompound, ref frozen by page_ref_freeze */
+ if (do_lru)
+ lruvec = folio_lruvec_lock(folio);
+
+ ret = __split_unmapped_folio(folio, new_order, split_at, xas,
+ mapping, split_type);
+
+ /*
+ * Unfreeze after-split folios and put them back to the right
+ * list. @folio should be kept frozon until page cache
+ * entries are updated with all the other after-split folios
+ * to prevent others seeing stale page cache entries.
+ * As a result, new_folio starts from the next folio of
+ * @folio.
+ */
+ for (new_folio = folio_next(folio); new_folio != end_folio;
+ new_folio = next) {
+ unsigned long nr_pages = folio_nr_pages(new_folio);
+
+ next = folio_next(new_folio);
+
+ zone_device_private_split_cb(folio, new_folio);
+
+ expected_refs = folio_expected_ref_count(new_folio) + 1;
+ folio_ref_unfreeze(new_folio, expected_refs);
+
+ if (do_lru)
+ lru_add_split_folio(folio, new_folio, lruvec, list);
+
+ /*
+ * Anonymous folio with swap cache.
+ * NOTE: shmem in swap cache is not supported yet.
+ */
+ if (ci) {
+ __swap_cache_replace_folio(ci, folio, new_folio);
+ continue;
+ }
+
+ /* Anonymous folio without swap cache */
+ if (!mapping)
+ continue;
+
+ /* Add the new folio to the page cache. */
+ if (new_folio->index < end) {
+ __xa_store(&mapping->i_pages, new_folio->index,
+ new_folio, 0);
+ continue;
+ }
+
+ /* Drop folio beyond EOF: ->index >= end */
+ if (shmem_mapping(mapping))
+ nr_shmem_dropped += nr_pages;
+ else if (folio_test_clear_dirty(new_folio))
+ folio_account_cleaned(
+ new_folio, inode_to_wb(mapping->host));
+ __filemap_remove_folio(new_folio, NULL);
+ folio_put_refs(new_folio, nr_pages);
+ }
+
+ zone_device_private_split_cb(folio, NULL);
+ /*
+ * Unfreeze @folio only after all page cache entries, which
+ * used to point to it, have been updated with new folios.
+ * Otherwise, a parallel folio_try_get() can grab @folio
+ * and its caller can see stale page cache entries.
+ */
+ expected_refs = folio_expected_ref_count(folio) + 1;
+ folio_ref_unfreeze(folio, expected_refs);
+
+ if (do_lru)
+ unlock_page_lruvec(lruvec);
+
+ if (ci)
+ swap_cluster_unlock(ci);
+ } else {
+ split_queue_unlock(ds_queue);
+ return -EAGAIN;
+ }
+
+ return ret;
+}
+
/**
* __folio_split() - split a folio at @split_at to a @new_order folio
* @folio: folio to split
@@ -3747,7 +3892,6 @@ bool folio_split_supported(struct folio *folio, unsigned int new_order,
* @lock_at: a page within @folio to be left locked to caller
* @list: after-split folios will be put on it if non NULL
* @split_type: perform uniform split or not (non-uniform split)
- * @unmapped: The pages are already unmapped, they are migration entries.
*
* It calls __split_unmapped_folio() to perform uniform and non-uniform split.
* It is in charge of checking whether the split is supported or not and
@@ -3763,9 +3907,8 @@ bool folio_split_supported(struct folio *folio, unsigned int new_order,
*/
static int __folio_split(struct folio *folio, unsigned int new_order,
struct page *split_at, struct page *lock_at,
- struct list_head *list, enum split_type split_type, bool unmapped)
+ struct list_head *list, enum split_type split_type)
{
- struct deferred_split *ds_queue;
XA_STATE(xas, &folio->mapping->i_pages, folio->index);
struct folio *end_folio = folio_next(folio);
bool is_anon = folio_test_anon(folio);
@@ -3809,14 +3952,12 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
* is taken to serialise against parallel split or collapse
* operations.
*/
- if (!unmapped) {
- anon_vma = folio_get_anon_vma(folio);
- if (!anon_vma) {
- ret = -EBUSY;
- goto out;
- }
- anon_vma_lock_write(anon_vma);
+ anon_vma = folio_get_anon_vma(folio);
+ if (!anon_vma) {
+ ret = -EBUSY;
+ goto out;
}
+ anon_vma_lock_write(anon_vma);
mapping = NULL;
} else {
unsigned int min_order;
@@ -3882,8 +4023,7 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
goto out_unlock;
}
- if (!unmapped)
- unmap_folio(folio);
+ unmap_folio(folio);
/* block interrupt reentry in xa_lock and spinlock */
local_irq_disable();
@@ -3900,142 +4040,14 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
}
}
- /* Prevent deferred_split_scan() touching ->_refcount */
- ds_queue = folio_split_queue_lock(folio);
- if (folio_ref_freeze(folio, 1 + extra_pins)) {
- struct swap_cluster_info *ci = NULL;
- struct lruvec *lruvec;
- int expected_refs;
-
- if (old_order > 1) {
- if (!list_empty(&folio->_deferred_list)) {
- ds_queue->split_queue_len--;
- /*
- * Reinitialize page_deferred_list after removing the
- * page from the split_queue, otherwise a subsequent
- * split will see list corruption when checking the
- * page_deferred_list.
- */
- list_del_init(&folio->_deferred_list);
- }
- if (folio_test_partially_mapped(folio)) {
- folio_clear_partially_mapped(folio);
- mod_mthp_stat(old_order,
- MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
- }
- }
- split_queue_unlock(ds_queue);
- if (mapping) {
- int nr = folio_nr_pages(folio);
-
- if (folio_test_pmd_mappable(folio) &&
- new_order < HPAGE_PMD_ORDER) {
- if (folio_test_swapbacked(folio)) {
- __lruvec_stat_mod_folio(folio,
- NR_SHMEM_THPS, -nr);
- } else {
- __lruvec_stat_mod_folio(folio,
- NR_FILE_THPS, -nr);
- filemap_nr_thps_dec(mapping);
- }
- }
- }
-
- if (folio_test_swapcache(folio)) {
- if (mapping) {
- VM_WARN_ON_ONCE_FOLIO(mapping, folio);
- ret = -EINVAL;
- goto fail;
- }
-
- ci = swap_cluster_get_and_lock(folio);
- }
-
- /* lock lru list/PageCompound, ref frozen by page_ref_freeze */
- lruvec = folio_lruvec_lock(folio);
-
- ret = __split_unmapped_folio(folio, new_order, split_at, &xas,
- mapping, split_type);
-
- /*
- * Unfreeze after-split folios and put them back to the right
- * list. @folio should be kept frozon until page cache
- * entries are updated with all the other after-split folios
- * to prevent others seeing stale page cache entries.
- * As a result, new_folio starts from the next folio of
- * @folio.
- */
- for (new_folio = folio_next(folio); new_folio != end_folio;
- new_folio = next) {
- unsigned long nr_pages = folio_nr_pages(new_folio);
-
- next = folio_next(new_folio);
-
- zone_device_private_split_cb(folio, new_folio);
-
- expected_refs = folio_expected_ref_count(new_folio) + 1;
- folio_ref_unfreeze(new_folio, expected_refs);
-
- if (!unmapped)
- lru_add_split_folio(folio, new_folio, lruvec, list);
-
- /*
- * Anonymous folio with swap cache.
- * NOTE: shmem in swap cache is not supported yet.
- */
- if (ci) {
- __swap_cache_replace_folio(ci, folio, new_folio);
- continue;
- }
-
- /* Anonymous folio without swap cache */
- if (!mapping)
- continue;
-
- /* Add the new folio to the page cache. */
- if (new_folio->index < end) {
- __xa_store(&mapping->i_pages, new_folio->index,
- new_folio, 0);
- continue;
- }
-
- /* Drop folio beyond EOF: ->index >= end */
- if (shmem_mapping(mapping))
- nr_shmem_dropped += nr_pages;
- else if (folio_test_clear_dirty(new_folio))
- folio_account_cleaned(
- new_folio, inode_to_wb(mapping->host));
- __filemap_remove_folio(new_folio, NULL);
- folio_put_refs(new_folio, nr_pages);
- }
-
- zone_device_private_split_cb(folio, NULL);
- /*
- * Unfreeze @folio only after all page cache entries, which
- * used to point to it, have been updated with new folios.
- * Otherwise, a parallel folio_try_get() can grab @folio
- * and its caller can see stale page cache entries.
- */
- expected_refs = folio_expected_ref_count(folio) + 1;
- folio_ref_unfreeze(folio, expected_refs);
-
- unlock_page_lruvec(lruvec);
-
- if (ci)
- swap_cluster_unlock(ci);
- } else {
- split_queue_unlock(ds_queue);
- ret = -EAGAIN;
- }
+ ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,
+ true, list, split_type, end, extra_pins);
fail:
if (mapping)
xas_unlock(&xas);
local_irq_enable();
- if (unmapped)
- return ret;
-
if (nr_shmem_dropped)
shmem_uncharge(mapping->host, nr_shmem_dropped);
@@ -4079,6 +4091,36 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
return ret;
}
+/*
+ * This function is a helper for splitting folios that have already been unmapped.
+ * The use case is that the device or the CPU can refuse to migrate THP pages in
+ * the middle of migration, due to allocation issues on either side
+ *
+ * The high level code is copied from __folio_split, since the pages are anonymous
+ * and are already isolated from the LRU, the code has been simplified to not
+ * burden __folio_split with unmapped sprinkled into the code.
+ *
+ * None of the split folios are unlocked
+ */
+int folio_split_unmapped(struct folio *folio, unsigned int new_order)
+{
+ int extra_pins, ret = 0;
+
+ VM_WARN_ON_FOLIO(folio_mapped(folio), folio);
+ VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
+ VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
+
+ if (!can_split_folio(folio, 1, &extra_pins))
+ return -EAGAIN;
+
+ local_irq_disable();
+ ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,
+ NULL, false, NULL, SPLIT_TYPE_UNIFORM,
+ 0, extra_pins);
+ local_irq_enable();
+ return ret;
+}
+
/*
* This function splits a large folio into smaller folios of order @new_order.
* @page can point to any page of the large folio to split. The split operation
@@ -4127,12 +4169,12 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
* with the folio. Splitting to order 0 is compatible with all folios.
*/
int __split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
- unsigned int new_order, bool unmapped)
+ unsigned int new_order)
{
struct folio *folio = page_folio(page);
return __folio_split(folio, new_order, &folio->page, page, list,
- SPLIT_TYPE_UNIFORM, unmapped);
+ SPLIT_TYPE_UNIFORM);
}
/**
@@ -4163,7 +4205,7 @@ int folio_split(struct folio *folio, unsigned int new_order,
struct page *split_at, struct list_head *list)
{
return __folio_split(folio, new_order, split_at, &folio->page, list,
- SPLIT_TYPE_NON_UNIFORM, false);
+ SPLIT_TYPE_NON_UNIFORM);
}
int min_order_for_split(struct folio *folio)
diff --git a/mm/migrate_device.c b/mm/migrate_device.c
index c50abbd32f21..723ef42550dc 100644
--- a/mm/migrate_device.c
+++ b/mm/migrate_device.c
@@ -918,8 +918,7 @@ static int migrate_vma_split_unmapped_folio(struct migrate_vma *migrate,
folio_get(folio);
split_huge_pmd_address(migrate->vma, addr, true);
- ret = __split_huge_page_to_list_to_order(folio_page(folio, 0), NULL,
- 0, true);
+ ret = folio_split_unmapped(folio, 0);
if (ret)
return ret;
migrate->src[idx] &= ~MIGRATE_PFN_COMPOUND;
--
2.51.1
Hi Balbir,
kernel test robot noticed the following build warnings:
url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com
patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped
config: i386-randconfig-141-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151216.rhK2ItOb-lkp@intel.com/config)
compiler: gcc-12 (Debian 12.4.0-5) 12.4.0
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@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202511151216.rhK2ItOb-lkp@intel.com/
smatch warnings:
mm/huge_memory.c:4044 __folio_split() error: uninitialized symbol 'end'.
mm/huge_memory.c:4052 __folio_split() error: we previously assumed 'mapping' could be null (see line 4046)
vim +/end +4044 mm/huge_memory.c
6384dd1d18de7b Zi Yan 2025-03-07 3908 static int __folio_split(struct folio *folio, unsigned int new_order,
58729c04cf1092 Zi Yan 2025-03-07 3909 struct page *split_at, struct page *lock_at,
f6b1f167ffe29f Balbir Singh 2025-11-14 3910 struct list_head *list, enum split_type split_type)
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3911 {
58729c04cf1092 Zi Yan 2025-03-07 3912 XA_STATE(xas, &folio->mapping->i_pages, folio->index);
6c7de9c83be68b Zi Yan 2025-07-18 3913 struct folio *end_folio = folio_next(folio);
5d65c8d758f259 Barry Song 2024-08-24 3914 bool is_anon = folio_test_anon(folio);
baa355fd331424 Kirill A. Shutemov 2016-07-26 3915 struct address_space *mapping = NULL;
5d65c8d758f259 Barry Song 2024-08-24 3916 struct anon_vma *anon_vma = NULL;
8ec26327c18e1d Wei Yang 2025-10-10 3917 int old_order = folio_order(folio);
6c7de9c83be68b Zi Yan 2025-07-18 3918 struct folio *new_folio, *next;
391dc7f40590d7 Zi Yan 2025-07-18 3919 int nr_shmem_dropped = 0;
391dc7f40590d7 Zi Yan 2025-07-18 3920 int remap_flags = 0;
504e070dc08f75 Yang Shi 2021-06-15 3921 int extra_pins, ret;
006d3ff27e884f Hugh Dickins 2018-11-30 3922 pgoff_t end;
478d134e9506c7 Xu Yu 2022-04-28 3923 bool is_hzp;
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3924
714b056c832106 Zi Yan 2025-07-17 3925 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
714b056c832106 Zi Yan 2025-07-17 3926 VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3927
58729c04cf1092 Zi Yan 2025-03-07 3928 if (folio != page_folio(split_at) || folio != page_folio(lock_at))
1412ecb3d256e5 Zi Yan 2024-03-07 3929 return -EINVAL;
1412ecb3d256e5 Zi Yan 2024-03-07 3930
8ec26327c18e1d Wei Yang 2025-10-10 3931 if (new_order >= old_order)
c010d47f107f60 Zi Yan 2024-02-26 3932 return -EINVAL;
58729c04cf1092 Zi Yan 2025-03-07 3933
aa27253af32c74 Wei Yang 2025-11-06 3934 if (!folio_split_supported(folio, new_order, split_type, /* warn = */ true))
6a50c9b512f773 Ran Xiaokai 2024-06-07 3935 return -EINVAL;
c010d47f107f60 Zi Yan 2024-02-26 3936
5beaee54a324ba Matthew Wilcox (Oracle 2024-03-26 3937) is_hzp = is_huge_zero_folio(folio);
4737edbbdd4958 Naoya Horiguchi 2023-04-06 3938 if (is_hzp) {
4737edbbdd4958 Naoya Horiguchi 2023-04-06 3939 pr_warn_ratelimited("Called split_huge_page for huge zero page\n");
478d134e9506c7 Xu Yu 2022-04-28 3940 return -EBUSY;
4737edbbdd4958 Naoya Horiguchi 2023-04-06 3941 }
478d134e9506c7 Xu Yu 2022-04-28 3942
3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3943) if (folio_test_writeback(folio))
59807685a7e77e Ying Huang 2017-09-06 3944 return -EBUSY;
59807685a7e77e Ying Huang 2017-09-06 3945
5d65c8d758f259 Barry Song 2024-08-24 3946 if (is_anon) {
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3947 /*
c1e8d7c6a7a682 Michel Lespinasse 2020-06-08 3948 * The caller does not necessarily hold an mmap_lock that would
baa355fd331424 Kirill A. Shutemov 2016-07-26 3949 * prevent the anon_vma disappearing so we first we take a
baa355fd331424 Kirill A. Shutemov 2016-07-26 3950 * reference to it and then lock the anon_vma for write. This
2f031c6f042cb8 Matthew Wilcox (Oracle 2022-01-29 3951) * is similar to folio_lock_anon_vma_read except the write lock
baa355fd331424 Kirill A. Shutemov 2016-07-26 3952 * is taken to serialise against parallel split or collapse
baa355fd331424 Kirill A. Shutemov 2016-07-26 3953 * operations.
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3954 */
29eea9b5a9c9ec Matthew Wilcox (Oracle 2022-09-02 3955) anon_vma = folio_get_anon_vma(folio);
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3956 if (!anon_vma) {
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3957 ret = -EBUSY;
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3958 goto out;
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3959 }
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3960 anon_vma_lock_write(anon_vma);
3d4c0d98eb8572 Balbir Singh 2025-10-01 3961 mapping = NULL;
end is not initialized for anonymous folios.
baa355fd331424 Kirill A. Shutemov 2016-07-26 3962 } else {
e220917fa50774 Luis Chamberlain 2024-08-22 3963 unsigned int min_order;
6a3edd29395631 Yin Fengwei 2022-08-10 3964 gfp_t gfp;
6a3edd29395631 Yin Fengwei 2022-08-10 3965
3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3966) mapping = folio->mapping;
baa355fd331424 Kirill A. Shutemov 2016-07-26 3967
baa355fd331424 Kirill A. Shutemov 2016-07-26 3968 /* Truncated ? */
6384dd1d18de7b Zi Yan 2025-03-07 3969 /*
6384dd1d18de7b Zi Yan 2025-03-07 3970 * TODO: add support for large shmem folio in swap cache.
6384dd1d18de7b Zi Yan 2025-03-07 3971 * When shmem is in swap cache, mapping is NULL and
6384dd1d18de7b Zi Yan 2025-03-07 3972 * folio_test_swapcache() is true.
6384dd1d18de7b Zi Yan 2025-03-07 3973 */
baa355fd331424 Kirill A. Shutemov 2016-07-26 3974 if (!mapping) {
baa355fd331424 Kirill A. Shutemov 2016-07-26 3975 ret = -EBUSY;
baa355fd331424 Kirill A. Shutemov 2016-07-26 3976 goto out;
baa355fd331424 Kirill A. Shutemov 2016-07-26 3977 }
baa355fd331424 Kirill A. Shutemov 2016-07-26 3978
e220917fa50774 Luis Chamberlain 2024-08-22 3979 min_order = mapping_min_folio_order(folio->mapping);
e220917fa50774 Luis Chamberlain 2024-08-22 3980 if (new_order < min_order) {
e220917fa50774 Luis Chamberlain 2024-08-22 3981 ret = -EINVAL;
e220917fa50774 Luis Chamberlain 2024-08-22 3982 goto out;
e220917fa50774 Luis Chamberlain 2024-08-22 3983 }
e220917fa50774 Luis Chamberlain 2024-08-22 3984
6a3edd29395631 Yin Fengwei 2022-08-10 3985 gfp = current_gfp_context(mapping_gfp_mask(mapping) &
6a3edd29395631 Yin Fengwei 2022-08-10 3986 GFP_RECLAIM_MASK);
6a3edd29395631 Yin Fengwei 2022-08-10 3987
0201ebf274a306 David Howells 2023-06-28 3988 if (!filemap_release_folio(folio, gfp)) {
6a3edd29395631 Yin Fengwei 2022-08-10 3989 ret = -EBUSY;
6a3edd29395631 Yin Fengwei 2022-08-10 3990 goto out;
6a3edd29395631 Yin Fengwei 2022-08-10 3991 }
6a3edd29395631 Yin Fengwei 2022-08-10 3992
3c844d850e4486 Wei Yang 2025-11-06 3993 if (split_type == SPLIT_TYPE_UNIFORM) {
58729c04cf1092 Zi Yan 2025-03-07 3994 xas_set_order(&xas, folio->index, new_order);
8ec26327c18e1d Wei Yang 2025-10-10 3995 xas_split_alloc(&xas, folio, old_order, gfp);
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3996) if (xas_error(&xas)) {
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3997) ret = xas_error(&xas);
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3998) goto out;
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3999) }
58729c04cf1092 Zi Yan 2025-03-07 4000 }
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4001)
baa355fd331424 Kirill A. Shutemov 2016-07-26 4002 anon_vma = NULL;
baa355fd331424 Kirill A. Shutemov 2016-07-26 4003 i_mmap_lock_read(mapping);
006d3ff27e884f Hugh Dickins 2018-11-30 4004
006d3ff27e884f Hugh Dickins 2018-11-30 4005 /*
58729c04cf1092 Zi Yan 2025-03-07 4006 *__split_unmapped_folio() may need to trim off pages beyond
58729c04cf1092 Zi Yan 2025-03-07 4007 * EOF: but on 32-bit, i_size_read() takes an irq-unsafe
58729c04cf1092 Zi Yan 2025-03-07 4008 * seqlock, which cannot be nested inside the page tree lock.
58729c04cf1092 Zi Yan 2025-03-07 4009 * So note end now: i_size itself may be changed at any moment,
58729c04cf1092 Zi Yan 2025-03-07 4010 * but folio lock is good enough to serialize the trimming.
006d3ff27e884f Hugh Dickins 2018-11-30 4011 */
006d3ff27e884f Hugh Dickins 2018-11-30 4012 end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
d144bf6205342a Hugh Dickins 2021-09-02 4013 if (shmem_mapping(mapping))
d144bf6205342a Hugh Dickins 2021-09-02 4014 end = shmem_fallocend(mapping->host, end);
baa355fd331424 Kirill A. Shutemov 2016-07-26 4015 }
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4016
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4017 /*
684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4018) * Racy check if we can split the page, before unmap_folio() will
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4019 * split PMDs
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4020 */
8710f6ed34e7bc David Hildenbrand 2024-08-02 4021 if (!can_split_folio(folio, 1, &extra_pins)) {
fd4a7ac32918d3 Baolin Wang 2022-10-24 4022 ret = -EAGAIN;
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4023 goto out_unlock;
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4024 }
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4025
684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4026) unmap_folio(folio);
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4027
b6769834aac1d4 Alex Shi 2020-12-15 4028 /* block interrupt reentry in xa_lock and spinlock */
b6769834aac1d4 Alex Shi 2020-12-15 4029 local_irq_disable();
baa355fd331424 Kirill A. Shutemov 2016-07-26 4030 if (mapping) {
baa355fd331424 Kirill A. Shutemov 2016-07-26 4031 /*
3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4032) * Check if the folio is present in page cache.
3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4033) * We assume all tail are present too, if folio is there.
baa355fd331424 Kirill A. Shutemov 2016-07-26 4034 */
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4035) xas_lock(&xas);
6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4036) xas_reset(&xas);
391dc7f40590d7 Zi Yan 2025-07-18 4037 if (xas_load(&xas) != folio) {
391dc7f40590d7 Zi Yan 2025-07-18 4038 ret = -EAGAIN;
baa355fd331424 Kirill A. Shutemov 2016-07-26 4039 goto fail;
baa355fd331424 Kirill A. Shutemov 2016-07-26 4040 }
391dc7f40590d7 Zi Yan 2025-07-18 4041 }
baa355fd331424 Kirill A. Shutemov 2016-07-26 4042
f6b1f167ffe29f Balbir Singh 2025-11-14 4043 ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,
f6b1f167ffe29f Balbir Singh 2025-11-14 @4044 true, list, split_type, end, extra_pins);
^^^
Passing uninitialized variables isn't allowed unless the function is
inlined. It triggers a UBSan warning at runtime as well.
391dc7f40590d7 Zi Yan 2025-07-18 4045 fail:
6c7de9c83be68b Zi Yan 2025-07-18 @4046 if (mapping)
6c7de9c83be68b Zi Yan 2025-07-18 4047 xas_unlock(&xas);
6c7de9c83be68b Zi Yan 2025-07-18 4048
6c7de9c83be68b Zi Yan 2025-07-18 4049 local_irq_enable();
6c7de9c83be68b Zi Yan 2025-07-18 4050
391dc7f40590d7 Zi Yan 2025-07-18 4051 if (nr_shmem_dropped)
391dc7f40590d7 Zi Yan 2025-07-18 @4052 shmem_uncharge(mapping->host, nr_shmem_dropped);
Smatch complains that mapping can be NULL, but this is false positive
because nr_shmem_dropped is always zero.
6c7de9c83be68b Zi Yan 2025-07-18 4053
958fea4c1e2eb6 Balbir Singh 2025-10-01 4054 if (!ret && is_anon && !folio_is_device_private(folio))
391dc7f40590d7 Zi Yan 2025-07-18 4055 remap_flags = RMP_USE_SHARED_ZEROPAGE;
958fea4c1e2eb6 Balbir Singh 2025-10-01 4056
8ec26327c18e1d Wei Yang 2025-10-10 4057 remap_page(folio, 1 << old_order, remap_flags);
6c7de9c83be68b Zi Yan 2025-07-18 4058
6c7de9c83be68b Zi Yan 2025-07-18 4059 /*
6c7de9c83be68b Zi Yan 2025-07-18 4060 * Unlock all after-split folios except the one containing
6c7de9c83be68b Zi Yan 2025-07-18 4061 * @lock_at page. If @folio is not split, it will be kept locked.
6c7de9c83be68b Zi Yan 2025-07-18 4062 */
391dc7f40590d7 Zi Yan 2025-07-18 4063 for (new_folio = folio; new_folio != end_folio; new_folio = next) {
6c7de9c83be68b Zi Yan 2025-07-18 4064 next = folio_next(new_folio);
6c7de9c83be68b Zi Yan 2025-07-18 4065 if (new_folio == page_folio(lock_at))
6c7de9c83be68b Zi Yan 2025-07-18 4066 continue;
6c7de9c83be68b Zi Yan 2025-07-18 4067
6c7de9c83be68b Zi Yan 2025-07-18 4068 folio_unlock(new_folio);
6c7de9c83be68b Zi Yan 2025-07-18 4069 /*
6c7de9c83be68b Zi Yan 2025-07-18 4070 * Subpages may be freed if there wasn't any mapping
6c7de9c83be68b Zi Yan 2025-07-18 4071 * like if add_to_swap() is running on a lru page that
6c7de9c83be68b Zi Yan 2025-07-18 4072 * had its mapping zapped. And freeing these pages
6c7de9c83be68b Zi Yan 2025-07-18 4073 * requires taking the lru_lock so we do the put_page
6c7de9c83be68b Zi Yan 2025-07-18 4074 * of the tail pages after the split is complete.
6c7de9c83be68b Zi Yan 2025-07-18 4075 */
6c7de9c83be68b Zi Yan 2025-07-18 4076 free_folio_and_swap_cache(new_folio);
6c7de9c83be68b Zi Yan 2025-07-18 4077 }
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4078
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4079 out_unlock:
baa355fd331424 Kirill A. Shutemov 2016-07-26 4080 if (anon_vma) {
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4081 anon_vma_unlock_write(anon_vma);
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4082 put_anon_vma(anon_vma);
baa355fd331424 Kirill A. Shutemov 2016-07-26 4083 }
baa355fd331424 Kirill A. Shutemov 2016-07-26 4084 if (mapping)
baa355fd331424 Kirill A. Shutemov 2016-07-26 4085 i_mmap_unlock_read(mapping);
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4086 out:
69a37a8ba1b408 Matthew Wilcox (Oracle 2022-06-08 4087) xas_destroy(&xas);
8ec26327c18e1d Wei Yang 2025-10-10 4088 if (old_order == HPAGE_PMD_ORDER)
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4089 count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED);
8ec26327c18e1d Wei Yang 2025-10-10 4090 count_mthp_stat(old_order, !ret ? MTHP_STAT_SPLIT : MTHP_STAT_SPLIT_FAILED);
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4091 return ret;
e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4092 }
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On 11/19/25 23:32, Dan Carpenter wrote:
> Hi Balbir,
>
> kernel test robot noticed the following build warnings:
>
> url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541
> base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
> patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com
> patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped
> config: i386-randconfig-141-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151216.rhK2ItOb-lkp@intel.com/config)
> compiler: gcc-12 (Debian 12.4.0-5) 12.4.0
>
> 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@intel.com>
> | Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
> | Closes: https://lore.kernel.org/r/202511151216.rhK2ItOb-lkp@intel.com/
>
> smatch warnings:
> mm/huge_memory.c:4044 __folio_split() error: uninitialized symbol 'end'.
> mm/huge_memory.c:4052 __folio_split() error: we previously assumed 'mapping' could be null (see line 4046)
>
Thanks for the report!
If mapping is not NULL, end is initialized. More comments on UBSan below
> vim +/end +4044 mm/huge_memory.c
>
> 6384dd1d18de7b Zi Yan 2025-03-07 3908 static int __folio_split(struct folio *folio, unsigned int new_order,
> 58729c04cf1092 Zi Yan 2025-03-07 3909 struct page *split_at, struct page *lock_at,
> f6b1f167ffe29f Balbir Singh 2025-11-14 3910 struct list_head *list, enum split_type split_type)
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3911 {
> 58729c04cf1092 Zi Yan 2025-03-07 3912 XA_STATE(xas, &folio->mapping->i_pages, folio->index);
> 6c7de9c83be68b Zi Yan 2025-07-18 3913 struct folio *end_folio = folio_next(folio);
> 5d65c8d758f259 Barry Song 2024-08-24 3914 bool is_anon = folio_test_anon(folio);
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3915 struct address_space *mapping = NULL;
> 5d65c8d758f259 Barry Song 2024-08-24 3916 struct anon_vma *anon_vma = NULL;
> 8ec26327c18e1d Wei Yang 2025-10-10 3917 int old_order = folio_order(folio);
> 6c7de9c83be68b Zi Yan 2025-07-18 3918 struct folio *new_folio, *next;
> 391dc7f40590d7 Zi Yan 2025-07-18 3919 int nr_shmem_dropped = 0;
> 391dc7f40590d7 Zi Yan 2025-07-18 3920 int remap_flags = 0;
> 504e070dc08f75 Yang Shi 2021-06-15 3921 int extra_pins, ret;
> 006d3ff27e884f Hugh Dickins 2018-11-30 3922 pgoff_t end;
> 478d134e9506c7 Xu Yu 2022-04-28 3923 bool is_hzp;
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3924
> 714b056c832106 Zi Yan 2025-07-17 3925 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
> 714b056c832106 Zi Yan 2025-07-17 3926 VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3927
> 58729c04cf1092 Zi Yan 2025-03-07 3928 if (folio != page_folio(split_at) || folio != page_folio(lock_at))
> 1412ecb3d256e5 Zi Yan 2024-03-07 3929 return -EINVAL;
> 1412ecb3d256e5 Zi Yan 2024-03-07 3930
> 8ec26327c18e1d Wei Yang 2025-10-10 3931 if (new_order >= old_order)
> c010d47f107f60 Zi Yan 2024-02-26 3932 return -EINVAL;
> 58729c04cf1092 Zi Yan 2025-03-07 3933
> aa27253af32c74 Wei Yang 2025-11-06 3934 if (!folio_split_supported(folio, new_order, split_type, /* warn = */ true))
> 6a50c9b512f773 Ran Xiaokai 2024-06-07 3935 return -EINVAL;
> c010d47f107f60 Zi Yan 2024-02-26 3936
> 5beaee54a324ba Matthew Wilcox (Oracle 2024-03-26 3937) is_hzp = is_huge_zero_folio(folio);
> 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3938 if (is_hzp) {
> 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3939 pr_warn_ratelimited("Called split_huge_page for huge zero page\n");
> 478d134e9506c7 Xu Yu 2022-04-28 3940 return -EBUSY;
> 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3941 }
> 478d134e9506c7 Xu Yu 2022-04-28 3942
> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3943) if (folio_test_writeback(folio))
> 59807685a7e77e Ying Huang 2017-09-06 3944 return -EBUSY;
> 59807685a7e77e Ying Huang 2017-09-06 3945
> 5d65c8d758f259 Barry Song 2024-08-24 3946 if (is_anon) {
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3947 /*
> c1e8d7c6a7a682 Michel Lespinasse 2020-06-08 3948 * The caller does not necessarily hold an mmap_lock that would
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3949 * prevent the anon_vma disappearing so we first we take a
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3950 * reference to it and then lock the anon_vma for write. This
> 2f031c6f042cb8 Matthew Wilcox (Oracle 2022-01-29 3951) * is similar to folio_lock_anon_vma_read except the write lock
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3952 * is taken to serialise against parallel split or collapse
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3953 * operations.
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3954 */
> 29eea9b5a9c9ec Matthew Wilcox (Oracle 2022-09-02 3955) anon_vma = folio_get_anon_vma(folio);
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3956 if (!anon_vma) {
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3957 ret = -EBUSY;
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3958 goto out;
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3959 }
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3960 anon_vma_lock_write(anon_vma);
> 3d4c0d98eb8572 Balbir Singh 2025-10-01 3961 mapping = NULL;
>
> end is not initialized for anonymous folios.
>
Yes
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3962 } else {
> e220917fa50774 Luis Chamberlain 2024-08-22 3963 unsigned int min_order;
> 6a3edd29395631 Yin Fengwei 2022-08-10 3964 gfp_t gfp;
> 6a3edd29395631 Yin Fengwei 2022-08-10 3965
> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3966) mapping = folio->mapping;
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3967
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3968 /* Truncated ? */
> 6384dd1d18de7b Zi Yan 2025-03-07 3969 /*
> 6384dd1d18de7b Zi Yan 2025-03-07 3970 * TODO: add support for large shmem folio in swap cache.
> 6384dd1d18de7b Zi Yan 2025-03-07 3971 * When shmem is in swap cache, mapping is NULL and
> 6384dd1d18de7b Zi Yan 2025-03-07 3972 * folio_test_swapcache() is true.
> 6384dd1d18de7b Zi Yan 2025-03-07 3973 */
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3974 if (!mapping) {
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3975 ret = -EBUSY;
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3976 goto out;
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3977 }
> baa355fd331424 Kirill A. Shutemov 2016-07-26 3978
> e220917fa50774 Luis Chamberlain 2024-08-22 3979 min_order = mapping_min_folio_order(folio->mapping);
> e220917fa50774 Luis Chamberlain 2024-08-22 3980 if (new_order < min_order) {
> e220917fa50774 Luis Chamberlain 2024-08-22 3981 ret = -EINVAL;
> e220917fa50774 Luis Chamberlain 2024-08-22 3982 goto out;
> e220917fa50774 Luis Chamberlain 2024-08-22 3983 }
> e220917fa50774 Luis Chamberlain 2024-08-22 3984
> 6a3edd29395631 Yin Fengwei 2022-08-10 3985 gfp = current_gfp_context(mapping_gfp_mask(mapping) &
> 6a3edd29395631 Yin Fengwei 2022-08-10 3986 GFP_RECLAIM_MASK);
> 6a3edd29395631 Yin Fengwei 2022-08-10 3987
> 0201ebf274a306 David Howells 2023-06-28 3988 if (!filemap_release_folio(folio, gfp)) {
> 6a3edd29395631 Yin Fengwei 2022-08-10 3989 ret = -EBUSY;
> 6a3edd29395631 Yin Fengwei 2022-08-10 3990 goto out;
> 6a3edd29395631 Yin Fengwei 2022-08-10 3991 }
> 6a3edd29395631 Yin Fengwei 2022-08-10 3992
> 3c844d850e4486 Wei Yang 2025-11-06 3993 if (split_type == SPLIT_TYPE_UNIFORM) {
> 58729c04cf1092 Zi Yan 2025-03-07 3994 xas_set_order(&xas, folio->index, new_order);
> 8ec26327c18e1d Wei Yang 2025-10-10 3995 xas_split_alloc(&xas, folio, old_order, gfp);
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3996) if (xas_error(&xas)) {
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3997) ret = xas_error(&xas);
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3998) goto out;
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3999) }
> 58729c04cf1092 Zi Yan 2025-03-07 4000 }
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4001)
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4002 anon_vma = NULL;
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4003 i_mmap_lock_read(mapping);
> 006d3ff27e884f Hugh Dickins 2018-11-30 4004
> 006d3ff27e884f Hugh Dickins 2018-11-30 4005 /*
> 58729c04cf1092 Zi Yan 2025-03-07 4006 *__split_unmapped_folio() may need to trim off pages beyond
> 58729c04cf1092 Zi Yan 2025-03-07 4007 * EOF: but on 32-bit, i_size_read() takes an irq-unsafe
> 58729c04cf1092 Zi Yan 2025-03-07 4008 * seqlock, which cannot be nested inside the page tree lock.
> 58729c04cf1092 Zi Yan 2025-03-07 4009 * So note end now: i_size itself may be changed at any moment,
> 58729c04cf1092 Zi Yan 2025-03-07 4010 * but folio lock is good enough to serialize the trimming.
> 006d3ff27e884f Hugh Dickins 2018-11-30 4011 */
> 006d3ff27e884f Hugh Dickins 2018-11-30 4012 end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
> d144bf6205342a Hugh Dickins 2021-09-02 4013 if (shmem_mapping(mapping))
> d144bf6205342a Hugh Dickins 2021-09-02 4014 end = shmem_fallocend(mapping->host, end);
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4015 }
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4016
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4017 /*
> 684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4018) * Racy check if we can split the page, before unmap_folio() will
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4019 * split PMDs
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4020 */
> 8710f6ed34e7bc David Hildenbrand 2024-08-02 4021 if (!can_split_folio(folio, 1, &extra_pins)) {
> fd4a7ac32918d3 Baolin Wang 2022-10-24 4022 ret = -EAGAIN;
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4023 goto out_unlock;
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4024 }
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4025
> 684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4026) unmap_folio(folio);
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4027
> b6769834aac1d4 Alex Shi 2020-12-15 4028 /* block interrupt reentry in xa_lock and spinlock */
> b6769834aac1d4 Alex Shi 2020-12-15 4029 local_irq_disable();
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4030 if (mapping) {
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4031 /*
> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4032) * Check if the folio is present in page cache.
> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4033) * We assume all tail are present too, if folio is there.
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4034 */
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4035) xas_lock(&xas);
> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4036) xas_reset(&xas);
> 391dc7f40590d7 Zi Yan 2025-07-18 4037 if (xas_load(&xas) != folio) {
> 391dc7f40590d7 Zi Yan 2025-07-18 4038 ret = -EAGAIN;
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4039 goto fail;
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4040 }
> 391dc7f40590d7 Zi Yan 2025-07-18 4041 }
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4042
> f6b1f167ffe29f Balbir Singh 2025-11-14 4043 ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,
> f6b1f167ffe29f Balbir Singh 2025-11-14 @4044 true, list, split_type, end, extra_pins);
> ^^^
> Passing uninitialized variables isn't allowed unless the function is
> inlined. It triggers a UBSan warning at runtime as well.
end is expected to be unused when uninitialized, are you suggesting we need to have a default value even if unused inside the function.
My daily build has UBSan enabled, I'll try again
CONFIG_UBSAN=y
CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
# CONFIG_UBSAN_BOUNDS is not set
CONFIG_UBSAN_SHIFT=y
# CONFIG_UBSAN_UNREACHABLE is not set
# CONFIG_UBSAN_BOOL is not set
# CONFIG_UBSAN_ENUM is not set
>
> 391dc7f40590d7 Zi Yan 2025-07-18 4045 fail:
> 6c7de9c83be68b Zi Yan 2025-07-18 @4046 if (mapping)
> 6c7de9c83be68b Zi Yan 2025-07-18 4047 xas_unlock(&xas);
> 6c7de9c83be68b Zi Yan 2025-07-18 4048
> 6c7de9c83be68b Zi Yan 2025-07-18 4049 local_irq_enable();
> 6c7de9c83be68b Zi Yan 2025-07-18 4050
> 391dc7f40590d7 Zi Yan 2025-07-18 4051 if (nr_shmem_dropped)
> 391dc7f40590d7 Zi Yan 2025-07-18 @4052 shmem_uncharge(mapping->host, nr_shmem_dropped);
>
> Smatch complains that mapping can be NULL, but this is false positive
> because nr_shmem_dropped is always zero.
>
Agreed
> 6c7de9c83be68b Zi Yan 2025-07-18 4053
> 958fea4c1e2eb6 Balbir Singh 2025-10-01 4054 if (!ret && is_anon && !folio_is_device_private(folio))
> 391dc7f40590d7 Zi Yan 2025-07-18 4055 remap_flags = RMP_USE_SHARED_ZEROPAGE;
> 958fea4c1e2eb6 Balbir Singh 2025-10-01 4056
> 8ec26327c18e1d Wei Yang 2025-10-10 4057 remap_page(folio, 1 << old_order, remap_flags);
> 6c7de9c83be68b Zi Yan 2025-07-18 4058
> 6c7de9c83be68b Zi Yan 2025-07-18 4059 /*
> 6c7de9c83be68b Zi Yan 2025-07-18 4060 * Unlock all after-split folios except the one containing
> 6c7de9c83be68b Zi Yan 2025-07-18 4061 * @lock_at page. If @folio is not split, it will be kept locked.
> 6c7de9c83be68b Zi Yan 2025-07-18 4062 */
> 391dc7f40590d7 Zi Yan 2025-07-18 4063 for (new_folio = folio; new_folio != end_folio; new_folio = next) {
> 6c7de9c83be68b Zi Yan 2025-07-18 4064 next = folio_next(new_folio);
> 6c7de9c83be68b Zi Yan 2025-07-18 4065 if (new_folio == page_folio(lock_at))
> 6c7de9c83be68b Zi Yan 2025-07-18 4066 continue;
> 6c7de9c83be68b Zi Yan 2025-07-18 4067
> 6c7de9c83be68b Zi Yan 2025-07-18 4068 folio_unlock(new_folio);
> 6c7de9c83be68b Zi Yan 2025-07-18 4069 /*
> 6c7de9c83be68b Zi Yan 2025-07-18 4070 * Subpages may be freed if there wasn't any mapping
> 6c7de9c83be68b Zi Yan 2025-07-18 4071 * like if add_to_swap() is running on a lru page that
> 6c7de9c83be68b Zi Yan 2025-07-18 4072 * had its mapping zapped. And freeing these pages
> 6c7de9c83be68b Zi Yan 2025-07-18 4073 * requires taking the lru_lock so we do the put_page
> 6c7de9c83be68b Zi Yan 2025-07-18 4074 * of the tail pages after the split is complete.
> 6c7de9c83be68b Zi Yan 2025-07-18 4075 */
> 6c7de9c83be68b Zi Yan 2025-07-18 4076 free_folio_and_swap_cache(new_folio);
> 6c7de9c83be68b Zi Yan 2025-07-18 4077 }
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4078
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4079 out_unlock:
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4080 if (anon_vma) {
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4081 anon_vma_unlock_write(anon_vma);
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4082 put_anon_vma(anon_vma);
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4083 }
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4084 if (mapping)
> baa355fd331424 Kirill A. Shutemov 2016-07-26 4085 i_mmap_unlock_read(mapping);
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4086 out:
> 69a37a8ba1b408 Matthew Wilcox (Oracle 2022-06-08 4087) xas_destroy(&xas);
> 8ec26327c18e1d Wei Yang 2025-10-10 4088 if (old_order == HPAGE_PMD_ORDER)
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4089 count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED);
> 8ec26327c18e1d Wei Yang 2025-10-10 4090 count_mthp_stat(old_order, !ret ? MTHP_STAT_SPLIT : MTHP_STAT_SPLIT_FAILED);
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4091 return ret;
> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4092 }
>
Balbir
On Thu, Nov 20, 2025 at 10:58:07AM +1100, Balbir Singh wrote:
> On 11/19/25 23:32, Dan Carpenter wrote:
> > Hi Balbir,
> >
> > kernel test robot noticed the following build warnings:
> >
> > url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541
> > base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
> > patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com
> > patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped
> > config: i386-randconfig-141-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151216.rhK2ItOb-lkp@intel.com/config)
> > compiler: gcc-12 (Debian 12.4.0-5) 12.4.0
> >
> > 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@intel.com>
> > | Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
> > | Closes: https://lore.kernel.org/r/202511151216.rhK2ItOb-lkp@intel.com/
> >
> > smatch warnings:
> > mm/huge_memory.c:4044 __folio_split() error: uninitialized symbol 'end'.
> > mm/huge_memory.c:4052 __folio_split() error: we previously assumed 'mapping' could be null (see line 4046)
> >
>
> Thanks for the report!
>
> If mapping is not NULL, end is initialized. More comments on UBSan below
>
> > vim +/end +4044 mm/huge_memory.c
> >
> > 6384dd1d18de7b Zi Yan 2025-03-07 3908 static int __folio_split(struct folio *folio, unsigned int new_order,
> > 58729c04cf1092 Zi Yan 2025-03-07 3909 struct page *split_at, struct page *lock_at,
> > f6b1f167ffe29f Balbir Singh 2025-11-14 3910 struct list_head *list, enum split_type split_type)
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3911 {
> > 58729c04cf1092 Zi Yan 2025-03-07 3912 XA_STATE(xas, &folio->mapping->i_pages, folio->index);
> > 6c7de9c83be68b Zi Yan 2025-07-18 3913 struct folio *end_folio = folio_next(folio);
> > 5d65c8d758f259 Barry Song 2024-08-24 3914 bool is_anon = folio_test_anon(folio);
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3915 struct address_space *mapping = NULL;
> > 5d65c8d758f259 Barry Song 2024-08-24 3916 struct anon_vma *anon_vma = NULL;
> > 8ec26327c18e1d Wei Yang 2025-10-10 3917 int old_order = folio_order(folio);
> > 6c7de9c83be68b Zi Yan 2025-07-18 3918 struct folio *new_folio, *next;
> > 391dc7f40590d7 Zi Yan 2025-07-18 3919 int nr_shmem_dropped = 0;
> > 391dc7f40590d7 Zi Yan 2025-07-18 3920 int remap_flags = 0;
> > 504e070dc08f75 Yang Shi 2021-06-15 3921 int extra_pins, ret;
> > 006d3ff27e884f Hugh Dickins 2018-11-30 3922 pgoff_t end;
> > 478d134e9506c7 Xu Yu 2022-04-28 3923 bool is_hzp;
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3924
> > 714b056c832106 Zi Yan 2025-07-17 3925 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
> > 714b056c832106 Zi Yan 2025-07-17 3926 VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3927
> > 58729c04cf1092 Zi Yan 2025-03-07 3928 if (folio != page_folio(split_at) || folio != page_folio(lock_at))
> > 1412ecb3d256e5 Zi Yan 2024-03-07 3929 return -EINVAL;
> > 1412ecb3d256e5 Zi Yan 2024-03-07 3930
> > 8ec26327c18e1d Wei Yang 2025-10-10 3931 if (new_order >= old_order)
> > c010d47f107f60 Zi Yan 2024-02-26 3932 return -EINVAL;
> > 58729c04cf1092 Zi Yan 2025-03-07 3933
> > aa27253af32c74 Wei Yang 2025-11-06 3934 if (!folio_split_supported(folio, new_order, split_type, /* warn = */ true))
> > 6a50c9b512f773 Ran Xiaokai 2024-06-07 3935 return -EINVAL;
> > c010d47f107f60 Zi Yan 2024-02-26 3936
> > 5beaee54a324ba Matthew Wilcox (Oracle 2024-03-26 3937) is_hzp = is_huge_zero_folio(folio);
> > 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3938 if (is_hzp) {
> > 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3939 pr_warn_ratelimited("Called split_huge_page for huge zero page\n");
> > 478d134e9506c7 Xu Yu 2022-04-28 3940 return -EBUSY;
> > 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3941 }
> > 478d134e9506c7 Xu Yu 2022-04-28 3942
> > 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3943) if (folio_test_writeback(folio))
> > 59807685a7e77e Ying Huang 2017-09-06 3944 return -EBUSY;
> > 59807685a7e77e Ying Huang 2017-09-06 3945
> > 5d65c8d758f259 Barry Song 2024-08-24 3946 if (is_anon) {
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3947 /*
> > c1e8d7c6a7a682 Michel Lespinasse 2020-06-08 3948 * The caller does not necessarily hold an mmap_lock that would
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3949 * prevent the anon_vma disappearing so we first we take a
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3950 * reference to it and then lock the anon_vma for write. This
> > 2f031c6f042cb8 Matthew Wilcox (Oracle 2022-01-29 3951) * is similar to folio_lock_anon_vma_read except the write lock
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3952 * is taken to serialise against parallel split or collapse
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3953 * operations.
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3954 */
> > 29eea9b5a9c9ec Matthew Wilcox (Oracle 2022-09-02 3955) anon_vma = folio_get_anon_vma(folio);
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3956 if (!anon_vma) {
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3957 ret = -EBUSY;
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3958 goto out;
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3959 }
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3960 anon_vma_lock_write(anon_vma);
> > 3d4c0d98eb8572 Balbir Singh 2025-10-01 3961 mapping = NULL;
> >
> > end is not initialized for anonymous folios.
> >
>
> Yes
>
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3962 } else {
> > e220917fa50774 Luis Chamberlain 2024-08-22 3963 unsigned int min_order;
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3964 gfp_t gfp;
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3965
> > 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3966) mapping = folio->mapping;
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3967
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3968 /* Truncated ? */
> > 6384dd1d18de7b Zi Yan 2025-03-07 3969 /*
> > 6384dd1d18de7b Zi Yan 2025-03-07 3970 * TODO: add support for large shmem folio in swap cache.
> > 6384dd1d18de7b Zi Yan 2025-03-07 3971 * When shmem is in swap cache, mapping is NULL and
> > 6384dd1d18de7b Zi Yan 2025-03-07 3972 * folio_test_swapcache() is true.
> > 6384dd1d18de7b Zi Yan 2025-03-07 3973 */
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3974 if (!mapping) {
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3975 ret = -EBUSY;
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3976 goto out;
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3977 }
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 3978
> > e220917fa50774 Luis Chamberlain 2024-08-22 3979 min_order = mapping_min_folio_order(folio->mapping);
> > e220917fa50774 Luis Chamberlain 2024-08-22 3980 if (new_order < min_order) {
> > e220917fa50774 Luis Chamberlain 2024-08-22 3981 ret = -EINVAL;
> > e220917fa50774 Luis Chamberlain 2024-08-22 3982 goto out;
> > e220917fa50774 Luis Chamberlain 2024-08-22 3983 }
> > e220917fa50774 Luis Chamberlain 2024-08-22 3984
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3985 gfp = current_gfp_context(mapping_gfp_mask(mapping) &
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3986 GFP_RECLAIM_MASK);
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3987
> > 0201ebf274a306 David Howells 2023-06-28 3988 if (!filemap_release_folio(folio, gfp)) {
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3989 ret = -EBUSY;
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3990 goto out;
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3991 }
> > 6a3edd29395631 Yin Fengwei 2022-08-10 3992
> > 3c844d850e4486 Wei Yang 2025-11-06 3993 if (split_type == SPLIT_TYPE_UNIFORM) {
> > 58729c04cf1092 Zi Yan 2025-03-07 3994 xas_set_order(&xas, folio->index, new_order);
> > 8ec26327c18e1d Wei Yang 2025-10-10 3995 xas_split_alloc(&xas, folio, old_order, gfp);
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3996) if (xas_error(&xas)) {
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3997) ret = xas_error(&xas);
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3998) goto out;
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3999) }
> > 58729c04cf1092 Zi Yan 2025-03-07 4000 }
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4001)
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4002 anon_vma = NULL;
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4003 i_mmap_lock_read(mapping);
> > 006d3ff27e884f Hugh Dickins 2018-11-30 4004
> > 006d3ff27e884f Hugh Dickins 2018-11-30 4005 /*
> > 58729c04cf1092 Zi Yan 2025-03-07 4006 *__split_unmapped_folio() may need to trim off pages beyond
> > 58729c04cf1092 Zi Yan 2025-03-07 4007 * EOF: but on 32-bit, i_size_read() takes an irq-unsafe
> > 58729c04cf1092 Zi Yan 2025-03-07 4008 * seqlock, which cannot be nested inside the page tree lock.
> > 58729c04cf1092 Zi Yan 2025-03-07 4009 * So note end now: i_size itself may be changed at any moment,
> > 58729c04cf1092 Zi Yan 2025-03-07 4010 * but folio lock is good enough to serialize the trimming.
> > 006d3ff27e884f Hugh Dickins 2018-11-30 4011 */
> > 006d3ff27e884f Hugh Dickins 2018-11-30 4012 end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
> > d144bf6205342a Hugh Dickins 2021-09-02 4013 if (shmem_mapping(mapping))
> > d144bf6205342a Hugh Dickins 2021-09-02 4014 end = shmem_fallocend(mapping->host, end);
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4015 }
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4016
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4017 /*
> > 684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4018) * Racy check if we can split the page, before unmap_folio() will
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4019 * split PMDs
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4020 */
> > 8710f6ed34e7bc David Hildenbrand 2024-08-02 4021 if (!can_split_folio(folio, 1, &extra_pins)) {
> > fd4a7ac32918d3 Baolin Wang 2022-10-24 4022 ret = -EAGAIN;
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4023 goto out_unlock;
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4024 }
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4025
> > 684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4026) unmap_folio(folio);
> > e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4027
> > b6769834aac1d4 Alex Shi 2020-12-15 4028 /* block interrupt reentry in xa_lock and spinlock */
> > b6769834aac1d4 Alex Shi 2020-12-15 4029 local_irq_disable();
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4030 if (mapping) {
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4031 /*
> > 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4032) * Check if the folio is present in page cache.
> > 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4033) * We assume all tail are present too, if folio is there.
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4034 */
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4035) xas_lock(&xas);
> > 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4036) xas_reset(&xas);
> > 391dc7f40590d7 Zi Yan 2025-07-18 4037 if (xas_load(&xas) != folio) {
> > 391dc7f40590d7 Zi Yan 2025-07-18 4038 ret = -EAGAIN;
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4039 goto fail;
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4040 }
> > 391dc7f40590d7 Zi Yan 2025-07-18 4041 }
> > baa355fd331424 Kirill A. Shutemov 2016-07-26 4042
> > f6b1f167ffe29f Balbir Singh 2025-11-14 4043 ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,
> > f6b1f167ffe29f Balbir Singh 2025-11-14 @4044 true, list, split_type, end, extra_pins);
> > ^^^
> > Passing uninitialized variables isn't allowed unless the function is
> > inlined. It triggers a UBSan warning at runtime as well.
>
> end is expected to be unused when uninitialized, are you suggesting we need to have a default value even if unused inside the function.
> My daily build has UBSan enabled, I'll try again
>
> CONFIG_UBSAN=y
> CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
> # CONFIG_UBSAN_BOUNDS is not set
> CONFIG_UBSAN_SHIFT=y
> # CONFIG_UBSAN_UNREACHABLE is not set
> # CONFIG_UBSAN_BOOL is not set
> # CONFIG_UBSAN_ENUM is not set
>
Huh. It's interesting that UBSan doesn't complain. Potentially, the
function is inlined?
Technically, passing uninitialized variables to a function is undefined
behavior in C. But in practical terms (and it make Linus cross that
the C standard doesn't account for this), when a function is inlined
then that shouldn't really be undefined. But otherwise, yes, passing
uninitialized variables is not allowed, even when they're not used.
Everyone sensible is going to set CONFIG_INIT_STACK_ALL_ZERO for
production systems so initializing variables to zero doesn't affect
anything.
regards,
dan carpenter
On 19 Nov 2025, at 18:58, Balbir Singh wrote:
> On 11/19/25 23:32, Dan Carpenter wrote:
>> Hi Balbir,
>>
>> kernel test robot noticed the following build warnings:
>>
>> url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541
>> base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
>> patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com
>> patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped
>> config: i386-randconfig-141-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151216.rhK2ItOb-lkp@intel.com/config)
>> compiler: gcc-12 (Debian 12.4.0-5) 12.4.0
>>
>> 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@intel.com>
>> | Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
>> | Closes: https://lore.kernel.org/r/202511151216.rhK2ItOb-lkp@intel.com/
>>
>> smatch warnings:
>> mm/huge_memory.c:4044 __folio_split() error: uninitialized symbol 'end'.
>> mm/huge_memory.c:4052 __folio_split() error: we previously assumed 'mapping' could be null (see line 4046)
>>
>
> Thanks for the report!
>
> If mapping is not NULL, end is initialized. More comments on UBSan below
Maybe initialize end to -1 and add
VM_WARN_ONCE_ON(!mapping && end != -1);
in __folio_freeze_and_split_unmapped() to make static analyzer happy?
I assume end cannot be -1 for file-mapped folios. Let me know if I get
this wrong.
>
>> vim +/end +4044 mm/huge_memory.c
>>
>> 6384dd1d18de7b Zi Yan 2025-03-07 3908 static int __folio_split(struct folio *folio, unsigned int new_order,
>> 58729c04cf1092 Zi Yan 2025-03-07 3909 struct page *split_at, struct page *lock_at,
>> f6b1f167ffe29f Balbir Singh 2025-11-14 3910 struct list_head *list, enum split_type split_type)
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3911 {
>> 58729c04cf1092 Zi Yan 2025-03-07 3912 XA_STATE(xas, &folio->mapping->i_pages, folio->index);
>> 6c7de9c83be68b Zi Yan 2025-07-18 3913 struct folio *end_folio = folio_next(folio);
>> 5d65c8d758f259 Barry Song 2024-08-24 3914 bool is_anon = folio_test_anon(folio);
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3915 struct address_space *mapping = NULL;
>> 5d65c8d758f259 Barry Song 2024-08-24 3916 struct anon_vma *anon_vma = NULL;
>> 8ec26327c18e1d Wei Yang 2025-10-10 3917 int old_order = folio_order(folio);
>> 6c7de9c83be68b Zi Yan 2025-07-18 3918 struct folio *new_folio, *next;
>> 391dc7f40590d7 Zi Yan 2025-07-18 3919 int nr_shmem_dropped = 0;
>> 391dc7f40590d7 Zi Yan 2025-07-18 3920 int remap_flags = 0;
>> 504e070dc08f75 Yang Shi 2021-06-15 3921 int extra_pins, ret;
>> 006d3ff27e884f Hugh Dickins 2018-11-30 3922 pgoff_t end;
>> 478d134e9506c7 Xu Yu 2022-04-28 3923 bool is_hzp;
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3924
>> 714b056c832106 Zi Yan 2025-07-17 3925 VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
>> 714b056c832106 Zi Yan 2025-07-17 3926 VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3927
>> 58729c04cf1092 Zi Yan 2025-03-07 3928 if (folio != page_folio(split_at) || folio != page_folio(lock_at))
>> 1412ecb3d256e5 Zi Yan 2024-03-07 3929 return -EINVAL;
>> 1412ecb3d256e5 Zi Yan 2024-03-07 3930
>> 8ec26327c18e1d Wei Yang 2025-10-10 3931 if (new_order >= old_order)
>> c010d47f107f60 Zi Yan 2024-02-26 3932 return -EINVAL;
>> 58729c04cf1092 Zi Yan 2025-03-07 3933
>> aa27253af32c74 Wei Yang 2025-11-06 3934 if (!folio_split_supported(folio, new_order, split_type, /* warn = */ true))
>> 6a50c9b512f773 Ran Xiaokai 2024-06-07 3935 return -EINVAL;
>> c010d47f107f60 Zi Yan 2024-02-26 3936
>> 5beaee54a324ba Matthew Wilcox (Oracle 2024-03-26 3937) is_hzp = is_huge_zero_folio(folio);
>> 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3938 if (is_hzp) {
>> 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3939 pr_warn_ratelimited("Called split_huge_page for huge zero page\n");
>> 478d134e9506c7 Xu Yu 2022-04-28 3940 return -EBUSY;
>> 4737edbbdd4958 Naoya Horiguchi 2023-04-06 3941 }
>> 478d134e9506c7 Xu Yu 2022-04-28 3942
>> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3943) if (folio_test_writeback(folio))
>> 59807685a7e77e Ying Huang 2017-09-06 3944 return -EBUSY;
>> 59807685a7e77e Ying Huang 2017-09-06 3945
>> 5d65c8d758f259 Barry Song 2024-08-24 3946 if (is_anon) {
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3947 /*
>> c1e8d7c6a7a682 Michel Lespinasse 2020-06-08 3948 * The caller does not necessarily hold an mmap_lock that would
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3949 * prevent the anon_vma disappearing so we first we take a
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3950 * reference to it and then lock the anon_vma for write. This
>> 2f031c6f042cb8 Matthew Wilcox (Oracle 2022-01-29 3951) * is similar to folio_lock_anon_vma_read except the write lock
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3952 * is taken to serialise against parallel split or collapse
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3953 * operations.
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3954 */
>> 29eea9b5a9c9ec Matthew Wilcox (Oracle 2022-09-02 3955) anon_vma = folio_get_anon_vma(folio);
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3956 if (!anon_vma) {
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3957 ret = -EBUSY;
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3958 goto out;
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3959 }
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 3960 anon_vma_lock_write(anon_vma);
>> 3d4c0d98eb8572 Balbir Singh 2025-10-01 3961 mapping = NULL;
>>
>> end is not initialized for anonymous folios.
>>
>
> Yes
>
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3962 } else {
>> e220917fa50774 Luis Chamberlain 2024-08-22 3963 unsigned int min_order;
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3964 gfp_t gfp;
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3965
>> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 3966) mapping = folio->mapping;
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3967
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3968 /* Truncated ? */
>> 6384dd1d18de7b Zi Yan 2025-03-07 3969 /*
>> 6384dd1d18de7b Zi Yan 2025-03-07 3970 * TODO: add support for large shmem folio in swap cache.
>> 6384dd1d18de7b Zi Yan 2025-03-07 3971 * When shmem is in swap cache, mapping is NULL and
>> 6384dd1d18de7b Zi Yan 2025-03-07 3972 * folio_test_swapcache() is true.
>> 6384dd1d18de7b Zi Yan 2025-03-07 3973 */
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3974 if (!mapping) {
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3975 ret = -EBUSY;
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3976 goto out;
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3977 }
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 3978
>> e220917fa50774 Luis Chamberlain 2024-08-22 3979 min_order = mapping_min_folio_order(folio->mapping);
>> e220917fa50774 Luis Chamberlain 2024-08-22 3980 if (new_order < min_order) {
>> e220917fa50774 Luis Chamberlain 2024-08-22 3981 ret = -EINVAL;
>> e220917fa50774 Luis Chamberlain 2024-08-22 3982 goto out;
>> e220917fa50774 Luis Chamberlain 2024-08-22 3983 }
>> e220917fa50774 Luis Chamberlain 2024-08-22 3984
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3985 gfp = current_gfp_context(mapping_gfp_mask(mapping) &
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3986 GFP_RECLAIM_MASK);
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3987
>> 0201ebf274a306 David Howells 2023-06-28 3988 if (!filemap_release_folio(folio, gfp)) {
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3989 ret = -EBUSY;
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3990 goto out;
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3991 }
>> 6a3edd29395631 Yin Fengwei 2022-08-10 3992
>> 3c844d850e4486 Wei Yang 2025-11-06 3993 if (split_type == SPLIT_TYPE_UNIFORM) {
>> 58729c04cf1092 Zi Yan 2025-03-07 3994 xas_set_order(&xas, folio->index, new_order);
>> 8ec26327c18e1d Wei Yang 2025-10-10 3995 xas_split_alloc(&xas, folio, old_order, gfp);
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3996) if (xas_error(&xas)) {
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3997) ret = xas_error(&xas);
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3998) goto out;
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 3999) }
>> 58729c04cf1092 Zi Yan 2025-03-07 4000 }
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4001)
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4002 anon_vma = NULL;
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4003 i_mmap_lock_read(mapping);
>> 006d3ff27e884f Hugh Dickins 2018-11-30 4004
>> 006d3ff27e884f Hugh Dickins 2018-11-30 4005 /*
>> 58729c04cf1092 Zi Yan 2025-03-07 4006 *__split_unmapped_folio() may need to trim off pages beyond
>> 58729c04cf1092 Zi Yan 2025-03-07 4007 * EOF: but on 32-bit, i_size_read() takes an irq-unsafe
>> 58729c04cf1092 Zi Yan 2025-03-07 4008 * seqlock, which cannot be nested inside the page tree lock.
>> 58729c04cf1092 Zi Yan 2025-03-07 4009 * So note end now: i_size itself may be changed at any moment,
>> 58729c04cf1092 Zi Yan 2025-03-07 4010 * but folio lock is good enough to serialize the trimming.
>> 006d3ff27e884f Hugh Dickins 2018-11-30 4011 */
>> 006d3ff27e884f Hugh Dickins 2018-11-30 4012 end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
>> d144bf6205342a Hugh Dickins 2021-09-02 4013 if (shmem_mapping(mapping))
>> d144bf6205342a Hugh Dickins 2021-09-02 4014 end = shmem_fallocend(mapping->host, end);
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4015 }
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4016
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4017 /*
>> 684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4018) * Racy check if we can split the page, before unmap_folio() will
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4019 * split PMDs
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4020 */
>> 8710f6ed34e7bc David Hildenbrand 2024-08-02 4021 if (!can_split_folio(folio, 1, &extra_pins)) {
>> fd4a7ac32918d3 Baolin Wang 2022-10-24 4022 ret = -EAGAIN;
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4023 goto out_unlock;
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4024 }
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4025
>> 684555aacc90d7 Matthew Wilcox (Oracle 2022-09-02 4026) unmap_folio(folio);
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4027
>> b6769834aac1d4 Alex Shi 2020-12-15 4028 /* block interrupt reentry in xa_lock and spinlock */
>> b6769834aac1d4 Alex Shi 2020-12-15 4029 local_irq_disable();
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4030 if (mapping) {
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4031 /*
>> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4032) * Check if the folio is present in page cache.
>> 3e9a13daa61253 Matthew Wilcox (Oracle 2022-09-02 4033) * We assume all tail are present too, if folio is there.
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4034 */
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4035) xas_lock(&xas);
>> 6b24ca4a1a8d4e Matthew Wilcox (Oracle 2020-06-27 4036) xas_reset(&xas);
>> 391dc7f40590d7 Zi Yan 2025-07-18 4037 if (xas_load(&xas) != folio) {
>> 391dc7f40590d7 Zi Yan 2025-07-18 4038 ret = -EAGAIN;
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4039 goto fail;
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4040 }
>> 391dc7f40590d7 Zi Yan 2025-07-18 4041 }
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4042
>> f6b1f167ffe29f Balbir Singh 2025-11-14 4043 ret = __folio_freeze_and_split_unmapped(folio, new_order, split_at, &xas, mapping,
>> f6b1f167ffe29f Balbir Singh 2025-11-14 @4044 true, list, split_type, end, extra_pins);
>> ^^^
>> Passing uninitialized variables isn't allowed unless the function is
>> inlined. It triggers a UBSan warning at runtime as well.
>
> end is expected to be unused when uninitialized, are you suggesting we need to have a default value even if unused inside the function.
> My daily build has UBSan enabled, I'll try again
>
> CONFIG_UBSAN=y
> CONFIG_CC_HAS_UBSAN_ARRAY_BOUNDS=y
> # CONFIG_UBSAN_BOUNDS is not set
> CONFIG_UBSAN_SHIFT=y
> # CONFIG_UBSAN_UNREACHABLE is not set
> # CONFIG_UBSAN_BOOL is not set
> # CONFIG_UBSAN_ENUM is not set
>
>
>>
>> 391dc7f40590d7 Zi Yan 2025-07-18 4045 fail:
>> 6c7de9c83be68b Zi Yan 2025-07-18 @4046 if (mapping)
>> 6c7de9c83be68b Zi Yan 2025-07-18 4047 xas_unlock(&xas);
>> 6c7de9c83be68b Zi Yan 2025-07-18 4048
>> 6c7de9c83be68b Zi Yan 2025-07-18 4049 local_irq_enable();
>> 6c7de9c83be68b Zi Yan 2025-07-18 4050
>> 391dc7f40590d7 Zi Yan 2025-07-18 4051 if (nr_shmem_dropped)
>> 391dc7f40590d7 Zi Yan 2025-07-18 @4052 shmem_uncharge(mapping->host, nr_shmem_dropped);
>>
>> Smatch complains that mapping can be NULL, but this is false positive
>> because nr_shmem_dropped is always zero.
>>
>
> Agreed
>
>> 6c7de9c83be68b Zi Yan 2025-07-18 4053
>> 958fea4c1e2eb6 Balbir Singh 2025-10-01 4054 if (!ret && is_anon && !folio_is_device_private(folio))
>> 391dc7f40590d7 Zi Yan 2025-07-18 4055 remap_flags = RMP_USE_SHARED_ZEROPAGE;
>> 958fea4c1e2eb6 Balbir Singh 2025-10-01 4056
>> 8ec26327c18e1d Wei Yang 2025-10-10 4057 remap_page(folio, 1 << old_order, remap_flags);
>> 6c7de9c83be68b Zi Yan 2025-07-18 4058
>> 6c7de9c83be68b Zi Yan 2025-07-18 4059 /*
>> 6c7de9c83be68b Zi Yan 2025-07-18 4060 * Unlock all after-split folios except the one containing
>> 6c7de9c83be68b Zi Yan 2025-07-18 4061 * @lock_at page. If @folio is not split, it will be kept locked.
>> 6c7de9c83be68b Zi Yan 2025-07-18 4062 */
>> 391dc7f40590d7 Zi Yan 2025-07-18 4063 for (new_folio = folio; new_folio != end_folio; new_folio = next) {
>> 6c7de9c83be68b Zi Yan 2025-07-18 4064 next = folio_next(new_folio);
>> 6c7de9c83be68b Zi Yan 2025-07-18 4065 if (new_folio == page_folio(lock_at))
>> 6c7de9c83be68b Zi Yan 2025-07-18 4066 continue;
>> 6c7de9c83be68b Zi Yan 2025-07-18 4067
>> 6c7de9c83be68b Zi Yan 2025-07-18 4068 folio_unlock(new_folio);
>> 6c7de9c83be68b Zi Yan 2025-07-18 4069 /*
>> 6c7de9c83be68b Zi Yan 2025-07-18 4070 * Subpages may be freed if there wasn't any mapping
>> 6c7de9c83be68b Zi Yan 2025-07-18 4071 * like if add_to_swap() is running on a lru page that
>> 6c7de9c83be68b Zi Yan 2025-07-18 4072 * had its mapping zapped. And freeing these pages
>> 6c7de9c83be68b Zi Yan 2025-07-18 4073 * requires taking the lru_lock so we do the put_page
>> 6c7de9c83be68b Zi Yan 2025-07-18 4074 * of the tail pages after the split is complete.
>> 6c7de9c83be68b Zi Yan 2025-07-18 4075 */
>> 6c7de9c83be68b Zi Yan 2025-07-18 4076 free_folio_and_swap_cache(new_folio);
>> 6c7de9c83be68b Zi Yan 2025-07-18 4077 }
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4078
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4079 out_unlock:
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4080 if (anon_vma) {
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4081 anon_vma_unlock_write(anon_vma);
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4082 put_anon_vma(anon_vma);
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4083 }
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4084 if (mapping)
>> baa355fd331424 Kirill A. Shutemov 2016-07-26 4085 i_mmap_unlock_read(mapping);
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4086 out:
>> 69a37a8ba1b408 Matthew Wilcox (Oracle 2022-06-08 4087) xas_destroy(&xas);
>> 8ec26327c18e1d Wei Yang 2025-10-10 4088 if (old_order == HPAGE_PMD_ORDER)
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4089 count_vm_event(!ret ? THP_SPLIT_PAGE : THP_SPLIT_PAGE_FAILED);
>> 8ec26327c18e1d Wei Yang 2025-10-10 4090 count_mthp_stat(old_order, !ret ? MTHP_STAT_SPLIT : MTHP_STAT_SPLIT_FAILED);
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4091 return ret;
>> e9b61f19858a5d Kirill A. Shutemov 2016-01-15 4092 }
>>
>
> Balbir
Best Regards,
Yan, Zi
Hi Balbir,
kernel test robot noticed the following build warnings:
[auto build test WARNING on akpm-mm/mm-everything]
url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541
base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything
patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com
patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped
config: arm64-randconfig-002-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151007.F1gixfc8-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251115/202511151007.F1gixfc8-lkp@intel.com/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@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511151007.F1gixfc8-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> mm/huge_memory.c:3751:6: warning: variable 'nr_shmem_dropped' set but not used [-Wunused-but-set-variable]
3751 | int nr_shmem_dropped = 0;
| ^
1 warning generated.
vim +/nr_shmem_dropped +3751 mm/huge_memory.c
3741
3742 static int __folio_freeze_and_split_unmapped(struct folio *folio, unsigned int new_order,
3743 struct page *split_at, struct xa_state *xas,
3744 struct address_space *mapping, bool do_lru,
3745 struct list_head *list, enum split_type split_type,
3746 pgoff_t end, int extra_pins)
3747 {
3748 struct folio *end_folio = folio_next(folio);
3749 struct folio *new_folio, *next;
3750 int old_order = folio_order(folio);
> 3751 int nr_shmem_dropped = 0;
3752 int ret = 0;
3753 struct deferred_split *ds_queue;
3754
3755 /* Prevent deferred_split_scan() touching ->_refcount */
3756 ds_queue = folio_split_queue_lock(folio);
3757 if (folio_ref_freeze(folio, 1 + extra_pins)) {
3758 struct swap_cluster_info *ci = NULL;
3759 struct lruvec *lruvec;
3760 int expected_refs;
3761
3762 if (old_order > 1) {
3763 if (!list_empty(&folio->_deferred_list)) {
3764 ds_queue->split_queue_len--;
3765 /*
3766 * Reinitialize page_deferred_list after removing the
3767 * page from the split_queue, otherwise a subsequent
3768 * split will see list corruption when checking the
3769 * page_deferred_list.
3770 */
3771 list_del_init(&folio->_deferred_list);
3772 }
3773 if (folio_test_partially_mapped(folio)) {
3774 folio_clear_partially_mapped(folio);
3775 mod_mthp_stat(old_order,
3776 MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
3777 }
3778 }
3779 split_queue_unlock(ds_queue);
3780 if (mapping) {
3781 int nr = folio_nr_pages(folio);
3782
3783 if (folio_test_pmd_mappable(folio) &&
3784 new_order < HPAGE_PMD_ORDER) {
3785 if (folio_test_swapbacked(folio)) {
3786 __lruvec_stat_mod_folio(folio,
3787 NR_SHMEM_THPS, -nr);
3788 } else {
3789 __lruvec_stat_mod_folio(folio,
3790 NR_FILE_THPS, -nr);
3791 filemap_nr_thps_dec(mapping);
3792 }
3793 }
3794 }
3795
3796 if (folio_test_swapcache(folio)) {
3797 if (mapping) {
3798 VM_WARN_ON_ONCE_FOLIO(mapping, folio);
3799 return -EINVAL;
3800 }
3801
3802 ci = swap_cluster_get_and_lock(folio);
3803 }
3804
3805 /* lock lru list/PageCompound, ref frozen by page_ref_freeze */
3806 if (do_lru)
3807 lruvec = folio_lruvec_lock(folio);
3808
3809 ret = __split_unmapped_folio(folio, new_order, split_at, xas,
3810 mapping, split_type);
3811
3812 /*
3813 * Unfreeze after-split folios and put them back to the right
3814 * list. @folio should be kept frozon until page cache
3815 * entries are updated with all the other after-split folios
3816 * to prevent others seeing stale page cache entries.
3817 * As a result, new_folio starts from the next folio of
3818 * @folio.
3819 */
3820 for (new_folio = folio_next(folio); new_folio != end_folio;
3821 new_folio = next) {
3822 unsigned long nr_pages = folio_nr_pages(new_folio);
3823
3824 next = folio_next(new_folio);
3825
3826 zone_device_private_split_cb(folio, new_folio);
3827
3828 expected_refs = folio_expected_ref_count(new_folio) + 1;
3829 folio_ref_unfreeze(new_folio, expected_refs);
3830
3831 if (do_lru)
3832 lru_add_split_folio(folio, new_folio, lruvec, list);
3833
3834 /*
3835 * Anonymous folio with swap cache.
3836 * NOTE: shmem in swap cache is not supported yet.
3837 */
3838 if (ci) {
3839 __swap_cache_replace_folio(ci, folio, new_folio);
3840 continue;
3841 }
3842
3843 /* Anonymous folio without swap cache */
3844 if (!mapping)
3845 continue;
3846
3847 /* Add the new folio to the page cache. */
3848 if (new_folio->index < end) {
3849 __xa_store(&mapping->i_pages, new_folio->index,
3850 new_folio, 0);
3851 continue;
3852 }
3853
3854 /* Drop folio beyond EOF: ->index >= end */
3855 if (shmem_mapping(mapping))
3856 nr_shmem_dropped += nr_pages;
3857 else if (folio_test_clear_dirty(new_folio))
3858 folio_account_cleaned(
3859 new_folio, inode_to_wb(mapping->host));
3860 __filemap_remove_folio(new_folio, NULL);
3861 folio_put_refs(new_folio, nr_pages);
3862 }
3863
3864 zone_device_private_split_cb(folio, NULL);
3865 /*
3866 * Unfreeze @folio only after all page cache entries, which
3867 * used to point to it, have been updated with new folios.
3868 * Otherwise, a parallel folio_try_get() can grab @folio
3869 * and its caller can see stale page cache entries.
3870 */
3871 expected_refs = folio_expected_ref_count(folio) + 1;
3872 folio_ref_unfreeze(folio, expected_refs);
3873
3874 if (do_lru)
3875 unlock_page_lruvec(lruvec);
3876
3877 if (ci)
3878 swap_cluster_unlock(ci);
3879 } else {
3880 split_queue_unlock(ds_queue);
3881 return -EAGAIN;
3882 }
3883
3884 return ret;
3885 }
3886
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On 11/15/25 13:15, kernel test robot wrote: > Hi Balbir, > > kernel test robot noticed the following build warnings: > > [auto build test WARNING on akpm-mm/mm-everything] > > url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541 > base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything > patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com > patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped > config: arm64-randconfig-002-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151007.F1gixfc8-lkp@intel.com/config) > compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff) > reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251115/202511151007.F1gixfc8-lkp@intel.com/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@intel.com> > | Closes: https://lore.kernel.org/oe-kbuild-all/202511151007.F1gixfc8-lkp@intel.com/ > > All warnings (new ones prefixed by >>): > >>> mm/huge_memory.c:3751:6: warning: variable 'nr_shmem_dropped' set but not used [-Wunused-but-set-variable] > 3751 | int nr_shmem_dropped = 0; > | ^ > 1 warning generated. > > > vim +/nr_shmem_dropped +3751 mm/huge_memory.c > [...] Thanks for the report, I'll send an updated version after I investigate it Balbir
On 14 Nov 2025, at 21:33, Balbir Singh wrote: > On 11/15/25 13:15, kernel test robot wrote: >> Hi Balbir, >> >> kernel test robot noticed the following build warnings: >> >> [auto build test WARNING on akpm-mm/mm-everything] >> >> url: https://github.com/intel-lab-lkp/linux/commits/Balbir-Singh/mm-huge_memory-c-introduce-folio_split_unmapped/20251114-093541 >> base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything >> patch link: https://lore.kernel.org/r/20251114012228.2634882-1-balbirs%40nvidia.com >> patch subject: [PATCH] mm/huge_memory.c: introduce folio_split_unmapped >> config: arm64-randconfig-002-20251115 (https://download.01.org/0day-ci/archive/20251115/202511151007.F1gixfc8-lkp@intel.com/config) >> compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff) >> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251115/202511151007.F1gixfc8-lkp@intel.com/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@intel.com> >> | Closes: https://lore.kernel.org/oe-kbuild-all/202511151007.F1gixfc8-lkp@intel.com/ >> >> All warnings (new ones prefixed by >>): >> >>>> mm/huge_memory.c:3751:6: warning: variable 'nr_shmem_dropped' set but not used [-Wunused-but-set-variable] >> 3751 | int nr_shmem_dropped = 0; >> | ^ >> 1 warning generated. >> >> >> vim +/nr_shmem_dropped +3751 mm/huge_memory.c >> > > [...] > > Thanks for the report, I'll send an updated version after I investigate it nr_shmem_dropped is updated in __folio_freeze_and_split_unmapped() but is used in its caller. It needs to be passed into __folio_freeze_and_split_unmapped(). -- Best Regards, Yan, Zi
On 14.11.25 02:22, Balbir Singh wrote: > Unmapped was added as a parameter to __folio_split() and related > call sites to support splitting of folios already in the midst > of a migration. This special case arose for device private folio > migration since during migration there could be a disconnect between > source and destination on the folio size. Didn't I already comment that the subject should start with "mm/huge_memory: introduce ..." ? Yes I did: https://lore.kernel.org/all/048134fd-6a3d-4a6c-a2eb-9a9911c3b35f@kernel.org/ You know, I'm a busy man, can you *please* * take better care of addressing all previous comments? * wait more than 12 h after asking a question before you resend? -- Cheers David
On 11/14/25 19:36, David Hildenbrand (Red Hat) wrote: > On 14.11.25 02:22, Balbir Singh wrote: >> Unmapped was added as a parameter to __folio_split() and related >> call sites to support splitting of folios already in the midst >> of a migration. This special case arose for device private folio >> migration since during migration there could be a disconnect between >> source and destination on the folio size. > > Didn't I already comment that the subject should start with "mm/huge_memory: introduce ..." ? > Yeah.. the .c in the prefix is not desirable, I missed that in the subject line > Yes I did: https://lore.kernel.org/all/048134fd-6a3d-4a6c-a2eb-9a9911c3b35f@kernel.org/ > > You know, I'm a busy man, can you *please* > > * take better care of addressing all previous comments? > * wait more than 12 h after asking a question before you resend? > I think addressed most of it, I missed the subject line, but in general addressed 1. Using folio_split_ as the prefix to split functions, the main function is called folio_split_unmapped and the helper name was suggested by Zi to be __folio_freeze_and_split_unmapped() and it sounded better than what I had __folio_split_unmapped() or even __folio_split_freeze_unmapped() 2. Got rid of _to_order() as the function suffix Do you have any more outstanding comments that I missed? Thanks for the review! Balbir
On 14.11.25 10:10, Balbir Singh wrote: > On 11/14/25 19:36, David Hildenbrand (Red Hat) wrote: >> On 14.11.25 02:22, Balbir Singh wrote: >>> Unmapped was added as a parameter to __folio_split() and related >>> call sites to support splitting of folios already in the midst >>> of a migration. This special case arose for device private folio >>> migration since during migration there could be a disconnect between >>> source and destination on the folio size. >> >> Didn't I already comment that the subject should start with "mm/huge_memory: introduce ..." ? >> > > Yeah.. the .c in the prefix is not desirable, I missed that in the subject line > >> Yes I did: https://lore.kernel.org/all/048134fd-6a3d-4a6c-a2eb-9a9911c3b35f@kernel.org/ >> >> You know, I'm a busy man, can you *please* >> >> * take better care of addressing all previous comments? >> * wait more than 12 h after asking a question before you resend? >> > > I think addressed most of it, I missed the subject line, but in general addressed > > 1. Using folio_split_ as the prefix to split functions, the main function is called folio_split_unmapped and the helper name was suggested by Zi to be __folio_freeze_and_split_unmapped() and it sounded better than what I had __folio_split_unmapped() or even __folio_split_freeze_unmapped() > 2. Got rid of _to_order() as the function suffix > > Do you have any more outstanding comments that I missed? I'll take a look at v2 now given that I was distracted for 2 days :( -- Cheers David
On Fri, Nov 14, 2025 at 12:22:28PM +1100, Balbir Singh wrote:
[...]
>@@ -4079,6 +4091,36 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
> return ret;
> }
>
>+/*
>+ * This function is a helper for splitting folios that have already been unmapped.
>+ * The use case is that the device or the CPU can refuse to migrate THP pages in
>+ * the middle of migration, due to allocation issues on either side
>+ *
>+ * The high level code is copied from __folio_split, since the pages are anonymous
>+ * and are already isolated from the LRU, the code has been simplified to not
>+ * burden __folio_split with unmapped sprinkled into the code.
>+ *
>+ * None of the split folios are unlocked
>+ */
>+int folio_split_unmapped(struct folio *folio, unsigned int new_order)
>+{
>+ int extra_pins, ret = 0;
>+
>+ VM_WARN_ON_FOLIO(folio_mapped(folio), folio);
>+ VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
>+ VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
>+
Compared with original logic, we did check folio_split_supported() and
check whether new_order is supported for the file system.
Currently folio_split_unmapped() only pass 0 as new_order, which looks good.
But for a generic helper, it looks reasonable to do the check, IMHO.
>+ if (!can_split_folio(folio, 1, &extra_pins))
>+ return -EAGAIN;
>+
>+ local_irq_disable();
>+ ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,
>+ NULL, false, NULL, SPLIT_TYPE_UNIFORM,
>+ 0, extra_pins);
>+ local_irq_enable();
>+ return ret;
>+}
>+
> /*
> * This function splits a large folio into smaller folios of order @new_order.
> * @page can point to any page of the large folio to split. The split operation
--
Wei Yang
Help you, Help me
On 11/14/25 14:21, Wei Yang wrote:
> On Fri, Nov 14, 2025 at 12:22:28PM +1100, Balbir Singh wrote:
> [...]
>> @@ -4079,6 +4091,36 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
>> return ret;
>> }
>>
>> +/*
>> + * This function is a helper for splitting folios that have already been unmapped.
>> + * The use case is that the device or the CPU can refuse to migrate THP pages in
>> + * the middle of migration, due to allocation issues on either side
>> + *
>> + * The high level code is copied from __folio_split, since the pages are anonymous
>> + * and are already isolated from the LRU, the code has been simplified to not
>> + * burden __folio_split with unmapped sprinkled into the code.
>> + *
>> + * None of the split folios are unlocked
>> + */
>> +int folio_split_unmapped(struct folio *folio, unsigned int new_order)
>> +{
>> + int extra_pins, ret = 0;
>> +
>> + VM_WARN_ON_FOLIO(folio_mapped(folio), folio);
>> + VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
>> + VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
>> +
>
> Compared with original logic, we did check folio_split_supported() and
> check whether new_order is supported for the file system.
>
> Currently folio_split_unmapped() only pass 0 as new_order, which looks good.
> But for a generic helper, it looks reasonable to do the check, IMHO.
>
This is meant to be used in the middle of a migration where the src/dst do
no agree on the folio_order() due to allocation issues. When mTHP support
is added to device migration, order support will be added and checked.
FYI: This routines supports just anonymous pages ATM
>> + if (!can_split_folio(folio, 1, &extra_pins))
>> + return -EAGAIN;
>> +
>> + local_irq_disable();
>> + ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,
>> + NULL, false, NULL, SPLIT_TYPE_UNIFORM,
>> + 0, extra_pins);
>> + local_irq_enable();
>> + return ret;
>> +}
>> +
>> /*
>> * This function splits a large folio into smaller folios of order @new_order.
>> * @page can point to any page of the large folio to split. The split operation
>
>
Balbir
On Fri, Nov 14, 2025 at 02:30:03PM +1100, Balbir Singh wrote:
>On 11/14/25 14:21, Wei Yang wrote:
>> On Fri, Nov 14, 2025 at 12:22:28PM +1100, Balbir Singh wrote:
>> [...]
>>> @@ -4079,6 +4091,36 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
>>> return ret;
>>> }
>>>
>>> +/*
>>> + * This function is a helper for splitting folios that have already been unmapped.
>>> + * The use case is that the device or the CPU can refuse to migrate THP pages in
>>> + * the middle of migration, due to allocation issues on either side
>>> + *
>>> + * The high level code is copied from __folio_split, since the pages are anonymous
>>> + * and are already isolated from the LRU, the code has been simplified to not
>>> + * burden __folio_split with unmapped sprinkled into the code.
>>> + *
>>> + * None of the split folios are unlocked
>>> + */
>>> +int folio_split_unmapped(struct folio *folio, unsigned int new_order)
>>> +{
>>> + int extra_pins, ret = 0;
>>> +
>>> + VM_WARN_ON_FOLIO(folio_mapped(folio), folio);
>>> + VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
>>> + VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
>>> +
>>
>> Compared with original logic, we did check folio_split_supported() and
>> check whether new_order is supported for the file system.
>>
>> Currently folio_split_unmapped() only pass 0 as new_order, which looks good.
>> But for a generic helper, it looks reasonable to do the check, IMHO.
>>
>
>This is meant to be used in the middle of a migration where the src/dst do
>no agree on the folio_order() due to allocation issues. When mTHP support
>is added to device migration, order support will be added and checked.
>FYI: This routines supports just anonymous pages ATM
>
OK, I don't see these assumptions. Not sure it would be abused.
Maybe a comment would help? Or remove the new_order now? We can add it when it
is truly used.
>>> + if (!can_split_folio(folio, 1, &extra_pins))
>>> + return -EAGAIN;
>>> +
>>> + local_irq_disable();
>>> + ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,
>>> + NULL, false, NULL, SPLIT_TYPE_UNIFORM,
>>> + 0, extra_pins);
>>> + local_irq_enable();
>>> + return ret;
>>> +}
>>> +
>>> /*
>>> * This function splits a large folio into smaller folios of order @new_order.
>>> * @page can point to any page of the large folio to split. The split operation
>>
>>
>
>Balbir
--
Wei Yang
Help you, Help me
On Fri, Nov 14, 2025 at 03:21:05AM +0000, Wei Yang wrote:
>On Fri, Nov 14, 2025 at 12:22:28PM +1100, Balbir Singh wrote:
>[...]
>>@@ -4079,6 +4091,36 @@ static int __folio_split(struct folio *folio, unsigned int new_order,
>> return ret;
>> }
>>
>>+/*
>>+ * This function is a helper for splitting folios that have already been unmapped.
>>+ * The use case is that the device or the CPU can refuse to migrate THP pages in
>>+ * the middle of migration, due to allocation issues on either side
>>+ *
>>+ * The high level code is copied from __folio_split, since the pages are anonymous
>>+ * and are already isolated from the LRU, the code has been simplified to not
>>+ * burden __folio_split with unmapped sprinkled into the code.
>>+ *
>>+ * None of the split folios are unlocked
>>+ */
>>+int folio_split_unmapped(struct folio *folio, unsigned int new_order)
>>+{
>>+ int extra_pins, ret = 0;
>>+
>>+ VM_WARN_ON_FOLIO(folio_mapped(folio), folio);
>>+ VM_WARN_ON_ONCE_FOLIO(!folio_test_locked(folio), folio);
>>+ VM_WARN_ON_ONCE_FOLIO(!folio_test_large(folio), folio);
>>+
>
>Compared with original logic, we did check folio_split_supported() and
>check whether new_order is supported for the file system.
>
>Currently folio_split_unmapped() only pass 0 as new_order, which looks good.
>But for a generic helper, it looks reasonable to do the check, IMHO.
>
BTW, I proposed to do the min_order/new_order check in folio_split_supported()
in [1], which may help to make the code looks cleaner.
[1]: lkml.kernel.org/r/20251107072944.zvqvr4kyibyofhuw@master
>>+ if (!can_split_folio(folio, 1, &extra_pins))
>>+ return -EAGAIN;
>>+
>>+ local_irq_disable();
>>+ ret = __folio_freeze_and_split_unmapped(folio, new_order, &folio->page, NULL,
>>+ NULL, false, NULL, SPLIT_TYPE_UNIFORM,
>>+ 0, extra_pins);
>>+ local_irq_enable();
>>+ return ret;
>>+}
>>+
>> /*
>> * This function splits a large folio into smaller folios of order @new_order.
>> * @page can point to any page of the large folio to split. The split operation
>
>
>--
>Wei Yang
>Help you, Help me
--
Wei Yang
Help you, Help me
On 13 Nov 2025, at 20:22, Balbir Singh wrote: > Unmapped was added as a parameter to __folio_split() and related > call sites to support splitting of folios already in the midst > of a migration. This special case arose for device private folio > migration since during migration there could be a disconnect between > source and destination on the folio size. > > Introduce folio_split_unmapped() to handle this special case. Also > refactor code and add __folio_freeze_and_split_unmapped() helper that > is common to both __folio_split() and folio_split_unmapped(). > > This in turn removes the special casing introduced by the unmapped > parameter in __folio_split(). > > Cc: Andrew Morton <akpm@linux-foundation.org> > Cc: David Hildenbrand <david@redhat.com> > Cc: Zi Yan <ziy@nvidia.com> > Cc: Joshua Hahn <joshua.hahnjy@gmail.com> > Cc: Rakie Kim <rakie.kim@sk.com> > Cc: Byungchul Park <byungchul@sk.com> > Cc: Gregory Price <gourry@gourry.net> > Cc: Ying Huang <ying.huang@linux.alibaba.com> > Cc: Alistair Popple <apopple@nvidia.com> > Cc: Oscar Salvador <osalvador@suse.de> > Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> > Cc: Baolin Wang <baolin.wang@linux.alibaba.com> > Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com> > Cc: Nico Pache <npache@redhat.com> > Cc: Ryan Roberts <ryan.roberts@arm.com> > Cc: Dev Jain <dev.jain@arm.com> > Cc: Barry Song <baohua@kernel.org> > Cc: Lyude Paul <lyude@redhat.com> > Cc: Danilo Krummrich <dakr@kernel.org> > Cc: David Airlie <airlied@gmail.com> > Cc: Simona Vetter <simona@ffwll.ch> > Cc: Ralph Campbell <rcampbell@nvidia.com> > Cc: Mika Penttilä <mpenttil@redhat.com> > Cc: Matthew Brost <matthew.brost@intel.com> > Cc: Francois Dugast <francois.dugast@intel.com> > > Suggested-by: Zi Yan <ziy@nvidia.com> > Signed-off-by: Balbir Singh <balbirs@nvidia.com> > --- > include/linux/huge_mm.h | 5 +- > mm/huge_memory.c | 332 ++++++++++++++++++++++------------------ > mm/migrate_device.c | 3 +- > 3 files changed, 191 insertions(+), 149 deletions(-) > LGTM. Acked-by: Zi Yan <ziy@nvidia.com> Best Regards, Yan, Zi
© 2016 - 2026 Red Hat, Inc.