On Wed 25-01-23 00:38:46, Suren Baghdasaryan wrote: > vm_flags are among VMA attributes which affect decisions like VMA merging > and splitting. Therefore all vm_flags modifications are performed after > taking exclusive mmap_lock to prevent vm_flags updates racing with such > operations. Introduce modifier functions for vm_flags to be used whenever > flags are updated. This way we can better check and control correct > locking behavior during these updates. > > Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx> Acked-by: Michal Hocko <mhocko@xxxxxxxx> > --- > include/linux/mm.h | 37 +++++++++++++++++++++++++++++++++++++ > include/linux/mm_types.h | 8 +++++++- > 2 files changed, 44 insertions(+), 1 deletion(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index c2f62bdce134..b71f2809caac 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -627,6 +627,43 @@ static inline void vma_init(struct vm_area_struct *vma, struct mm_struct *mm) > INIT_LIST_HEAD(&vma->anon_vma_chain); > } > > +/* Use when VMA is not part of the VMA tree and needs no locking */ > +static inline void init_vm_flags(struct vm_area_struct *vma, > + unsigned long flags) > +{ > + vma->vm_flags = flags; > +} > + > +/* Use when VMA is part of the VMA tree and modifications need coordination */ > +static inline void reset_vm_flags(struct vm_area_struct *vma, > + unsigned long flags) > +{ > + mmap_assert_write_locked(vma->vm_mm); > + init_vm_flags(vma, flags); > +} > + > +static inline void set_vm_flags(struct vm_area_struct *vma, > + unsigned long flags) > +{ > + mmap_assert_write_locked(vma->vm_mm); > + vma->vm_flags |= flags; > +} > + > +static inline void clear_vm_flags(struct vm_area_struct *vma, > + unsigned long flags) > +{ > + mmap_assert_write_locked(vma->vm_mm); > + vma->vm_flags &= ~flags; > +} > + > +static inline void mod_vm_flags(struct vm_area_struct *vma, > + unsigned long set, unsigned long clear) > +{ > + mmap_assert_write_locked(vma->vm_mm); > + vma->vm_flags |= set; > + vma->vm_flags &= ~clear; > +} > + > static inline void vma_set_anonymous(struct vm_area_struct *vma) > { > vma->vm_ops = NULL; > diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h > index 2d6d790d9bed..6c7c70bf50dd 100644 > --- a/include/linux/mm_types.h > +++ b/include/linux/mm_types.h > @@ -491,7 +491,13 @@ struct vm_area_struct { > * See vmf_insert_mixed_prot() for discussion. > */ > pgprot_t vm_page_prot; > - unsigned long vm_flags; /* Flags, see mm.h. */ > + > + /* > + * Flags, see mm.h. > + * WARNING! Do not modify directly. > + * Use {init|reset|set|clear|mod}_vm_flags() functions instead. > + */ > + unsigned long vm_flags; > > /* > * For areas with an address space and backing store, > -- > 2.39.1 -- Michal Hocko SUSE Labs