From: "David Hildenbrand (Red Hat)" <david@kernel.org>
To: Mike Rapoport <rppt@kernel.org>, linux-mm@kvack.org
Cc: Andrea Arcangeli <aarcange@redhat.com>,
Andrew Morton <akpm@linux-foundation.org>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
Hugh Dickins <hughd@google.com>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
Lorenzo Stoakes <lorenzo.stoakes@oracle.com>,
Michal Hocko <mhocko@suse.com>,
Nikita Kalyazin <kalyazin@amazon.com>,
Paolo Bonzini <pbonzini@redhat.com>, Peter Xu <peterx@redhat.com>,
Sean Christopherson <seanjc@google.com>,
Shuah Khan <shuah@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Vlastimil Babka <vbabka@suse.cz>,
linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
linux-kselftest@vger.kernel.org
Subject: Re: [RFC PATCH 2/4] userfaultfd, shmem: use a VMA callback to handle UFFDIO_CONTINUE
Date: Mon, 17 Nov 2025 18:08:57 +0100 [thread overview]
Message-ID: <94fcc32f-574a-4934-b7a9-1ed8bd32a97f@kernel.org> (raw)
In-Reply-To: <20251117114631.2029447-3-rppt@kernel.org>
On 17.11.25 12:46, Mike Rapoport wrote:
> From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>
>
> When userspace resolves a page fault in a shmem VMA with UFFDIO_CONTINUE
> it needs to get a folio that already exists in the pagecache backing
> that VMA.
>
> Instead of using shmem_get_folio() for that, add a get_pagecache_folio()
> method to 'struct vm_operations_struct' that will return a folio if it
> exists in the VMA's pagecache at given pgoff.
>
> Implement get_pagecache_folio() method for shmem and slightly refactor
> userfaultfd's mfill_atomic() and mfill_atomic_pte_continue() to support
> this new API.
>
> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
> ---
> include/linux/mm.h | 9 +++++++
> mm/shmem.c | 20 ++++++++++++++++
> mm/userfaultfd.c | 60 ++++++++++++++++++++++++++++++----------------
> 3 files changed, 69 insertions(+), 20 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index d16b33bacc32..c35c1e1ac4dd 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -690,6 +690,15 @@ struct vm_operations_struct {
> struct page *(*find_normal_page)(struct vm_area_struct *vma,
> unsigned long addr);
> #endif /* CONFIG_FIND_NORMAL_PAGE */
> +#ifdef CONFIG_USERFAULTFD
> + /*
> + * Called by userfault to resolve UFFDIO_CONTINUE request.
> + * Should return the folio found at pgoff in the VMA's pagecache if it
> + * exists or ERR_PTR otherwise.
> + */
What are the locking +refcount rules? Without looking at the code, I
would assume we return with a folio reference held and the folio locked?
> + struct folio *(*get_pagecache_folio)(struct vm_area_struct *vma,
> + pgoff_t pgoff);
The combination of VMA + pgoff looks weird at first. Would vma + addr or
vma+vma_offset into vma be better?
But it also makes me wonder if the callback would ever even require the
VMA, or actually only vma->vm_file?
Thinking out loud, I wonder if one could just call that "get_folio" or
"get_shared_folio" (IOW, never an anon folio in a MAP_PRIVATE mapping).
> +#endif
> };
>
> #ifdef CONFIG_NUMA_BALANCING
> diff --git a/mm/shmem.c b/mm/shmem.c
> index b9081b817d28..4ac122284bff 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -3260,6 +3260,20 @@ int shmem_mfill_atomic_pte(pmd_t *dst_pmd,
> shmem_inode_unacct_blocks(inode, 1);
> return ret;
> }
> +
> +static struct folio *shmem_get_pagecache_folio(struct vm_area_struct *vma,
> + pgoff_t pgoff)
> +{
> + struct inode *inode = file_inode(vma->vm_file);
> + struct folio *folio;
> + int err;
> +
> + err = shmem_get_folio(inode, pgoff, 0, &folio, SGP_NOALLOC);
> + if (err)
> + return ERR_PTR(err);
> +
> + return folio;
> +}
> #endif /* CONFIG_USERFAULTFD */
>
> #ifdef CONFIG_TMPFS
> @@ -5292,6 +5306,9 @@ static const struct vm_operations_struct shmem_vm_ops = {
> .set_policy = shmem_set_policy,
> .get_policy = shmem_get_policy,
> #endif
> +#ifdef CONFIG_USERFAULTFD
> + .get_pagecache_folio = shmem_get_pagecache_folio,
> +#endif
> };
>
> static const struct vm_operations_struct shmem_anon_vm_ops = {
> @@ -5301,6 +5318,9 @@ static const struct vm_operations_struct shmem_anon_vm_ops = {
> .set_policy = shmem_set_policy,
> .get_policy = shmem_get_policy,
> #endif
> +#ifdef CONFIG_USERFAULTFD
> + .get_pagecache_folio = shmem_get_pagecache_folio,
> +#endif
> };
>
> int shmem_init_fs_context(struct fs_context *fc)
> diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c
> index 8dc964389b0d..60b3183a72c0 100644
> --- a/mm/userfaultfd.c
> +++ b/mm/userfaultfd.c
> @@ -382,21 +382,17 @@ static int mfill_atomic_pte_continue(pmd_t *dst_pmd,
> unsigned long dst_addr,
> uffd_flags_t flags)
> {
> - struct inode *inode = file_inode(dst_vma->vm_file);
> pgoff_t pgoff = linear_page_index(dst_vma, dst_addr);
> struct folio *folio;
> struct page *page;
> int ret;
>
> - ret = shmem_get_folio(inode, pgoff, 0, &folio, SGP_NOALLOC);
> + folio = dst_vma->vm_ops->get_pagecache_folio(dst_vma, pgoff);
> /* Our caller expects us to return -EFAULT if we failed to find folio */
> - if (ret == -ENOENT)
> - ret = -EFAULT;
> - if (ret)
> - goto out;
> - if (!folio) {
> - ret = -EFAULT;
> - goto out;
> + if (IS_ERR_OR_NULL(folio)) {
> + if (PTR_ERR(folio) == -ENOENT || !folio)
> + return -EFAULT;
> + return PTR_ERR(folio);
> }
>
> page = folio_file_page(folio, pgoff);
> @@ -411,13 +407,12 @@ static int mfill_atomic_pte_continue(pmd_t *dst_pmd,
> goto out_release;
>
> folio_unlock(folio);
> - ret = 0;
> -out:
> - return ret;
> + return 0;
> +
> out_release:
> folio_unlock(folio);
> folio_put(folio);
> - goto out;
> + return ret;
> }
>
> /* Handles UFFDIO_POISON for all non-hugetlb VMAs. */
> @@ -694,6 +689,22 @@ static __always_inline ssize_t mfill_atomic_pte(pmd_t *dst_pmd,
> return err;
> }
>
> +static __always_inline bool vma_can_mfill_atomic(struct vm_area_struct *vma,
> + uffd_flags_t flags)
> +{
> + if (uffd_flags_mode_is(flags, MFILL_ATOMIC_CONTINUE)) {
> + if (vma->vm_ops && vma->vm_ops->get_pagecache_folio)
> + return true;
> + else
> + return false;
Probably easier to read is
return vma->vm_ops && vma->vm_ops->get_pagecache_folio;
> + }
> +
> + if (vma_is_anonymous(vma) || vma_is_shmem(vma))
> + return true;
> +
> + return false;
Could also be simplified to:
return vma_is_anonymous(vma) || vma_is_shmem(vma);
--
Cheers
David
next prev parent reply other threads:[~2025-11-17 17:09 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-17 11:46 [RFC PATCH 0/4] mm, kvm: add guest_memfd support for uffd minor faults Mike Rapoport
2025-11-17 11:46 ` [RFC PATCH 1/4] userfaultfd: move vma_can_userfault out of line Mike Rapoport
2025-11-17 17:00 ` David Hildenbrand (Red Hat)
2025-11-17 11:46 ` [RFC PATCH 2/4] userfaultfd, shmem: use a VMA callback to handle UFFDIO_CONTINUE Mike Rapoport
2025-11-17 17:08 ` David Hildenbrand (Red Hat) [this message]
2025-11-21 11:52 ` Mike Rapoport
2025-11-17 11:46 ` [RFC PATCH 3/4] userfaultfd, guest_memfd: support userfault minor mode in guest_memfd Mike Rapoport
2025-11-18 16:41 ` David Hildenbrand (Red Hat)
2025-11-21 11:59 ` Mike Rapoport
2025-11-17 11:46 ` [RFC PATCH 4/4] KVM: selftests: test userfaultfd minor for guest_memfd Mike Rapoport
2025-11-17 17:55 ` [RFC PATCH 0/4] mm, kvm: add guest_memfd support for uffd minor faults Nikita Kalyazin
2025-11-17 19:39 ` Peter Xu
2025-11-19 17:35 ` Nikita Kalyazin
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=94fcc32f-574a-4934-b7a9-1ed8bd32a97f@kernel.org \
--to=david@kernel.org \
--cc=Liam.Howlett@oracle.com \
--cc=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=hughd@google.com \
--cc=kalyazin@amazon.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=mhocko@suse.com \
--cc=pbonzini@redhat.com \
--cc=peterx@redhat.com \
--cc=rppt@kernel.org \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@suse.cz \
/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