mirror of
https://github.com/torvalds/linux.git
synced 2024-12-24 20:01:55 +00:00
mm: switch vma_merge(), split_vma(), and __split_vma to vma iterator
Drop the vmi_* functions and transition all users to use the vma iterator directly. Link: https://lkml.kernel.org/r/20230120162650.984577-30-Liam.Howlett@oracle.com Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
07f1bc5ad7
commit
9760ebffbf
@ -909,7 +909,7 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
|
new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
|
||||||
prev = vmi_vma_merge(&vmi, mm, prev, vma->vm_start, vma->vm_end,
|
prev = vma_merge(&vmi, mm, prev, vma->vm_start, vma->vm_end,
|
||||||
new_flags, vma->anon_vma,
|
new_flags, vma->anon_vma,
|
||||||
vma->vm_file, vma->vm_pgoff,
|
vma->vm_file, vma->vm_pgoff,
|
||||||
vma_policy(vma),
|
vma_policy(vma),
|
||||||
@ -1452,7 +1452,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
|||||||
vma_end = min(end, vma->vm_end);
|
vma_end = min(end, vma->vm_end);
|
||||||
|
|
||||||
new_flags = (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags;
|
new_flags = (vma->vm_flags & ~__VM_UFFD_FLAGS) | vm_flags;
|
||||||
prev = vmi_vma_merge(&vmi, mm, prev, start, vma_end, new_flags,
|
prev = vma_merge(&vmi, mm, prev, start, vma_end, new_flags,
|
||||||
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
||||||
vma_policy(vma),
|
vma_policy(vma),
|
||||||
((struct vm_userfaultfd_ctx){ ctx }),
|
((struct vm_userfaultfd_ctx){ ctx }),
|
||||||
@ -1463,12 +1463,12 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if (vma->vm_start < start) {
|
if (vma->vm_start < start) {
|
||||||
ret = vmi_split_vma(&vmi, mm, vma, start, 1);
|
ret = split_vma(&vmi, vma, start, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (vma->vm_end > end) {
|
if (vma->vm_end > end) {
|
||||||
ret = vmi_split_vma(&vmi, mm, vma, end, 0);
|
ret = split_vma(&vmi, vma, end, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1632,7 +1632,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
|
|||||||
uffd_wp_range(mm, vma, start, vma_end - start, false);
|
uffd_wp_range(mm, vma, start, vma_end - start, false);
|
||||||
|
|
||||||
new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
|
new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
|
||||||
prev = vmi_vma_merge(&vmi, mm, prev, start, vma_end, new_flags,
|
prev = vma_merge(&vmi, mm, prev, start, vma_end, new_flags,
|
||||||
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
vma->anon_vma, vma->vm_file, vma->vm_pgoff,
|
||||||
vma_policy(vma),
|
vma_policy(vma),
|
||||||
NULL_VM_UFFD_CTX, anon_vma_name(vma));
|
NULL_VM_UFFD_CTX, anon_vma_name(vma));
|
||||||
@ -1641,12 +1641,12 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
|
|||||||
goto next;
|
goto next;
|
||||||
}
|
}
|
||||||
if (vma->vm_start < start) {
|
if (vma->vm_start < start) {
|
||||||
ret = vmi_split_vma(&vmi, mm, vma, start, 1);
|
ret = split_vma(&vmi, vma, start, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (vma->vm_end > end) {
|
if (vma->vm_end > end) {
|
||||||
ret = vmi_split_vma(&vmi, mm, vma, end, 0);
|
ret = split_vma(&vmi, vma, end, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2839,24 +2839,16 @@ static inline int vma_adjust(struct vm_area_struct *vma, unsigned long start,
|
|||||||
{
|
{
|
||||||
return __vma_adjust(vma, start, end, pgoff, insert, NULL);
|
return __vma_adjust(vma, start, end, pgoff, insert, NULL);
|
||||||
}
|
}
|
||||||
extern struct vm_area_struct *vma_merge(struct mm_struct *,
|
extern struct vm_area_struct *vma_merge(struct vma_iterator *vmi,
|
||||||
struct vm_area_struct *prev, unsigned long addr, unsigned long end,
|
|
||||||
unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t,
|
|
||||||
struct mempolicy *, struct vm_userfaultfd_ctx, struct anon_vma_name *);
|
|
||||||
extern struct vm_area_struct *vmi_vma_merge(struct vma_iterator *vmi,
|
|
||||||
struct mm_struct *, struct vm_area_struct *prev, unsigned long addr,
|
struct mm_struct *, struct vm_area_struct *prev, unsigned long addr,
|
||||||
unsigned long end, unsigned long vm_flags, struct anon_vma *,
|
unsigned long end, unsigned long vm_flags, struct anon_vma *,
|
||||||
struct file *, pgoff_t, struct mempolicy *, struct vm_userfaultfd_ctx,
|
struct file *, pgoff_t, struct mempolicy *, struct vm_userfaultfd_ctx,
|
||||||
struct anon_vma_name *);
|
struct anon_vma_name *);
|
||||||
extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
|
extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
|
||||||
extern int __split_vma(struct mm_struct *, struct vm_area_struct *,
|
extern int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *,
|
||||||
unsigned long addr, int new_below);
|
unsigned long addr, int new_below);
|
||||||
extern int vmi__split_vma(struct vma_iterator *vmi, struct mm_struct *,
|
extern int split_vma(struct vma_iterator *vmi, struct vm_area_struct *,
|
||||||
struct vm_area_struct *, unsigned long addr, int new_below);
|
unsigned long addr, int new_below);
|
||||||
extern int split_vma(struct mm_struct *, struct vm_area_struct *,
|
|
||||||
unsigned long addr, int new_below);
|
|
||||||
extern int vmi_split_vma(struct vma_iterator *vmi, struct mm_struct *,
|
|
||||||
struct vm_area_struct *, unsigned long addr, int new_below);
|
|
||||||
extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
|
extern int insert_vm_struct(struct mm_struct *, struct vm_area_struct *);
|
||||||
extern void unlink_file_vma(struct vm_area_struct *);
|
extern void unlink_file_vma(struct vm_area_struct *);
|
||||||
extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
|
extern struct vm_area_struct *copy_vma(struct vm_area_struct **,
|
||||||
|
@ -150,7 +150,7 @@ static int madvise_update_vma(struct vm_area_struct *vma,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
||||||
*prev = vmi_vma_merge(&vmi, mm, *prev, start, end, new_flags,
|
*prev = vma_merge(&vmi, mm, *prev, start, end, new_flags,
|
||||||
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
||||||
vma->vm_userfaultfd_ctx, anon_name);
|
vma->vm_userfaultfd_ctx, anon_name);
|
||||||
if (*prev) {
|
if (*prev) {
|
||||||
@ -163,7 +163,7 @@ static int madvise_update_vma(struct vm_area_struct *vma,
|
|||||||
if (start != vma->vm_start) {
|
if (start != vma->vm_start) {
|
||||||
if (unlikely(mm->map_count >= sysctl_max_map_count))
|
if (unlikely(mm->map_count >= sysctl_max_map_count))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
error = vmi__split_vma(&vmi, mm, vma, start, 1);
|
error = __split_vma(&vmi, vma, start, 1);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ static int madvise_update_vma(struct vm_area_struct *vma,
|
|||||||
if (end != vma->vm_end) {
|
if (end != vma->vm_end) {
|
||||||
if (unlikely(mm->map_count >= sysctl_max_map_count))
|
if (unlikely(mm->map_count >= sysctl_max_map_count))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
error = vmi__split_vma(&vmi, mm, vma, end, 0);
|
error = __split_vma(&vmi, vma, end, 0);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -810,7 +810,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
|
|||||||
|
|
||||||
pgoff = vma->vm_pgoff +
|
pgoff = vma->vm_pgoff +
|
||||||
((vmstart - vma->vm_start) >> PAGE_SHIFT);
|
((vmstart - vma->vm_start) >> PAGE_SHIFT);
|
||||||
prev = vmi_vma_merge(&vmi, mm, prev, vmstart, vmend, vma->vm_flags,
|
prev = vma_merge(&vmi, mm, prev, vmstart, vmend, vma->vm_flags,
|
||||||
vma->anon_vma, vma->vm_file, pgoff,
|
vma->anon_vma, vma->vm_file, pgoff,
|
||||||
new_pol, vma->vm_userfaultfd_ctx,
|
new_pol, vma->vm_userfaultfd_ctx,
|
||||||
anon_vma_name(vma));
|
anon_vma_name(vma));
|
||||||
@ -819,12 +819,12 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
|
|||||||
goto replace;
|
goto replace;
|
||||||
}
|
}
|
||||||
if (vma->vm_start != vmstart) {
|
if (vma->vm_start != vmstart) {
|
||||||
err = vmi_split_vma(&vmi, vma->vm_mm, vma, vmstart, 1);
|
err = split_vma(&vmi, vma, vmstart, 1);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (vma->vm_end != vmend) {
|
if (vma->vm_end != vmend) {
|
||||||
err = vmi_split_vma(&vmi, vma->vm_mm, vma, vmend, 0);
|
err = split_vma(&vmi, vma, vmend, 0);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
@ -418,7 +418,7 @@ static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
||||||
*prev = vmi_vma_merge(vmi, mm, *prev, start, end, newflags,
|
*prev = vma_merge(vmi, mm, *prev, start, end, newflags,
|
||||||
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
||||||
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
||||||
if (*prev) {
|
if (*prev) {
|
||||||
@ -427,13 +427,13 @@ static int mlock_fixup(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (start != vma->vm_start) {
|
if (start != vma->vm_start) {
|
||||||
ret = vmi_split_vma(vmi, mm, vma, start, 1);
|
ret = split_vma(vmi, vma, start, 1);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end != vma->vm_end) {
|
if (end != vma->vm_end) {
|
||||||
ret = vmi_split_vma(vmi, mm, vma, end, 0);
|
ret = split_vma(vmi, vma, end, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
79
mm/mmap.c
79
mm/mmap.c
@ -1010,7 +1010,7 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
|
|||||||
* parameter) may establish ptes with the wrong permissions of NNNN
|
* parameter) may establish ptes with the wrong permissions of NNNN
|
||||||
* instead of the right permissions of XXXX.
|
* instead of the right permissions of XXXX.
|
||||||
*/
|
*/
|
||||||
struct vm_area_struct *vma_merge(struct mm_struct *mm,
|
struct vm_area_struct *vma_merge(struct vma_iterator *vmi, struct mm_struct *mm,
|
||||||
struct vm_area_struct *prev, unsigned long addr,
|
struct vm_area_struct *prev, unsigned long addr,
|
||||||
unsigned long end, unsigned long vm_flags,
|
unsigned long end, unsigned long vm_flags,
|
||||||
struct anon_vma *anon_vma, struct file *file,
|
struct anon_vma *anon_vma, struct file *file,
|
||||||
@ -1019,7 +1019,7 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
|
|||||||
struct anon_vma_name *anon_name)
|
struct anon_vma_name *anon_name)
|
||||||
{
|
{
|
||||||
pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
|
pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
|
||||||
struct vm_area_struct *mid, *next, *res;
|
struct vm_area_struct *mid, *next, *res = NULL;
|
||||||
int err = -1;
|
int err = -1;
|
||||||
bool merge_prev = false;
|
bool merge_prev = false;
|
||||||
bool merge_next = false;
|
bool merge_next = false;
|
||||||
@ -1085,26 +1085,11 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
|
|||||||
if (err)
|
if (err)
|
||||||
return NULL;
|
return NULL;
|
||||||
khugepaged_enter_vma(res, vm_flags);
|
khugepaged_enter_vma(res, vm_flags);
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct vm_area_struct *vmi_vma_merge(struct vma_iterator *vmi,
|
if (res)
|
||||||
struct mm_struct *mm,
|
|
||||||
struct vm_area_struct *prev, unsigned long addr,
|
|
||||||
unsigned long end, unsigned long vm_flags,
|
|
||||||
struct anon_vma *anon_vma, struct file *file,
|
|
||||||
pgoff_t pgoff, struct mempolicy *policy,
|
|
||||||
struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
|
|
||||||
struct anon_vma_name *anon_name)
|
|
||||||
{
|
|
||||||
struct vm_area_struct *tmp;
|
|
||||||
|
|
||||||
tmp = vma_merge(mm, prev, addr, end, vm_flags, anon_vma, file, pgoff,
|
|
||||||
policy, vm_userfaultfd_ctx, anon_name);
|
|
||||||
if (tmp)
|
|
||||||
vma_iter_set(vmi, end);
|
vma_iter_set(vmi, end);
|
||||||
|
|
||||||
return tmp;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2228,12 +2213,14 @@ static void unmap_region(struct mm_struct *mm, struct maple_tree *mt,
|
|||||||
* __split_vma() bypasses sysctl_max_map_count checking. We use this where it
|
* __split_vma() bypasses sysctl_max_map_count checking. We use this where it
|
||||||
* has already been checked or doesn't make sense to fail.
|
* has already been checked or doesn't make sense to fail.
|
||||||
*/
|
*/
|
||||||
int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
||||||
unsigned long addr, int new_below)
|
unsigned long addr, int new_below)
|
||||||
{
|
{
|
||||||
struct vm_area_struct *new;
|
struct vm_area_struct *new;
|
||||||
int err;
|
int err;
|
||||||
validate_mm_mt(mm);
|
unsigned long end = vma->vm_end;
|
||||||
|
|
||||||
|
validate_mm_mt(vma->vm_mm);
|
||||||
|
|
||||||
if (vma->vm_ops && vma->vm_ops->may_split) {
|
if (vma->vm_ops && vma->vm_ops->may_split) {
|
||||||
err = vma->vm_ops->may_split(vma, addr);
|
err = vma->vm_ops->may_split(vma, addr);
|
||||||
@ -2273,8 +2260,10 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||||||
err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
|
err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
|
||||||
|
|
||||||
/* Success. */
|
/* Success. */
|
||||||
if (!err)
|
if (!err) {
|
||||||
|
vma_iter_set(vmi, end);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Avoid vm accounting in close() operation */
|
/* Avoid vm accounting in close() operation */
|
||||||
new->vm_start = new->vm_end;
|
new->vm_start = new->vm_end;
|
||||||
@ -2289,46 +2278,21 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
|||||||
mpol_put(vma_policy(new));
|
mpol_put(vma_policy(new));
|
||||||
out_free_vma:
|
out_free_vma:
|
||||||
vm_area_free(new);
|
vm_area_free(new);
|
||||||
validate_mm_mt(mm);
|
validate_mm_mt(vma->vm_mm);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
int vmi__split_vma(struct vma_iterator *vmi, struct mm_struct *mm,
|
|
||||||
struct vm_area_struct *vma, unsigned long addr, int new_below)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned long end = vma->vm_end;
|
|
||||||
|
|
||||||
ret = __split_vma(mm, vma, addr, new_below);
|
|
||||||
if (!ret)
|
|
||||||
vma_iter_set(vmi, end);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Split a vma into two pieces at address 'addr', a new vma is allocated
|
* Split a vma into two pieces at address 'addr', a new vma is allocated
|
||||||
* either for the first part or the tail.
|
* either for the first part or the tail.
|
||||||
*/
|
*/
|
||||||
int split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
|
int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
||||||
unsigned long addr, int new_below)
|
unsigned long addr, int new_below)
|
||||||
{
|
{
|
||||||
if (mm->map_count >= sysctl_max_map_count)
|
if (vma->vm_mm->map_count >= sysctl_max_map_count)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
return __split_vma(mm, vma, addr, new_below);
|
return __split_vma(vmi, vma, addr, new_below);
|
||||||
}
|
|
||||||
|
|
||||||
int vmi_split_vma(struct vma_iterator *vmi, struct mm_struct *mm,
|
|
||||||
struct vm_area_struct *vma, unsigned long addr, int new_below)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
unsigned long end = vma->vm_end;
|
|
||||||
|
|
||||||
ret = split_vma(mm, vma, addr, new_below);
|
|
||||||
if (!ret)
|
|
||||||
vma_iter_set(vmi, end);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int munmap_sidetree(struct vm_area_struct *vma,
|
static inline int munmap_sidetree(struct vm_area_struct *vma,
|
||||||
@ -2388,7 +2352,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
|||||||
if (end < vma->vm_end && mm->map_count >= sysctl_max_map_count)
|
if (end < vma->vm_end && mm->map_count >= sysctl_max_map_count)
|
||||||
goto map_count_exceeded;
|
goto map_count_exceeded;
|
||||||
|
|
||||||
error = vmi__split_vma(vmi, mm, vma, start, 0);
|
error = __split_vma(vmi, vma, start, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto start_split_failed;
|
goto start_split_failed;
|
||||||
|
|
||||||
@ -2409,7 +2373,7 @@ do_vmi_align_munmap(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
|||||||
if (next->vm_end > end) {
|
if (next->vm_end > end) {
|
||||||
struct vm_area_struct *split;
|
struct vm_area_struct *split;
|
||||||
|
|
||||||
error = vmi__split_vma(vmi, mm, next, end, 1);
|
error = __split_vma(vmi, next, end, 1);
|
||||||
if (error)
|
if (error)
|
||||||
goto end_split_failed;
|
goto end_split_failed;
|
||||||
|
|
||||||
@ -2690,9 +2654,10 @@ cannot_expand:
|
|||||||
* vma again as we may succeed this time.
|
* vma again as we may succeed this time.
|
||||||
*/
|
*/
|
||||||
if (unlikely(vm_flags != vma->vm_flags && prev)) {
|
if (unlikely(vm_flags != vma->vm_flags && prev)) {
|
||||||
merge = vmi_vma_merge(&vmi, mm, prev, vma->vm_start,
|
merge = vma_merge(&vmi, mm, prev, vma->vm_start,
|
||||||
vma->vm_end, vma->vm_flags, NULL, vma->vm_file,
|
vma->vm_end, vma->vm_flags, NULL,
|
||||||
vma->vm_pgoff, NULL, NULL_VM_UFFD_CTX, NULL);
|
vma->vm_file, vma->vm_pgoff, NULL,
|
||||||
|
NULL_VM_UFFD_CTX, NULL);
|
||||||
if (merge) {
|
if (merge) {
|
||||||
/*
|
/*
|
||||||
* ->mmap() can change vma->vm_file and fput
|
* ->mmap() can change vma->vm_file and fput
|
||||||
@ -3249,7 +3214,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
|
|||||||
if (new_vma && new_vma->vm_start < addr + len)
|
if (new_vma && new_vma->vm_start < addr + len)
|
||||||
return NULL; /* should never get here */
|
return NULL; /* should never get here */
|
||||||
|
|
||||||
new_vma = vmi_vma_merge(&vmi, mm, prev, addr, addr + len, vma->vm_flags,
|
new_vma = vma_merge(&vmi, mm, prev, addr, addr + len, vma->vm_flags,
|
||||||
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
||||||
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
||||||
if (new_vma) {
|
if (new_vma) {
|
||||||
|
@ -642,7 +642,7 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb,
|
|||||||
* First try to merge with previous and/or next vma.
|
* First try to merge with previous and/or next vma.
|
||||||
*/
|
*/
|
||||||
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
|
||||||
*pprev = vmi_vma_merge(vmi, mm, *pprev, start, end, newflags,
|
*pprev = vma_merge(vmi, mm, *pprev, start, end, newflags,
|
||||||
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
|
||||||
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
||||||
if (*pprev) {
|
if (*pprev) {
|
||||||
@ -654,13 +654,13 @@ mprotect_fixup(struct vma_iterator *vmi, struct mmu_gather *tlb,
|
|||||||
*pprev = vma;
|
*pprev = vma;
|
||||||
|
|
||||||
if (start != vma->vm_start) {
|
if (start != vma->vm_start) {
|
||||||
error = vmi_split_vma(vmi, mm, vma, start, 1);
|
error = split_vma(vmi, vma, start, 1);
|
||||||
if (error)
|
if (error)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end != vma->vm_end) {
|
if (end != vma->vm_end) {
|
||||||
error = vmi_split_vma(vmi, mm, vma, end, 0);
|
error = split_vma(vmi, vma, end, 0);
|
||||||
if (error)
|
if (error)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
10
mm/mremap.c
10
mm/mremap.c
@ -1043,12 +1043,10 @@ SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
|
|||||||
* when a vma would be actually removed due to a merge.
|
* when a vma would be actually removed due to a merge.
|
||||||
*/
|
*/
|
||||||
if (!vma->vm_ops || !vma->vm_ops->close) {
|
if (!vma->vm_ops || !vma->vm_ops->close) {
|
||||||
vma = vmi_vma_merge(&vmi, mm, vma,
|
vma = vma_merge(&vmi, mm, vma, extension_start,
|
||||||
extension_start, extension_end,
|
extension_end, vma->vm_flags, vma->anon_vma,
|
||||||
vma->vm_flags, vma->anon_vma,
|
vma->vm_file, extension_pgoff, vma_policy(vma),
|
||||||
vma->vm_file, extension_pgoff,
|
vma->vm_userfaultfd_ctx, anon_vma_name(vma));
|
||||||
vma_policy(vma), vma->vm_userfaultfd_ctx,
|
|
||||||
anon_vma_name(vma));
|
|
||||||
} else if (vma_adjust(vma, vma->vm_start, addr + new_len,
|
} else if (vma_adjust(vma, vma->vm_start, addr + new_len,
|
||||||
vma->vm_pgoff, NULL)) {
|
vma->vm_pgoff, NULL)) {
|
||||||
vma = NULL;
|
vma = NULL;
|
||||||
|
@ -1297,18 +1297,20 @@ SYSCALL_DEFINE1(old_mmap, struct mmap_arg_struct __user *, arg)
|
|||||||
* split a vma into two pieces at address 'addr', a new vma is allocated either
|
* split a vma into two pieces at address 'addr', a new vma is allocated either
|
||||||
* for the first part or the tail.
|
* for the first part or the tail.
|
||||||
*/
|
*/
|
||||||
int vmi_split_vma(struct vma_iterator *vmi, struct mm_struct *mm,
|
int split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
|
||||||
struct vm_area_struct *vma, unsigned long addr, int new_below)
|
unsigned long addr, int new_below)
|
||||||
{
|
{
|
||||||
struct vm_area_struct *new;
|
struct vm_area_struct *new;
|
||||||
struct vm_region *region;
|
struct vm_region *region;
|
||||||
unsigned long npages;
|
unsigned long npages;
|
||||||
|
struct mm_struct *mm;
|
||||||
|
|
||||||
/* we're only permitted to split anonymous regions (these should have
|
/* we're only permitted to split anonymous regions (these should have
|
||||||
* only a single usage on the region) */
|
* only a single usage on the region) */
|
||||||
if (vma->vm_file)
|
if (vma->vm_file)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
mm = vma->vm_mm;
|
||||||
if (mm->map_count >= sysctl_max_map_count)
|
if (mm->map_count >= sysctl_max_map_count)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -1465,7 +1467,7 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len, struct list
|
|||||||
if (end != vma->vm_end && offset_in_page(end))
|
if (end != vma->vm_end && offset_in_page(end))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (start != vma->vm_start && end != vma->vm_end) {
|
if (start != vma->vm_start && end != vma->vm_end) {
|
||||||
ret = vmi_split_vma(&vmi, mm, vma, start, 1);
|
ret = split_vma(&vmi, vma, start, 1);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user