All of lore.kernel.org
 help / color / mirror / Atom feed
From: Miaohe Lin <linmiaohe@huawei.com>
To: David Hildenbrand <david@redhat.com>
Cc: <ying.huang@intel.com>, <hch@lst.de>, <dhowells@redhat.com>,
	<cl@linux.com>, <linux-mm@kvack.org>,
	<linux-kernel@vger.kernel.org>, <akpm@linux-foundation.org>,
	<mike.kravetz@oracle.com>, <naoya.horiguchi@nec.com>,
	Minchan Kim <minchan@kernel.org>
Subject: Re: [PATCH v2 2/4] mm/migration: remove unneeded lock page and PageMovable check
Date: Wed, 8 Jun 2022 21:31:58 +0800	[thread overview]
Message-ID: <e86786e5-a514-54ed-dfeb-ed1f57b173d4@huawei.com> (raw)
In-Reply-To: <56f013a8-b585-4683-a998-83ea0dc53d95@redhat.com>

On 2022/6/8 18:05, David Hildenbrand wrote:
> On 07.06.22 04:20, Miaohe Lin wrote:
>> On 2022/6/2 16:47, David Hildenbrand wrote:
>>> On 02.06.22 09:40, Miaohe Lin wrote:
>>>> On 2022/6/1 18:31, David Hildenbrand wrote:
>>>>> On 31.05.22 14:37, Miaohe Lin wrote:
>>>>>> On 2022/5/31 19:59, David Hildenbrand wrote:
>>>>>>> Sorry for the late reply, was on vacation.
>>>>>>
>>>>>> That's all right. Hope you have a great time. ;)
>>>>>>
>>>>>>>
>>>>>>>>>>
>>>>>>>>>> But for isolated page, PageLRU is cleared. So when the isolated page is released, __clear_page_lru_flags
>>>>>>>>>> won't be called. So we have to clear the PG_active and PG_unevictable here manully. So I think
>>>>>>>>>> this code block works. Or am I miss something again?
>>>>>>>>>
>>>>>>>>> Let's assume the following: page as freed by the owner and we enter
>>>>>>>>> unmap_and_move().
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> #1: enter unmap_and_move() // page_count is 1
>>>>>>>>> #2: enter isolate_movable_page() // page_count is 1
>>>>>>>>> #2: get_page_unless_zero() // page_count is now 2
>>>>>>>>> #1: if (page_count(page) == 1) { // does not trigger
>>>>>>>>> #2: put_page(page); // page_count is now 1
>>>>>>>>> #1: put_page(page); // page_count is now 0 -> freed
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> #1 will trigger __put_page() -> __put_single_page() ->
>>>>>>>>> __page_cache_release() will not clear the flags because it's not an LRU
>>>>>>>>> page at that point in time, right (-> isolated)?
>>>>>>>>
>>>>>>>> Sorry, you're right. I thought the old page will be freed via putback_lru_page which will
>>>>>>>> set PageLRU back instead of put_page directly. So if the above race occurs, PG_active and
>>>>>>>> PG_unevictable will remain set while page goes to the buddy and check_free_page will complain
>>>>>>>> about it. But it seems this is never witnessed?
>>>>>>>
>>>>>>> Maybe
>>>>>>>
>>>>>>> a) we were lucky so far and didn't trigger it
>>>>>>> b) the whole code block is dead code because we are missing something
>>>>>>> c) we are missing something else :)
>>>>>>
>>>>>> I think I found the things we missed in another email [1].
>>>>>> [1]: https://lore.kernel.org/all/948ea45e-3b2b-e16c-5b8c-4c34de0ea593@huawei.com/
>>>>>>
>>>>>> Paste the main content of [1] here:
>>>>>>
>>>>>> "
>>>>>> There are 3 cases in unmap_and_move:
>>>>>>
>>>>>> 1.page is freed through "if (page_count(page) == 1)" code block. This works
>>>>>> as PG_active and PG_unevictable are cleared here.
>>>>>>
>>>>>> 2. Failed to migrate the page. The page won't be release so we don't care about it.
>>>>>
>>>>> Right, page is un-isolated.
>>>>>
>>>>>>
>>>>>> 3. The page is migrated successfully. The PG_active and PG_unevictable are cleared
>>>>>> via folio_migrate_flags():
>>>>>>
>>>>>> 	if (folio_test_clear_active(folio)) {
>>>>>> 		VM_BUG_ON_FOLIO(folio_test_unevictable(folio), folio);
>>>>>> 		folio_set_active(newfolio);
>>>>>> 	} else if (folio_test_clear_unevictable(folio))
>>>>>> 		folio_set_unevictable(newfolio);
>>>>>
>>>>> Right.
>>>>>
>>>>>>
>>>>>> For the above race case, the page won't be freed through "if (page_count(page) == 1)" code block.
>>>>>> It will just be migrated and freed via put_page() after folio_migrate_flags() having cleared PG_active
>>>>>> and PG_unevictable.
>>>>>> "
>>>>>> Or Am I miss something again? :)
>>>>>
>>>>> For #1, I'm still not sure what would happen on a speculative reference.
>>>>>
>>>>> It's worth summarizing that
>>>>>
>>>>> a) free_pages_prepare() will clear both flags via page->flags &=
>>>>> ~PAGE_FLAGS_CHECK_AT_PREP;
>>>>>
>>>>> b) free_pages_prepare() will bail out if any flag is set in
>>>>> check_free_page().
>>>>>
>>>>> As we've never seen b) in the wild, this certainly has low priority, and
>>>>> maybe it really cannot happen right now.
>>>>>
>>>>> However, maybe really allowing these flags to be set when freeing the
>>>>> page and removing the "page_count(page) == 1" case from migration code
>>>>> would be the clean thing to do.
>>>>
>>>> IMHO, check_free_page is used to catch possible problem. There's the comment of PAGE_FLAGS_CHECK_AT_FREE:
>>>>
>>>> /*
>>>>  * Flags checked when a page is freed.  Pages being freed should not have
>>>>  * these flags set.  If they are, there is a problem.
>>>>  */
>>>> #define PAGE_FLAGS_CHECK_AT_FREE
>>>>
>>>> There might be an assumption: when page is freed, it shouldn't be an active or unevictable page. It should be
>>>> inactive and evictable. So allowing these flags to be set when freeing the page might not be a good idea?
>>>
>>> Yeah, and we'd be lifting that restriction because there is good reason
>>> to do so.
>>>
>>> Maybe we *could* special case for isolated pages; however, that adds
>>> runtime overhead. Of course, we could perform different checks for e.g.,
>>> DEBUG_VM vs !DEBUG_VM.
>>
>> I found there is one assumption about PG_active and PG_unevictable, i.e. in __folio_clear_lru_flags:
>>
>> 	/* this shouldn't happen, so leave the flags to bad_page() */
>> 	if (folio_test_active(folio) && folio_test_unevictable(folio))
>> 		return;
>>
>> If PG_active and PG_unevictable are both set, this case will be caught in the bad_page() via check_free_page().
>> There might be some other assumptions about PG_active and PG_unevictable. So I think it's not safe to lift that
>> restriction.
>>
>> But maybe we could limit this check within DEBUG_VM as you suggested. Am I supposed to do it?
> 
> Well, if you want, you can look into ways of cleaning that up and
> removing the "if there is more than one reference, the owner hasn't
> freed the page" condition, because there are corner cases where the
> owner might have freed the page but speculative references keep the
> refcount temporarily incremented.>

Let me queue it to my TODO list. :)

Thanks for your valuable suggestion!

  reply	other threads:[~2022-06-08 13:32 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-25 13:27 [PATCH v2 0/4] A few cleanup and fixup patches for migration Miaohe Lin
2022-04-25 13:27 ` [PATCH v2 1/4] mm/migration: reduce the rcu lock duration Miaohe Lin
2022-04-29  9:54   ` David Hildenbrand
2022-05-09  3:14     ` Miaohe Lin
2022-05-24 12:36     ` Miaohe Lin
2022-05-06  3:23   ` ying.huang
2022-05-09  3:20     ` Miaohe Lin
2022-04-25 13:27 ` [PATCH v2 2/4] mm/migration: remove unneeded lock page and PageMovable check Miaohe Lin
2022-04-29 10:07   ` David Hildenbrand
2022-05-09  8:51     ` Miaohe Lin
2022-05-11 15:23       ` David Hildenbrand
2022-05-12  2:25         ` Miaohe Lin
2022-05-12  7:10           ` David Hildenbrand
2022-05-12 13:26             ` Miaohe Lin
2022-05-12 16:50               ` David Hildenbrand
2022-05-16  2:44                 ` Miaohe Lin
2022-05-31 11:59                   ` David Hildenbrand
2022-05-31 12:37                     ` Miaohe Lin
2022-06-01 10:31                       ` David Hildenbrand
2022-06-02  7:40                         ` Miaohe Lin
2022-06-02  8:47                           ` David Hildenbrand
2022-06-07  2:20                             ` Miaohe Lin
2022-06-08 10:05                               ` David Hildenbrand
2022-06-08 13:31                                 ` Miaohe Lin [this message]
2022-05-24 12:47                 ` Miaohe Lin
2022-04-25 13:27 ` [PATCH v2 3/4] mm/migration: return errno when isolate_huge_page failed Miaohe Lin
2022-04-29 10:08   ` David Hildenbrand
2022-05-09  8:03     ` Miaohe Lin
2022-04-29 11:36   ` Muchun Song
2022-05-09  3:23     ` Miaohe Lin
2022-05-09  4:21       ` Muchun Song
2022-05-09  7:51         ` Miaohe Lin
2022-04-25 13:27 ` [PATCH v2 4/4] mm/migration: fix potential pte_unmap on an not mapped pte Miaohe Lin
2022-04-29  9:48   ` David Hildenbrand

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=e86786e5-a514-54ed-dfeb-ed1f57b173d4@huawei.com \
    --to=linmiaohe@huawei.com \
    --cc=akpm@linux-foundation.org \
    --cc=cl@linux.com \
    --cc=david@redhat.com \
    --cc=dhowells@redhat.com \
    --cc=hch@lst.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mike.kravetz@oracle.com \
    --cc=minchan@kernel.org \
    --cc=naoya.horiguchi@nec.com \
    --cc=ying.huang@intel.com \
    /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.