Re: [PATCH v3 4/4] mm: Apply vm_uffd_ops API to core mm

From: David Hildenbrand

Date: Tue Sep 30 2025 - 05:23:26 EST


On 26.09.25 23:16, Peter Xu wrote:
Move userfaultfd core to use new vm_uffd_ops API. After this change file
systems that implement vm_operations_struct can start using new API for
userfaultfd operations.

When at it, moving vma_can_userfault() into mm/userfaultfd.c instead,
because it's getting too big. It's only used in slow paths so it shouldn't
be an issue. Move the pte marker check before wp_async, which might be
more intuitive because wp_async depends on pte markers. That shouldn't
cause any functional change though because only one check would take effect
depending on whether pte marker was selected in config.

This will also remove quite some hard-coded checks for either shmem or
hugetlbfs. Now all the old checks should still work but with vm_uffd_ops.

Note that anonymous memory will still need to be processed separately
because it doesn't have vm_ops at all.

Reviewed-by: James Houghton <jthoughton@xxxxxxxxxx>
Acked-by: Mike Rapoport <rppt@xxxxxxxxxx>
Signed-off-by: Peter Xu <peterx@xxxxxxxxxx>
---

[...]

+++ b/mm/userfaultfd.c
@@ -20,6 +20,43 @@
#include "internal.h"
#include "swap.h"
+bool vma_can_userfault(struct vm_area_struct *vma, vm_flags_t vm_flags,
+ bool wp_async)
+{
+ unsigned long supported;
+
+ if (vma->vm_flags & VM_DROPPABLE)
+ return false;
+
+ vm_flags &= __VM_UFFD_FLAGS;
+
+#ifndef CONFIG_PTE_MARKER_UFFD_WP

While at it, you can turn that into an
!IS_ENABLED(CONFIG_PTE_MARKER_UFFD_WP) to avoid the ifdef.

+ /*
+ * If user requested uffd-wp but not enabled pte markers for
+ * uffd-wp, then any file system (like shmem or hugetlbfs) are not
+ * supported but only anonymous.
+ */
+ if ((vm_flags & VM_UFFD_WP) && !vma_is_anonymous(vma))
+ return false;
+#endif
+ /*
+ * If wp async enabled, and WP is the only mode enabled, allow any
+ * memory type.
+ */
+ if (wp_async && (vm_flags == VM_UFFD_WP))
+ return true;


+
+ if (vma_is_anonymous(vma))
+ /* Anonymous has no page cache, MINOR not supported */
+ supported = VM_UFFD_MISSING | VM_UFFD_WP;
+ else if (vma_get_uffd_ops(vma))
+ supported = vma_get_uffd_ops(vma)->uffd_features;
+ else
+ return false;

To avoid the hidde return here, I think you can just do

supported = 0;


Or even cleaner, just do

unsigned long supported = 0
...
if (vma_is_anonymous(vma))
supported = ...
else if (vma_get_uffd_ops(vma))
supported = ...
return ...

+
+ return !(vm_flags & (~supported));

I think this can just be:

return !(vm_flags & ~supported);


--
Cheers

David / dhildenb