On Thu, Sep 17, 2026 at 9:24 AM Lorenzo Stoakes (ARM) <[email protected]> wrote: > > Replace the open-coded VMA_SPECIAL_FLAGS check in the VMA merge logic with > two new functions vma_flags_can_merge() and vma_can_merge() and update the > merge logic to use the former. > > This abstracts the check and expresses it in terms of the desired behaviour > rather than an arbitrary and confusing VMA flag. > > This also lays the groundwork for making further improvements in VMA flag > usage. > > Also update the userland VMA tests to reflect the change. > > No functional change intended. > > Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
Reviewed-by: Suren Baghdasaryan <[email protected]> > --- > include/linux/mm.h | 21 +++++++++++++++++++++ > mm/vma.c | 19 +++++++++++-------- > tools/testing/vma/include/dup.h | 5 +++++ > 3 files changed, 37 insertions(+), 8 deletions(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index 969594074fd2..68250ece4219 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -1612,6 +1612,27 @@ static inline bool vma_is_shared_maywrite(const struct > vm_area_struct *vma) > return is_shared_maywrite(&vma->flags); > } > > +/** > + * vma_flags_can_merge() - Do the specified VMA flags permit the VMA to be > + * merged with another? > + * @flags: The VMA flags to test. > + * Returns: true if the flags permit merging, false otherwise. > + */ > +static inline bool vma_flags_can_merge(const vma_flags_t *flags) > +{ > + return !vma_flags_test_any_mask(flags, VMA_SPECIAL_FLAGS); > +} > + > +/** > + * vma_can_merge() - Do @vma's flags permit it to be merged with another VMA? > + * @vma: The VMA to test. > + * Returns: true if the flags permit merging, otherwise false. > + */ > +static inline bool vma_can_merge(const struct vm_area_struct *vma) > +{ > + return vma_flags_can_merge(&vma->flags); > +} > + > /** > * vma_kernel_pagesize - Default page size granularity for this VMA. > * @vma: The user mapping. > diff --git a/mm/vma.c b/mm/vma.c > index 4b74b48c29b7..05d2c676672e 100644 > --- a/mm/vma.c > +++ b/mm/vma.c > @@ -924,13 +924,14 @@ static __must_check struct vm_area_struct > *vma_merge_existing_range( > > vmg->state = VMA_MERGE_NOMERGE; > > + if (!vma_flags_can_merge(&vmg->vma_flags)) > + return NULL; > /* > - * If a special mapping or if the range being modified is neither at > the > - * furthermost left or right side of the VMA, then we have no chance > of > - * merging and should abort. > + * If the range being modified is neither at the furthermost left or > + * right side of the VMA, then we have no chance of merging and should > + * abort. > */ > - if (vma_flags_test_any_mask(&vmg->vma_flags, VMA_SPECIAL_FLAGS) || > - (!left_side && !right_side)) > + if (!left_side && !right_side) > return NULL; > > if (left_side) > @@ -1152,9 +1153,11 @@ struct vm_area_struct *vma_merge_new_range(struct > vma_merge_struct *vmg) > > vmg->state = VMA_MERGE_NOMERGE; > > - /* Special VMAs are unmergeable, also if no prev/next. */ > - if (vma_flags_test_any_mask(&vmg->vma_flags, VMA_SPECIAL_FLAGS) || > - (!prev && !next)) > + if (!vma_flags_can_merge(&vmg->vma_flags)) > + return NULL; > + > + /* VMAs with no prev/next are unmergeable. */ > + if (!prev && !next) > return NULL; > > can_merge_left = can_vma_merge_left(vmg); > diff --git a/tools/testing/vma/include/dup.h b/tools/testing/vma/include/dup.h > index 16c09dac59d9..2fd422789717 100644 > --- a/tools/testing/vma/include/dup.h > +++ b/tools/testing/vma/include/dup.h > @@ -1647,3 +1647,8 @@ static inline bool file_is_dev_zero(const struct file > *file) > { > return file && file->f_op == &zero_fops; > } > + > +static inline bool vma_flags_can_merge(const vma_flags_t *flags) > +{ > + return !vma_flags_test_any_mask(flags, VMA_SPECIAL_FLAGS); > +} > > -- > 2.55.0 >
