[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <877cvq8gng.fsf@yhuang6-desk2.ccr.corp.intel.com>
Date: Thu, 09 Mar 2023 16:37:07 +0800
From: "Huang, Ying" <ying.huang@...el.com>
To: Vlastimil Babka <vbabka@...e.cz>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>,
Andrew Morton <akpm@...ux-foundation.org>, linux-mm@...ck.org,
mm-commits@...r.kernel.org, linux-kernel@...r.kernel.org,
Matthew Wilcox <willy@...radead.org>
Subject: Re: [GIT PULL] hotfixes for 6.3-rc1
Vlastimil Babka <vbabka@...e.cz> writes:
> On 3/6/23 02:25, Huang, Ying wrote:
>> Hi, Linus,
>>
>> Linus Torvalds <torvalds@...ux-foundation.org> writes:
>>
>>> On Sat, Mar 4, 2023 at 3:21 PM Andrew Morton <akpm@...ux-foundation.org> wrote:
>>>>
>>>> Ah. Ying did it this way:
>>>
>>> Yeah, I saw that patch flying past, but I actually think that it only
>>> silences the warning almost by mistake. There's nothing fundamental in
>>> there that a compiler wouldn't just follow across two assignments, and
>>> it just happens to now not trigger any more.
>>>
>>> Assigning to a union entry is a more fundamental operation in that
>>> respect. Not that the compiler still doesn't see that it's assigning a
>>> value that in the end is not really type compatible, so a different
>>> version of gcc could still warn, but at that point I feel like it's
>>> more of an actual compiler bug than just "oh, the compiler didn't
>>> happen to follow the cast through a temporary".
>>
>> Yes. Your fix is much better. This can be used for
>> __page_set_anon_rmap() family too to make the code look better?
>
> Those are trickier due to the PAGE_MAPPING_ANON tagging bit which your
> code doesn't need to handle because you can simply store an untagged
> anon_vma pointer. Otherwise we could have the union at the struct page
> level already (but probably not at this point as IIRC Matthew is
> planning to have completely separate types for anon and file folios).
>
> So right now we have e.g. folio_get_anon_vma() using unsigned long as
> the intermediate variable, page_move_anon_rmap() using a void *
> variable, __page_set_anon_rmap() casting through a (void *) ... Is there
> a single recommended way for "tagged pointers" that we could unify that to?
Ah, you are right. We need to deal with tagging bit and maybe struct
movable_operations *. I tried to write the below debug patch (only
build test it). The code adds 1 or 2 lines for each function. But to
be honest, the original force casting method appears more natural to me.
Best Regards,
Huang, Ying
---------------------------8<------------------------------------
>From 68a0f54921beca8aeaa8fe78867e62b5a66658b8 Mon Sep 17 00:00:00 2001
From: Huang Ying <ying.huang@...el.com>
Date: Thu, 9 Mar 2023 15:29:58 +0800
Subject: [PATCH] dbg mapping_ptr
---
mm/rmap.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/mm/rmap.c b/mm/rmap.c
index 8632e02661ac..50ee208baff9 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -466,6 +466,13 @@ void __init anon_vma_init(void)
SLAB_PANIC|SLAB_ACCOUNT);
}
+union mapping_ptr {
+ struct address_space *mapping;
+ unsigned long tag;
+ struct anon_vma *anon_vma;
+ struct movable_operations *mops;
+};
+
/*
* Getting a lock on a stable anon_vma from a page off the LRU is tricky!
*
@@ -493,16 +500,17 @@ void __init anon_vma_init(void)
struct anon_vma *folio_get_anon_vma(struct folio *folio)
{
struct anon_vma *anon_vma = NULL;
- unsigned long anon_mapping;
+ union mapping_ptr mptr;
rcu_read_lock();
- anon_mapping = (unsigned long)READ_ONCE(folio->mapping);
- if ((anon_mapping & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON)
+ mptr.mapping = READ_ONCE(folio->mapping);
+ if ((mptr.tag & PAGE_MAPPING_FLAGS) != PAGE_MAPPING_ANON)
goto out;
if (!folio_mapped(folio))
goto out;
- anon_vma = (struct anon_vma *) (anon_mapping - PAGE_MAPPING_ANON);
+ mptr.tag &= ~PAGE_MAPPING_FLAGS;
+ anon_vma = mptr.anon_vma;
if (!atomic_inc_not_zero(&anon_vma->refcount)) {
anon_vma = NULL;
goto out;
@@ -1115,18 +1123,20 @@ int folio_total_mapcount(struct folio *folio)
void page_move_anon_rmap(struct page *page, struct vm_area_struct *vma)
{
void *anon_vma = vma->anon_vma;
+ union mapping_ptr mptr;
struct folio *folio = page_folio(page);
VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio);
VM_BUG_ON_VMA(!anon_vma, vma);
- anon_vma += PAGE_MAPPING_ANON;
+ mptr.anon_vma = anon_vma;
+ mptr.tag |= PAGE_MAPPING_ANON;
/*
* Ensure that anon_vma and the PAGE_MAPPING_ANON bit are written
* simultaneously, so a concurrent reader (eg folio_referenced()'s
* folio_test_anon()) will not see one without the other.
*/
- WRITE_ONCE(folio->mapping, anon_vma);
+ WRITE_ONCE(folio->mapping, mptr.mapping);
SetPageAnonExclusive(page);
}
@@ -1142,6 +1152,7 @@ static void __page_set_anon_rmap(struct folio *folio, struct page *page,
struct vm_area_struct *vma, unsigned long address, int exclusive)
{
struct anon_vma *anon_vma = vma->anon_vma;
+ union mapping_ptr mptr;
BUG_ON(!anon_vma);
@@ -1162,8 +1173,9 @@ static void __page_set_anon_rmap(struct folio *folio, struct page *page,
* the PAGE_MAPPING_ANON type identifier, otherwise the rmap code
* could mistake the mapping for a struct address_space and crash.
*/
- anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
- WRITE_ONCE(folio->mapping, (struct address_space *) anon_vma);
+ mptr.anon_vma = anon_vma;
+ mptr.tag |= PAGE_MAPPING_ANON;
+ WRITE_ONCE(folio->mapping, mptr.mapping);
folio->index = linear_page_index(vma, address);
out:
if (exclusive)
--
2.39.2
Powered by blists - more mailing lists