Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Lorenzo Stoakes and committed by
Andrew Morton
a30de4c6 a8700d42

+10 -8
+2 -2
include/linux/mm.h
··· 943 943 * system word. 944 944 */ 945 945 if (NUM_VMA_FLAG_BITS > BITS_PER_LONG) { 946 - unsigned long *bitmap = ACCESS_PRIVATE(&vma->flags, __vma_flags); 946 + unsigned long *bitmap = vma->flags.__vma_flags; 947 947 948 948 bitmap_zero(&bitmap[1], NUM_VMA_FLAG_BITS - BITS_PER_LONG); 949 949 } ··· 1006 1006 static inline void vma_flag_set_atomic(struct vm_area_struct *vma, 1007 1007 vma_flag_t bit) 1008 1008 { 1009 - unsigned long *bitmap = ACCESS_PRIVATE(&vma->flags, __vma_flags); 1009 + unsigned long *bitmap = vma->flags.__vma_flags; 1010 1010 1011 1011 vma_assert_stabilised(vma); 1012 1012 if (__vma_flag_atomic_valid(vma, bit))
+8 -6
include/linux/mm_types.h
··· 866 866 #define NUM_VMA_FLAG_BITS BITS_PER_LONG 867 867 typedef struct { 868 868 DECLARE_BITMAP(__vma_flags, NUM_VMA_FLAG_BITS); 869 - } __private vma_flags_t; 869 + } vma_flags_t; 870 870 871 871 /* 872 872 * Describes a VMA that is about to be mmap()'ed. Drivers may choose to ··· 1059 1059 /* Clears all bits in the VMA flags bitmap, non-atomically. */ 1060 1060 static inline void vma_flags_clear_all(vma_flags_t *flags) 1061 1061 { 1062 - bitmap_zero(ACCESS_PRIVATE(flags, __vma_flags), NUM_VMA_FLAG_BITS); 1062 + bitmap_zero(flags->__vma_flags, NUM_VMA_FLAG_BITS); 1063 1063 } 1064 1064 1065 1065 /* ··· 1070 1070 */ 1071 1071 static inline void vma_flags_overwrite_word(vma_flags_t *flags, unsigned long value) 1072 1072 { 1073 - *ACCESS_PRIVATE(flags, __vma_flags) = value; 1073 + unsigned long *bitmap = flags->__vma_flags; 1074 + 1075 + bitmap[0] = value; 1074 1076 } 1075 1077 1076 1078 /* ··· 1083 1081 */ 1084 1082 static inline void vma_flags_overwrite_word_once(vma_flags_t *flags, unsigned long value) 1085 1083 { 1086 - unsigned long *bitmap = ACCESS_PRIVATE(flags, __vma_flags); 1084 + unsigned long *bitmap = flags->__vma_flags; 1087 1085 1088 1086 WRITE_ONCE(*bitmap, value); 1089 1087 } ··· 1091 1089 /* Update the first system word of VMA flags setting bits, non-atomically. */ 1092 1090 static inline void vma_flags_set_word(vma_flags_t *flags, unsigned long value) 1093 1091 { 1094 - unsigned long *bitmap = ACCESS_PRIVATE(flags, __vma_flags); 1092 + unsigned long *bitmap = flags->__vma_flags; 1095 1093 1096 1094 *bitmap |= value; 1097 1095 } ··· 1099 1097 /* Update the first system word of VMA flags clearing bits, non-atomically. */ 1100 1098 static inline void vma_flags_clear_word(vma_flags_t *flags, unsigned long value) 1101 1099 { 1102 - unsigned long *bitmap = ACCESS_PRIVATE(flags, __vma_flags); 1100 + unsigned long *bitmap = flags->__vma_flags; 1103 1101 1104 1102 *bitmap &= ~value; 1105 1103 }