summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenzo Stoakes <lorenzo.stoakes@oracle.com>2026-01-22 16:06:10 +0000
committerAndrew Morton <akpm@linux-foundation.org>2026-02-12 15:42:56 -0800
commita30de4c6b79a83944d0d6a54cd6ae63014b62ef7 (patch)
tree85439c0164d34e9a43399d75b892b939a7ccbdcd
parenta8700d42b0af3a1751f70d53ee90c97fb4dc50f2 (diff)
mm/vma: remove __private sparse decoration from vma_flags_t
Patch series "mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them", v2. 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. This patch (of 13): We need to pass around these values and access them in a way that sparse does not allow, as __private implies noderef, i.e. disallowing dereference of the value, which manifests as sparse warnings even when passed around benignly. Link: https://lkml.kernel.org/r/cover.1769097829.git.lorenzo.stoakes@oracle.com Link: https://lkml.kernel.org/r/64fa89f416f22a60ae74cfff8fd565e7677be192.1769097829.git.lorenzo.stoakes@oracle.com Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Reviewed-by: Pedro Falcato <pfalcato@suse.de> Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Cc: Barry Song <baohua@kernel.org> Cc: David Hildenbrand <david@kernel.org> Cc: Dev Jain <dev.jain@arm.com> Cc: Jason Gunthorpe <jgg@nvidia.com> Cc: Suren Baghdasaryan <surenb@google.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Zi Yan <ziy@nvidia.com> Cc: Damien Le Moal <dlemoal@kernel.org> Cc: "Darrick J. Wong" <djwong@kernel.org> Cc: Jarkko Sakkinen <jarkko@kernel.org> Cc: Yury Norov <ynorov@nvidia.com> Cc: Chris Mason <clm@fb.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
-rw-r--r--include/linux/mm.h4
-rw-r--r--include/linux/mm_types.h14
2 files changed, 10 insertions, 8 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 945902d23d47..c27d79f6b8c0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -943,7 +943,7 @@ static inline void vm_flags_reset_once(struct vm_area_struct *vma,
* system word.
*/
if (NUM_VMA_FLAG_BITS > BITS_PER_LONG) {
- unsigned long *bitmap = ACCESS_PRIVATE(&vma->flags, __vma_flags);
+ unsigned long *bitmap = vma->flags.__vma_flags;
bitmap_zero(&bitmap[1], NUM_VMA_FLAG_BITS - BITS_PER_LONG);
}
@@ -1006,7 +1006,7 @@ 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);
+ unsigned long *bitmap = vma->flags.__vma_flags;
vma_assert_stabilised(vma);
if (__vma_flag_atomic_valid(vma, bit))
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 8731606d8d36..ed0e128361f7 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -866,7 +866,7 @@ struct mmap_action {
#define NUM_VMA_FLAG_BITS BITS_PER_LONG
typedef struct {
DECLARE_BITMAP(__vma_flags, NUM_VMA_FLAG_BITS);
-} __private vma_flags_t;
+} vma_flags_t;
/*
* Describes a VMA that is about to be mmap()'ed. Drivers may choose to
@@ -1059,7 +1059,7 @@ struct vm_area_struct {
/* 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);
+ bitmap_zero(flags->__vma_flags, NUM_VMA_FLAG_BITS);
}
/*
@@ -1070,7 +1070,9 @@ static inline void vma_flags_clear_all(vma_flags_t *flags)
*/
static inline void vma_flags_overwrite_word(vma_flags_t *flags, unsigned long value)
{
- *ACCESS_PRIVATE(flags, __vma_flags) = value;
+ unsigned long *bitmap = flags->__vma_flags;
+
+ bitmap[0] = value;
}
/*
@@ -1081,7 +1083,7 @@ static inline void vma_flags_overwrite_word(vma_flags_t *flags, unsigned long va
*/
static inline void vma_flags_overwrite_word_once(vma_flags_t *flags, unsigned long value)
{
- unsigned long *bitmap = ACCESS_PRIVATE(flags, __vma_flags);
+ unsigned long *bitmap = flags->__vma_flags;
WRITE_ONCE(*bitmap, value);
}
@@ -1089,7 +1091,7 @@ static inline void vma_flags_overwrite_word_once(vma_flags_t *flags, unsigned lo
/* 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);
+ unsigned long *bitmap = flags->__vma_flags;
*bitmap |= value;
}
@@ -1097,7 +1099,7 @@ static inline void vma_flags_set_word(vma_flags_t *flags, unsigned long 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);
+ unsigned long *bitmap = flags->__vma_flags;
*bitmap &= ~value;
}