| From: "Matthew Wilcox (Oracle)" <willy@infradead.org> |
| Subject: mm: add the first tail page to struct folio |
| Date: Fri, 2 Sep 2022 20:45:58 +0100 |
| |
| Some of the static checkers get confused by extracting the page from the |
| folio and referring to fields in the first tail page. Adding these fields |
| to struct folio lets us avoid doing that. It has the risk that people |
| will refer to those fields without checking that the folio is actually a |
| large folio, so prefix them with underscores and document the preferred |
| function to use instead. |
| |
| Link: https://lkml.kernel.org/r/20220902194653.1739778-3-willy@infradead.org |
| Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| include/linux/mm_types.h | 30 +++++++++++++++++++++++++++++- |
| 1 file changed, 29 insertions(+), 1 deletion(-) |
| |
| --- a/include/linux/mm_types.h~mm-add-the-first-tail-page-to-struct-folio |
| +++ a/include/linux/mm_types.h |
| @@ -245,6 +245,13 @@ struct page { |
| * @_refcount: Do not access this member directly. Use folio_ref_count() |
| * to find how many references there are to this folio. |
| * @memcg_data: Memory Control Group data. |
| + * @_flags_1: For large folios, additional page flags. |
| + * @__head: Points to the folio. Do not use. |
| + * @_folio_dtor: Which destructor to use for this folio. |
| + * @_folio_order: Do not use directly, call folio_order(). |
| + * @_total_mapcount: Do not use directly, call folio_entire_mapcount(). |
| + * @_pincount: Do not use directly, call folio_maybe_dma_pinned(). |
| + * @_folio_nr_pages: Do not use directly, call folio_nr_pages(). |
| * |
| * A folio is a physically, virtually and logically contiguous set |
| * of bytes. It is a power-of-two in size, and it is aligned to that |
| @@ -283,9 +290,17 @@ struct folio { |
| }; |
| struct page page; |
| }; |
| + unsigned long _flags_1; |
| + unsigned long __head; |
| + unsigned char _folio_dtor; |
| + unsigned char _folio_order; |
| + atomic_t _total_mapcount; |
| + atomic_t _pincount; |
| +#ifdef CONFIG_64BIT |
| + unsigned int _folio_nr_pages; |
| +#endif |
| }; |
| |
| -static_assert(sizeof(struct page) == sizeof(struct folio)); |
| #define FOLIO_MATCH(pg, fl) \ |
| static_assert(offsetof(struct page, pg) == offsetof(struct folio, fl)) |
| FOLIO_MATCH(flags, flags); |
| @@ -300,6 +315,19 @@ FOLIO_MATCH(_refcount, _refcount); |
| FOLIO_MATCH(memcg_data, memcg_data); |
| #endif |
| #undef FOLIO_MATCH |
| +#define FOLIO_MATCH(pg, fl) \ |
| + static_assert(offsetof(struct folio, fl) == \ |
| + offsetof(struct page, pg) + sizeof(struct page)) |
| +FOLIO_MATCH(flags, _flags_1); |
| +FOLIO_MATCH(compound_head, __head); |
| +FOLIO_MATCH(compound_dtor, _folio_dtor); |
| +FOLIO_MATCH(compound_order, _folio_order); |
| +FOLIO_MATCH(compound_mapcount, _total_mapcount); |
| +FOLIO_MATCH(compound_pincount, _pincount); |
| +#ifdef CONFIG_64BIT |
| +FOLIO_MATCH(compound_nr, _folio_nr_pages); |
| +#endif |
| +#undef FOLIO_MATCH |
| |
| static inline atomic_t *folio_mapcount_ptr(struct folio *folio) |
| { |
| _ |