All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH RFC v3] mm: Proper document tail pages fields for folio
@ 2023-08-15 21:25 Peter Xu
  2023-08-16 13:33 ` David Hildenbrand
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Xu @ 2023-08-15 21:25 UTC (permalink / raw)
  To: linux-kernel, linux-mm
  Cc: peterx, Hugh Dickins, Kirill A . Shutemov, Randy Dunlap,
	Mike Kravetz, Matthew Wilcox, Yu Zhao, Ryan Roberts,
	Andrew Morton, Yang Shi, David Hildenbrand

Tail page struct reuse is over-comlicated.  Not only because we have
implicit uses of tail page fields (mapcounts, or private for thp swap
support, etc., that we may still use in the page structs, but not obvious
the relationship between that and the folio definitions), but also because
we have 32/64 bits layouts for struct page so it's unclear what we can use
and what we cannot when trying to find a new spot in folio struct.

It's also unclear on how many fields we can reuse for a tail page.  The
real answer is (after help from Matthew): we have 7 WORDs guaranteed on 64
bits and 8 WORDs on 32 bits.  Nothing more than that is guaranteed to even
exist.  That means nothing over page->_refcount field can be reused.

Let's document it clearly on what we can use and what we can't when
extending folio on reusing tail page fields, with explanations on each of
them.  Hopefully after the doc update it will make it easier when:

  (1) Any reader to know exactly what folio field is where and for what,
  the relationships between folio tail pages and struct page definitions,

  (2) Any potential new fields to be added to a large folio, so we're clear
  which field one can still reuse.

This is assuming WORD is defined as sizeof(void *) on any archs, just like
the other comment in struct page we already have.

The _mapcount/_refcount fields are also added for each tail page to clamp
the fields tight, with FOLIO_MATCH() making sure nothing messed up the
ordering.

Signed-off-by: Peter Xu <peterx@redhat.com>
---

rfcv1: https://lore.kernel.org/all/20230810204944.53471-1-peterx@redhat.com
rfcv2: https://lore.kernel.org/r/20230814184411.330496-1-peterx@redhat.com

No change log since it changed quite a bit; I sent patch 1 separately as
non-rfc, while I merged the rest two patches because I just noticed I can
avoid reorder the fields, so no functional change should be intended, hence
no reason to split either.

Matthew, I wanted to remove the whole chunk of comments above the tail
pages from last version (which might fall into "over-documented" category),
but at last I still kept it; not only because I found that helpful to give
me a whole picture (maybe only me?), but also it's a good place to document
a few important things (e.g., on the fact that refcnt==0 is a must for all
tails).  I'm open to removing the chunk or part of it, if you think the
rest is still ok.

This of course also conflict so far with the other series to drop
folio_order/... but I can always rebase if this is not NACKed.

Comments welcomed, thanks.
---
 include/linux/mm_types.h | 69 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 3 deletions(-)

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 81456fa5fda5..66f1b0814334 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -324,6 +324,35 @@ struct folio {
 		};
 		struct page page;
 	};
+	/*
+	 * Some of the tail page fields may not be reused by the folio
+	 * object because they have already been used by the page struct.
+	 * On 32bits there are at least 8 WORDs while on 64 bits there're
+	 * at least 7 WORDs, all ending at _refcount field.
+	 *
+	 * |--------+-------------+-------------------|
+	 * |  index | 32 bits     | 64 bits           |
+	 * |--------+-------------+-------------------|
+	 * |      0 | flags       | flags             |
+	 * |      1 | head        | head              |
+	 * |      2 | FREE        | FREE              |
+	 * |      3 | FREE [1]    | FREE [1]          |
+	 * |      4 | FREE        | FREE              |
+	 * |      5 | FREE        | private [2]       |
+	 * |      6 | mapcnt      | mapcnt+refcnt [3] |
+	 * |      7 | refcnt [3]  |                   |
+	 * |--------+-------------+-------------------|
+	 *
+	 * [1] "mapping" field.  It is free to use but needs to be with
+	 *     some caution due to poisoning, see TAIL_MAPPING_REUSED_MAX.
+	 *
+	 * [2] "private" field, used when THP_SWAP is on (but disabled on
+	 *     32 bits, so this index is FREE on 32bit or hugetlb folios).
+	 *     May need to be fixed finally.
+	 *
+	 * [3] "refcount" field must be zero for all tail pages.  See e.g.
+	 *     has_unmovable_pages() on page_ref_count() check and comment.
+	 */
 	union {
 		struct {
 			unsigned long _flags_1;
@@ -331,18 +360,29 @@ struct folio {
 	/* public: */
 			unsigned char _folio_dtor;
 			unsigned char _folio_order;
+	/* private: 2 bytes can be reused later */
+			unsigned char _free_1_0[2];
+	/* public: */
 			atomic_t _entire_mapcount;
 			atomic_t _nr_pages_mapped;
 			atomic_t _pincount;
 #ifdef CONFIG_64BIT
 			unsigned int _folio_nr_pages;
+	/* private: 4 bytes can be reused later (64 bits only) */
+			unsigned char _free_1_1[4];
+	/* Currently used by THP_SWAP, to be fixed */
+			void *_private_1;
+	/* public: */
 #endif
+	/* private: */
+			atomic_t _mapcount_1;
+			atomic_t _refcount_1;
 	/* private: the union with struct page is transitional */
 		};
 		struct page __page_1;
 	};
 	union {
-		struct {
+		struct {	/* hugetlb folios */
 			unsigned long _flags_2;
 			unsigned long _head_2;
 	/* public: */
@@ -351,13 +391,22 @@ struct folio {
 			void *_hugetlb_cgroup_rsvd;
 			void *_hugetlb_hwpoison;
 	/* private: the union with struct page is transitional */
+			atomic_t _mapcount_2;
+			atomic_t _refcount_2;
 		};
-		struct {
+		struct {	/* non-hugetlb folios */
 			unsigned long _flags_2a;
 			unsigned long _head_2a;
 	/* public: */
 			struct list_head _deferred_list;
-	/* private: the union with struct page is transitional */
+	/* private: 8 more free bytes for either 32/64 bits */
+			unsigned char _free_2_2[8];
+#ifdef CONFIG_64BIT
+	/* currently used by THP_SWAP, to be fixed */
+			void *_private_2a;
+#endif
+			atomic_t _mapcount_2a;
+			atomic_t _refcount_2a;
 		};
 		struct page __page_2;
 	};
@@ -382,12 +431,26 @@ FOLIO_MATCH(memcg_data, memcg_data);
 			offsetof(struct page, pg) + sizeof(struct page))
 FOLIO_MATCH(flags, _flags_1);
 FOLIO_MATCH(compound_head, _head_1);
+#ifdef CONFIG_64BIT
+FOLIO_MATCH(private, _private_1);
+#endif
+FOLIO_MATCH(_mapcount, _mapcount_1);
+FOLIO_MATCH(_refcount, _refcount_1);
 #undef FOLIO_MATCH
 #define FOLIO_MATCH(pg, fl)						\
 	static_assert(offsetof(struct folio, fl) ==			\
 			offsetof(struct page, pg) + 2 * sizeof(struct page))
 FOLIO_MATCH(flags, _flags_2);
 FOLIO_MATCH(compound_head, _head_2);
+FOLIO_MATCH(_mapcount, _mapcount_2);
+FOLIO_MATCH(_refcount, _refcount_2);
+FOLIO_MATCH(flags, _flags_2a);
+FOLIO_MATCH(compound_head, _head_2a);
+FOLIO_MATCH(_mapcount, _mapcount_2a);
+FOLIO_MATCH(_refcount, _refcount_2a);
+#ifdef CONFIG_64BIT
+FOLIO_MATCH(private, _private_2a);
+#endif
 #undef FOLIO_MATCH
 
 /*
-- 
2.41.0



^ permalink raw reply related	[flat|nested] 9+ messages in thread
* Re: [PATCH RFC v3] mm: Proper document tail pages fields for folio
@ 2023-08-18  5:48 kernel test robot
  0 siblings, 0 replies; 9+ messages in thread
From: kernel test robot @ 2023-08-18  5:48 UTC (permalink / raw)
  To: oe-kbuild; +Cc: lkp

:::::: 
:::::: Manual check reason: "low confidence static check warning: include/linux/mm_types.h:440:1: sparse: sparse: static assertion failed: "offsetof(struct folio, _mapcount_1) == offsetof(struct page, _mapcount) + sizeof(struct page)""
:::::: 

BCC: lkp@intel.com
CC: oe-kbuild-all@lists.linux.dev
In-Reply-To: <20230815212547.431693-1-peterx@redhat.com>
References: <20230815212547.431693-1-peterx@redhat.com>
TO: Peter Xu <peterx@redhat.com>

Hi Peter,

[This is a private test report for your RFC patch.]
kernel test robot noticed the following build warnings:

[auto build test WARNING on linus/master]
[also build test WARNING on v6.5-rc6 next-20230817]
[cannot apply to akpm-mm/mm-everything]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Peter-Xu/mm-Proper-document-tail-pages-fields-for-folio/20230816-052726
base:   linus/master
patch link:    https://lore.kernel.org/r/20230815212547.431693-1-peterx%40redhat.com
patch subject: [PATCH RFC v3] mm: Proper document tail pages fields for folio
:::::: branch date: 2 days ago
:::::: commit date: 2 days ago
config: mips-randconfig-r073-20230818 (https://download.01.org/0day-ci/archive/20230818/202308181323.AdR1xgvN-lkp@intel.com/config)
compiler: mips64-linux-gcc (GCC) 12.3.0
reproduce: (https://download.01.org/0day-ci/archive/20230818/202308181323.AdR1xgvN-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/r/202308181323.AdR1xgvN-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
   command-line: note: in included file:
   builtin:1:9: sparse: sparse: preprocessor token __STDC_HOSTED__ redefined
   builtin:0:0: sparse: this was the original definition
   command-line: note: in included file (through arch/mips/include/asm/vdso.h, arch/mips/include/asm/vdso/vdso.h, arch/mips/include/asm/vdso/gettimeofday.h, ...):
>> include/linux/mm_types.h:440:1: sparse: sparse: static assertion failed: "offsetof(struct folio, _mapcount_1) == offsetof(struct page, _mapcount) + sizeof(struct page)"
>> include/linux/mm_types.h:441:1: sparse: sparse: static assertion failed: "offsetof(struct folio, _refcount_1) == offsetof(struct page, _refcount) + sizeof(struct page)"
>> include/linux/mm_types.h:452:1: sparse: sparse: static assertion failed: "offsetof(struct folio, _mapcount_2a) == offsetof(struct page, _mapcount) + 2 * sizeof(struct page)"
>> include/linux/mm_types.h:453:1: sparse: sparse: static assertion failed: "offsetof(struct folio, _refcount_2a) == offsetof(struct page, _refcount) + 2 * sizeof(struct page)"
   command-line: note: in included file (through builtin):
   lib/vdso/gettimeofday.c:282:24: sparse: sparse: undefined identifier 'clock_gettime32_fallback'
   lib/vdso/gettimeofday.c:425:24: sparse: sparse: undefined identifier 'clock_getres32_fallback'

vim +440 include/linux/mm_types.h

7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  417) 
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  418) #define FOLIO_MATCH(pg, fl)						\
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  419) 	static_assert(offsetof(struct page, pg) == offsetof(struct folio, fl))
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  420) FOLIO_MATCH(flags, flags);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  421) FOLIO_MATCH(lru, lru);
536f4217ced62b Wei Yang                2022-01-29  422  FOLIO_MATCH(mapping, mapping);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  423) FOLIO_MATCH(compound_head, lru);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  424) FOLIO_MATCH(index, index);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  425) FOLIO_MATCH(private, private);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  426) FOLIO_MATCH(_mapcount, _mapcount);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  427) FOLIO_MATCH(_refcount, _refcount);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  428) #ifdef CONFIG_MEMCG
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  429) FOLIO_MATCH(memcg_data, memcg_data);
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  430) #endif
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  431) #undef FOLIO_MATCH
379708ffde1b04 Matthew Wilcox (Oracle  2022-09-02  432) #define FOLIO_MATCH(pg, fl)						\
379708ffde1b04 Matthew Wilcox (Oracle  2022-09-02  433) 	static_assert(offsetof(struct folio, fl) ==			\
379708ffde1b04 Matthew Wilcox (Oracle  2022-09-02  434) 			offsetof(struct page, pg) + sizeof(struct page))
379708ffde1b04 Matthew Wilcox (Oracle  2022-09-02  435) FOLIO_MATCH(flags, _flags_1);
dad6a5eb555648 Hugh Dickins            2022-11-02  436  FOLIO_MATCH(compound_head, _head_1);
2a678a0821365b Peter Xu                2023-08-15  437  #ifdef CONFIG_64BIT
2a678a0821365b Peter Xu                2023-08-15  438  FOLIO_MATCH(private, _private_1);
2a678a0821365b Peter Xu                2023-08-15  439  #endif
2a678a0821365b Peter Xu                2023-08-15 @440  FOLIO_MATCH(_mapcount, _mapcount_1);
2a678a0821365b Peter Xu                2023-08-15 @441  FOLIO_MATCH(_refcount, _refcount_1);
379708ffde1b04 Matthew Wilcox (Oracle  2022-09-02  442) #undef FOLIO_MATCH
dad6a5eb555648 Hugh Dickins            2022-11-02  443  #define FOLIO_MATCH(pg, fl)						\
dad6a5eb555648 Hugh Dickins            2022-11-02  444  	static_assert(offsetof(struct folio, fl) ==			\
dad6a5eb555648 Hugh Dickins            2022-11-02  445  			offsetof(struct page, pg) + 2 * sizeof(struct page))
dad6a5eb555648 Hugh Dickins            2022-11-02  446  FOLIO_MATCH(flags, _flags_2);
dad6a5eb555648 Hugh Dickins            2022-11-02  447  FOLIO_MATCH(compound_head, _head_2);
2a678a0821365b Peter Xu                2023-08-15  448  FOLIO_MATCH(_mapcount, _mapcount_2);
2a678a0821365b Peter Xu                2023-08-15  449  FOLIO_MATCH(_refcount, _refcount_2);
2a678a0821365b Peter Xu                2023-08-15  450  FOLIO_MATCH(flags, _flags_2a);
2a678a0821365b Peter Xu                2023-08-15  451  FOLIO_MATCH(compound_head, _head_2a);
2a678a0821365b Peter Xu                2023-08-15 @452  FOLIO_MATCH(_mapcount, _mapcount_2a);
2a678a0821365b Peter Xu                2023-08-15 @453  FOLIO_MATCH(_refcount, _refcount_2a);
2a678a0821365b Peter Xu                2023-08-15  454  #ifdef CONFIG_64BIT
2a678a0821365b Peter Xu                2023-08-15  455  FOLIO_MATCH(private, _private_2a);
2a678a0821365b Peter Xu                2023-08-15  456  #endif
dad6a5eb555648 Hugh Dickins            2022-11-02  457  #undef FOLIO_MATCH
7b230db3b8d373 Matthew Wilcox (Oracle  2020-12-06  458) 

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-08-18 14:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-15 21:25 [PATCH RFC v3] mm: Proper document tail pages fields for folio Peter Xu
2023-08-16 13:33 ` David Hildenbrand
2023-08-16 16:53   ` Peter Xu
2023-08-16 18:59     ` David Hildenbrand
2023-08-16 18:41   ` Matthew Wilcox
2023-08-16 18:51     ` David Hildenbrand
2023-08-16 22:05       ` Matthew Wilcox
2023-08-18 14:38         ` David Hildenbrand
  -- strict thread matches above, loose matches on Subject: below --
2023-08-18  5:48 kernel test robot

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.