* [PATCH] mm: mmap: Merge vma after call_mmap() if possible
@ 2020-07-14 3:07 linmiaohe
2020-07-14 3:20 ` Andrew Morton
2020-07-16 22:24 ` Andrew Morton
0 siblings, 2 replies; 6+ messages in thread
From: linmiaohe @ 2020-07-14 3:07 UTC (permalink / raw)
To: akpm; +Cc: linux-mm, linux-kernel, linmiaohe
From: Miaohe Lin <linmiaohe@huawei.com>
The vm_flags may be changed after call_mmap() because drivers may set some
flags for their own purpose. As a result, we failed to merge the adjacent
vma due to the different vm_flags as userspace can't pass in the same one.
Try to merge vma after call_mmap() to fix this issue.
Signed-off-by: Hongxiang Lou <louhongxiang@huawei.com>
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
---
mm/mmap.c | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c
index 59a4682ebf3f..9568117471f8 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1689,7 +1689,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
struct list_head *uf)
{
struct mm_struct *mm = current->mm;
- struct vm_area_struct *vma, *prev;
+ struct vm_area_struct *vma, *prev, *merge;
int error;
struct rb_node **rb_link, *rb_parent;
unsigned long charged = 0;
@@ -1773,6 +1773,20 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
if (error)
goto unmap_and_free_vma;
+ /* If vm_flags changed after call_mmap(), we should try merge vma again
+ * as we may succeed this time.
+ */
+ if (unlikely(vm_flags != vma->vm_flags && prev)) {
+ merge = vma_merge(mm, prev, vma->vm_start, vma->vm_end, vma->vm_flags,
+ NULL, vma->vm_file, vma->vm_pgoff, NULL, NULL_VM_UFFD_CTX);
+ if (merge) {
+ fput(file);
+ vm_area_free(vma);
+ vma = merge;
+ goto unmap_writable;
+ }
+ }
+
/* Can addr have changed??
*
* Answer: Yes, several device drivers can do it in their
@@ -1795,6 +1809,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
vma_link(mm, vma, prev, rb_link, rb_parent);
/* Once vma denies write, undo our temporary denial count */
if (file) {
+unmap_writable:
if (vm_flags & VM_SHARED)
mapping_unmap_writable(file->f_mapping);
if (vm_flags & VM_DENYWRITE)
--
2.19.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] mm: mmap: Merge vma after call_mmap() if possible
2020-07-14 3:07 [PATCH] mm: mmap: Merge vma after call_mmap() if possible linmiaohe
@ 2020-07-14 3:20 ` Andrew Morton
2020-07-16 22:24 ` Andrew Morton
1 sibling, 0 replies; 6+ messages in thread
From: Andrew Morton @ 2020-07-14 3:20 UTC (permalink / raw)
To: linmiaohe; +Cc: linux-mm, linux-kernel
On Tue, 14 Jul 2020 11:07:44 +0800 linmiaohe <linmiaohe@huawei.com> wrote:
> The vm_flags may be changed after call_mmap() because drivers may set some
> flags for their own purpose. As a result, we failed to merge the adjacent
> vma due to the different vm_flags as userspace can't pass in the same one.
> Try to merge vma after call_mmap() to fix this issue.
Which drivers do this?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm: mmap: Merge vma after call_mmap() if possible
2020-07-14 3:07 [PATCH] mm: mmap: Merge vma after call_mmap() if possible linmiaohe
2020-07-14 3:20 ` Andrew Morton
@ 2020-07-16 22:24 ` Andrew Morton
1 sibling, 0 replies; 6+ messages in thread
From: Andrew Morton @ 2020-07-16 22:24 UTC (permalink / raw)
To: linmiaohe; +Cc: linux-mm, linux-kernel
On Tue, 14 Jul 2020 11:07:44 +0800 linmiaohe <linmiaohe@huawei.com> wrote:
> From: Miaohe Lin <linmiaohe@huawei.com>
>
> The vm_flags may be changed after call_mmap() because drivers may set some
> flags for their own purpose. As a result, we failed to merge the adjacent
> vma due to the different vm_flags as userspace can't pass in the same one.
> Try to merge vma after call_mmap() to fix this issue.
>
> Signed-off-by: Hongxiang Lou <louhongxiang@huawei.com>
> Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
> ---
> mm/mmap.c | 17 ++++++++++++++++-
> 1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 59a4682ebf3f..9568117471f8 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -1689,7 +1689,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
> struct list_head *uf)
> {
> struct mm_struct *mm = current->mm;
> - struct vm_area_struct *vma, *prev;
> + struct vm_area_struct *vma, *prev, *merge;
> int error;
> struct rb_node **rb_link, *rb_parent;
> unsigned long charged = 0;
> @@ -1773,6 +1773,20 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
> if (error)
> goto unmap_and_free_vma;
>
> + /* If vm_flags changed after call_mmap(), we should try merge vma again
> + * as we may succeed this time.
> + */
> + if (unlikely(vm_flags != vma->vm_flags && prev)) {
> + merge = vma_merge(mm, prev, vma->vm_start, vma->vm_end, vma->vm_flags,
> + NULL, vma->vm_file, vma->vm_pgoff, NULL, NULL_VM_UFFD_CTX);
> + if (merge) {
> + fput(file);
> + vm_area_free(vma);
> + vma = merge;
> + goto unmap_writable;
Shouldn't we update local variable `vm_flags' here, to pick up the
change? And possibly `addr'?
> + }
> + }
> +
> /* Can addr have changed??
> *
> * Answer: Yes, several device drivers can do it in their
> @@ -1795,6 +1809,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
> vma_link(mm, vma, prev, rb_link, rb_parent);
> /* Once vma denies write, undo our temporary denial count */
> if (file) {
> +unmap_writable:
> if (vm_flags & VM_SHARED)
> mapping_unmap_writable(file->f_mapping);
> if (vm_flags & VM_DENYWRITE)
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm: mmap: Merge vma after call_mmap() if possible
@ 2020-07-17 1:04 linmiaohe
0 siblings, 0 replies; 6+ messages in thread
From: linmiaohe @ 2020-07-17 1:04 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-mm, linux-kernel
Andrew Morton <akpm@linux-foundation.org> wrote:
>On Tue, 14 Jul 2020 11:07:44 +0800 linmiaohe <linmiaohe@huawei.com> wrote:
>
>> From: Miaohe Lin <linmiaohe@huawei.com>
>>
>> The vm_flags may be changed after call_mmap() because drivers may set
>> some flags for their own purpose. As a result, we failed to merge the
>> adjacent vma due to the different vm_flags as userspace can't pass in the same one.
>> Try to merge vma after call_mmap() to fix this issue.
>>
>> Signed-off-by: Hongxiang Lou <louhongxiang@huawei.com>
>> Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
>> ---
>> + /* If vm_flags changed after call_mmap(), we should try merge vma again
>> + * as we may succeed this time.
>> + */
>> + if (unlikely(vm_flags != vma->vm_flags && prev)) {
>> + merge = vma_merge(mm, prev, vma->vm_start, vma->vm_end, vma->vm_flags,
>> + NULL, vma->vm_file, vma->vm_pgoff, NULL, NULL_VM_UFFD_CTX);
>> + if (merge) {
>> + fput(file);
>> + vm_area_free(vma);
>> + vma = merge;
>> + goto unmap_writable;
>
>Shouldn't we update local variable `vm_flags' here, to pick up the change? And possibly `addr'?
Yes, we should. `vm_flags` and `addr` should be updated to continue the work. Many thanks for your
great review. I will fix it and test again. I will send a patch v2 soon.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm: mmap: Merge vma after call_mmap() if possible
@ 2020-07-16 7:33 linmiaohe
0 siblings, 0 replies; 6+ messages in thread
From: linmiaohe @ 2020-07-16 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-mm, linux-kernel
linmiaohe <linmiaohe@huawei.com> wrote:
>Andrew Morton <akpm@linux-foundation.org> wrote:
> On Tue, 14 Jul 2020 11:07:44 +0800 linmiaohe <linmiaohe@huawei.com> wrote:
>>
>>> The vm_flags may be changed after call_mmap() because drivers may set
>>> some flags for their own purpose. As a result, we failed to merge the
>>> adjacent vma due to the different vm_flags as userspace can't pass in the same one.
>>> Try to merge vma after call_mmap() to fix this issue.
>>
>>Which drivers do this?
>
>> I searched the code and I see many drivers change the vm_flags, such as aio_ring_mmap set VM_DONTEXPAND and amdgpu_mmap , binder_mmap also change the vm_flags , and so on...
>>
>>Thanks.
>>
I'am sorry. I offered the VM_DONTEXPAND case to you which belongs to VM_SPECIAL. I found some other cases:
i810_mmap_buffers:
set VM_DONTCOPY
dax_mmap:
ext4_file_mmap:
xfs_file_mmap:
set VM_HUGEPAGE
These vm_flags don't belong to VM_SPECIAL and should be vma mergeable case.
In fact, this problem is found on my own product env. We set VM_DONTCOPY in driver mmap ops, and we got this:
400000000000-400000001000 rw-s 105cee000 00:06 64086 /dev/...
400000001000-400000002000 rw-s 105cef000 00:06 64086 /dev/...
400000002000-400000003000 rw-s 105cf0000 00:06 64086 /dev/...
400000003000-400000004000 rw-s 105cf1000 00:06 64086 /dev/...
400000004000-400000005000 rw-s 105cf2000 00:06 64086 /dev/...
400000005000-400000006000 rw-s 105cf3000 00:06 64086 /dev/...
400000006000-400000007000 rw-s 105cf4000 00:06 64086 /dev/...
400000007000-400000008000 rw-s 105cf5000 00:06 64086 /dev/...
400000008000-400000009000 rw-s 105cf6000 00:06 64086 /dev/...
400000009000-40000000a000 rw-s 105cf7000 00:06 64086 /dev/...
40000000a000-40000000b000 rw-s 105cf8000 00:06 64086 /dev/...
40000000b000-40000000c000 rw-s 105cf9000 00:06 64086 /dev/...
40000000c000-40000000d000 rw-s 105cfa000 00:06 64086 /dev/...
40000000d000-40000000e000 rw-s 105cfb000 00:06 64086 /dev/...
40000000e000-40000000f000 rw-s 105cfc000 00:06 64086 /dev/...
40000000f000-400000010000 rw-s 105cfd000 00:06 64086 /dev/...
400000010000-400000011000 rw-s 105cfe000 00:06 64086 /dev/...
400000011000-400000012000 rw-s 105cff000 00:06 64086 /dev/...
400000012000-400000013000 rw-s 105d00000 00:06 64086 /dev/...
400000013000-400000014000 rw-s 105d01000 00:06 64086 /dev/...
400000014000-400000015000 rw-s 105d02000 00:06 64086 /dev/...
400000015000-400000016000 rw-s 105d03000 00:06 64086 /dev/...
400000016000-400000017000 rw-s 105d04000 00:06 64086 /dev/...
400000017000-400000018000 rw-s 105d05000 00:06 64086 /dev/...
400000018000-400000019000 rw-s 105d06000 00:06 64086 /dev/...
400000019000-40000001a000 rw-s 105d07000 00:06 64086 /dev/...
40000001a000-40000001b000 rw-s 105d08000 00:06 64086 /dev/...
40000001b000-40000001c000 rw-s 105d09000 00:06 64086 /dev/...
40000001c000-40000001d000 rw-s 105d0a000 00:06 64086 /dev/...
40000001d000-40000001e000 rw-s 105d0b000 00:06 64086 /dev/...
40000001e000-40000001f000 rw-s 105d0c000 00:06 64086 /dev/...
The vma flags are same, vma address are adjacent, belong to same file and so on...
I believe this expose the old uncommon bug. I hope I explain it clearly this time.
Many thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] mm: mmap: Merge vma after call_mmap() if possible
@ 2020-07-14 3:55 linmiaohe
0 siblings, 0 replies; 6+ messages in thread
From: linmiaohe @ 2020-07-14 3:55 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-mm, linux-kernel
Andrew Morton <akpm@linux-foundation.org> wrote:
> On Tue, 14 Jul 2020 11:07:44 +0800 linmiaohe <linmiaohe@huawei.com> wrote:
>
>> The vm_flags may be changed after call_mmap() because drivers may set
>> some flags for their own purpose. As a result, we failed to merge the
>> adjacent vma due to the different vm_flags as userspace can't pass in the same one.
>> Try to merge vma after call_mmap() to fix this issue.
>
>Which drivers do this?
I searched the code and I see many drivers change the vm_flags, such as aio_ring_mmap set
VM_DONTEXPAND and amdgpu_mmap , binder_mmap also change the vm_flags , and so on...
Thanks.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-07-17 1:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-14 3:07 [PATCH] mm: mmap: Merge vma after call_mmap() if possible linmiaohe
2020-07-14 3:20 ` Andrew Morton
2020-07-16 22:24 ` Andrew Morton
2020-07-14 3:55 linmiaohe
2020-07-16 7:33 linmiaohe
2020-07-17 1:04 linmiaohe
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.