[PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them

Lorenzo Stoakes posted 13 patches 2 weeks, 1 day ago
arch/x86/kernel/cpu/sgx/ioctl.c            |    2 +-
drivers/char/mem.c                         |    6 +-
drivers/dax/device.c                       |   10 +-
drivers/gpu/drm/drm_gem.c                  |    5 +-
drivers/gpu/drm/i915/gem/i915_gem_shmem.c  |    2 +-
drivers/gpu/drm/i915/gem/i915_gem_ttm.c    |    3 +-
drivers/gpu/drm/i915/gt/shmem_utils.c      |    3 +-
drivers/gpu/drm/ttm/tests/ttm_tt_test.c    |    2 +-
drivers/gpu/drm/ttm/ttm_backup.c           |    3 +-
drivers/gpu/drm/ttm/ttm_tt.c               |    2 +-
fs/aio.c                                   |    2 +-
fs/erofs/data.c                            |    5 +-
fs/ext4/file.c                             |    4 +-
fs/hugetlbfs/inode.c                       |   14 +-
fs/ntfs3/file.c                            |    2 +-
fs/orangefs/file.c                         |    4 +-
fs/ramfs/file-nommu.c                      |    2 +-
fs/resctrl/pseudo_lock.c                   |    2 +-
fs/romfs/mmap-nommu.c                      |    2 +-
fs/xfs/scrub/xfile.c                       |    3 +-
fs/xfs/xfs_buf_mem.c                       |    2 +-
fs/xfs/xfs_file.c                          |    4 +-
fs/zonefs/file.c                           |    3 +-
include/linux/dax.h                        |    8 +-
include/linux/hugetlb.h                    |    6 +-
include/linux/hugetlb_inline.h             |   10 +
include/linux/mm.h                         |  248 ++-
include/linux/mm_types.h                   |   23 +-
include/linux/shmem_fs.h                   |    8 +-
ipc/shm.c                                  |   12 +-
kernel/relay.c                             |    2 +-
mm/filemap.c                               |    2 +-
mm/hugetlb.c                               |   22 +-
mm/internal.h                              |    2 +-
mm/khugepaged.c                            |    2 +-
mm/madvise.c                               |    2 +-
mm/memfd.c                                 |    6 +-
mm/memfd_luo.c                             |    2 +-
mm/memory.c                                |   17 +-
mm/mmap.c                                  |   10 +-
mm/mremap.c                                |    2 +-
mm/secretmem.c                             |    7 +-
mm/shmem.c                                 |   59 +-
mm/util.c                                  |    2 +-
mm/vma.c                                   |   13 +-
mm/vma.h                                   |    3 +-
security/keys/big_key.c                    |    2 +-
tools/include/linux/bitmap.h               |   22 +
tools/lib/bitmap.c                         |   29 +
tools/testing/vma/Makefile                 |    7 +-
tools/testing/vma/include/custom.h         |  119 ++
tools/testing/vma/include/dup.h            | 1332 ++++++++++++++
tools/testing/vma/include/stubs.h          |  428 +++++
tools/testing/vma/main.c                   |   55 +
tools/testing/vma/shared.c                 |  131 ++
tools/testing/vma/shared.h                 |  114 ++
tools/testing/vma/{vma.c => tests/merge.c} |  332 +---
tools/testing/vma/tests/mmap.c             |   57 +
tools/testing/vma/tests/vma.c              |  339 ++++
tools/testing/vma/vma_internal.h           | 1847 +-------------------
60 files changed, 3055 insertions(+), 2314 deletions(-)
create mode 100644 tools/testing/vma/include/custom.h
create mode 100644 tools/testing/vma/include/dup.h
create mode 100644 tools/testing/vma/include/stubs.h
create mode 100644 tools/testing/vma/main.c
create mode 100644 tools/testing/vma/shared.c
create mode 100644 tools/testing/vma/shared.h
rename tools/testing/vma/{vma.c => tests/merge.c} (82%)
create mode 100644 tools/testing/vma/tests/mmap.c
create mode 100644 tools/testing/vma/tests/vma.c
[PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Lorenzo Stoakes 2 weeks, 1 day ago
We introduced the bitmap VMA type vma_flags_t in the aptly named commit
9ea35a25d51b ("mm: introduce VMA flags bitmap type") in order to permit
future growth in VMA flags and to prevent the asinine requirement that VMA
flags be available to 64-bit kernels only if they happened to use a bit
number about 32-bits.

This is a long-term project as there are very many users of VMA flags
within the kernel that need to be updated in order to utilise this new
type.

In order to further this aim, this series adds a number of helper functions
to enable ordinary interactions with VMA flags - that is testing, setting
and clearing them.

In order to make working with VMA bit numbers less cumbersome this series
introduces the mk_vma_flags() helper macro which generates a vma_flags_t
from a variadic parameter list, e.g.:

	vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT,
					 VMA_EXEC_BIT);

It turns out that the compiler optimises this very well to the point that
this is just as efficient as using VM_xxx pre-computed bitmap values.

This series then introduces the following functions:

	bool vma_flags_test_mask(vma_flags_t flags, vma_flags_t to_test);
	bool vma_flags_test_all_mask(vma_flags_t flags, vma_flags_t to_test);
	void vma_flags_set_mask(vma_flags_t *flags, vma_flags_t to_set);
	void vma_flags_clear_mask(vma_flags_t *flags, vma_flags_t to_clear);

Providing means of testing any flag, testing all flags, setting, and clearing a
specific vma_flags_t mask.

For convenience, helper macros are provided - vma_flags_test(),
vma_flags_set() and vma_flags_clear(), each of which utilise mk_vma_flags()
to make these operations easier, as well as an EMPTY_VMA_FLAGS macro to
make initialisation of an empty vma_flags_t value easier, e.g.:

	vma_flags_t flags = EMPTY_VMA_FLAGS;

	vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
	...
	if (vma_flags_test(flags, VMA_READ_BIT)) {
		...
	}
	...
	if (vma_flags_test_all_mask(flags, VMA_REMAP_FLAGS)) {
		...
	}
	...
	vma_flags_clear(&flags, VMA_READ_BIT);

Since callers are often dealing with a vm_area_struct (VMA) or vm_area_desc
(VMA descriptor as used in .mmap_prepare) object, this series further
provides helpers for these - firstly vma_set_flags_mask() and vma_set_flags() for a
VMA:

	vma_flags_t flags = EMPTY_VMA_FLAGS:

	vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
	...
	vma_set_flags_mask(&vma, flags);
	...
	vma_set_flags(&vma, VMA_DONTDUMP_BIT);

Note that these do NOT ensure appropriate locks are taken and assume the
callers takes care of this.

For VMA descriptors this series adds vma_desc_[test, set,
clear]_flags_mask() and vma_desc_[test, set, clear]_flags() for a VMA
descriptor, e.g.:

	static int foo_mmap_prepare(struct vm_area_desc *desc)
	{
		...
		vma_desc_set_flags(desc, VMA_SEQ_READ_BIT);
		vma_desc_clear_flags(desc, VMA_RAND_READ_BIT);
		...
		if (vma_desc_test_flags(desc, VMA_SHARED_BIT) {
			...
		}
		...
	}

With these helpers introduced, this series then updates all mmap_prepare
users to make use of the vma_flags_t vm_area_desc->vma_flags field rather
than the legacy vm_flags_t vm_area_desc->vm_flags field.

In order to do so, several other related functions need to be updated, with
separate patches for larger changes in hugetlbfs, secretmem and shmem
before finally removing vm_area_desc->vm_flags altogether.

This lays the foundations for future elimination of vm_flags_t and
associated defines and functionality altogether in the long run, and
elimination of the use of vm_flags_t in f_op->mmap() hooks in the near term
as mmap_prepare replaces these.

There is a useful synergy between the VMA flags and mmap_prepare work here
as with this change in place, converting f_op->mmap() to f_op->mmap_prepare
naturally also converts use of vm_flags_t to vma_flags_t in all drivers
which declare mmap handlers.

This accounts for the majority of the users of the legacy vm_flags_*()
helpers and thus a large number of drivers which need to interact with VMA
flags in general.

This series also updates the userland VMA tests to account for the change,
and adds unit tests for these helper functions to assert that they behave
as expected.

In order to faciliate this change in a sensible way, the series also
separates out the VMA unit tests into - code that is duplicated from the
kernel that should be kept in sync, code that is customised for test
purposes and code that is stubbed out.

We also separate out the VMA userland tests into separate files to make it
easier to manage and to provide a sensible baseline for adding the userland
tests for these helpers.


REVIEWS NOTE: I rebased this on
https://lore.kernel.org/linux-mm/cover.1769086312.git.lorenzo.stoakes@oracle.com/
in order to make life easier with conflict resolutions.

v2:
* Rebased on mm-unstable again, and then on my other series :)
* Removed sparse __private decoration - it is not doing us any good, and
  anybody accessing vma->flags.__vma_flags will be very obviously doing
  something wrong (TM) so we don't really need it. This will shut up the
  various bots reporting sparse issues :)
* Made functions which test VMA flags reference a const vma_flags_t *
  pointer for the flags being checked as per Jason.
* Updated entire series to affect this change, including userland tests.
* Fixed missed fixup in memfd_luo_retrieve() and folded into series. Turns
  out this doesn't get built with allmodconfig due to my arch not support.
* Fixed up issue with dev dax reported by Zi (thanks, much appreciated!)

v1 resend:
* Rebased on mm-unstable to fix vma_internal.h conflict tested and confirmed
  working.
https://lore.kernel.org/all/cover.1768857200.git.lorenzo.stoakes@oracle.com/

v1:
https://lore.kernel.org/all/cover.1768834061.git.lorenzo.stoakes@oracle.com/

Lorenzo Stoakes (13):
  mm/vma: remove __private sparse decoration from vma_flags_t
  mm: rename vma_flag_test/set_atomic() to vma_test/set_atomic_flag()
  mm: add mk_vma_flags() bitmap flag macro helper
  tools: bitmap: add missing bitmap_[subset(), andnot()]
  mm: add basic VMA flag operation helper functions
  mm: update hugetlbfs to use VMA flags on mmap_prepare
  mm: update secretmem to use VMA flags on mmap_prepare
  mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
  mm: update all remaining mmap_prepare users to use vma_flags_t
  mm: make vm_area_desc utilise vma_flags_t only
  tools/testing/vma: separate VMA userland tests into separate files
  tools/testing/vma: separate out vma_internal.h into logical headers
  tools/testing/vma: add VMA userland tests for VMA flag functions

 arch/x86/kernel/cpu/sgx/ioctl.c            |    2 +-
 drivers/char/mem.c                         |    6 +-
 drivers/dax/device.c                       |   10 +-
 drivers/gpu/drm/drm_gem.c                  |    5 +-
 drivers/gpu/drm/i915/gem/i915_gem_shmem.c  |    2 +-
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c    |    3 +-
 drivers/gpu/drm/i915/gt/shmem_utils.c      |    3 +-
 drivers/gpu/drm/ttm/tests/ttm_tt_test.c    |    2 +-
 drivers/gpu/drm/ttm/ttm_backup.c           |    3 +-
 drivers/gpu/drm/ttm/ttm_tt.c               |    2 +-
 fs/aio.c                                   |    2 +-
 fs/erofs/data.c                            |    5 +-
 fs/ext4/file.c                             |    4 +-
 fs/hugetlbfs/inode.c                       |   14 +-
 fs/ntfs3/file.c                            |    2 +-
 fs/orangefs/file.c                         |    4 +-
 fs/ramfs/file-nommu.c                      |    2 +-
 fs/resctrl/pseudo_lock.c                   |    2 +-
 fs/romfs/mmap-nommu.c                      |    2 +-
 fs/xfs/scrub/xfile.c                       |    3 +-
 fs/xfs/xfs_buf_mem.c                       |    2 +-
 fs/xfs/xfs_file.c                          |    4 +-
 fs/zonefs/file.c                           |    3 +-
 include/linux/dax.h                        |    8 +-
 include/linux/hugetlb.h                    |    6 +-
 include/linux/hugetlb_inline.h             |   10 +
 include/linux/mm.h                         |  248 ++-
 include/linux/mm_types.h                   |   23 +-
 include/linux/shmem_fs.h                   |    8 +-
 ipc/shm.c                                  |   12 +-
 kernel/relay.c                             |    2 +-
 mm/filemap.c                               |    2 +-
 mm/hugetlb.c                               |   22 +-
 mm/internal.h                              |    2 +-
 mm/khugepaged.c                            |    2 +-
 mm/madvise.c                               |    2 +-
 mm/memfd.c                                 |    6 +-
 mm/memfd_luo.c                             |    2 +-
 mm/memory.c                                |   17 +-
 mm/mmap.c                                  |   10 +-
 mm/mremap.c                                |    2 +-
 mm/secretmem.c                             |    7 +-
 mm/shmem.c                                 |   59 +-
 mm/util.c                                  |    2 +-
 mm/vma.c                                   |   13 +-
 mm/vma.h                                   |    3 +-
 security/keys/big_key.c                    |    2 +-
 tools/include/linux/bitmap.h               |   22 +
 tools/lib/bitmap.c                         |   29 +
 tools/testing/vma/Makefile                 |    7 +-
 tools/testing/vma/include/custom.h         |  119 ++
 tools/testing/vma/include/dup.h            | 1332 ++++++++++++++
 tools/testing/vma/include/stubs.h          |  428 +++++
 tools/testing/vma/main.c                   |   55 +
 tools/testing/vma/shared.c                 |  131 ++
 tools/testing/vma/shared.h                 |  114 ++
 tools/testing/vma/{vma.c => tests/merge.c} |  332 +---
 tools/testing/vma/tests/mmap.c             |   57 +
 tools/testing/vma/tests/vma.c              |  339 ++++
 tools/testing/vma/vma_internal.h           | 1847 +-------------------
 60 files changed, 3055 insertions(+), 2314 deletions(-)
 create mode 100644 tools/testing/vma/include/custom.h
 create mode 100644 tools/testing/vma/include/dup.h
 create mode 100644 tools/testing/vma/include/stubs.h
 create mode 100644 tools/testing/vma/main.c
 create mode 100644 tools/testing/vma/shared.c
 create mode 100644 tools/testing/vma/shared.h
 rename tools/testing/vma/{vma.c => tests/merge.c} (82%)
 create mode 100644 tools/testing/vma/tests/mmap.c
 create mode 100644 tools/testing/vma/tests/vma.c

--
2.52.0
Re: [PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Andrew Morton 2 weeks, 1 day ago
On Thu, 22 Jan 2026 16:06:09 +0000 Lorenzo Stoakes <lorenzo.stoakes@oracle.com> wrote:

> We introduced the bitmap VMA type vma_flags_t in the aptly named commit
> 9ea35a25d51b ("mm: introduce VMA flags bitmap type") in order to permit
> future growth in VMA flags and to prevent the asinine requirement that VMA
> flags be available to 64-bit kernels only if they happened to use a bit
> number about 32-bits.
> 
> This is a long-term project as there are very many users of VMA flags
> within the kernel that need to be updated in order to utilise this new
> type.
> 
> In order to further this aim, this series adds a number of helper functions
> to enable ordinary interactions with VMA flags - that is testing, setting
> and clearing them.

Thanks, I updated mm.git to this version.

I dropped the memfd_luo.c hunk due to today's inclusion of
https://lkml.kernel.org/r/20260122151842.4069702-3-pratyush@kernel.org

`get_maintainer --nogit' wants me to cc 72 people on this patchset.  I
didn't ;)
Re: [PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Yury Norov 1 week, 3 days ago
On Thu, Jan 22, 2026 at 04:06:09PM +0000, Lorenzo Stoakes wrote:
> We introduced the bitmap VMA type vma_flags_t in the aptly named commit
> 9ea35a25d51b ("mm: introduce VMA flags bitmap type") in order to permit
> future growth in VMA flags and to prevent the asinine requirement that VMA
> flags be available to 64-bit kernels only if they happened to use a bit
> number about 32-bits.
> 
> This is a long-term project as there are very many users of VMA flags
> within the kernel that need to be updated in order to utilise this new
> type.
> 
> In order to further this aim, this series adds a number of helper functions
> to enable ordinary interactions with VMA flags - that is testing, setting
> and clearing them.
> 
> In order to make working with VMA bit numbers less cumbersome this series
> introduces the mk_vma_flags() helper macro which generates a vma_flags_t
> from a variadic parameter list, e.g.:
> 
> 	vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT,
> 					 VMA_EXEC_BIT);

This should go on the bitmaps level. There's at least one another
possible client for this function - mm_flags_t. Maybe another generic
header bitmap_flags.h?

> It turns out that the compiler optimises this very well to the point that
> this is just as efficient as using VM_xxx pre-computed bitmap values.

It turns out, it's not a compiler - it's people writing code well. :)
Can you please mention the test_bitmap_const_eval() here and also
discuss configurations that break compile-time evaluation, like
KASAN+GCOV?

> This series then introduces the following functions:
> 
> 	bool vma_flags_test_mask(vma_flags_t flags, vma_flags_t to_test);
> 	bool vma_flags_test_all_mask(vma_flags_t flags, vma_flags_t to_test);
> 	void vma_flags_set_mask(vma_flags_t *flags, vma_flags_t to_set);
> 	void vma_flags_clear_mask(vma_flags_t *flags, vma_flags_t to_clear);
> 
> Providing means of testing any flag, testing all flags, setting, and clearing a
> specific vma_flags_t mask.
> 
> For convenience, helper macros are provided - vma_flags_test(),
> vma_flags_set() and vma_flags_clear(), each of which utilise mk_vma_flags()
> to make these operations easier, as well as an EMPTY_VMA_FLAGS macro to
> make initialisation of an empty vma_flags_t value easier, e.g.:
> 
> 	vma_flags_t flags = EMPTY_VMA_FLAGS;
> 
> 	vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
> 	...
> 	if (vma_flags_test(flags, VMA_READ_BIT)) {
> 		...
> 	}
> 	...
> 	if (vma_flags_test_all_mask(flags, VMA_REMAP_FLAGS)) {
> 		...
> 	}
> 	...
> 	vma_flags_clear(&flags, VMA_READ_BIT);
> 
> Since callers are often dealing with a vm_area_struct (VMA) or vm_area_desc
> (VMA descriptor as used in .mmap_prepare) object, this series further
> provides helpers for these - firstly vma_set_flags_mask() and vma_set_flags() for a
> VMA:
> 
> 	vma_flags_t flags = EMPTY_VMA_FLAGS:
> 
> 	vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
> 	...
> 	vma_set_flags_mask(&vma, flags);
> 	...
> 	vma_set_flags(&vma, VMA_DONTDUMP_BIT);

Having both vma_set_flags() and vma_flags_set() looks confusing...

> Note that these do NOT ensure appropriate locks are taken and assume the
> callers takes care of this.
> 
> For VMA descriptors this series adds vma_desc_[test, set,
> clear]_flags_mask() and vma_desc_[test, set, clear]_flags() for a VMA
> descriptor, e.g.:
> 
> 	static int foo_mmap_prepare(struct vm_area_desc *desc)
> 	{
> 		...
> 		vma_desc_set_flags(desc, VMA_SEQ_READ_BIT);
> 		vma_desc_clear_flags(desc, VMA_RAND_READ_BIT);
> 		...
> 		if (vma_desc_test_flags(desc, VMA_SHARED_BIT) {
> 			...
> 		}
> 		...
> 	}
> 
> With these helpers introduced, this series then updates all mmap_prepare
> users to make use of the vma_flags_t vm_area_desc->vma_flags field rather
> than the legacy vm_flags_t vm_area_desc->vm_flags field.
> 
> In order to do so, several other related functions need to be updated, with
> separate patches for larger changes in hugetlbfs, secretmem and shmem
> before finally removing vm_area_desc->vm_flags altogether.
> 
> This lays the foundations for future elimination of vm_flags_t and
> associated defines and functionality altogether in the long run, and
> elimination of the use of vm_flags_t in f_op->mmap() hooks in the near term
> as mmap_prepare replaces these.
> 
> There is a useful synergy between the VMA flags and mmap_prepare work here
> as with this change in place, converting f_op->mmap() to f_op->mmap_prepare
> naturally also converts use of vm_flags_t to vma_flags_t in all drivers
> which declare mmap handlers.
> 
> This accounts for the majority of the users of the legacy vm_flags_*()
> helpers and thus a large number of drivers which need to interact with VMA
> flags in general.
> 
> This series also updates the userland VMA tests to account for the change,
> and adds unit tests for these helper functions to assert that they behave
> as expected.
> 
> In order to faciliate this change in a sensible way, the series also
> separates out the VMA unit tests into - code that is duplicated from the
> kernel that should be kept in sync, code that is customised for test
> purposes and code that is stubbed out.
> 
> We also separate out the VMA userland tests into separate files to make it
> easier to manage and to provide a sensible baseline for adding the userland
> tests for these helpers.
> 
> 
> REVIEWS NOTE: I rebased this on
> https://lore.kernel.org/linux-mm/cover.1769086312.git.lorenzo.stoakes@oracle.com/
> in order to make life easier with conflict resolutions.

Before I deep into implementation details, can you share more background?

It seems you're implementing an arbitrary-length flags for VMAs, but the
length that you actually set is unconditionally 64. So why just not use
u64 for this?

Even if you expect adding more flags, u128 would double your capacity,
and people will still be able to use language-supported operation on
the bits in flag. Which looks simpler to me...

Thanks,
Yury
Re: [PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Lorenzo Stoakes 1 week, 3 days ago
On Tue, Jan 27, 2026 at 08:53:44AM -0500, Yury Norov wrote:
> On Thu, Jan 22, 2026 at 04:06:09PM +0000, Lorenzo Stoakes wrote:
> > We introduced the bitmap VMA type vma_flags_t in the aptly named commit
> > 9ea35a25d51b ("mm: introduce VMA flags bitmap type") in order to permit
> > future growth in VMA flags and to prevent the asinine requirement that VMA
> > flags be available to 64-bit kernels only if they happened to use a bit
> > number about 32-bits.
> >
> > This is a long-term project as there are very many users of VMA flags
> > within the kernel that need to be updated in order to utilise this new
> > type.
> >
> > In order to further this aim, this series adds a number of helper functions
> > to enable ordinary interactions with VMA flags - that is testing, setting
> > and clearing them.
> >
> > In order to make working with VMA bit numbers less cumbersome this series
> > introduces the mk_vma_flags() helper macro which generates a vma_flags_t
> > from a variadic parameter list, e.g.:
> >
> > 	vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT,
> > 					 VMA_EXEC_BIT);
>
> This should go on the bitmaps level. There's at least one another
> possible client for this function - mm_flags_t. Maybe another generic
> header bitmap_flags.h?

Well as the implementor of mm_flags_t I'm aware of this case :P

mm flags doesn't really need it as users were already using set_bit(),
clear_bit(), etc. and don't often set multiple flags.

I also would rather not make this too generic at this point, I explicitly want
an opaque type for describing VMA flags for type safety even if underneath it's
a bitmap.

>
> > It turns out that the compiler optimises this very well to the point that
> > this is just as efficient as using VM_xxx pre-computed bitmap values.
>
> It turns out, it's not a compiler - it's people writing code well. :)
> Can you please mention the test_bitmap_const_eval() here and also
> discuss configurations that break compile-time evaluation, like
> KASAN+GCOV?

Ah I wasn't even aware of this... :) so thanks for the heads up and thanks to
everybody who worked to make sure this was the case :)

That's useful information re:kasan,gcov. And I see you addressed this in the
test there in commit 2356d198d2b4 :)

If it makes sense to you I'll update it if I do a respin, since the Link: to
this discussion should provide this very additional background :) But I have
noted it down to change if/when any respin of this happens, if that's ok with
you?

In terms of impact, well users who are using KASAN/GCOV are already asking for
performance impact so it isn't too egregious.

>
> > This series then introduces the following functions:
> >
> > 	bool vma_flags_test_mask(vma_flags_t flags, vma_flags_t to_test);
> > 	bool vma_flags_test_all_mask(vma_flags_t flags, vma_flags_t to_test);
> > 	void vma_flags_set_mask(vma_flags_t *flags, vma_flags_t to_set);
> > 	void vma_flags_clear_mask(vma_flags_t *flags, vma_flags_t to_clear);
> >
> > Providing means of testing any flag, testing all flags, setting, and clearing a
> > specific vma_flags_t mask.
> >
> > For convenience, helper macros are provided - vma_flags_test(),
> > vma_flags_set() and vma_flags_clear(), each of which utilise mk_vma_flags()
> > to make these operations easier, as well as an EMPTY_VMA_FLAGS macro to
> > make initialisation of an empty vma_flags_t value easier, e.g.:
> >
> > 	vma_flags_t flags = EMPTY_VMA_FLAGS;
> >
> > 	vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
> > 	...
> > 	if (vma_flags_test(flags, VMA_READ_BIT)) {
> > 		...
> > 	}
> > 	...
> > 	if (vma_flags_test_all_mask(flags, VMA_REMAP_FLAGS)) {
> > 		...
> > 	}
> > 	...
> > 	vma_flags_clear(&flags, VMA_READ_BIT);
> >
> > Since callers are often dealing with a vm_area_struct (VMA) or vm_area_desc
> > (VMA descriptor as used in .mmap_prepare) object, this series further
> > provides helpers for these - firstly vma_set_flags_mask() and vma_set_flags() for a
> > VMA:
> >
> > 	vma_flags_t flags = EMPTY_VMA_FLAGS:
> >
> > 	vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
> > 	...
> > 	vma_set_flags_mask(&vma, flags);
> > 	...
> > 	vma_set_flags(&vma, VMA_DONTDUMP_BIT);
>
> Having both vma_set_flags() and vma_flags_set() looks confusing...

It's a trade-off against readability. I don't want these helpers to be too long.

Yes it's possibly confusing, but I keep a
consistent convention of [thing we are doing action on]_[action]_flags() and when
dealing with pure vma flags - vma_flags_[action]().

You're not going to run into issues with accidentally choosing the wrong one -
as it's strongly typed (well as strongly typed as C gets anyway) so the compiler
will catch mistakes.

So I think it's not too bad this way.

>
> > Note that these do NOT ensure appropriate locks are taken and assume the
> > callers takes care of this.
> >
> > For VMA descriptors this series adds vma_desc_[test, set,
> > clear]_flags_mask() and vma_desc_[test, set, clear]_flags() for a VMA
> > descriptor, e.g.:
> >
> > 	static int foo_mmap_prepare(struct vm_area_desc *desc)
> > 	{
> > 		...
> > 		vma_desc_set_flags(desc, VMA_SEQ_READ_BIT);
> > 		vma_desc_clear_flags(desc, VMA_RAND_READ_BIT);
> > 		...
> > 		if (vma_desc_test_flags(desc, VMA_SHARED_BIT) {
> > 			...
> > 		}
> > 		...
> > 	}
> >
> > With these helpers introduced, this series then updates all mmap_prepare
> > users to make use of the vma_flags_t vm_area_desc->vma_flags field rather
> > than the legacy vm_flags_t vm_area_desc->vm_flags field.
> >
> > In order to do so, several other related functions need to be updated, with
> > separate patches for larger changes in hugetlbfs, secretmem and shmem
> > before finally removing vm_area_desc->vm_flags altogether.
> >
> > This lays the foundations for future elimination of vm_flags_t and
> > associated defines and functionality altogether in the long run, and
> > elimination of the use of vm_flags_t in f_op->mmap() hooks in the near term
> > as mmap_prepare replaces these.
> >
> > There is a useful synergy between the VMA flags and mmap_prepare work here
> > as with this change in place, converting f_op->mmap() to f_op->mmap_prepare
> > naturally also converts use of vm_flags_t to vma_flags_t in all drivers
> > which declare mmap handlers.
> >
> > This accounts for the majority of the users of the legacy vm_flags_*()
> > helpers and thus a large number of drivers which need to interact with VMA
> > flags in general.
> >
> > This series also updates the userland VMA tests to account for the change,
> > and adds unit tests for these helper functions to assert that they behave
> > as expected.
> >
> > In order to faciliate this change in a sensible way, the series also
> > separates out the VMA unit tests into - code that is duplicated from the
> > kernel that should be kept in sync, code that is customised for test
> > purposes and code that is stubbed out.
> >
> > We also separate out the VMA userland tests into separate files to make it
> > easier to manage and to provide a sensible baseline for adding the userland
> > tests for these helpers.
> >
> >
> > REVIEWS NOTE: I rebased this on
> > https://lore.kernel.org/linux-mm/cover.1769086312.git.lorenzo.stoakes@oracle.com/
> > in order to make life easier with conflict resolutions.
>
> Before I deep into implementation details, can you share more background?

I'm surprised the above isn't enough but the background is that we currently
cannot implement certain features for all kernels because for 32-bit kernels we
have run out of VMA flags.

We are utilising new VMA flags for new features which make them 64-bit only with
annoying checks added everywhere to account for this, and there are a finite
number avaialble.

To future-proof the kernel we want to be able to adjust this as we please in
future.

>
> It seems you're implementing an arbitrary-length flags for VMAs, but the
> length that you actually set is unconditionally 64. So why just not use
> u64 for this?

It's not unconditionaly 64 (yet), it's currently equal to the system word size
so we can union this with the existing legacy VMA flags:

#define NUM_VMA_FLAG_BITS BITS_PER_LONG

I'll answer the 'why not u64' below.

>
> Even if you expect adding more flags, u128 would double your capacity,
> and people will still be able to use language-supported operation on
> the bits in flag. Which looks simpler to me...

u128 isn't supported on all architectures, VMA flags have to have absolutely
universal support.

We want to be able to arbitrarily extend this as we please in the future. So
using u64 wouldn't buy us _anything_ except getting the 32-bit kernels in line.

Using an integral value doesn't give us any kind of type safety, nor does it
give us as easy a means to track what users are doing with flags - both
additional benefits of this change.

>
> Thanks,
> Yury

Cheers, Lorenzo
Re: [PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Yury Norov 1 week, 3 days ago
On Tue, Jan 27, 2026 at 02:40:03PM +0000, Lorenzo Stoakes wrote:
> On Tue, Jan 27, 2026 at 08:53:44AM -0500, Yury Norov wrote:
> > On Thu, Jan 22, 2026 at 04:06:09PM +0000, Lorenzo Stoakes wrote:

...

> > Even if you expect adding more flags, u128 would double your capacity,
> > and people will still be able to use language-supported operation on
> > the bits in flag. Which looks simpler to me...
> 
> u128 isn't supported on all architectures, VMA flags have to have absolutely
 
What about big integers?

        typedef unsigned _BitInt(VMA_FLAGS_COUNT) vma_flags_t

> We want to be able to arbitrarily extend this as we please in the future. So
> using u64 wouldn't buy us _anything_ except getting the 32-bit kernels in line.

So enabling 32-bit arches is a big deal, even if it's a temporary
solution. Again, how many flags in your opinion are blocked because of
32-bit integer limitation? How soon 64-bit capacity will get fully
used?

> Using an integral value doesn't give us any kind of type safety, nor does it
> give us as easy a means to track what users are doing with flags - both
> additional benefits of this change.

I tried the below, and it works OK for me with i386:

$ cat bi.c
#include <stdio.h>
#include <limits.h>

int main() {
    unsigned _BitInt(128) a = (_BitInt(128))1 << 65;
    unsigned _BitInt(128) b = (_BitInt(128))1 << 66;

    printf("a | b == %llx\n", (unsigned long long)((a | b)>>64));
    printf("BITINT_MAXWIDTH ==  0x%x\n", BITINT_MAXWIDTH);

    return 0;
}

$ clang -m32 -std=c2x bi.c
$ ./a.out
a | b == 6
BITINT_MAXWIDTH == 0x800000

I didn't make GCC building it, at least out of the box. So the above
question about 64-bit capacity has a practical meaning. If we've got a
few years to let GCC fully support big integers as clang does, we don't 
have to wish anything else.

I'd like to put it right. I maintain bitmaps, and I like it widely
adopted. But when it comes to flags, being able to use plain logic
operations looks so important to me so I'd like to make sure that
switching to bitmaps is the only working option.
Re: [PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Lorenzo Stoakes 1 week, 3 days ago
On Tue, Jan 27, 2026 at 04:36:44PM -0500, Yury Norov wrote:
> On Tue, Jan 27, 2026 at 02:40:03PM +0000, Lorenzo Stoakes wrote:
> > On Tue, Jan 27, 2026 at 08:53:44AM -0500, Yury Norov wrote:
> > > On Thu, Jan 22, 2026 at 04:06:09PM +0000, Lorenzo Stoakes wrote:
>
> ...
>
> > > Even if you expect adding more flags, u128 would double your capacity,
> > > and people will still be able to use language-supported operation on
> > > the bits in flag. Which looks simpler to me...
> >
> > u128 isn't supported on all architectures, VMA flags have to have absolutely
>
> What about big integers?
>
>         typedef unsigned _BitInt(VMA_FLAGS_COUNT) vma_flags_t

There is no use of _BitInt anywhere in the kernel. That seems to be a
C23-only feature with limited compiler support that we simply couldn't use
yet.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3639r0.html tells
me that it's supported in clang 16+ and gcc 14+.

We cannot put such a restriction on compilers in the kernel, obviously.

>
> > We want to be able to arbitrarily extend this as we please in the future. So
> > using u64 wouldn't buy us _anything_ except getting the 32-bit kernels in line.
>
> So enabling 32-bit arches is a big deal, even if it's a temporary
> solution. Again, how many flags in your opinion are blocked because of
> 32-bit integer limitation? How soon 64-bit capacity will get fully
> used?

In my opinion? I'm not sure where my opinion comes into this? There are 43 VMA
flags and 32-bits available in 32-bit kernels.

As I said to you before Yury, when adding new flags you have to add a whole
load of mess of #ifdef CONFIG_64BIT ... #endif etc. around things that have
nothing to do with 64-bit vs 32-bit architecture as a result.

It's a mess, we've run out.

Also something that might not have occurred to you - there is a chilling
effect of limited VMA flag availability - the bar to adding flags is
higher, and features that might have used VMA flags but need general kernel
support (incl. 32-bit) have to find other ways to store state like this.

>
> > Using an integral value doesn't give us any kind of type safety, nor does it
> > give us as easy a means to track what users are doing with flags - both
> > additional benefits of this change.
>
> I tried the below, and it works OK for me with i386:
>
> $ cat bi.c
> #include <stdio.h>
> #include <limits.h>
>
> int main() {
>     unsigned _BitInt(128) a = (_BitInt(128))1 << 65;
>     unsigned _BitInt(128) b = (_BitInt(128))1 << 66;
>
>     printf("a | b == %llx\n", (unsigned long long)((a | b)>>64));
>     printf("BITINT_MAXWIDTH ==  0x%x\n", BITINT_MAXWIDTH);
>
>     return 0;
> }
>
> $ clang -m32 -std=c2x bi.c
> $ ./a.out
> a | b == 6
> BITINT_MAXWIDTH == 0x800000

I'm not sure why you're replying to my points about type safety,
traceability with this program but OK?

I mean thanks for that, I wasn't aware of the c23 standard (proposal?)
_BitInt(). It's useful to know that.

We can't use it right now, but it's good to know for the future.

>
> I didn't make GCC building it, at least out of the box. So the above
> question about 64-bit capacity has a practical meaning. If we've got a
> few years to let GCC fully support big integers as clang does, we don't
> have to wish anything else.

As long as you assume that all architectures will be supported, all
compilers used by users to build the kernel will support it, and Linus will
be fine with us using this.

That could be years, that could be never.

Also - and here's a really important point - the underlying implementation
_doesn't matter_.

Right now it's bitmaps.

By abstracting the VMA flags into an opaque type and providing helper
functions we also enable the ability to _change the implementation_.

So if this time comes, we can simply switch everything over. Job done.

Your suggested 'do nothing and hope' approach achieves none of this.

>
> I'd like to put it right. I maintain bitmaps, and I like it widely
> adopted. But when it comes to flags, being able to use plain logic
> operations looks so important to me so I'd like to make sure that
> switching to bitmaps is the only working option.

I'm not sure you're making a technical argument here?

From the point of view of mm, the ability to arbitrarily manipulate VMA
flags is a bug not a feature. The other part of this series is to make
changes to the f_op->mmap_prepare feature, which was explicitly implemented
in order to avoid such arbitrarily behaviour from drivers.

It's actually hugely valueable to make this change in such a way as we can
trace, with type safety, VMA flag usage throughout the kernel, and know
that for instance - on mmap setup - we don't need to worry about VMA
stabilisation - which feeds into other work re: killable VMA locks.

In summary, this series represents a workable and sensible means of
addressing all of these issues in one fell swoop, similar to the means
through which mm flags were extended across both 32-bit and 64-bit kernels.

We can in future choose to use _BitInt(), u128, or whatever we please
underneath, and which makes sense to use should conditions change and we
choose to do so for good technical reasons.

Any argument on the basis of 'allow the flags to continue to be manipulated
as they are' is I think mistaken.

Keep in mind that bitmap VMA flags are _already_ a merged feature in the
kernel, and this series only works to add sensible helper functions to
manipulate these flags and moves mmap_prepare to using them exclusively.

If we find cases where somehow the compiler does the wrong thing, we
already have functions in mm_types.h that allow us to address the first
system-word bits of the underlying type and can restrict core flags to
being at system word count or less.

I hope that won't ever be necessary, but we have means of adressing that
should any issue arise like that.

Thanks, Lorenzo
Re: [PATCH v2 00/13] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
Posted by Pedro Falcato 1 week, 2 days ago
On Wed, Jan 28, 2026 at 09:33:44AM +0000, Lorenzo Stoakes wrote:
> On Tue, Jan 27, 2026 at 04:36:44PM -0500, Yury Norov wrote:
> > On Tue, Jan 27, 2026 at 02:40:03PM +0000, Lorenzo Stoakes wrote:
> > > On Tue, Jan 27, 2026 at 08:53:44AM -0500, Yury Norov wrote:
> > > > On Thu, Jan 22, 2026 at 04:06:09PM +0000, Lorenzo Stoakes wrote:
> >
> > ...
> >
> > > > Even if you expect adding more flags, u128 would double your capacity,
> > > > and people will still be able to use language-supported operation on
> > > > the bits in flag. Which looks simpler to me...
> > >
> > > u128 isn't supported on all architectures, VMA flags have to have absolutely
> >
> > What about big integers?
> >
> >         typedef unsigned _BitInt(VMA_FLAGS_COUNT) vma_flags_t
> 
> There is no use of _BitInt anywhere in the kernel. That seems to be a
> C23-only feature with limited compiler support that we simply couldn't use
> yet.
> 
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3639r0.html tells
> me that it's supported in clang 16+ and gcc 14+.
> 
> We cannot put such a restriction on compilers in the kernel, obviously.
> 
> >
> > > We want to be able to arbitrarily extend this as we please in the future. So
> > > using u64 wouldn't buy us _anything_ except getting the 32-bit kernels in line.
> >
> > So enabling 32-bit arches is a big deal, even if it's a temporary
> > solution. Again, how many flags in your opinion are blocked because of
> > 32-bit integer limitation? How soon 64-bit capacity will get fully
> > used?
> 
> In my opinion? I'm not sure where my opinion comes into this? There are 43 VMA
> flags and 32-bits available in 32-bit kernels.
> 
> As I said to you before Yury, when adding new flags you have to add a whole
> load of mess of #ifdef CONFIG_64BIT ... #endif etc. around things that have
> nothing to do with 64-bit vs 32-bit architecture as a result.
> 
> It's a mess, we've run out.
> 
> Also something that might not have occurred to you - there is a chilling
> effect of limited VMA flag availability - the bar to adding flags is
> higher, and features that might have used VMA flags but need general kernel
> support (incl. 32-bit) have to find other ways to store state like this.
> 

For the record, I fully agree with all of the points you made. I don't think
it makes sense to hold this change back waiting for a feature that right
now is relatively unobtainable (also IIRC the ABI around _BitInt was a bit
unstable and confusing in general, I don't know if that changed).

The goals are to:
1) get more than sizeof(unsigned long) * 8 flags so we don't have to uglify
and gatekeep things behind 64-bit. Also letting us use VMA flags more freely.
2) not cause any performance/codegen regression

Yes, the current patchset (and the current state of things too) uglifies
things a bit, but it also provides things like type safety which are sorely
needed here. And which 128-bit integers, or N-bit integers would not provide.

And if any of the above suddenly become available to us in the future, it
will be trivial to change because the VMA flags types will be fully
encapsulated with proper accessors.

Or perhaps we'll rewrite it all in rust by the end of the decade and this is
all a moot point, who knows ;)

-- 
Pedro