Linux-mm Archive on lore.kernel.org
 help / color / Atom feed
* [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy
@ 2019-10-10 13:58 Wei Yang
  2019-10-10 13:58 ` [Patch v2 2/2] mm/rmap.c: reuse mergeable anon_vma as parent when fork Wei Yang
  2019-10-10 15:29 ` [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Konstantin Khlebnikov
  0 siblings, 2 replies; 5+ messages in thread
From: Wei Yang @ 2019-10-10 13:58 UTC (permalink / raw)
  To: akpm, kirill.shutemov, jglisse, mike.kravetz, riel, khlebnikov,
	cai, shakeelb
  Cc: linux-mm, linux-kernel, Wei Yang

Before commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
hierarchy"), anon_vma_clone() doesn't change dst->anon_vma. While after
this commit, anon_vma_clone() will try to reuse an exist one on forking.

But this commit go a little bit further for the case not forking.
anon_vma_clone() is called from __vma_split(), __split_vma(), copy_vma()
and anon_vma_fork(). For the first three places, the purpose here is get
a copy of src and we don't expect to touch dst->anon_vma even it is
NULL. While after that commit, it is possible to reuse an anon_vma when
dst->anon_vma is NULL. This is not we intend to have.

This patch stop reuse anon_vma for non-fork cases.

Fix commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
hierarchy")

Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
---
 include/linux/rmap.h | 3 ++-
 mm/mmap.c            | 6 +++---
 mm/rmap.c            | 7 ++++---
 3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 988d176472df..963e6ab09b9b 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -142,7 +142,8 @@ static inline void anon_vma_unlock_read(struct anon_vma *anon_vma)
 void anon_vma_init(void);	/* create anon_vma_cachep */
 int  __anon_vma_prepare(struct vm_area_struct *);
 void unlink_anon_vmas(struct vm_area_struct *);
-int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
+int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
+		   bool reuse);
 int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
 
 static inline int anon_vma_prepare(struct vm_area_struct *vma)
diff --git a/mm/mmap.c b/mm/mmap.c
index 93f221785956..21e94f8ac4c7 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -791,7 +791,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
 			int error;
 
 			importer->anon_vma = exporter->anon_vma;
-			error = anon_vma_clone(importer, exporter);
+			error = anon_vma_clone(importer, exporter, false);
 			if (error)
 				return error;
 		}
@@ -2666,7 +2666,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
 	if (err)
 		goto out_free_vma;
 
-	err = anon_vma_clone(new, vma);
+	err = anon_vma_clone(new, vma, false);
 	if (err)
 		goto out_free_mpol;
 
@@ -3247,7 +3247,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
 		new_vma->vm_pgoff = pgoff;
 		if (vma_dup_policy(vma, new_vma))
 			goto out_free_vma;
-		if (anon_vma_clone(new_vma, vma))
+		if (anon_vma_clone(new_vma, vma, false))
 			goto out_free_mempol;
 		if (new_vma->vm_file)
 			get_file(new_vma->vm_file);
diff --git a/mm/rmap.c b/mm/rmap.c
index d9a23bb773bf..f729e4013613 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -258,7 +258,8 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
  * good chance of avoiding scanning the whole hierarchy when it searches where
  * page is mapped.
  */
-int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
+int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
+		   bool reuse)
 {
 	struct anon_vma_chain *avc, *pavc;
 	struct anon_vma *root = NULL;
@@ -286,7 +287,7 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
 		 * will always reuse it. Root anon_vma is never reused:
 		 * it has self-parent reference and at least one child.
 		 */
-		if (!dst->anon_vma && anon_vma != src->anon_vma &&
+		if (reuse && !dst->anon_vma && anon_vma != src->anon_vma &&
 				anon_vma->degree < 2)
 			dst->anon_vma = anon_vma;
 	}
@@ -329,7 +330,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
 	 * First, attach the new VMA to the parent VMA's anon_vmas,
 	 * so rmap can find non-COWed pages in child processes.
 	 */
-	error = anon_vma_clone(vma, pvma);
+	error = anon_vma_clone(vma, pvma, true);
 	if (error)
 		return error;
 
-- 
2.17.1



^ permalink raw reply	[flat|nested] 5+ messages in thread

* [Patch v2 2/2] mm/rmap.c: reuse mergeable anon_vma as parent when fork
  2019-10-10 13:58 [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Wei Yang
@ 2019-10-10 13:58 ` Wei Yang
  2019-10-10 15:29 ` [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Konstantin Khlebnikov
  1 sibling, 0 replies; 5+ messages in thread
From: Wei Yang @ 2019-10-10 13:58 UTC (permalink / raw)
  To: akpm, kirill.shutemov, jglisse, mike.kravetz, riel, khlebnikov,
	cai, shakeelb
  Cc: linux-mm, linux-kernel, Wei Yang

In function __anon_vma_prepare(), we will try to find anon_vma if it is
possible to reuse it. While on fork, the logic is different.

Since commit 5beb49305251 ("mm: change anon_vma linking to fix
multi-process server scalability issue"), function anon_vma_clone()
tries to allocate new anon_vma for child process. But the logic here
will allocate a new anon_vma for each vma, even in parent this vma
is mergeable and share the same anon_vma with its sibling. This may do
better for scalability issue, while it is not necessary to do so
especially after interval tree is used.

Commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma hierarchy")
tries to reuse some anon_vma by counting child anon_vma and attached
vmas. While for those mergeable anon_vmas, we can just reuse it and not
necessary to go through the logic.

After this change, kernel build test reduces 20% anon_vma allocation.

Do the same kernel build test, it shows run time in sys reduced 8.1%.

Origin

real	2m50.467s
user	17m52.002s
sys	1m51.953s

real	2m48.662s
user	17m55.464s
sys	1m50.553s

real	2m51.143s
user	17m59.687s
sys	1m53.600s

Patched

real	2m45.478s
user	17m37.069s
sys	1m42.671s

real	2m46.420s
user	17m45.970s
sys	1m43.175s

real	2m47.404s
user	17m51.531s
sys	1m43.005s

Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
---
 mm/rmap.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index f729e4013613..4314b9be70f6 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -250,7 +250,7 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
  * Attach the anon_vmas from src to dst.
  * Returns 0 on success, -ENOMEM on failure.
  *
- * If dst->anon_vma is NULL this function tries to find and reuse existing
+ * If reuse is true, this function tries to find and reuse existing
  * anon_vma which has no vmas and only one child anon_vma. This prevents
  * degradation of anon_vma hierarchy to endless linear chain in case of
  * constantly forking task. On the other hand, an anon_vma with more than one
@@ -263,6 +263,18 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
 {
 	struct anon_vma_chain *avc, *pavc;
 	struct anon_vma *root = NULL;
+	struct vm_area_struct *prev = dst->vm_prev, *pprev = src->vm_prev;
+
+	/*
+	 * If parent share anon_vma with its vm_prev, keep this sharing in in
+	 * child.
+	 *
+	 * 1. Parent has vm_prev, which implies we have vm_prev.
+	 * 2. Parent and its vm_prev have the same anon_vma.
+	 */
+	if (reuse && pprev && pprev->anon_vma == src->anon_vma)
+		dst->anon_vma = prev->anon_vma;
+
 
 	list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
 		struct anon_vma *anon_vma;
-- 
2.17.1



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy
  2019-10-10 13:58 [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Wei Yang
  2019-10-10 13:58 ` [Patch v2 2/2] mm/rmap.c: reuse mergeable anon_vma as parent when fork Wei Yang
@ 2019-10-10 15:29 ` Konstantin Khlebnikov
  2019-10-11  0:36   ` Wei Yang
  2019-10-11  1:23   ` Wei Yang
  1 sibling, 2 replies; 5+ messages in thread
From: Konstantin Khlebnikov @ 2019-10-10 15:29 UTC (permalink / raw)
  To: Wei Yang, akpm, kirill.shutemov, jglisse, mike.kravetz, riel,
	cai, shakeelb
  Cc: linux-mm, linux-kernel

On 10/10/2019 16.58, Wei Yang wrote:
> Before commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
> hierarchy"), anon_vma_clone() doesn't change dst->anon_vma. While after
> this commit, anon_vma_clone() will try to reuse an exist one on forking.
> 
> But this commit go a little bit further for the case not forking.
> anon_vma_clone() is called from __vma_split(), __split_vma(), copy_vma()
> and anon_vma_fork(). For the first three places, the purpose here is get
> a copy of src and we don't expect to touch dst->anon_vma even it is
> NULL. While after that commit, it is possible to reuse an anon_vma when
> dst->anon_vma is NULL. This is not we intend to have.

In all these cases dst->anon_vma is a copy of src->anon_vma except
anon_vma_fork where dst_>anon_vma explicitly set to NULL before call.

So reuse == true iff (!dst->anon_vma && src->anon_vma)

> 
> This patch stop reuse anon_vma for non-fork cases.
> 
> Fix commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
> hierarchy")
> 
> Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
> ---
>   include/linux/rmap.h | 3 ++-
>   mm/mmap.c            | 6 +++---
>   mm/rmap.c            | 7 ++++---
>   3 files changed, 9 insertions(+), 7 deletions(-)
> 
> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
> index 988d176472df..963e6ab09b9b 100644
> --- a/include/linux/rmap.h
> +++ b/include/linux/rmap.h
> @@ -142,7 +142,8 @@ static inline void anon_vma_unlock_read(struct anon_vma *anon_vma)
>   void anon_vma_init(void);	/* create anon_vma_cachep */
>   int  __anon_vma_prepare(struct vm_area_struct *);
>   void unlink_anon_vmas(struct vm_area_struct *);
> -int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
> +int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
> +		   bool reuse);
>   int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
>   
>   static inline int anon_vma_prepare(struct vm_area_struct *vma)
> diff --git a/mm/mmap.c b/mm/mmap.c
> index 93f221785956..21e94f8ac4c7 100644
> --- a/mm/mmap.c
> +++ b/mm/mmap.c
> @@ -791,7 +791,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
>   			int error;
>   
>   			importer->anon_vma = exporter->anon_vma;
> -			error = anon_vma_clone(importer, exporter);
> +			error = anon_vma_clone(importer, exporter, false);
>   			if (error)
>   				return error;
>   		}
> @@ -2666,7 +2666,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
>   	if (err)
>   		goto out_free_vma;
>   
> -	err = anon_vma_clone(new, vma);
> +	err = anon_vma_clone(new, vma, false);
>   	if (err)
>   		goto out_free_mpol;
>   
> @@ -3247,7 +3247,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
>   		new_vma->vm_pgoff = pgoff;
>   		if (vma_dup_policy(vma, new_vma))
>   			goto out_free_vma;
> -		if (anon_vma_clone(new_vma, vma))
> +		if (anon_vma_clone(new_vma, vma, false))
>   			goto out_free_mempol;
>   		if (new_vma->vm_file)
>   			get_file(new_vma->vm_file);
> diff --git a/mm/rmap.c b/mm/rmap.c
> index d9a23bb773bf..f729e4013613 100644
> --- a/mm/rmap.c
> +++ b/mm/rmap.c
> @@ -258,7 +258,8 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
>    * good chance of avoiding scanning the whole hierarchy when it searches where
>    * page is mapped.
>    */
> -int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
> +int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
> +		   bool reuse)
>   {
>   	struct anon_vma_chain *avc, *pavc;
>   	struct anon_vma *root = NULL;
> @@ -286,7 +287,7 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
>   		 * will always reuse it. Root anon_vma is never reused:
>   		 * it has self-parent reference and at least one child.
>   		 */
> -		if (!dst->anon_vma && anon_vma != src->anon_vma &&
> +		if (reuse && !dst->anon_vma && anon_vma != src->anon_vma &&
>   				anon_vma->degree < 2)
>   			dst->anon_vma = anon_vma;
>   	}
> @@ -329,7 +330,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
>   	 * First, attach the new VMA to the parent VMA's anon_vmas,
>   	 * so rmap can find non-COWed pages in child processes.
>   	 */
> -	error = anon_vma_clone(vma, pvma);
> +	error = anon_vma_clone(vma, pvma, true);
>   	if (error)
>   		return error;
>   
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy
  2019-10-10 15:29 ` [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Konstantin Khlebnikov
@ 2019-10-11  0:36   ` Wei Yang
  2019-10-11  1:23   ` Wei Yang
  1 sibling, 0 replies; 5+ messages in thread
From: Wei Yang @ 2019-10-11  0:36 UTC (permalink / raw)
  To: Konstantin Khlebnikov
  Cc: Wei Yang, akpm, kirill.shutemov, jglisse, mike.kravetz, riel,
	cai, shakeelb, linux-mm, linux-kernel

On Thu, Oct 10, 2019 at 06:29:32PM +0300, Konstantin Khlebnikov wrote:
>On 10/10/2019 16.58, Wei Yang wrote:
>> Before commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
>> hierarchy"), anon_vma_clone() doesn't change dst->anon_vma. While after
>> this commit, anon_vma_clone() will try to reuse an exist one on forking.
>> 
>> But this commit go a little bit further for the case not forking.
>> anon_vma_clone() is called from __vma_split(), __split_vma(), copy_vma()
>> and anon_vma_fork(). For the first three places, the purpose here is get
>> a copy of src and we don't expect to touch dst->anon_vma even it is
>> NULL. While after that commit, it is possible to reuse an anon_vma when
>> dst->anon_vma is NULL. This is not we intend to have.
>
>In all these cases dst->anon_vma is a copy of src->anon_vma except
>anon_vma_fork where dst_>anon_vma explicitly set to NULL before call.
>
>So reuse == true iff (!dst->anon_vma && src->anon_vma)
>

What if src->anon_vma is NULL?

>> 
>> This patch stop reuse anon_vma for non-fork cases.
>> 
>> Fix commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
>> hierarchy")
>> 
>> Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
>> ---
>>   include/linux/rmap.h | 3 ++-
>>   mm/mmap.c            | 6 +++---
>>   mm/rmap.c            | 7 ++++---
>>   3 files changed, 9 insertions(+), 7 deletions(-)
>> 
>> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
>> index 988d176472df..963e6ab09b9b 100644
>> --- a/include/linux/rmap.h
>> +++ b/include/linux/rmap.h
>> @@ -142,7 +142,8 @@ static inline void anon_vma_unlock_read(struct anon_vma *anon_vma)
>>   void anon_vma_init(void);	/* create anon_vma_cachep */
>>   int  __anon_vma_prepare(struct vm_area_struct *);
>>   void unlink_anon_vmas(struct vm_area_struct *);
>> -int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
>> +int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
>> +		   bool reuse);
>>   int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
>>   static inline int anon_vma_prepare(struct vm_area_struct *vma)
>> diff --git a/mm/mmap.c b/mm/mmap.c
>> index 93f221785956..21e94f8ac4c7 100644
>> --- a/mm/mmap.c
>> +++ b/mm/mmap.c
>> @@ -791,7 +791,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
>>   			int error;
>>   			importer->anon_vma = exporter->anon_vma;
>> -			error = anon_vma_clone(importer, exporter);
>> +			error = anon_vma_clone(importer, exporter, false);
>>   			if (error)
>>   				return error;
>>   		}
>> @@ -2666,7 +2666,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
>>   	if (err)
>>   		goto out_free_vma;
>> -	err = anon_vma_clone(new, vma);
>> +	err = anon_vma_clone(new, vma, false);
>>   	if (err)
>>   		goto out_free_mpol;
>> @@ -3247,7 +3247,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
>>   		new_vma->vm_pgoff = pgoff;
>>   		if (vma_dup_policy(vma, new_vma))
>>   			goto out_free_vma;
>> -		if (anon_vma_clone(new_vma, vma))
>> +		if (anon_vma_clone(new_vma, vma, false))
>>   			goto out_free_mempol;
>>   		if (new_vma->vm_file)
>>   			get_file(new_vma->vm_file);
>> diff --git a/mm/rmap.c b/mm/rmap.c
>> index d9a23bb773bf..f729e4013613 100644
>> --- a/mm/rmap.c
>> +++ b/mm/rmap.c
>> @@ -258,7 +258,8 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
>>    * good chance of avoiding scanning the whole hierarchy when it searches where
>>    * page is mapped.
>>    */
>> -int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
>> +int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
>> +		   bool reuse)
>>   {
>>   	struct anon_vma_chain *avc, *pavc;
>>   	struct anon_vma *root = NULL;
>> @@ -286,7 +287,7 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
>>   		 * will always reuse it. Root anon_vma is never reused:
>>   		 * it has self-parent reference and at least one child.
>>   		 */
>> -		if (!dst->anon_vma && anon_vma != src->anon_vma &&
>> +		if (reuse && !dst->anon_vma && anon_vma != src->anon_vma &&
>>   				anon_vma->degree < 2)
>>   			dst->anon_vma = anon_vma;
>>   	}
>> @@ -329,7 +330,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
>>   	 * First, attach the new VMA to the parent VMA's anon_vmas,
>>   	 * so rmap can find non-COWed pages in child processes.
>>   	 */
>> -	error = anon_vma_clone(vma, pvma);
>> +	error = anon_vma_clone(vma, pvma, true);
>>   	if (error)
>>   		return error;
>> 

-- 
Wei Yang
Help you, Help me


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy
  2019-10-10 15:29 ` [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Konstantin Khlebnikov
  2019-10-11  0:36   ` Wei Yang
@ 2019-10-11  1:23   ` Wei Yang
  1 sibling, 0 replies; 5+ messages in thread
From: Wei Yang @ 2019-10-11  1:23 UTC (permalink / raw)
  To: Konstantin Khlebnikov
  Cc: Wei Yang, akpm, kirill.shutemov, jglisse, mike.kravetz, riel,
	cai, shakeelb, linux-mm, linux-kernel

On Thu, Oct 10, 2019 at 06:29:32PM +0300, Konstantin Khlebnikov wrote:
>On 10/10/2019 16.58, Wei Yang wrote:
>> Before commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
>> hierarchy"), anon_vma_clone() doesn't change dst->anon_vma. While after
>> this commit, anon_vma_clone() will try to reuse an exist one on forking.
>> 
>> But this commit go a little bit further for the case not forking.
>> anon_vma_clone() is called from __vma_split(), __split_vma(), copy_vma()
>> and anon_vma_fork(). For the first three places, the purpose here is get
>> a copy of src and we don't expect to touch dst->anon_vma even it is
>> NULL. While after that commit, it is possible to reuse an anon_vma when
>> dst->anon_vma is NULL. This is not we intend to have.
>
>In all these cases dst->anon_vma is a copy of src->anon_vma except
>anon_vma_fork where dst_>anon_vma explicitly set to NULL before call.
>
>So reuse == true iff (!dst->anon_vma && src->anon_vma)
>

Ok, I think you are right. Thanks

>> 
>> This patch stop reuse anon_vma for non-fork cases.
>> 
>> Fix commit 7a3ef208e662 ("mm: prevent endless growth of anon_vma
>> hierarchy")
>> 
>> Signed-off-by: Wei Yang <richardw.yang@linux.intel.com>
>> ---
>>   include/linux/rmap.h | 3 ++-
>>   mm/mmap.c            | 6 +++---
>>   mm/rmap.c            | 7 ++++---
>>   3 files changed, 9 insertions(+), 7 deletions(-)
>> 
>> diff --git a/include/linux/rmap.h b/include/linux/rmap.h
>> index 988d176472df..963e6ab09b9b 100644
>> --- a/include/linux/rmap.h
>> +++ b/include/linux/rmap.h
>> @@ -142,7 +142,8 @@ static inline void anon_vma_unlock_read(struct anon_vma *anon_vma)
>>   void anon_vma_init(void);	/* create anon_vma_cachep */
>>   int  __anon_vma_prepare(struct vm_area_struct *);
>>   void unlink_anon_vmas(struct vm_area_struct *);
>> -int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
>> +int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
>> +		   bool reuse);
>>   int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
>>   static inline int anon_vma_prepare(struct vm_area_struct *vma)
>> diff --git a/mm/mmap.c b/mm/mmap.c
>> index 93f221785956..21e94f8ac4c7 100644
>> --- a/mm/mmap.c
>> +++ b/mm/mmap.c
>> @@ -791,7 +791,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
>>   			int error;
>>   			importer->anon_vma = exporter->anon_vma;
>> -			error = anon_vma_clone(importer, exporter);
>> +			error = anon_vma_clone(importer, exporter, false);
>>   			if (error)
>>   				return error;
>>   		}
>> @@ -2666,7 +2666,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
>>   	if (err)
>>   		goto out_free_vma;
>> -	err = anon_vma_clone(new, vma);
>> +	err = anon_vma_clone(new, vma, false);
>>   	if (err)
>>   		goto out_free_mpol;
>> @@ -3247,7 +3247,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
>>   		new_vma->vm_pgoff = pgoff;
>>   		if (vma_dup_policy(vma, new_vma))
>>   			goto out_free_vma;
>> -		if (anon_vma_clone(new_vma, vma))
>> +		if (anon_vma_clone(new_vma, vma, false))
>>   			goto out_free_mempol;
>>   		if (new_vma->vm_file)
>>   			get_file(new_vma->vm_file);
>> diff --git a/mm/rmap.c b/mm/rmap.c
>> index d9a23bb773bf..f729e4013613 100644
>> --- a/mm/rmap.c
>> +++ b/mm/rmap.c
>> @@ -258,7 +258,8 @@ static inline void unlock_anon_vma_root(struct anon_vma *root)
>>    * good chance of avoiding scanning the whole hierarchy when it searches where
>>    * page is mapped.
>>    */
>> -int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
>> +int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src,
>> +		   bool reuse)
>>   {
>>   	struct anon_vma_chain *avc, *pavc;
>>   	struct anon_vma *root = NULL;
>> @@ -286,7 +287,7 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
>>   		 * will always reuse it. Root anon_vma is never reused:
>>   		 * it has self-parent reference and at least one child.
>>   		 */
>> -		if (!dst->anon_vma && anon_vma != src->anon_vma &&
>> +		if (reuse && !dst->anon_vma && anon_vma != src->anon_vma &&
>>   				anon_vma->degree < 2)
>>   			dst->anon_vma = anon_vma;
>>   	}
>> @@ -329,7 +330,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
>>   	 * First, attach the new VMA to the parent VMA's anon_vmas,
>>   	 * so rmap can find non-COWed pages in child processes.
>>   	 */
>> -	error = anon_vma_clone(vma, pvma);
>> +	error = anon_vma_clone(vma, pvma, true);
>>   	if (error)
>>   		return error;
>> 

-- 
Wei Yang
Help you, Help me


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, back to index

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-10 13:58 [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Wei Yang
2019-10-10 13:58 ` [Patch v2 2/2] mm/rmap.c: reuse mergeable anon_vma as parent when fork Wei Yang
2019-10-10 15:29 ` [Patch v2 1/2] mm/rmap.c: don't reuse anon_vma if we just want a copy Konstantin Khlebnikov
2019-10-11  0:36   ` Wei Yang
2019-10-11  1:23   ` Wei Yang

Linux-mm Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-mm/0 linux-mm/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-mm linux-mm/ https://lore.kernel.org/linux-mm \
		linux-mm@kvack.org linux-mm@archiver.kernel.org
	public-inbox-index linux-mm

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kvack.linux-mm


AGPL code for this site: git clone https://public-inbox.org/ public-inbox