From: Pratyush Yadav <pratyush@kernel.org>
To: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Pratyush Yadav <pratyush@kernel.org>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christian Brauner <brauner@kernel.org>, Jan Kara <jack@suse.cz>,
"Matthew Wilcox (Oracle)" <willy@infradead.org>,
Hugh Dickins <hughd@google.com>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>, Zi Yan <ziy@nvidia.com>,
"Liam R. Howlett" <liam@infradead.org>,
Nico Pache <nico.pache@linux.dev>,
Ryan Roberts <ryan.roberts@arm.com>,
Dev Jain <dev.jain@arm.com>, Barry Song <baohua@kernel.org>,
Lance Yang <lance.yang@linux.dev>,
Usama Arif <usama.arif@linux.dev>,
Kiryl Shutsemau <kas@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Matthew Brost <matthew.brost@intel.com>,
Joshua Hahn <joshua.hahnjy@gmail.com>,
Byungchul Park <byungchul@sk.com>,
Gregory Price <gourry@gourry.net>,
Ying Huang <ying.huang@linux.alibaba.com>,
Alistair Popple <apopple@nvidia.com>,
Kairui Song <kasong@tencent.com>, Qi Zheng <qi.zheng@linux.dev>,
Shakeel Butt <shakeel.butt@linux.dev>,
Axel Rasmussen <axelrasmussen@google.com>,
Yuanchu Xie <yuanchu@google.com>, Wei Xu <weixugc@google.com>,
Baoquan He <baoquan.he@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, kexec@lists.infradead.org
Subject: Re: [PATCH 1/3] mm/memfd_luo: don't use memfd_pin_folios()
Date: Thu, 29 Oct 2026 00:04:03 +0100 [thread overview]
Message-ID: <2vxz4ie5o2ak.fsf@kernel.org> (raw)
In-Reply-To: <179321872100.1775665.6881420026761127422.b4-review@b4> (Pasha Tatashin's message of "Wed, 28 Oct 2026 16:18:41 -0400")
On Wed, Oct 28 2026, Pasha Tatashin wrote:
>> memfd_luo takes a snapshot of the folios in the file's mapping. To make
>> sure the snapshot does not go out of sync, it pins the folios in the
>> file via memfd_pin_folios(). The pinning also migrates the folios out of
>> MIGRATE_MOVABLE to make sure doesn't land in KHO boot memory or in a CMA
>> region.
>>
>> memfd_pin_folios() does not lock the folios. So it can race with
>> shmem_writeout(). A folio returned by memfd_pin_folios() might already
>> be in swap cache. This happens to work but is fragile. memfd_luo looks
>> at folio flags and index on a folio that isn't in the memfd's page
>> cache.
>>
>> In addition, memfd_pin_folios() needs the caller to allocate an array of
>> folios. memfd_luo does not really need that since it will vmalloc
>> folios_ser and store the information there anyway. The folios array is
>> unnecessary overhead.
>>
>> Finally, memfd_pin_folios() fills in holes in the memfd. This makes
>> preserving sparse memfds very expensive in both compute and memory.
>> While this patch doesn't yet stop filling in the holes, it sets up the
>> infrastructure to make it simpler.
>
> +1, this is problematic and should be resolved. In some setups, VMMs
> leave holes for PCI/IO space; with the current approach, single memfd
> preservation does not work for such use cases.
Yep, agreed. There are a couple parts to this. First is this patch. Next
is KHO xarray. The patchset is ready, I'll send it after -rc1.
I think I will move this patch to that series and then make the series
also support holes.
>
>> Fix all this by walking the page cache directly using shmem_get_folio()
>> with SGP_CACHE. This returns a locked folio with an elevated refcount.
>> memfd_luo holds that reference until the memfd is unpreserved. This
>> blocks compaction, migration, etc.
>>
>> There is still a need to migrate folios out of MIGRATE_MOVABLE page
>> blocks. This is because those might be CMA or KHO scratch. memfd_luo
>> will hold a longterm reference to the folios so it will block migration
>> in that pageblock. Introduce memfd_luo_migrate_folio() to do this.
>>
>> Also factor out folio unpreservation logic into memfd_luo_put_folios()
>> and use it from memfd_luo_unpreserve_folios() and from error paths in
>> memfd_luo_preserve_folios().
>>
>> Since shmem_get_folio() always returns uptodate folios, drop the folio
>> zeroing logic.
>>
>> This change also improves preservation performance, shown in the table
>> below.
>>
>> |------------------+----------+------------+-------|
>> | memfd | baseline | this patch | delta |
>> |------------------+----------+------------+-------|
>> | 4K pages, 32 GiB | 748 ms | 600 ms | -20% |
>> | THP, 4 GiB | 0.59 ms | 0.59 ms | 0% |
>> | THP, 16 GiB | 2.99 ms | 2.61 ms | -13% |
>> | THP, 32 GiB | 4.83 ms | 5.21 ms | +8% |
>> | sparse, 32 GiB | 8695 ms | 7269 ms | -16% |
>> |------------------+----------+------------+-------|
>
> For THP 16 GiB / 32 GiB, the -13% / +8% swings look like high run-to-run
> variance. However, maybe not: is it because vmalloc_array() is
> overallocating memory for folios_ser?
Could be, I only did a handful of runs. But I also reckon this is
vmalloc_array() over-allocating. It over-allocated before this patch
too, for the folios array, but that allocation was half as big since
folios_ser is 16 bytes each.
>
> Also, could you clarify what "sparse, 32 GiB" means in this benchmark?
> Was the memfd completely unfaulted before preserve (so preserve faults
> in all 4K pages), or partially populated?
It was completely unfaulted. Size was set via ftruncate() and then
preserved. So it is the worse case of "sparse".
[...]
>> @@ -113,99 +213,77 @@ static int memfd_luo_preserve_folios(struct file *file,
>> * Guess the number of folios based on inode size. Real number might end
>> * up being smaller if there are higher order folios.
>> */
>> - max_folios = PAGE_ALIGN(size) / PAGE_SIZE;
>> - folios = kvmalloc_objs(*folios, max_folios);
>> - if (!folios)
>> + end = DIV_ROUND_UP_ULL(size, PAGE_SIZE);
>> + max_folios = end;
>> + folios_ser = vmalloc_array(max_folios, sizeof(*folios_ser));
>> + if (!folios_ser)
>> return -ENOMEM;
>
> I bet in practice memfds almost always contain folios of the same size,
> so why not estimate the folios_ser size based on the first folio's
> order, and only if that ends up being too small, vrealloc() to match the
> maximum possible remaining size?
That's a good idea! But I think the switch to KHO Xarray will remove the
need for this.
>
> It would be a different change though.
>
[...]
>> +
>> + if (unlikely(!folio_is_longterm_pinnable(folio))) {
>> + folio_unlock(folio);
>> + err = memfd_luo_migrate_folio(folio);
>> + /* Someone else might have it isolated, retry a bit. */
>> + if (err == -EBUSY && ++busy_retries < MEMFD_LUO_MIGRATE_RETRIES)
>> + continue;
>> + if (err)
>> + goto err_restore;
>> + continue;
>> }
>
> Nit:
>
> I would suggest adding another helper, memfd_luo_get_folio(inode, index,
> &folio), that wraps:
>
> - shmem_get_folio()
> - The !folio_is_longterm_pinnable() migration retry loop logic
>
> I think this would make the final code a bit more manageable.
Sounds good, will do.
>
> Other than that the patch looks alright, feel free to add
> Acked-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Once the nit is addressed.
Thanks!
I think the MM side might take some time to gather reviews so I will
send this out as part of a liveupdate-only series. This patch is useful
on its own anyway.
--
Regards,
Pratyush Yadav
next prev parent reply other threads:[~2026-10-28 23:04 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 17:30 [PATCH 0/3] mm: allow freezing mappings Pratyush Yadav
2026-10-27 17:30 ` [PATCH 1/3] mm/memfd_luo: don't use memfd_pin_folios() Pratyush Yadav
2026-10-28 20:18 ` Pasha Tatashin
2026-10-28 23:04 ` Pratyush Yadav [this message]
2026-10-29 0:01 ` Pasha Tatashin
2026-10-27 17:30 ` [PATCH 2/3] mm: allow freezing i_pages Pratyush Yadav
2026-10-27 17:30 ` [PATCH 3/3] mm: shmem: use mapping_set_frozen() for memfd preservation Pratyush Yadav
2026-10-27 17:35 ` [PATCH 0/3] mm: allow freezing mappings David Hildenbrand (Arm)
2026-10-27 17:38 ` Pratyush Yadav
2026-10-27 18:59 ` David Hildenbrand (Arm)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2vxz4ie5o2ak.fsf@kernel.org \
--to=pratyush@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=apopple@nvidia.com \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=baoquan.he@linux.dev \
--cc=brauner@kernel.org \
--cc=byungchul@sk.com \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=gourry@gourry.net \
--cc=hannes@cmpxchg.org \
--cc=hughd@google.com \
--cc=jack@suse.cz \
--cc=joshua.hahnjy@gmail.com \
--cc=kas@kernel.org \
--cc=kasong@tencent.com \
--cc=kexec@lists.infradead.org \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=matthew.brost@intel.com \
--cc=mhocko@kernel.org \
--cc=nico.pache@linux.dev \
--cc=pasha.tatashin@soleen.com \
--cc=qi.zheng@linux.dev \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=shakeel.butt@linux.dev \
--cc=usama.arif@linux.dev \
--cc=viro@zeniv.linux.org.uk \
--cc=weixugc@google.com \
--cc=willy@infradead.org \
--cc=ying.huang@linux.alibaba.com \
--cc=yuanchu@google.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox