Vlastimil Babka <vbabka@xxxxxxx> writes: > On 3/6/23 02:25, Huang, Ying wrote: >> Hi, Linus, >> >> Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> writes: >> >>> On Sat, Mar 4, 2023 at 3:21 PM Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> 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@xxxxxxxxx> 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