@@ -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.
@@ -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);
@@ -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);
+}