All of lore.kernel.org
 help / color / mirror / Atom feed
From: zhouchengming <zhouchengming1@huawei.com>
To: Zhou Chengming <zhouchengming1@huawei.com>
Cc: akpm@linux-foundation.org, hughd@google.com, aarcange@redhat.com,
	kirill.shutemov@linux.intel.com, vbabka@suse.cz,
	geliangtang@163.com, minchan@kernel.org, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org, guohanjun@huawei.com,
	dingtianhong@huawei.com, huawei.libin@huawei.com,
	thunder.leizhen@huawei.com, qiuxishi@huawei.com
Subject: Re: [PATCH v3] ksm: fix conflict between mmput and scan_get_next_rmap_item
Date: Sun, 8 May 2016 20:09:08 +0800	[thread overview]
Message-ID: <572F2C64.6040901@huawei.com> (raw)
In-Reply-To: <1462690586-50973-1-git-send-email-zhouchengming1@huawei.com>

Please ignore this patch v3. I forgot to change the function
unmerge_and_remove_all_rmap_items(). Patch v4 will be the
final version, I think.. Sorry for my carelessness.

Thanks!

On 2016/5/8 14:56, Zhou Chengming wrote:
> A concurrency issue about KSM in the function scan_get_next_rmap_item.
>
> task A (ksmd):				|task B (the mm's task):
> 					|
> mm = slot->mm;				|
> down_read(&mm->mmap_sem);		|
> 					|
> ...					|
> 					|
> spin_lock(&ksm_mmlist_lock);		|
> 					|
> ksm_scan.mm_slot go to the next slot;	|
> 					|
> spin_unlock(&ksm_mmlist_lock);		|
> 					|mmput() ->
> 					|	ksm_exit():
> 					|
> 					|spin_lock(&ksm_mmlist_lock);
> 					|if (mm_slot&&  ksm_scan.mm_slot != mm_slot) {
> 					|	if (!mm_slot->rmap_list) {
> 					|		easy_to_free = 1;
> 					|		...
> 					|
> 					|if (easy_to_free) {
> 					|	mmdrop(mm);
> 					|	...
> 					|
> 					|So this mm_struct may be freed in the mmput().
> 					|
> up_read(&mm->mmap_sem);			|
>
> As we can see above, the ksmd thread may access a mm_struct that already
> been freed to the kmem_cache.
> Suppose a fork will get this mm_struct from the kmem_cache, the ksmd thread
> then call up_read(&mm->mmap_sem), will cause mmap_sem.count to become -1.
>> From the suggestion of Andrea Arcangeli, unmerge_and_remove_all_rmap_items
> has the same SMP race condition, so fix it too. My prev fix in function
> scan_get_next_rmap_item will introduce a different SMP race condition,
> so just invert the up_read/spin_unlock order as Andrea Arcangeli said.
>
> Signed-off-by: Zhou Chengming<zhouchengming1@huawei.com>
> Suggested-by: Andrea Arcangeli<aarcange@redhat.com>
> Reviewed-by: Andrea Arcangeli<aarcange@redhat.com>
> ---
>   mm/ksm.c |   16 ++++++++++------
>   1 files changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/mm/ksm.c b/mm/ksm.c
> index ca6d2a0..b6dc387 100644
> --- a/mm/ksm.c
> +++ b/mm/ksm.c
> @@ -777,6 +777,7 @@ static int unmerge_and_remove_all_rmap_items(void)
>   		}
>
>   		remove_trailing_rmap_items(mm_slot,&mm_slot->rmap_list);
> +		up_read(&mm->mmap_sem);
>
>   		spin_lock(&ksm_mmlist_lock);
>   		ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next,
> @@ -784,16 +785,12 @@ static int unmerge_and_remove_all_rmap_items(void)
>   		if (ksm_test_exit(mm)) {
>   			hash_del(&mm_slot->link);
>   			list_del(&mm_slot->mm_list);
> -			spin_unlock(&ksm_mmlist_lock);
>
>   			free_mm_slot(mm_slot);
>   			clear_bit(MMF_VM_MERGEABLE,&mm->flags);
> -			up_read(&mm->mmap_sem);
>   			mmdrop(mm);
> -		} else {
> -			spin_unlock(&ksm_mmlist_lock);
> -			up_read(&mm->mmap_sem);
>   		}
> +		spin_unlock(&ksm_mmlist_lock);
>   	}
>
>   	/* Clean up stable nodes, but don't worry if some are still busy */
> @@ -1657,8 +1654,15 @@ next_mm:
>   		up_read(&mm->mmap_sem);
>   		mmdrop(mm);
>   	} else {
> -		spin_unlock(&ksm_mmlist_lock);
>   		up_read(&mm->mmap_sem);
> +		/*
> +		 * up_read(&mm->mmap_sem) first because after
> +		 * spin_unlock(&ksm_mmlist_lock) run, the "mm" may
> +		 * already have been freed under us by __ksm_exit()
> +		 * because the "mm_slot" is still hashed and
> +		 * ksm_scan.mm_slot doesn't point to it anymore.
> +		 */
> +		spin_unlock(&ksm_mmlist_lock);
>   	}
>
>   	/* Repeat until we've completed scanning the whole list */


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

WARNING: multiple messages have this Message-ID (diff)
From: zhouchengming <zhouchengming1@huawei.com>
To: Zhou Chengming <zhouchengming1@huawei.com>
Cc: <akpm@linux-foundation.org>, <hughd@google.com>,
	<aarcange@redhat.com>, <kirill.shutemov@linux.intel.com>,
	<vbabka@suse.cz>, <geliangtang@163.com>, <minchan@kernel.org>,
	<linux-mm@kvack.org>, <linux-kernel@vger.kernel.org>,
	<guohanjun@huawei.com>, <dingtianhong@huawei.com>,
	<huawei.libin@huawei.com>, <thunder.leizhen@huawei.com>,
	<qiuxishi@huawei.com>
Subject: Re: [PATCH v3] ksm: fix conflict between mmput and scan_get_next_rmap_item
Date: Sun, 8 May 2016 20:09:08 +0800	[thread overview]
Message-ID: <572F2C64.6040901@huawei.com> (raw)
In-Reply-To: <1462690586-50973-1-git-send-email-zhouchengming1@huawei.com>

Please ignore this patch v3. I forgot to change the function
unmerge_and_remove_all_rmap_items(). Patch v4 will be the
final version, I think.. Sorry for my carelessness.

Thanks!

On 2016/5/8 14:56, Zhou Chengming wrote:
> A concurrency issue about KSM in the function scan_get_next_rmap_item.
>
> task A (ksmd):				|task B (the mm's task):
> 					|
> mm = slot->mm;				|
> down_read(&mm->mmap_sem);		|
> 					|
> ...					|
> 					|
> spin_lock(&ksm_mmlist_lock);		|
> 					|
> ksm_scan.mm_slot go to the next slot;	|
> 					|
> spin_unlock(&ksm_mmlist_lock);		|
> 					|mmput() ->
> 					|	ksm_exit():
> 					|
> 					|spin_lock(&ksm_mmlist_lock);
> 					|if (mm_slot&&  ksm_scan.mm_slot != mm_slot) {
> 					|	if (!mm_slot->rmap_list) {
> 					|		easy_to_free = 1;
> 					|		...
> 					|
> 					|if (easy_to_free) {
> 					|	mmdrop(mm);
> 					|	...
> 					|
> 					|So this mm_struct may be freed in the mmput().
> 					|
> up_read(&mm->mmap_sem);			|
>
> As we can see above, the ksmd thread may access a mm_struct that already
> been freed to the kmem_cache.
> Suppose a fork will get this mm_struct from the kmem_cache, the ksmd thread
> then call up_read(&mm->mmap_sem), will cause mmap_sem.count to become -1.
>> From the suggestion of Andrea Arcangeli, unmerge_and_remove_all_rmap_items
> has the same SMP race condition, so fix it too. My prev fix in function
> scan_get_next_rmap_item will introduce a different SMP race condition,
> so just invert the up_read/spin_unlock order as Andrea Arcangeli said.
>
> Signed-off-by: Zhou Chengming<zhouchengming1@huawei.com>
> Suggested-by: Andrea Arcangeli<aarcange@redhat.com>
> Reviewed-by: Andrea Arcangeli<aarcange@redhat.com>
> ---
>   mm/ksm.c |   16 ++++++++++------
>   1 files changed, 10 insertions(+), 6 deletions(-)
>
> diff --git a/mm/ksm.c b/mm/ksm.c
> index ca6d2a0..b6dc387 100644
> --- a/mm/ksm.c
> +++ b/mm/ksm.c
> @@ -777,6 +777,7 @@ static int unmerge_and_remove_all_rmap_items(void)
>   		}
>
>   		remove_trailing_rmap_items(mm_slot,&mm_slot->rmap_list);
> +		up_read(&mm->mmap_sem);
>
>   		spin_lock(&ksm_mmlist_lock);
>   		ksm_scan.mm_slot = list_entry(mm_slot->mm_list.next,
> @@ -784,16 +785,12 @@ static int unmerge_and_remove_all_rmap_items(void)
>   		if (ksm_test_exit(mm)) {
>   			hash_del(&mm_slot->link);
>   			list_del(&mm_slot->mm_list);
> -			spin_unlock(&ksm_mmlist_lock);
>
>   			free_mm_slot(mm_slot);
>   			clear_bit(MMF_VM_MERGEABLE,&mm->flags);
> -			up_read(&mm->mmap_sem);
>   			mmdrop(mm);
> -		} else {
> -			spin_unlock(&ksm_mmlist_lock);
> -			up_read(&mm->mmap_sem);
>   		}
> +		spin_unlock(&ksm_mmlist_lock);
>   	}
>
>   	/* Clean up stable nodes, but don't worry if some are still busy */
> @@ -1657,8 +1654,15 @@ next_mm:
>   		up_read(&mm->mmap_sem);
>   		mmdrop(mm);
>   	} else {
> -		spin_unlock(&ksm_mmlist_lock);
>   		up_read(&mm->mmap_sem);
> +		/*
> +		 * up_read(&mm->mmap_sem) first because after
> +		 * spin_unlock(&ksm_mmlist_lock) run, the "mm" may
> +		 * already have been freed under us by __ksm_exit()
> +		 * because the "mm_slot" is still hashed and
> +		 * ksm_scan.mm_slot doesn't point to it anymore.
> +		 */
> +		spin_unlock(&ksm_mmlist_lock);
>   	}
>
>   	/* Repeat until we've completed scanning the whole list */

  reply	other threads:[~2016-05-08 12:09 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-05-08  6:56 [PATCH v3] ksm: fix conflict between mmput and scan_get_next_rmap_item Zhou Chengming
2016-05-08  6:56 ` Zhou Chengming
2016-05-08 12:09 ` zhouchengming [this message]
2016-05-08 12:09   ` zhouchengming

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=572F2C64.6040901@huawei.com \
    --to=zhouchengming1@huawei.com \
    --cc=aarcange@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=dingtianhong@huawei.com \
    --cc=geliangtang@163.com \
    --cc=guohanjun@huawei.com \
    --cc=huawei.libin@huawei.com \
    --cc=hughd@google.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=minchan@kernel.org \
    --cc=qiuxishi@huawei.com \
    --cc=thunder.leizhen@huawei.com \
    --cc=vbabka@suse.cz \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.