| From: "Matthew Wilcox (Oracle)" <willy@infradead.org> |
| Subject: mm: add tail private fields to struct folio |
| Date: Wed, 16 Aug 2023 16:12:00 +0100 |
| |
| Because THP_SWAP uses page->private for each page, we must not use the |
| space which overlaps that field for anything which would conflict with |
| that. We avoid the conflict on 32-bit systems by disallowing THP_SWAP on |
| 32-bit. |
| |
| Link: https://lkml.kernel.org/r/20230816151201.3655946-13-willy@infradead.org |
| Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Cc: David Hildenbrand <david@redhat.com> |
| Cc: Jens Axboe <axboe@kernel.dk> |
| Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com> |
| Cc: Yanteng Si <siyanteng@loongson.cn> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| include/linux/mm_types.h | 14 +++++++++++++- |
| 1 file changed, 13 insertions(+), 1 deletion(-) |
| |
| --- a/include/linux/mm_types.h~mm-add-tail-private-fields-to-struct-folio |
| +++ a/include/linux/mm_types.h |
| @@ -322,8 +322,11 @@ struct folio { |
| atomic_t _pincount; |
| #ifdef CONFIG_64BIT |
| unsigned int _folio_nr_pages; |
| -#endif |
| + /* 4 byte gap here */ |
| /* private: the union with struct page is transitional */ |
| + /* Fix THP_SWAP to not use tail->private */ |
| + unsigned long _private_1; |
| +#endif |
| }; |
| struct page __page_1; |
| }; |
| @@ -344,6 +347,9 @@ struct folio { |
| /* public: */ |
| struct list_head _deferred_list; |
| /* private: the union with struct page is transitional */ |
| + unsigned long _avail_2a; |
| + /* Fix THP_SWAP to not use tail->private */ |
| + unsigned long _private_2a; |
| }; |
| struct page __page_2; |
| }; |
| @@ -368,12 +374,18 @@ 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 |
| #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(flags, _flags_2a); |
| +FOLIO_MATCH(compound_head, _head_2a); |
| +FOLIO_MATCH(private, _private_2a); |
| #undef FOLIO_MATCH |
| |
| /** |
| _ |