Re: [PATCH v3 1/5] mm: Make per-VMA locks available universally

Suren Baghdasaryan <[email protected]> Mon, 3 Aug 2026 10:45:00 -0700
Newsgroups org.kvack.linux-mm,org.kernel.vger.linux-kernel,org.kernel.vger.netdev
Message-ID <CAJuCfpFWSW0Pwh=qtFk14_0=6M9DsY_o8qQn2iFk8Fy2TW9abA@mail.gmail.com>
On Mon, Aug 3, 2026 at 7:01=E2=80=AFAM Vlastimil Babka (SUSE) <vbabka@kerne=
l.org> wrote:
>
> On 8/2/26 23:54, Suren Baghdasaryan wrote:
> > From: Dave Hansen <[email protected]>
> >
> > The per-VMA locks have been around for several years. They've had some
> > bugs worked out of them and have seen quite wide use. However, they
> > are still only available when architectures explicitly enable them.
> > Remove the conditional compilation around the per-VMA locks, making
> > them available on all architectures and configs.
> >
> > The approach up to now seemed to be to add ARCH_SUPPORTS_PER_VMA_LOCK
> > when the architecture started using per-VMA locks in the fault
> > handler. But, contrary to the naming, the Kconfig option does not
> > really indicate whether the architecture supports per-VMA locks or
> > not. It is more of a marker for whether the architecture is likely to
> > benefit from per-VMA locks.
> >
> > To me, the most important thing side-effect of universal availability
> > is letting per-VMA locks be used in SMP=3Dn configs. This lets us use
> > per-VMA locking in all x86 code without fallbacks.
> >
> > Overall, this just generally makes the kernel simpler. Just look at
> > the diffstat. It also opens the door to users that want to use the
> > per-VMA locks in common code. Doing *that* brings additional
> > simplifications.
> >
> > The downside of this is adding some fields to vm_area_struct and
> > mm_struct. There are likely ways to optimize this, especially for
> > things like SMP=3Dn configs. For now, do the simplest thing: use the
> > same implementation everywhere.
> >
> > Signed-off-by: Dave Hansen <[email protected]>
> > Signed-off-by: Suren Baghdasaryan <[email protected]>
>
> Reviewed-by: Vlastimil Babka (SUSE) <[email protected]>
>
> Nits:
>
> > diff --git a/mm/Kconfig b/mm/Kconfig
> > index 060190e12bce..77103b46b679 100644
> > --- a/mm/Kconfig
> > +++ b/mm/Kconfig
> > @@ -1425,19 +1425,6 @@ config LRU_GEN_STATS
> >  config LRU_GEN_WALKS_MMU
> >       def_bool y
> >       depends on LRU_GEN && ARCH_HAS_HW_PTE_YOUNG
> > -# }
>
> I think either leave this in place, or remove the line above with "#
> multi-gen LRU {" as well?

Ah, missed it. I'll keep it in place.

>
> > -
> > -config ARCH_SUPPORTS_PER_VMA_LOCK
> > -       def_bool n
> > -
> > -config PER_VMA_LOCK
> > -     def_bool y
> > -     depends on ARCH_SUPPORTS_PER_VMA_LOCK && MMU && SMP
> > -     help
> > -       Allow per-vma locking during page fault handling.
> > -
> > -       This feature allows locking each virtual memory area separately=
 when
> > -       handling page faults instead of taking mmap_lock.
> >
> >  config LOCK_MM_AND_FIND_VMA
> >       bool
>
> ...
>
> > diff --git a/rust/kernel/mm.rs b/rust/kernel/mm.rs
> > index 4764d7b68f2a..2633e704c83d 100644
> > --- a/rust/kernel/mm.rs
> > +++ b/rust/kernel/mm.rs
> > @@ -174,26 +174,20 @@ pub unsafe fn from_raw<'a>(ptr: *const bindings::=
mm_struct) -> &'a MmWithUser {
> >      /// When per-vma locks are disabled, this always returns `None`.
> >      #[inline]
> >      pub fn lock_vma_under_rcu(&self, vma_addr: usize) -> Option<VmaRea=
dGuard<'_>> {
> > -        #[cfg(CONFIG_PER_VMA_LOCK)]
> >          {
> >              // SAFETY: Calling `bindings::lock_vma_under_rcu` is alway=
s okay given an mm where
> >              // `mm_users` is non-zero.
> >              let vma =3D unsafe { bindings::lock_vma_under_rcu(self.as_=
raw(), vma_addr) };
> > -            if !vma.is_null() {
> > -                return Some(VmaReadGuard {
> > -                    // SAFETY: If `lock_vma_under_rcu` returns a non-n=
ull ptr, then it points at a
> > -                    // valid vma. The vma is stable for as long as the=
 vma read lock is held.
> > -                    vma: unsafe { VmaRef::from_raw(vma) },
> > -                    _nts: NotThreadSafe,
> > -                });
> > +            if vma.is_null() {
> > +                return None;
> >              }
> > +            Some(VmaReadGuard {
> > +                // SAFETY: If `lock_vma_under_rcu` returns a non-null =
ptr, then it points at a
> > +                // valid vma. The vma is stable for as long as the vma=
 read lock is held.
> > +                vma: unsafe { VmaRef::from_raw(vma) },
> > +                _nts: NotThreadSafe,
> > +            })
> >          }
>
> With the "#[cfg(CONFIG_PER_VMA_LOCK)]" does this still need to be in a { =
}
> block?

I don't think it needs to be. I'll remove the extra braces.
Thanks!

>
> > -
> > -        // Silence warnings about unused variables.
> > -        #[cfg(not(CONFIG_PER_VMA_LOCK))]
> > -        let _ =3D vma_addr;
> > -
> > -        None
> >      }
> >
> >      /// Lock the mmap read lock.