Add support for the new vm_uffd_ops API for shmem. Note that this only
introduces the support, the API is not yet used by core mm.
Due to the tailored uffd_copy() API, shmem is extremely easy to support it
by reusing the existing mfill function.
It only needs a separate uffd_get_folio() definition but that's oneliner.
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Peter Xu <peterx@redhat.com>
---
mm/shmem.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/mm/shmem.c b/mm/shmem.c
index 2b19965d27df..9a8b8dd4709b 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3151,6 +3151,13 @@ static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap,
#endif /* CONFIG_TMPFS_QUOTA */
#ifdef CONFIG_USERFAULTFD
+
+static int shmem_uffd_get_folio(struct inode *inode, pgoff_t pgoff,
+ struct folio **folio)
+{
+ return shmem_get_folio(inode, pgoff, 0, folio, SGP_NOALLOC);
+}
+
int shmem_mfill_atomic_pte(pmd_t *dst_pmd,
struct vm_area_struct *dst_vma,
unsigned long dst_addr,
@@ -5194,6 +5201,19 @@ static int shmem_error_remove_folio(struct address_space *mapping,
return 0;
}
+#ifdef CONFIG_USERFAULTFD
+static const vm_uffd_ops shmem_uffd_ops = {
+ .uffd_features = __VM_UFFD_FLAGS,
+ .uffd_ioctls = BIT(_UFFDIO_COPY) |
+ BIT(_UFFDIO_ZEROPAGE) |
+ BIT(_UFFDIO_WRITEPROTECT) |
+ BIT(_UFFDIO_CONTINUE) |
+ BIT(_UFFDIO_POISON),
+ .uffd_get_folio = shmem_uffd_get_folio,
+ .uffd_copy = shmem_mfill_atomic_pte,
+};
+#endif
+
static const struct address_space_operations shmem_aops = {
.dirty_folio = noop_dirty_folio,
#ifdef CONFIG_TMPFS
@@ -5296,6 +5316,9 @@ static const struct vm_operations_struct shmem_vm_ops = {
.set_policy = shmem_set_policy,
.get_policy = shmem_get_policy,
#endif
+#ifdef CONFIG_USERFAULTFD
+ .userfaultfd_ops = &shmem_uffd_ops,
+#endif
};
static const struct vm_operations_struct shmem_anon_vm_ops = {
@@ -5305,6 +5328,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
+ .userfaultfd_ops = &shmem_uffd_ops,
+#endif
};
int shmem_init_fs_context(struct fs_context *fc)
--
2.49.0
On Fri, Jun 27, 2025 at 11:46:53AM -0400, Peter Xu wrote: > Add support for the new vm_uffd_ops API for shmem. Note that this only > introduces the support, the API is not yet used by core mm. > > Due to the tailored uffd_copy() API, shmem is extremely easy to support it > by reusing the existing mfill function. > > It only needs a separate uffd_get_folio() definition but that's oneliner. > > Cc: Hugh Dickins <hughd@google.com> > Signed-off-by: Peter Xu <peterx@redhat.com> Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org> > --- > mm/shmem.c | 26 ++++++++++++++++++++++++++ > 1 file changed, 26 insertions(+) > > diff --git a/mm/shmem.c b/mm/shmem.c > index 2b19965d27df..9a8b8dd4709b 100644 > --- a/mm/shmem.c > +++ b/mm/shmem.c > @@ -3151,6 +3151,13 @@ static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap, > #endif /* CONFIG_TMPFS_QUOTA */ > > #ifdef CONFIG_USERFAULTFD > + > +static int shmem_uffd_get_folio(struct inode *inode, pgoff_t pgoff, > + struct folio **folio) > +{ > + return shmem_get_folio(inode, pgoff, 0, folio, SGP_NOALLOC); > +} > + > int shmem_mfill_atomic_pte(pmd_t *dst_pmd, > struct vm_area_struct *dst_vma, > unsigned long dst_addr, > @@ -5194,6 +5201,19 @@ static int shmem_error_remove_folio(struct address_space *mapping, > return 0; > } > > +#ifdef CONFIG_USERFAULTFD > +static const vm_uffd_ops shmem_uffd_ops = { > + .uffd_features = __VM_UFFD_FLAGS, > + .uffd_ioctls = BIT(_UFFDIO_COPY) | > + BIT(_UFFDIO_ZEROPAGE) | > + BIT(_UFFDIO_WRITEPROTECT) | > + BIT(_UFFDIO_CONTINUE) | > + BIT(_UFFDIO_POISON), > + .uffd_get_folio = shmem_uffd_get_folio, > + .uffd_copy = shmem_mfill_atomic_pte, > +}; > +#endif > + > static const struct address_space_operations shmem_aops = { > .dirty_folio = noop_dirty_folio, > #ifdef CONFIG_TMPFS > @@ -5296,6 +5316,9 @@ static const struct vm_operations_struct shmem_vm_ops = { > .set_policy = shmem_set_policy, > .get_policy = shmem_get_policy, > #endif > +#ifdef CONFIG_USERFAULTFD > + .userfaultfd_ops = &shmem_uffd_ops, > +#endif > }; > > static const struct vm_operations_struct shmem_anon_vm_ops = { > @@ -5305,6 +5328,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 > + .userfaultfd_ops = &shmem_uffd_ops, > +#endif > }; > > int shmem_init_fs_context(struct fs_context *fc) > -- > 2.49.0 > > -- Sincerely yours, Mike.
© 2016 - 2025 Red Hat, Inc.