* Lorenzo Stoakes <[email protected]> [260122 16:06]: > This patch introduces the mk_vma_flags() macro helper to allow easy > manipulation of VMA flags utilising the new bitmap representation > implemented of VMA flags defined by the vma_flags_t type. > > It is a variadic macro which provides a bitwise-or'd representation of all > of each individual VMA flag specified. > > Note that, while we maintain VM_xxx flags for backwards compatibility until > the conversion is complete, we define VMA flags of type vma_flag_t using > VMA_xxx_BIT to avoid confusing the two. > > This helper macro therefore can be used thusly: > > vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT); > > We allow for up to 5 flags to specified at a time which should accommodate > all current kernel uses of combined VMA flags. > > Testing has demonstrated that the compiler optimises this code such that it > generates the same assembly utilising this macro as it does if the flags > were specified manually, for instance: > > vma_flags_t get_flags(void) > { > return mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT); > } > > Generates the same code as: > > vma_flags_t get_flags(void) > { > vma_flags_t flags; > > vma_flags_clear_all(&flags); > vma_flag_set(&flags, VMA_READ_BIT); > vma_flag_set(&flags, VMA_WRITE_BIT); > vma_flag_set(&flags, VMA_EXEC_BIT); > > return flags; > } > > And: > > vma_flags_t get_flags(void) > { > vma_flags_t flags; > unsigned long *bitmap = ACCESS_PRIVATE(&flags, __vma_flags); > > *bitmap = 1UL << (__force int)VMA_READ_BIT; > *bitmap |= 1UL << (__force int)VMA_WRITE_BIT; > *bitmap |= 1UL << (__force int)VMA_EXEC_BIT; > > return flags; > } > > That is: > > get_flags: > movl $7, %eax > ret > > Suggested-by: Jason Gunthorpe <[email protected]> > Signed-off-by: Lorenzo Stoakes <[email protected]>
Besides the part about 5 arguments that has been discussed, Reviewed-by: Liam R. Howlett <[email protected]> > --- > include/linux/mm.h | 33 +++++++++++++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index e0d31238097c..32c3b5347dc6 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -2,6 +2,7 @@ > #ifndef _LINUX_MM_H > #define _LINUX_MM_H > > +#include <linux/args.h> > #include <linux/errno.h> > #include <linux/mmdebug.h> > #include <linux/gfp.h> > @@ -1026,6 +1027,38 @@ static inline bool vma_test_atomic_flag(struct > vm_area_struct *vma, vma_flag_t b > return false; > } > > +/* Set an individual VMA flag in flags, non-atomically. */ > +static inline void vma_flag_set(vma_flags_t *flags, vma_flag_t bit) > +{ > + unsigned long *bitmap = flags->__vma_flags; > + > + __set_bit((__force int)bit, bitmap); > +} > + > +static inline vma_flags_t __mk_vma_flags(size_t count, const vma_flag_t > *bits) > +{ > + vma_flags_t flags; > + int i; > + > + vma_flags_clear_all(&flags); > + for (i = 0; i < count; i++) > + vma_flag_set(&flags, bits[i]); > + return flags; > +} > + > +/* > + * Helper macro which bitwise-or combines the specified input flags into a > + * vma_flags_t bitmap value. E.g.: > + * > + * vma_flags_t flags = mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT, > + * VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT); > + * > + * The compiler cleverly optimises away all of the work and this ends up > being > + * equivalent to aggregating the values manually. > + */ > +#define mk_vma_flags(...) __mk_vma_flags(COUNT_ARGS(__VA_ARGS__), \ > + (const vma_flag_t []){__VA_ARGS__}) > + > static inline void vma_set_anonymous(struct vm_area_struct *vma) > { > vma->vm_ops = NULL; > -- > 2.52.0 >
