initial work on making VMA flags a bitmap
Subsystems (11)
v2 cover initial work on making VMA flags a bitmap
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
This is necessarily a highly iterative process given the extensive use of VMA flags throughout the kernel, so we start by performing basic steps.
Firstly, we declare VMA flags by bit number rather than by value, retaining the VM_xxx fields but in terms of these newly introduced VMA_xxx_BIT fields.
While we are here, we use sparse annotations to ensure that, when dealing with VMA bit number parameters, we cannot be passed values which are not declared as such - providing some useful type safety.
We then introduce an opaque VMA flag type, much like the opaque mm_struct flag type introduced in commit bb6525f2f8c4 ("mm: add bitmap mm->flags field"), which we establish in union with vma->vm_flags (but still set at system word size meaning there is no functional or data type size change).
We update the vm_flags_xxx() helpers to use this new bitmap, introducing sensible helpers to do so.
This series lays the foundation for further work to expand the use of bitmap VMA flags and eventually eliminate these arbitrary restrictions.
v2:
* Corrected kdoc for vma_flag_t.
* Introduced DECLARE_VMA_BIT() as per Jason. We can't also declare the VMA flags in the enum as this breaks assumptions in the kernel, resulting in errors like 'enum constant in boolean context [-Werror=int-in-bool-context]'.
* Dropped the conversion patch - To make life simpler this cycle, let's just fixup the flag declarations and introduce the new field type and introduce vm_flags_*() changes. We can do more later.
* Split out VMA testing vma->__vm_flags change.
* Fixed vma_flag_*_atomic() helper functions for sparse purposes to work with vma_flag_t.
* Fixed rust breakages as reported by Nico and help provided by Alice. For now we are doing a minimal fix, we can do a more substantial one once the VMA flag helper functions are introduced in an upcoming series.
v1:
https://lore.kernel.org/all/[email protected]/
Lorenzo Stoakes (4):
mm: declare VMA flags by bit
mm: simplify and rename mm flags function for clarity tools/testing/vma: eliminate dependency on vma->__vm_flags
mm: introduce VMA flags bitmap type
fs/proc/task_mmu.c | 4 +- include/linux/mm.h | 400 +++++++++++++++------------ include/linux/mm_types.h | 78 +++++- kernel/fork.c | 4 +- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- rust/bindings/bindings_helper.h | 25 ++ rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma.c | 20 +- tools/testing/vma/vma_internal.h | 446 ++++++++++++++++++++++++++----- 10 files changed, 716 insertions(+), 267 deletions(-)
--
2.51.0
PATCH v2 1/4 mm: declare VMA flags by bit
In order to lay the groundwork for VMA flags being a bitmap rather than a system word in size, we need to be able to consistently refer to VMA flags by bit number rather than value.
Take this opportunity to do so in an enum which we which is additionally useful for tooling to extract metadata from.
This additionally makes it very clear which bits are being used for what at a glance.
We use the VMA_ prefix for the bit values as it is logical to do so since these reference VMAs. We consistently suffix with _BIT to make it clear what the values refer to.
We declare bit values even when the flags that use them would not be enabled by config options as this is simply clearer and clearly defines what bit numbers are used for what, at no additional cost.
We declare a sparse-bitwise type vma_flag_t which ensures that users can't pass around invalid VMA flags by accident and prepares for future work towards VMA flags being a bitmap where we want to ensure bit values are type safe.
To make life easier, we declare some macro helpers - DECLARE_VMA_BIT() allows us to avoid duplication in the enum bit number declarations (and maintaining the sparse __bitwise attribute), and INIT_VM_FLAG() is used to assist with declaration of flags.
Unfortunately we can't declare both in the enum, as we run into issue with logic in the kernel requiring that flags are preprocessor definitions, and additionally we cannot have a macro which declares another macro so we must define each flag macro directly.
Additionally, update the VMA userland testing vma_internal.h header to include these changes.
We also have to fix the parameters to the vma_flag_*_atomic() functions since VMA_MAYBE_GUARD_BIT is now of type vma_flag_t and sparse will complain otherwise.
We have to update some rather silly if-deffery found in mm/task_mmu.c which would otherwise break.
Finally, we update the rust binding helper as now it cannot auto-detect the flags at all.
--- fs/proc/task_mmu.c | 4 +- include/linux/mm.h | 384 +++++++++++++++++-------------- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- rust/bindings/bindings_helper.h | 25 ++ tools/testing/vma/vma_internal.h | 303 ++++++++++++++++++++---- 6 files changed, 504 insertions(+), 216 deletions(-)
fs/proc/task_mmu.c +2 -2
@@ -1183,10 +1183,10 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) [ilog2(VM_PKEY_BIT0)] = "", [ilog2(VM_PKEY_BIT1)] = "", [ilog2 (VM_PKEY_BIT2 )] ="" , -#if VM_PKEY_BIT3 +#if CONFIG_ARCH_PKEY_BITS > 3 [ilog2 (VM_PKEY_BIT3 )] ="" , #endif -#if VM_PKEY_BIT4 +#if CONFIG_ARCH_PKEY_BITS > 4 [ilog2(VM_PKEY_BIT4)] = "", #endif #endif /* CONFIG_ARCH_HAS_PKEYS */
include/linux/mm.h +217 -167
477 lines not on this page · raw message
mm/khugepaged.c +1 -1
@@ -1742,7 +1742,7 @@ static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)* obtained on guard region installation after the flag is set, so this * check being performed under this lock excludes races. */ -if (vma_flag_test_atomic (vma,VM_MAYBE_GUARD_BIT )) +if (vma_flag_test_atomic (vma,VMA_MAYBE_GUARD_BIT ))return false;return true;
mm/madvise.c +1 -1
@@ -1142,7 +1142,7 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)* acquire an mmap/VMA write lock to read it. All remaining readers may * or may not see the flag set, but we don't care. */ -vma_flag_set_atomic (vma,VM_MAYBE_GUARD_BIT ); +vma_flag_set_atomic (vma,VMA_MAYBE_GUARD_BIT );/* * If anonymous and we are establishing page tables the VMA ought to
rust/bindings/bindings_helper.h +25 -0
@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC =XA_FLAGS_ALLOC ;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 =XA_FLAGS_ALLOC1 ; +const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE =VM_MERGEABLE ; +const vm_flags_t RUST_CONST_HELPER_VM_READ =VM_READ ; +const vm_flags_t RUST_CONST_HELPER_VM_WRITE =VM_WRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_EXEC =VM_EXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_SHARED =VM_SHARED ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_PFNMAP =VM_PFNMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_IO =VM_IO ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTCOPY =VM_DONTCOPY ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTEXPAND =VM_DONTEXPAND ; +const vm_flags_t RUST_CONST_HELPER_VM_LOCKONFAULT =VM_LOCKONFAULT ; +const vm_flags_t RUST_CONST_HELPER_VM_ACCOUNT =VM_ACCOUNT ; +const vm_flags_t RUST_CONST_HELPER_VM_NORESERVE =VM_NORESERVE ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGETLB =VM_HUGETLB ; +const vm_flags_t RUST_CONST_HELPER_VM_SYNC =VM_SYNC ; +const vm_flags_t RUST_CONST_HELPER_VM_ARCH_1 =VM_ARCH_1 ; +const vm_flags_t RUST_CONST_HELPER_VM_WIPEONFORK =VM_WIPEONFORK ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTDUMP =VM_DONTDUMP ; +const vm_flags_t RUST_CONST_HELPER_VM_SOFTDIRTY =VM_SOFTDIRTY ; +const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =VM_MIXEDMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =VM_HUGEPAGE ; +const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =VM_NOHUGEPAGE ;#if IS_ENABLED (CONFIG_ANDROID_BINDER_IPC_RUST )#include "../../drivers/android/binder/rust_binder.h"
tools/testing/vma/vma_internal.h +258 -45
326 lines not on this page · raw message
Signature · 1 line
2.51.0
Alice Ryhl
maintainerRe: [PATCH v2 1/4] mm: declare VMA flags by bit
Quoted 24 lines · Lorenzo Stoakes
rust/bindings/bindings_helper.h +15
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC =XA_FLAGS_ALLOC ;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 =XA_FLAGS_ALLOC1 ; +const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE =VM_MERGEABLE ; +const vm_flags_t RUST_CONST_HELPER_VM_READ =VM_READ ; +const vm_flags_t RUST_CONST_HELPER_VM_WRITE =VM_WRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_EXEC =VM_EXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_SHARED =VM_SHARED ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_PFNMAP =VM_PFNMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_IO =VM_IO ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTCOPY =VM_DONTCOPY ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTEXPAND =VM_DONTEXPAND ; +const vm_flags_t RUST_CONST_HELPER_VM_LOCKONFAULT =VM_LOCKONFAULT ; +const vm_flags_t RUST_CONST_HELPER_VM_ACCOUNT =VM_ACCOUNT ;
rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 136
Quoted 10 lines
rust/bindings/bindings_helper.h +10
-0+const vm_flags_t RUST_CONST_HELPER_VM_NORESERVE =VM_NORESERVE ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGETLB =VM_HUGETLB ; +const vm_flags_t RUST_CONST_HELPER_VM_SYNC =VM_SYNC ; +const vm_flags_t RUST_CONST_HELPER_VM_ARCH_1 =VM_ARCH_1 ; +const vm_flags_t RUST_CONST_HELPER_VM_WIPEONFORK =VM_WIPEONFORK ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTDUMP =VM_DONTDUMP ; +const vm_flags_t RUST_CONST_HELPER_VM_SOFTDIRTY =VM_SOFTDIRTY ; +const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =VM_MIXEDMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =VM_HUGEPAGE ; +const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =VM_NOHUGEPAGE ;
I got this error:
error[E0428]: the name VM_SOFTDIRTY is defined multiple times
--> rust/bindings/bindings_generated.rs:115967:1
|
13440 | pub const VM_SOFTDIRTY: u32 = 0;
| -------------------------------- previous definition of the value `VM_SOFTDIRTY` here
...
115967 | pub const VM_SOFTDIRTY: vm_flags_t = 0;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `VM_SOFTDIRTY` redefined here
| = note: VM_SOFTDIRTY must be defined only once in the value namespace of this module
Please add the constants in rust/bindgen_parameters next to ARCH_KMALLOC_MINALIGN to avoid this error. This ensures that only the version from bindings_helper.h is generated.
Alice
Re: [PATCH v2 1/4] mm: declare VMA flags by bit
Quoted 47 lines · Alice Ryhl
Quoted 24 lines · Lorenzo Stoakes
rust/bindings/bindings_helper.h +15
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC =XA_FLAGS_ALLOC ;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 =XA_FLAGS_ALLOC1 ; +const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE =VM_MERGEABLE ; +const vm_flags_t RUST_CONST_HELPER_VM_READ =VM_READ ; +const vm_flags_t RUST_CONST_HELPER_VM_WRITE =VM_WRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_EXEC =VM_EXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_SHARED =VM_SHARED ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_PFNMAP =VM_PFNMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_IO =VM_IO ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTCOPY =VM_DONTCOPY ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTEXPAND =VM_DONTEXPAND ; +const vm_flags_t RUST_CONST_HELPER_VM_LOCKONFAULT =VM_LOCKONFAULT ; +const vm_flags_t RUST_CONST_HELPER_VM_ACCOUNT =VM_ACCOUNT ;rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 136
Quoted 10 lines
rust/bindings/bindings_helper.h +10
-0+const vm_flags_t RUST_CONST_HELPER_VM_NORESERVE =VM_NORESERVE ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGETLB =VM_HUGETLB ; +const vm_flags_t RUST_CONST_HELPER_VM_SYNC =VM_SYNC ; +const vm_flags_t RUST_CONST_HELPER_VM_ARCH_1 =VM_ARCH_1 ; +const vm_flags_t RUST_CONST_HELPER_VM_WIPEONFORK =VM_WIPEONFORK ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTDUMP =VM_DONTDUMP ; +const vm_flags_t RUST_CONST_HELPER_VM_SOFTDIRTY =VM_SOFTDIRTY ; +const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =VM_MIXEDMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =VM_HUGEPAGE ; +const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =VM_NOHUGEPAGE ;I got this error:
error[E0428]: the name
VM_SOFTDIRTYis defined multiple times--> rust/bindings/bindings_generated.rs:115967:1 | 13440 | pub const VM_SOFTDIRTY: u32 = 0; | -------------------------------- previous definition of the value `VM_SOFTDIRTY` here ... 115967 | pub const VM_SOFTDIRTY: vm_flags_t = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `VM_SOFTDIRTY` redefined here |
Quoted 2 lines
= note:
VM_SOFTDIRTYmust be defined only once in the value namespace of this module
That's odd, obviously I build tested this and didn't get the same error.
Be good to know what config options to enable for testing for rust. I repro'd the previously reported issues, and new ones since I'm now declaring these values consistently using BIT().
But in my build locally, no errors with LLVM=1 and CONFIG_RUST=y.
Quoted 3 lines
Please add the constants in
rust/bindgen_parametersnext toARCH_KMALLOC_MINALIGNto avoid this error. This ensures that only the version frombindings_helper.his generated.
As in
--block-list-item <VM_blah> for every flag?
Quoted 2 lines
Alice
Thanks, Lorenzo
Alice Ryhl
maintainerRe: [PATCH v2 1/4] mm: declare VMA flags by bit
Quoted 52 lines · Lorenzo Stoakes
Quoted 47 lines · Alice Ryhl
Quoted 24 lines · Lorenzo Stoakes
rust/bindings/bindings_helper.h +15
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC =XA_FLAGS_ALLOC ;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 =XA_FLAGS_ALLOC1 ; +const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE =VM_MERGEABLE ; +const vm_flags_t RUST_CONST_HELPER_VM_READ =VM_READ ; +const vm_flags_t RUST_CONST_HELPER_VM_WRITE =VM_WRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_EXEC =VM_EXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_SHARED =VM_SHARED ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_PFNMAP =VM_PFNMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_IO =VM_IO ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTCOPY =VM_DONTCOPY ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTEXPAND =VM_DONTEXPAND ; +const vm_flags_t RUST_CONST_HELPER_VM_LOCKONFAULT =VM_LOCKONFAULT ; +const vm_flags_t RUST_CONST_HELPER_VM_ACCOUNT =VM_ACCOUNT ;rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 136
Quoted 10 lines
rust/bindings/bindings_helper.h +10
-0+const vm_flags_t RUST_CONST_HELPER_VM_NORESERVE =VM_NORESERVE ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGETLB =VM_HUGETLB ; +const vm_flags_t RUST_CONST_HELPER_VM_SYNC =VM_SYNC ; +const vm_flags_t RUST_CONST_HELPER_VM_ARCH_1 =VM_ARCH_1 ; +const vm_flags_t RUST_CONST_HELPER_VM_WIPEONFORK =VM_WIPEONFORK ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTDUMP =VM_DONTDUMP ; +const vm_flags_t RUST_CONST_HELPER_VM_SOFTDIRTY =VM_SOFTDIRTY ; +const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =VM_MIXEDMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =VM_HUGEPAGE ; +const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =VM_NOHUGEPAGE ;I got this error:
error[E0428]: the name
VM_SOFTDIRTYis defined multiple times--> rust/bindings/bindings_generated.rs:115967:1 | 13440 | pub const VM_SOFTDIRTY: u32 = 0; | -------------------------------- previous definition of the value `VM_SOFTDIRTY` here ... 115967 | pub const VM_SOFTDIRTY: vm_flags_t = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `VM_SOFTDIRTY` redefined here |Quoted 2 lines
= note:
VM_SOFTDIRTYmust be defined only once in the value namespace of this module
Quoted 7 lines
That's odd, obviously I build tested this and didn't get the same error.
Be good to know what config options to enable for testing for rust. I repro'd the previously reported issues, and new ones since I'm now declaring these values consistently using
BIT().But in my build locally, no errors with LLVM=1 and
CONFIG_RUST=y.
I got this error because my config defines VM_SOFTDIRTY as VM_NONE, which bindgen can resolve to zero. You probably have a config where it's defined using a function-like macro, so bindgen did not generate a duplicate for you.
Quoted 7 lines
Quoted 3 lines
Please add the constants in
rust/bindgen_parametersnext toARCH_KMALLOC_MINALIGNto avoid this error. This ensures that only the version frombindings_helper.his generated.As in
--block-list-item <
VM_blah> for every flag?
Yes.
Alice
Re: [PATCH v2 1/4] mm: declare VMA flags by bit
Quoted 60 lines · Alice Ryhl
Quoted 58 lines · Lorenzo Stoakes
Quoted 47 lines · Alice Ryhl
Quoted 24 lines · Lorenzo Stoakes
rust/bindings/bindings_helper.h +15
-0@@ -108,7 +108,32 @@ const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC =XA_FLAGS_ALLOC ;const gfp_t RUST_CONST_HELPER_XA_FLAGS_ALLOC1 =XA_FLAGS_ALLOC1 ; +const vm_flags_t RUST_CONST_HELPER_VM_MERGEABLE =VM_MERGEABLE ; +const vm_flags_t RUST_CONST_HELPER_VM_READ =VM_READ ; +const vm_flags_t RUST_CONST_HELPER_VM_WRITE =VM_WRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_EXEC =VM_EXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_SHARED =VM_SHARED ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYREAD =VM_MAYREAD ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYWRITE =VM_MAYWRITE ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYEXEC =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_MAYSHARE =VM_MAYEXEC ; +const vm_flags_t RUST_CONST_HELPER_VM_PFNMAP =VM_PFNMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_IO =VM_IO ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTCOPY =VM_DONTCOPY ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTEXPAND =VM_DONTEXPAND ; +const vm_flags_t RUST_CONST_HELPER_VM_LOCKONFAULT =VM_LOCKONFAULT ; +const vm_flags_t RUST_CONST_HELPER_VM_ACCOUNT =VM_ACCOUNT ;rust/bindings/bindings_helper.h const xa_mark_t RUST_CONST_HELPER_XA_PRESENT = XA_PRESENT; · line 136
Quoted 10 lines
rust/bindings/bindings_helper.h +10
-0+const vm_flags_t RUST_CONST_HELPER_VM_NORESERVE =VM_NORESERVE ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGETLB =VM_HUGETLB ; +const vm_flags_t RUST_CONST_HELPER_VM_SYNC =VM_SYNC ; +const vm_flags_t RUST_CONST_HELPER_VM_ARCH_1 =VM_ARCH_1 ; +const vm_flags_t RUST_CONST_HELPER_VM_WIPEONFORK =VM_WIPEONFORK ; +const vm_flags_t RUST_CONST_HELPER_VM_DONTDUMP =VM_DONTDUMP ; +const vm_flags_t RUST_CONST_HELPER_VM_SOFTDIRTY =VM_SOFTDIRTY ; +const vm_flags_t RUST_CONST_HELPER_VM_MIXEDMAP =VM_MIXEDMAP ; +const vm_flags_t RUST_CONST_HELPER_VM_HUGEPAGE =VM_HUGEPAGE ; +const vm_flags_t RUST_CONST_HELPER_VM_NOHUGEPAGE =VM_NOHUGEPAGE ;I got this error:
error[E0428]: the name
VM_SOFTDIRTYis defined multiple times--> rust/bindings/bindings_generated.rs:115967:1 | 13440 | pub const VM_SOFTDIRTY: u32 = 0; | -------------------------------- previous definition of the value `VM_SOFTDIRTY` here ... 115967 | pub const VM_SOFTDIRTY: vm_flags_t = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `VM_SOFTDIRTY` redefined here |Quoted 2 lines
= note:
VM_SOFTDIRTYmust be defined only once in the value namespace of this moduleThat's odd, obviously I build tested this and didn't get the same error.
Be good to know what config options to enable for testing for rust. I repro'd the previously reported issues, and new ones since I'm now declaring these values consistently using
BIT().
Quoted 6 lines
Quoted 1 line
But in my build locally, no errors with LLVM=1 and
CONFIG_RUST=y.I got this error because my config defines
VM_SOFTDIRTYasVM_NONE, which bindgen can resolve to zero. You probably have a config where it's defined using a function-like macro, so bindgen did not generate a duplicate for you.
Ugh yeah of course, damn.
Quoted 10 lines
Quoted 8 lines
Quoted 4 lines
Please add the constants in
rust/bindgen_parametersnext toARCH_KMALLOC_MINALIGNto avoid this error. This ensures that only the version frombindings_helper.his generated.As in
--block-list-item <
VM_blah> for every flag?Yes.
OK will send a fixpatch, better to add them all to be safe.
Bit ugly but we can fix this up later when I add in the actual accessor helpers.
Quoted 3 lines
Alice
Thanks, Lorenzo
Re: [PATCH v2 1/4] mm: declare VMA flags by bit
In reply to Lorenzo StoakesHi Andrew,
Please apply this fix-patch to solve an issue with the patch accidentally causing duplication in rust bindgen when a VMA flag resolves to something bindgen can generate itself.
To fix it, we simply blacklist all the VMA flags used by rust from bindgen auto-generating.
I repro'd the issue locally thanks to Alice for reporting and giving insight into the issue + explaining how to fix it! :)
Thanks, Lorenzo
----8<----
From f441480340ff608869f3655b2371ca70c77eb82b Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <[email protected]>
Date: Fri, 14 Nov 2025 14:19:04 +0000
Subject: [PATCH] fixup
--- rust/bindgen_parameters | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
rust/bindgen_parameters +25 -0
@@ -35,6 +35,31 @@ # recognized, block generation of the non-helper constants. --blocklist-item ARCH_SLAB_MINALIGN --blocklist-item ARCH_KMALLOC_MINALIGN +--blocklist-item VM_MERGEABLE +--blocklist-item VM_READ +--blocklist-item VM_WRITE +--blocklist-item VM_EXEC +--blocklist-item VM_SHARED +--blocklist-item VM_MAYREAD +--blocklist-item VM_MAYWRITE +--blocklist-item VM_MAYEXEC +--blocklist-item VM_MAYEXEC +--blocklist-item VM_PFNMAP +--blocklist-item VM_IO +--blocklist-item VM_DONTCOPY +--blocklist-item VM_DONTEXPAND +--blocklist-item VM_LOCKONFAULT +--blocklist-item VM_ACCOUNT +--blocklist-item VM_NORESERVE +--blocklist-item VM_HUGETLB +--blocklist-item VM_SYNC +--blocklist-item VM_ARCH_1 +--blocklist-item VM_WIPEONFORK +--blocklist-item VM_DONTDUMP +--blocklist-item VM_SOFTDIRTY +--blocklist-item VM_MIXEDMAP +--blocklist-item VM_HUGEPAGE +--blocklist-item VM_NOHUGEPAGE # Structs should implement `Zeroable` when all of their fields do. --with-derive-custom-struct .*=MaybeZeroable
--
2.51.0
kernel test robot
build botRe: [PATCH v2 1/4] mm: declare VMA flags by bit
In reply to Lorenzo Stoakeskernel test robot noticed the following build errors:
Hi Lorenzo,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on next-20251114]
[cannot apply to rust/rust-next tip/sched/core brauner-vfs/vfs.all kees/for-next/execve linus/master v6.18-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/mm-declare-VMA-flags-by-bit/20251114-213237 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/6289d60b6731ea7a111c87c87fb8486881151c25.1763126447.git.lorenzo.stoakes%40oracle.com patch subject: [PATCH v2 1/4] mm: declare VMA flags by bit config: m68k-allnoconfig (https://download.01.org/0day-ci/archive/20251114/[email protected]/config) compiler: m68k-linux-gcc (GCC) 15.1.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251114/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
In file included from kernel/sched/sched.h:46,
from kernel/sched/rq-offsets.c:5:
include/linux/mm.h: In function 'is_nommu_shared_mapping':
>> include/linux/mm.h:1734:39: error: 'VM_MAYOVERLAY' undeclared (first use in this function); did you mean 'VMA_MAYOVERLAY_BIT'?
1734 | return flags & (VM_MAYSHARE | VM_MAYOVERLAY);
| ^~~~~~~~~~~~~
| VMA_MAYOVERLAY_BIT include/linux/mm.h:1734:39: note: each undeclared identifier is reported only once for each function it appears in make[3]: *** [scripts/Makefile.build:182: kernel/sched/rq-offsets.s] Error 1
make[3]: Target 'prepare' not remade because of errors.
make[2]: *** [Makefile:1280: prepare0] Error 2
make[2]: Target 'prepare' not remade because of errors.
make[1]: *** [Makefile:248: __sub-make] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:248: __sub-make] Error 2
make: Target 'prepare' not remade because of errors.
vim +1734 include/linux/mm.h
97a7e4733b9b22 Peter Xu 2021-03-12 1722
fc4f4be9b5271e David Hildenbrand 2023-01-02 1723 #ifndef CONFIG_MMU
fc4f4be9b5271e David Hildenbrand 2023-01-02 1724 static inline bool is_nommu_shared_mapping(vm_flags_t flags)
fc4f4be9b5271e David Hildenbrand 2023-01-02 1725 {
fc4f4be9b5271e David Hildenbrand 2023-01-02 1726 /*
fc4f4be9b5271e David Hildenbrand 2023-01-02 1727 * NOMMU shared mappings are ordinary MAP_SHARED mappings and selected
fc4f4be9b5271e David Hildenbrand 2023-01-02 1728 * R/O MAP_PRIVATE file mappings that are an effective R/O overlay of
fc4f4be9b5271e David Hildenbrand 2023-01-02 1729 * a file mapping. R/O MAP_PRIVATE mappings might still modify
fc4f4be9b5271e David Hildenbrand 2023-01-02 1730 * underlying memory if ptrace is active, so this is only possible if
fc4f4be9b5271e David Hildenbrand 2023-01-02 1731 * ptrace does not apply. Note that there is no mprotect() to upgrade
fc4f4be9b5271e David Hildenbrand 2023-01-02 1732 * write permissions later.
fc4f4be9b5271e David Hildenbrand 2023-01-02 1733 */
b6b7a8faf05c70 David Hildenbrand 2023-01-02 @1734 return flags & (VM_MAYSHARE | VM_MAYOVERLAY);
fc4f4be9b5271e David Hildenbrand 2023-01-02 1735 }
fc4f4be9b5271e David Hildenbrand 2023-01-02 1736 #endiffc4f4be9b5271e David Hildenbrand 2023-01-02 1737
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
kernel test robot
build botRe: [PATCH v2 1/4] mm: declare VMA flags by bit
In reply to Lorenzo Stoakeskernel test robot noticed the following build errors:
Hi Lorenzo,
kernel test robot noticed the following build errors:
[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on next-20251114]
[cannot apply to rust/rust-next tip/sched/core brauner-vfs/vfs.all kees/for-next/execve linus/master v6.18-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Lorenzo-Stoakes/mm-declare-VMA-flags-by-bit/20251114-213237 base: https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git mm-everything patch link: https://lore.kernel.org/r/6289d60b6731ea7a111c87c87fb8486881151c25.1763126447.git.lorenzo.stoakes%40oracle.com patch subject: [PATCH v2 1/4] mm: declare VMA flags by bit config: arm-allnoconfig (https://download.01.org/0day-ci/archive/20251114/[email protected]/config) compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 0bba1e76581bad04e7d7f09f5115ae5e2989e0d9) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251114/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
In file included from arch/arm/kernel/asm-offsets.c:14:
>> include/linux/mm.h:1734:32: error: use of undeclared identifier 'VM_MAYOVERLAY'
1734 | return flags & (VM_MAYSHARE | VM_MAYOVERLAY);
| ^~~~~~~~~~~~~ 1 error generated.
make[3]: *** [scripts/Makefile.build:182: arch/arm/kernel/asm-offsets.s] Error 1 make[3]: Target 'prepare' not remade because of errors.
make[2]: *** [Makefile:1280: prepare0] Error 2
make[2]: Target 'prepare' not remade because of errors.
make[1]: *** [Makefile:248: __sub-make] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:248: __sub-make] Error 2
make: Target 'prepare' not remade because of errors.
vim +/VM_MAYOVERLAY +1734 include/linux/mm.h
97a7e4733b9b22 Peter Xu 2021-03-12 1722
fc4f4be9b5271e David Hildenbrand 2023-01-02 1723 #ifndef CONFIG_MMU
fc4f4be9b5271e David Hildenbrand 2023-01-02 1724 static inline bool is_nommu_shared_mapping(vm_flags_t flags)
fc4f4be9b5271e David Hildenbrand 2023-01-02 1725 {
fc4f4be9b5271e David Hildenbrand 2023-01-02 1726 /*
fc4f4be9b5271e David Hildenbrand 2023-01-02 1727 * NOMMU shared mappings are ordinary MAP_SHARED mappings and selected
fc4f4be9b5271e David Hildenbrand 2023-01-02 1728 * R/O MAP_PRIVATE file mappings that are an effective R/O overlay of
fc4f4be9b5271e David Hildenbrand 2023-01-02 1729 * a file mapping. R/O MAP_PRIVATE mappings might still modify
fc4f4be9b5271e David Hildenbrand 2023-01-02 1730 * underlying memory if ptrace is active, so this is only possible if
fc4f4be9b5271e David Hildenbrand 2023-01-02 1731 * ptrace does not apply. Note that there is no mprotect() to upgrade
fc4f4be9b5271e David Hildenbrand 2023-01-02 1732 * write permissions later.
fc4f4be9b5271e David Hildenbrand 2023-01-02 1733 */
b6b7a8faf05c70 David Hildenbrand 2023-01-02 @1734 return flags & (VM_MAYSHARE | VM_MAYOVERLAY);
fc4f4be9b5271e David Hildenbrand 2023-01-02 1735 }
fc4f4be9b5271e David Hildenbrand 2023-01-02 1736 #endiffc4f4be9b5271e David Hildenbrand 2023-01-02 1737
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Re: [PATCH v2 1/4] mm: declare VMA flags by bit
In reply to Lorenzo StoakesHi Andrew,
In typical fashion nommu has caused a problem. Sorry to send a couple in quick succession here, but nommu will nommu... :)
Thanks, Lorenzo
----8<----
From b14b98a2e78a06c6a3ff790bc2c188be94202e30 Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <[email protected]>
Date: Fri, 14 Nov 2025 15:32:14 +0000
Subject: [PATCH] nommu fixup
--- include/linux/mm.h | 1 + 1 file changed, 1 insertion(+)
include/linux/mm.h +1 -0
@@ -409,6 +409,7 @@ enum {#define VM_UFFD_MISSING INIT_VM_FLAG(UFFD_MISSING)#else #define VM_UFFD_MISSING VM_NONE +#define VM_MAYOVERLAY INIT_VM_FLAG(MAYOVERLAY)#endif #define VM_PFNMAP INIT_VM_FLAG(PFNMAP)#define VM_MAYBE_GUARD INIT_VM_FLAG(MAYBE_GUARD)
--
2.51.0
Re: [PATCH v2 1/4] mm: declare VMA flags by bit
In reply to Lorenzo StoakesHi Andrew,
Sorry to be a pain, seems build bots are sleeping on parisc32/64 as there was some accidental duplication of VM_STACK_EARLY when CONFIG_STACK_GROWSUP is specified (currently only a parisc thing :).
The attached fix-patch fixes this and some broken whitespace.
Many thanks to David H. who noticed this and pinged me off-list!
Cheers, Lorenzo
----8<----
From d706def8a4511b42bc7c7da0a01a3f30cd054e6e Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <[email protected]>
Date: Thu, 20 Nov 2025 14:23:13 +0000
Subject: [PATCH] fixup
--- include/linux/mm.h | 8 -------- 1 file changed, 8 deletions(-)
include/linux/mm.h +0 -8
@@ -529,14 +529,6 @@ enum {#define VM_STARTGAP_FLAGS (VM_GROWSDOWN | VM_SHADOW_STACK) - - -#ifdef CONFIG_STACK_GROWSUP -#define VM_STACK_EARLY VMA_BIT(VMA_STACK_EARLY_BIT) -#else -#define VM_STACK_EARLY VM_NONE -#endif -#ifdef CONFIG_MSEAL_SYSTEM_MAPPINGS #define VM_SEALED_SYSMAP VM_SEALED#else
--
2.51.2
PATCH v2 2/4 mm: simplify and rename mm flags function for clarity
In reply to Lorenzo StoakesThe __mm_flags_set_word() function is slightly ambiguous - we use 'set' to refer to setting individual bits (such as in mm_flags_set()) but here we use it to refer to overwriting the value altogether.
Rename it to __mm_flags_overwrite_word() to eliminate this ambiguity.
We additionally simplify the functions, eliminating unnecessary bitmap_xxx() operations (the compiler would have optimised these out but it's worth being as clear as we can be here).
--- include/linux/mm_types.h | 14 +++++--------- kernel/fork.c | 4 ++-- 2 files changed, 7 insertions(+), 11 deletions(-)
include/linux/mm_types.h +5 -9
@@ -1314,15 +1314,13 @@ struct mm_struct {unsigned long cpu_bitmap[]; }; -/* Set the first system word of mm flags, non-atomically. */ -static inline void __mm_flags_set_word (struct mm_struct *mm,unsigned long value) +/* Copy value to the first system word of mm flags, non-atomically. */ +static inline void __mm_flags_overwrite_word (struct mm_struct *mm,unsigned long value) { -unsigned long *bitmap =ACCESS_PRIVATE (&mm->flags, __mm_flags); - -bitmap_copy (bitmap, &value,BITS_PER_LONG ); + *ACCESS_PRIVATE (&mm->flags, __mm_flags) = value; } -/* Obtain a read-only view of the bitmap. */ +/* Obtain a read-only view of the mm flags bitmap. */ static inline const unsigned long *__mm_flags_get_bitmap (const struct mm_struct *mm) {return (const unsigned long *)ACCESS_PRIVATE (&mm->flags, __mm_flags);
@@ -1331,9 +1329,7 @@ static inline const unsigned long *__mm_flags_get_bitmap(const struct mm_struct/* Read the first system word of mm flags, non-atomically. */ static inline unsigned long __mm_flags_get_word (const struct mm_struct *mm) { -const unsigned long *bitmap =__mm_flags_get_bitmap (mm); - -return bitmap_read (bitmap,0 ,BITS_PER_LONG ); +return *__mm_flags_get_bitmap (mm); }/*
kernel/fork.c +2 -2
@@ -1061,10 +1061,10 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,if (current->mm) {unsigned long flags =__mm_flags_get_word (current->mm); -__mm_flags_set_word (mm,mmf_init_legacy_flags (flags)); +__mm_flags_overwrite_word (mm,mmf_init_legacy_flags (flags)); mm->def_flags = current->mm->def_flags &VM_INIT_DEF_MASK ; }else { -__mm_flags_set_word (mm, default_dump_filter); +__mm_flags_overwrite_word (mm, default_dump_filter); mm->def_flags =0 ; }
Signature · 1 line
2.51.0
PATCH v2 3/4 tools/testing/vma: eliminate dependency on vma->__vm_flags
In reply to Lorenzo StoakesThe userland VMA test code relied on an internal implementation detail - the existence of vma->__vm_flags to directly access VMA flags. There is no need to do so when we have the vm_flags_*() helper functions available.
This is both ugly, but also a subsequent commit will eliminate this field altogether so this will shortly become broken.
This patch has us utilise the helper functions instead.
--- tools/testing/vma/vma.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
tools/testing/vma/vma.c +10 -10
@@ -69,18 +69,18 @@ static struct vm_area_struct *alloc_vma(struct mm_struct *mm, pgoff_t pgoff, vm_flags_t vm_flags) { -struct vm_area_struct *ret =vm_area_alloc (mm); +struct vm_area_struct *vma =vm_area_alloc (mm); -if (ret ==NULL ) +if (vma ==NULL )return NULL ; - ret->vm_start = start; - ret->vm_end = end; - ret->vm_pgoff = pgoff; - ret->__vm_flags = vm_flags; -vma_assert_detached (ret); + vma->vm_start = start; + vma->vm_end = end; + vma->vm_pgoff = pgoff; +vm_flags_reset (vma, vm_flags); +vma_assert_detached (vma); -return ret; +return vma; }/* Helper function to allocate a VMA and link it to the tree. */
@@ -713,7 +713,7 @@ static bool test_vma_merge_special_flags(void)for (i =0 ; i <ARRAY_SIZE (special_flags); i++) {vm_flags_t special_flag = special_flags[i]; - vma_left->__vm_flags = vm_flags | special_flag; +vm_flags_reset (vma_left, vm_flags | special_flag); vmg.vm_flags = vm_flags | special_flag; vma =merge_new (&vmg);ASSERT_EQ (vma,NULL );
@@ -735,7 +735,7 @@ static bool test_vma_merge_special_flags(void)for (i =0 ; i <ARRAY_SIZE (special_flags); i++) {vm_flags_t special_flag = special_flags[i]; - vma_left->__vm_flags = vm_flags | special_flag; +vm_flags_reset (vma_left, vm_flags | special_flag); vmg.vm_flags = vm_flags | special_flag; vma =merge_existing (&vmg);ASSERT_EQ (vma,NULL );
Signature · 1 line
2.51.0
Re: [PATCH v2 3/4] tools/testing/vma: eliminate dependency on vma->__vm_flags
Hi Andrew,
Some small silly issue here, for some reason I seemed to have vm_flags_reset() available from the VMA tests when I tested but err, that doesn't seem to be the case at all.
Again I realise this is in mm-stable so this might be fiddly so we might have to live with minor bisect pain :(
Cheers, Lorenzo
----8<----
From afe5af105e7d64e39a4280c7fc8b34ad67cf0db0 Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <[email protected]>
Date: Fri, 21 Nov 2025 17:25:18 +0000
Subject: [PATCH] tools/testing/vma: add missing stub
The vm_flags_reset() function is not available in the userland VMA tests, so add a stub which const-casts vma->vm_flags and avoids the upcoming removal of the vma->__vm_flags field.
--- tools/testing/vma/vma_internal.h | 7 +++++++ 1 file changed, 7 insertions(+)
tools/testing/vma/vma_internal.h +7 -0
@@ -1760,4 +1760,11 @@ static inline int do_munmap(struct mm_struct *, unsigned long, size_t, return 0; } +static inline void vm_flags_reset (struct vm_area_struct *vma,vm_flags_t flags) +{ +vm_flags_t *dst = (vm_flags_t *)(&vma->vm_flags); + + *dst = flags; +} +#endif /* __MM_VMA_INTERNAL_H */
--
2.51.2
Re: [PATCH v2 3/4] tools/testing/vma: eliminate dependency on vma->__vm_flags
Hi Andrew,
It seems that the ordering of things has messed us up a bit here!
So this patch (3/4) currently introduces an issue where vm_flags_reset() is missing from the VMA userland tests.
Then 4/4, now with the vma_internal.h fixes in place, puts vm_flags_reset() back in place (this was my mistake in the series originally!).
But then this fix-patch, now applied as the latest patch from me in mm-new, breaks the tests again by duplicating this function :)
So, I'm not sure if too late for rebases - if not, then just squash this into 3/4.
If it is - then just drop this patch altogether and we'll live with this being broken for a single commit!
Cheers, Lorenzo
Quoted 44 lines · Lorenzo Stoakes
Hi Andrew,
Some small silly issue here, for some reason I seemed to have
vm_flags_reset()available from the VMA tests when I tested but err, that doesn't seem to be the case at all.Again I realise this is in mm-stable so this might be fiddly so we might have to live with minor bisect pain :(
Cheers, Lorenzo
----8<----
Fromafe5af105e7d64e39a4280c7fc8b34ad67cf0db0Mon Sep 17 00:00:00 2001
From: Lorenzo Stoakes <[email protected]>
Date: Fri, 21 Nov 2025 17:25:18 +0000
Subject: [PATCH]tools/testing/vma: add missing stubThe
vm_flags_reset()function is not available in the userland VMA tests, so add a stub which const-castsvma->vm_flagsand avoids the upcoming removal of thevma->__vm_flagsfield.Signed-off-by Lorenzo Stoakes <[email protected]>--- tools/testing/vma/vma_internal.h | 7 +++++++ 1 file changed, 7 insertions(+)tools/testing/vma/vma_internal.h +7
-1@@ -1760,4 +1760,11 @@ static inline int do_munmap(struct mm_struct *, unsigned long, size_t, return 0; } +static inline void vm_flags_reset (struct vm_area_struct *vma,vm_flags_t flags) +{ +vm_flags_t *dst = (vm_flags_t *)(&vma->vm_flags); + + *dst = flags; +} +#endif /* __MM_VMA_INTERNAL_H */ --2.51.2
Andrew Morton
maintainerRe: [PATCH v2 3/4] tools/testing/vma: eliminate dependency on vma->__vm_flags
Quoted 8 lines · On Mon, 24 Nov 2025 12:43:18 +0000 Lorenzo Stoakes…
It seems that the ordering of things has messed us up a bit here!
So this patch (3/4) currently introduces an issue where
vm_flags_reset()is missing from the VMA userland tests.Then 4/4, now with the
vma_internal.hfixes in place, putsvm_flags_reset()back in place (this was my mistake in the series originally!).
Quoted 8 lines
But then this fix-patch, now applied as the latest patch from me in mm-new, breaks the tests again by duplicating this function :)
So, I'm not sure if too late for rebases - if not, then just squash this into 3/4.
If it is - then just drop this patch altogether and we'll live with this being broken for a single commit!
All confused. I dropped the whole series - please resend?
Re: [PATCH v2 3/4] tools/testing/vma: eliminate dependency on vma->__vm_flags
Quoted 13 lines · Andrew Morton
Quoted 11 lines · On Mon, 24 Nov 2025 12:43:18 +0000 Lorenzo Stoakes…
It seems that the ordering of things has messed us up a bit here!
So this patch (3/4) currently introduces an issue where
vm_flags_reset()is missing from the VMA userland tests.Then 4/4, now with the
vma_internal.hfixes in place, putsvm_flags_reset()back in place (this was my mistake in the series originally!).But then this fix-patch, now applied as the latest patch from me in mm-new, breaks the tests again by duplicating this function :)
Quoted 7 lines
Quoted 5 lines
So, I'm not sure if too late for rebases - if not, then just squash this into 3/4.
If it is - then just drop this patch altogether and we'll live with this being broken for a single commit!
All confused. I dropped the whole series - please resend?
Ack will do shortly.
PATCH v2 4/4 mm: introduce VMA flags bitmap type
In reply to Lorenzo StoakesIt is useful to transition to using a bitmap for VMA flags so we can avoid running out of flags, especially for 32-bit kernels which are constrained to 32 flags, necessitating some features to be limited to 64-bit kernels only.
By doing so, we remove any constraint on the number of VMA flags moving forwards no matter the platform and can decide in future to extend beyond 64 if required.
We start by declaring an opaque types, vma_flags_t (which resembles mm_struct flags of type mm_flags_t), setting it to precisely the same size as vm_flags_t, and place it in union with vm_flags in the VMA declaration.
We additionally update struct vm_area_desc equivalently placing the new opaque type in union with vm_flags.
This change therefore does not impact the size of struct vm_area_struct or struct vm_area_desc.
In order for the change to be iterative and to avoid impacting performance, we designate VM_xxx declared bitmap flag values as those which must exist in the first system word of the VMA flags bitmap.
We therefore declare vma_flags_clear_all(), vma_flags_overwrite_word(), vma_flags_overwrite_word(), vma_flags_overwrite_word_once(), vma_flags_set_word() and vma_flags_clear_word() in order to allow us to update the existing vm_flags_*() functions to utilise these helpers.
This is a stepping stone towards converting users to the VMA flags bitmap and behaves precisely as before.
By doing this, we can eliminate the existing private vma->__vm_flags field in the vma->vm_flags union and replace it with the newly introduced opaque type vma_flags, which we call flags so we refer to the new bitmap field as vma->flags.
We update vma_flag_[test, set]_atomic() to account for the change also.
We additionally update the VMA userland test declarations to implement the same changes there.
Finally, we update the rust code to reference vma->vm_flags on update rather than vma->__vm_flags which has been removed. This is safe for now, albeit it is implicitly performing a const cast.
Once we introduce flag helpers we can improve this more.
No functional change intended.
--- include/linux/mm.h | 18 ++-- include/linux/mm_types.h | 64 +++++++++++++- rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma_internal.h | 143 ++++++++++++++++++++++++++----- 4 files changed, 196 insertions(+), 31 deletions(-)
include/linux/mm.h +13 -5
@@ -919,7 +919,8 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)static inline void vm_flags_init (struct vm_area_struct *vma,vm_flags_t flags) { -ACCESS_PRIVATE (vma, __vm_flags) = flags; +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word (&vma->flags, flags); }/*
@@ -938,21 +939,26 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma, vm_flags_t flags) {vma_assert_write_locked (vma); -WRITE_ONCE (ACCESS_PRIVATE (vma, __vm_flags), flags); +/* +* The user should only be interested in avoiding reordering of +* assignment to the first word. +*/ +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word_once (&vma->flags, flags); }static inline void vm_flags_set (struct vm_area_struct *vma,vm_flags_t flags) {vma_start_write (vma); -ACCESS_PRIVATE (vma, __vm_flags) |= flags; +vma_flags_set_word (&vma->flags, flags); }static inline void vm_flags_clear (struct vm_area_struct *vma,vm_flags_t flags) {vma_start_write (vma); -ACCESS_PRIVATE (vma, __vm_flags) &= ~flags; +vma_flags_clear_word (&vma->flags, flags); }/*
@@ -995,12 +1001,14 @@ static inline bool __vma_flag_atomic_valid(struct vm_area_struct *vma,static inline void vma_flag_set_atomic (struct vm_area_struct *vma,vma_flag_t bit) { +unsigned long *bitmap =ACCESS_PRIVATE (&vma->flags, __vma_flags); +/* mmap read lock/VMA read lock must be held. */ if (!rwsem_is_locked (&vma->vm_mm->mmap_lock))vma_assert_locked (vma);if (__vma_flag_atomic_valid (vma, bit)) -set_bit ((__force int )bit, &ACCESS_PRIVATE (vma, __vm_flags)); +set_bit ((__force int )bit, bitmap); }/*
include/linux/mm_types.h +62 -2
91 lines not on this page · raw message
rust/kernel/mm/virt.rs +1 -1
@@ -250,7 +250,7 @@ unsafe fn update_flags(&self, set: vm_flags_t, unset: vm_flags_t) {// SAFETY: This is not a data race: the vma is undergoing initial setup, so it's not yet // shared. Additionally, `VmaNew` is `!Sync`, so it cannot be used to write in parallel. // The caller promises that this does not set the flags to an invalid value. -unsafe { (*self.as_ptr ()).__bindgen_anon_2.__vm_flags = flags }; +unsafe { (*self.as_ptr ()).__bindgen_anon_2.vm_flags = flags }; }/// Set the `VM_MIXEDMAP` flag on this vma.
tools/testing/vma/vma_internal.h +120 -23
179 lines not on this page · raw message
Signature · 1 line
2.51.0
Re: [PATCH v2 4/4] mm: introduce VMA flags bitmap type
As Vlastimil noticed, something has gone fairly horribly wrong here in the actual commit [0] vs. the patch here for tools/testing/vma/vma_internal.h.
We should only have the delta shown here, let me know if I need to help with a conflict resolution! :)
Thanks, Lorenzo
Quoted 420 lines · Lorenzo Stoakes
It is useful to transition to using a bitmap for VMA flags so we can avoid running out of flags, especially for 32-bit kernels which are constrained to 32 flags, necessitating some features to be limited to 64-bit kernels only.
By doing so, we remove any constraint on the number of VMA flags moving forwards no matter the platform and can decide in future to extend beyond 64 if required.
We start by declaring an opaque types,
vma_flags_t(which resemblesmm_structflags of typemm_flags_t), setting it to precisely the same size asvm_flags_t, and place it in union withvm_flagsin the VMA declaration.We additionally update struct
vm_area_descequivalently placing the new opaque type in union withvm_flags.This change therefore does not impact the size of struct
vm_area_structor structvm_area_desc.In order for the change to be iterative and to avoid impacting performance, we designate
VM_xxxdeclared bitmap flag values as those which must exist in the first system word of the VMA flags bitmap.We therefore declare
vma_flags_clear_all(),vma_flags_overwrite_word(),vma_flags_overwrite_word(),vma_flags_overwrite_word_once(),vma_flags_set_word()andvma_flags_clear_word()in order to allow us to update the existing vm_flags_*() functions to utilise these helpers.This is a stepping stone towards converting users to the VMA flags bitmap and behaves precisely as before.
By doing this, we can eliminate the existing private
vma->__vm_flagsfield in thevma->vm_flagsunion and replace it with the newly introduced opaque typevma_flags, which we call flags so we refer to the new bitmap field asvma->flags.We update vma_flag_[test, set]_atomic() to account for the change also.
We additionally update the VMA userland test declarations to implement the same changes there.
Finally, we update the rust code to reference
vma->vm_flagson update rather thanvma->__vm_flagswhich has been removed. This is safe for now, albeit it is implicitly performing a const cast.Once we introduce flag helpers we can improve this more.
No functional change intended.
Signed-off-by Lorenzo Stoakes <[email protected]>--- include/linux/mm.h | 18 ++-- include/linux/mm_types.h | 64 +++++++++++++- rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma_internal.h | 143 ++++++++++++++++++++++++++----- 4 files changed, 196 insertions(+), 31 deletions(-)include/linux/mm.h +13
-5@@ -919,7 +919,8 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm)static inline void vm_flags_init (struct vm_area_struct *vma,vm_flags_t flags) { -ACCESS_PRIVATE (vma, __vm_flags) = flags; +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word (&vma->flags, flags); }/* @@ -938,21 +939,26 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma, vm_flags_t flags) {vma_assert_write_locked (vma); -WRITE_ONCE (ACCESS_PRIVATE (vma, __vm_flags), flags); +/* +* The user should only be interested in avoiding reordering of +* assignment to the first word. +*/ +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word_once (&vma->flags, flags); }static inline void vm_flags_set (struct vm_area_struct *vma,vm_flags_t flags) {vma_start_write (vma); -ACCESS_PRIVATE (vma, __vm_flags) |= flags; +vma_flags_set_word (&vma->flags, flags); }static inline void vm_flags_clear (struct vm_area_struct *vma,vm_flags_t flags) {vma_start_write (vma); -ACCESS_PRIVATE (vma, __vm_flags) &= ~flags; +vma_flags_clear_word (&vma->flags, flags); }/* @@ -995,12 +1001,14 @@ static inline bool __vma_flag_atomic_valid(struct vm_area_struct *vma,static inline void vma_flag_set_atomic (struct vm_area_struct *vma,vma_flag_t bit) { +unsigned long *bitmap =ACCESS_PRIVATE (&vma->flags, __vma_flags); +/* mmap read lock/VMA read lock must be held. */ if (!rwsem_is_locked (&vma->vm_mm->mmap_lock))vma_assert_locked (vma);if (__vma_flag_atomic_valid (vma, bit)) -set_bit ((__force int )bit, &ACCESS_PRIVATE (vma, __vm_flags)); +set_bit ((__force int )bit, bitmap); }/* include/linux/mm_types.h +62
-2@@ -848,6 +848,15 @@ struct mmap_action { bool hide_from_rmap_until_complete :1; }; +/* +* Opaque type representing current VMA (vm_area_struct) flag state. Must be +* accessed via vma_flags_xxx() helper functions. +*/ +#define NUM_VMA_FLAG_BITS BITS_PER_LONG +typedef struct { + DECLARE_BITMAP(__vma_flags, NUM_VMA_FLAG_BITS); +}__private vma_flags_t ; +/* * Describes a VMA that is about to be mmap()'ed. Drivers may choose to * manipulate mutable fields which will cause those fields to be updated in the @@ -865,7 +874,10 @@ struct vm_area_desc {/* Mutable fields. Populated with initial state. */ pgoff_t pgoff;struct file *vm_file; -vm_flags_t vm_flags; +union { +vm_flags_t vm_flags; +vma_flags_t vma_flags; + };pgprot_t page_prot;/* Write-only fields. */ @@ -910,10 +922,12 @@ struct vm_area_struct {/* * Flags, see mm.h. * To modify use vm_flags_{init|reset|set|clear|mod} functions. +* Preferably, use vma_flags_xxx() functions. */ union { +/* Temporary while VMA flags are being converted. */ const vm_flags_t vm_flags; -vm_flags_t __private __vm_flags; +vma_flags_t flags; };#ifdef CONFIG_PER_VMA_LOCK @@ -994,6 +1008,52 @@ struct vm_area_struct {#endif } __randomize_layout; +/* Clears all bits in the VMA flags bitmap, non-atomically. */ +static inline void vma_flags_clear_all (vma_flags_t *flags) +{ +bitmap_zero (ACCESS_PRIVATE (flags, __vma_flags),NUM_VMA_FLAG_BITS ); +} + +/* +* Copy value to the first system word of VMA flags, non-atomically. +* +* IMPORTANT: This does not overwrite bytes past the first system word. The +* caller must account for this. +*/ +static inline void vma_flags_overwrite_word (vma_flags_t *flags,unsigned long value) +{ + *ACCESS_PRIVATE (flags, __vma_flags) = value; +} + +/* +* Copy value to the first system word of VMA flags ONCE, non-atomically. +* +* IMPORTANT: This does not overwrite bytes past the first system word. The +* caller must account for this. +*/ +static inline void vma_flags_overwrite_word_once (vma_flags_t *flags,unsigned long value) +{ +unsigned long *bitmap =ACCESS_PRIVATE (flags, __vma_flags); + +WRITE_ONCE (*bitmap, value); +} + +/* Update the first system word of VMA flags setting bits, non-atomically. */ +static inline void vma_flags_set_word (vma_flags_t *flags,unsigned long value) +{ +unsigned long *bitmap =ACCESS_PRIVATE (flags, __vma_flags); + + *bitmap |= value; +} + +/* Update the first system word of VMA flags clearing bits, non-atomically. */ +static inline void vma_flags_clear_word (vma_flags_t *flags,unsigned long value) +{ +unsigned long *bitmap =ACCESS_PRIVATE (flags, __vma_flags); + + *bitmap &= ~value; +} +#ifdef CONFIG_NUMA #define vma_policy (vma) ((vma)->vm_policy)#else rust/kernel/mm/virt.rs +1
-1@@ -250,7 +250,7 @@ unsafe fn update_flags(&self, set: vm_flags_t, unset: vm_flags_t) {// SAFETY: This is not a data race: the vma is undergoing initial setup, so it's not yet // shared. Additionally, `VmaNew` is `!Sync`, so it cannot be used to write in parallel. // The caller promises that this does not set the flags to an invalid value. -unsafe { (*self.as_ptr ()).__bindgen_anon_2.__vm_flags = flags }; +unsafe { (*self.as_ptr ()).__bindgen_anon_2.vm_flags = flags }; }/// Set the `VM_MIXEDMAP` flag on this vma. tools/testing/vma/vma_internal.h +120
-24@@ -528,6 +528,15 @@ typedef struct {__private DECLARE_BITMAP (__mm_flags,NUM_MM_FLAG_BITS ); } mm_flags_t; +/* +* Opaque type representing current VMA (vm_area_struct) flag state. Must be +* accessed via vma_flags_xxx() helper functions. +*/ +#define NUM_VMA_FLAG_BITS BITS_PER_LONG +typedef struct { + DECLARE_BITMAP(__vma_flags, NUM_VMA_FLAG_BITS); +}__private vma_flags_t ; +struct mm_struct {struct maple_tree mm_mt;int map_count;/* number of VMAs */ @@ -612,7 +621,10 @@ struct vm_area_desc {/* Mutable fields. Populated with initial state. */ pgoff_t pgoff;struct file *vm_file; -vm_flags_t vm_flags; +union { +vm_flags_t vm_flags; +vma_flags_t vma_flags; + };pgprot_t page_prot;/* Write-only fields. */ @@ -658,7 +670,7 @@ struct vm_area_struct {*/ union {const vm_flags_t vm_flags; -vm_flags_t __private __vm_flags; +vma_flags_t flags; };#ifdef CONFIG_PER_VMA_LOCK @@ -1372,26 +1384,6 @@ static inline bool may_expand_vm(struct mm_struct *mm, vm_flags_t flags,return true; } -static inline void vm_flags_init (struct vm_area_struct *vma, -vm_flags_t flags) -{ - vma->__vm_flags = flags; -} - -static inline void vm_flags_set (struct vm_area_struct *vma, -vm_flags_t flags) -{ -vma_start_write (vma); - vma->__vm_flags |= flags; -} - -static inline void vm_flags_clear (struct vm_area_struct *vma, -vm_flags_t flags) -{ -vma_start_write (vma); - vma->__vm_flags &= ~flags; -} -static inline int shmem_zero_setup (struct vm_area_struct *vma) {return 0 ;@@ -1548,13 +1540,118 @@ static inline void userfaultfd_unmap_complete(struct mm_struct *mm, { } -# define ACCESS_PRIVATE (p, member) ((p)->member) +#define ACCESS_PRIVATE (p, member) ((p)->member) + +#define bitmap_size (nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE) + +static __always_inline void bitmap_zero(unsigned long *dst, unsigned int nbits) +{ +unsigned int len =bitmap_size (nbits); + +if (small_const_nbits (nbits)) + *dst =0 ; +else +memset (dst,0 , len); +}static inline bool mm_flags_test (int flag,const struct mm_struct *mm) {return test_bit (flag,ACCESS_PRIVATE (&mm->flags, __mm_flags)); } +/* Clears all bits in the VMA flags bitmap, non-atomically. */ +static inline void vma_flags_clear_all (vma_flags_t *flags) +{ +bitmap_zero (ACCESS_PRIVATE (flags, __vma_flags),NUM_VMA_FLAG_BITS ); +} + +/* +* Copy value to the first system word of VMA flags, non-atomically. +* +* IMPORTANT: This does not overwrite bytes past the first system word. The +* caller must account for this. +*/ +static inline void vma_flags_overwrite_word (vma_flags_t *flags,unsigned long value) +{ + *ACCESS_PRIVATE (flags, __vma_flags) = value; +} + +/* +* Copy value to the first system word of VMA flags ONCE, non-atomically. +* +* IMPORTANT: This does not overwrite bytes past the first system word. The +* caller must account for this. +*/ +static inline void vma_flags_overwrite_word_once (vma_flags_t *flags,unsigned long value) +{ +unsigned long *bitmap =ACCESS_PRIVATE (flags, __vma_flags); + +WRITE_ONCE (*bitmap, value); +} + +/* Update the first system word of VMA flags setting bits, non-atomically. */ +static inline void vma_flags_set_word (vma_flags_t *flags,unsigned long value) +{ +unsigned long *bitmap =ACCESS_PRIVATE (flags, __vma_flags); + + *bitmap |= value; +} + +/* Update the first system word of VMA flags clearing bits, non-atomically. */ +static inline void vma_flags_clear_word (vma_flags_t *flags,unsigned long value) +{ +unsigned long *bitmap =ACCESS_PRIVATE (flags, __vma_flags); + + *bitmap &= ~value; +} + + +/* Use when VMA is not part of the VMA tree and needs no locking */ +static inline void vm_flags_init (struct vm_area_struct *vma, +vm_flags_t flags) +{ +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word (&vma->flags, flags); +} + +/* +* Use when VMA is part of the VMA tree and modifications need coordination +* Note: vm_flags_reset and vm_flags_reset_once do not lock the vma and +* it should be locked explicitly beforehand. +*/ +static inline void vm_flags_reset (struct vm_area_struct *vma, +vm_flags_t flags) +{ +vma_assert_write_locked (vma); +vm_flags_init (vma, flags); +} + +static inline void vm_flags_reset_once (struct vm_area_struct *vma, +vm_flags_t flags) +{ +vma_assert_write_locked (vma); +/* +* The user should only be interested in avoiding reordering of +* assignment to the first word. +*/ +vma_flags_clear_all (&vma->flags); +vma_flags_overwrite_word_once (&vma->flags, flags); +} + +static inline void vm_flags_set (struct vm_area_struct *vma, +vm_flags_t flags) +{ +vma_start_write (vma); +vma_flags_set_word (&vma->flags, flags); +} + +static inline void vm_flags_clear (struct vm_area_struct *vma, +vm_flags_t flags) +{ +vma_start_write (vma); +vma_flags_clear_word (&vma->flags, flags); +} +/* * Denies creating a writable executable mapping or gaining executable permissions. * -- 2.51.0
Andrew Morton
maintainerRe: [PATCH v2 4/4] mm: introduce VMA flags bitmap type
Quoted 5 lines · On Fri, 21 Nov 2025 17:44:43 +0000 Lorenzo Stoakes…
As Vlastimil noticed, something has gone fairly horribly wrong here in the actual commit [0] vs. the patch here for
tools/testing/vma/vma_internal.h.We should only have the delta shown here, let me know if I need to help with a conflict resolution! :)
OK, thanks, easy fix.
Re: [PATCH v2 4/4] mm: introduce VMA flags bitmap type
Quoted 9 lines · Andrew Morton
Quoted 5 lines · On Fri, 21 Nov 2025 17:44:43 +0000 Lorenzo Stoakes…
As Vlastimil noticed, something has gone fairly horribly wrong here in the actual commit [0] vs. the patch here for
tools/testing/vma/vma_internal.h.We should only have the delta shown here, let me know if I need to help with a conflict resolution! :)
OK, thanks, easy fix.
Perfect, thanks! :)
Cheers, Lorenzo
Quoted 56 lines · Lorenzo Stoakes
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
This is necessarily a highly iterative process given the extensive use of VMA flags throughout the kernel, so we start by performing basic steps.
Firstly, we declare VMA flags by bit number rather than by value, retaining the
VM_xxxfields but in terms of these newly introducedVMA_xxx_BITfields.While we are here, we use sparse annotations to ensure that, when dealing with VMA bit number parameters, we cannot be passed values which are not declared as such - providing some useful type safety.
We then introduce an opaque VMA flag type, much like the opaque
mm_structflag type introduced in commitbb6525f2f8c4("mm: add bitmapmm->flagsfield"), which we establish in union withvma->vm_flags(but still set at system word size meaning there is no functional or data type size change).We update the
vm_flags_xxx()helpers to use this new bitmap, introducing sensible helpers to do so.This series lays the foundation for further work to expand the use of bitmap VMA flags and eventually eliminate these arbitrary restrictions.
v2:
* Corrected kdoc forvma_flag_t.
* IntroducedDECLARE_VMA_BIT()as per Jason. We can't also declare the VMA flags in the enum as this breaks assumptions in the kernel, resulting in errors like 'enum constant in boolean context [-Werror=int-in-bool-context]'.
* Dropped the conversion patch - To make life simpler this cycle, let's just fixup the flag declarations and introduce the new field type and introduce vm_flags_*() changes. We can do more later.
* Split out VMA testingvma->__vm_flagschange.
* Fixed vma_flag_*_atomic() helper functions for sparse purposes to work withvma_flag_t.
* Fixed rust breakages as reported by Nico and help provided by Alice. For now we are doing a minimal fix, we can do a more substantial one once the VMA flag helper functions are introduced in an upcoming series.
Quoted 8 lines
v1:
https://lore.kernel.org/all/[email protected]/Lorenzo Stoakes (4):
mm: declare VMA flags by bit
mm: simplify and rename mm flags function for claritytools/testing/vma: eliminate dependency onvma->__vm_flags
mm: introduce VMA flags bitmap type
However something has happened to patch 4/4 in git, it has a very different tools/testing/vma/vma_internal.h:
Quoted 15 lines
fs/proc/task_mmu.c | 4 +- include/linux/mm.h | 400 +++++++++++++++------------ include/linux/mm_types.h | 78 +++++- kernel/fork.c | 4 +- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- rust/bindings/bindings_helper.h | 25 ++ rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma.c | 20 +- tools/testing/vma/vma_internal.h | 446 ++++++++++++++++++++++++++----- 10 files changed, 716 insertions(+), 267 deletions(-)--
2.51.0
Quoted 60 lines · Vlastimil Babka
Quoted 59 lines · Lorenzo Stoakes
We are in the rather silly situation that we are running out of VMA flags as they are currently limited to a system word in size.
This leads to absurd situations where we limit features to 64-bit architectures only because we simply do not have the ability to add a flag for 32-bit ones.
This is very constraining and leads to hacks or, in the worst case, simply an inability to implement features we want for entirely arbitrary reasons.
This also of course gives us something of a Y2K type situation in mm where we might eventually exhaust all of the VMA flags even on 64-bit systems.
This series lays the groundwork for getting away from this limitation by establishing VMA flags as a bitmap whose size we can increase in future beyond 64 bits if required.
This is necessarily a highly iterative process given the extensive use of VMA flags throughout the kernel, so we start by performing basic steps.
Firstly, we declare VMA flags by bit number rather than by value, retaining the
VM_xxxfields but in terms of these newly introducedVMA_xxx_BITfields.While we are here, we use sparse annotations to ensure that, when dealing with VMA bit number parameters, we cannot be passed values which are not declared as such - providing some useful type safety.
We then introduce an opaque VMA flag type, much like the opaque
mm_structflag type introduced in commitbb6525f2f8c4("mm: add bitmapmm->flagsfield"), which we establish in union withvma->vm_flags(but still set at system word size meaning there is no functional or data type size change).We update the
vm_flags_xxx()helpers to use this new bitmap, introducing sensible helpers to do so.This series lays the foundation for further work to expand the use of bitmap VMA flags and eventually eliminate these arbitrary restrictions.
v2:
* Corrected kdoc forvma_flag_t.
* IntroducedDECLARE_VMA_BIT()as per Jason. We can't also declare the VMA flags in the enum as this breaks assumptions in the kernel, resulting in errors like 'enum constant in boolean context [-Werror=int-in-bool-context]'.
* Dropped the conversion patch - To make life simpler this cycle, let's just fixup the flag declarations and introduce the new field type and introduce vm_flags_*() changes. We can do more later.
* Split out VMA testingvma->__vm_flagschange.
* Fixed vma_flag_*_atomic() helper functions for sparse purposes to work withvma_flag_t.
* Fixed rust breakages as reported by Nico and help provided by Alice. For now we are doing a minimal fix, we can do a more substantial one once the VMA flag helper functions are introduced in an upcoming series.
Quoted 7 lines
Quoted 5 lines
Lorenzo Stoakes (4):
mm: declare VMA flags by bit
mm: simplify and rename mm flags function for claritytools/testing/vma: eliminate dependency onvma->__vm_flags
mm: introduce VMA flags bitmap typeAcked-by Vlastimil Babka <[email protected]>
Thanks!
Quoted 5 lines
However something has happened to patch 4/4 in git, it has a very different
tools/testing/vma/vma_internal.h:
Yeah something has gone very wrong here :)
3/4 also has an issue annoyingly, I tested it locally with no issues but now it seems to have issues... but also it seems like it should _always_ have.
Anyway let me address each at a time I guess... :)
Quoted 17 lines
Quoted 16 lines
fs/proc/task_mmu.c | 4 +- include/linux/mm.h | 400 +++++++++++++++------------ include/linux/mm_types.h | 78 +++++- kernel/fork.c | 4 +- mm/khugepaged.c | 2 +- mm/madvise.c | 2 +- rust/bindings/bindings_helper.h | 25 ++ rust/kernel/mm/virt.rs | 2 +- tools/testing/vma/vma.c | 20 +- tools/testing/vma/vma_internal.h | 446 ++++++++++++++++++++++++++----- 10 files changed, 716 insertions(+), 267 deletions(-)--
2.51.0