All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.