On Thu, Jan 14, 2021 at 11:09:01AM -0800, Linus Torvalds wrote: > On Thu, Jan 14, 2021 at 11:00 AM Will Deacon <will@xxxxxxxxxx> wrote: > > > > I tried that initially, but I found that I had to make all of the > > members const to get it to work, at which point the anonymous struct > > wasn't really adding anything. Did I just botch the syntax? > > I'm not sure what you tried. But this stupid test-case sure works for me: > > struct hello { > const struct { > unsigned long address; > }; > unsigned int flags; > }; > > extern int fn(struct hello *); > > int test(void) > { > struct hello a = { > .address = 1, > }; > a.flags = 0; > return fn(&a); > } > > and because "address" is in that unnamed constant struct, you can only > set it within that initializer, and cannot do > > a.address = 0; > > without an error (the way you _can_ do "a.flags = 0"). > > I don't see naming the struct making a difference - apart from forcing > that big rename patch, of course. > > But maybe we're talking about different issues? Urgh... We _are_ both on the same page, and your reply above had me thinking I've lost the plot, so I went back to the start. Check out v5.11-rc3 and apply this patch: diff --git a/include/linux/mm.h b/include/linux/mm.h index ecdf8a8cd6ae..1eb950865450 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -514,11 +514,14 @@ static inline bool fault_flag_allow_retry_first(unsigned int flags) * pgoff should be used in favour of virtual_address, if possible. */ struct vm_fault { - struct vm_area_struct *vma; /* Target VMA */ + const struct { + struct vm_area_struct *vma; /* Target VMA */ + gfp_t gfp_mask; /* gfp mask to be used for allocations */ + pgoff_t pgoff; /* Logical page offset based on vma */ + unsigned long address; /* Faulting virtual address */ + }; + unsigned int flags; /* FAULT_FLAG_xxx flags */ - gfp_t gfp_mask; /* gfp mask to be used for allocations */ - pgoff_t pgoff; /* Logical page offset based on vma */ - unsigned long address; /* Faulting virtual address */ pmd_t *pmd; /* Pointer to pmd entry matching * the 'address' */ pud_t *pud; /* Pointer to pud entry matching Sure enough, an arm64 defconfig builds perfectly alright with that change, but it really shouldn't. I'm using clang 11.0.5, so I had another go with GCC 9.2.1 and bang: mm/filemap.c: In function ‘filemap_map_pages’: mm/filemap.c:2963:16: error: assignment of member ‘address’ in read-only object 2963 | vmf->address += (xas.xa_index - last_pgoff) << PAGE_SHIFT; | ^~ make[1]: *** [scripts/Makefile.build:279: mm/filemap.o] Error 1 make[1]: *** Waiting for unfinished jobs.... make: *** [Makefile:1805: mm] Error 2 make: *** Waiting for unfinished jobs.... Nick -- any clue what's happening here? We would like that const anonymous struct to behave like a const struct member, as the alternative (naming the thing) results in a lot of refactoring churn. Cheers, Will