Skip to content

Commit cfeed8f

Browse files
davidhildenbrandakpm00
authored andcommitted
mm/swap: stop using page->private on tail pages for THP_SWAP
Patch series "mm/swap: stop using page->private on tail pages for THP_SWAP + cleanups". This series stops using page->private on tail pages for THP_SWAP, replaces folio->private by folio->swap for swapcache folios, and starts using "new_folio" for tail pages that we are splitting to remove the usage of page->private for swapcache handling completely. This patch (of 4): Let's stop using page->private on tail pages, making it possible to just unconditionally reuse that field in the tail pages of large folios. The remaining usage of the private field for THP_SWAP is in the THP splitting code (mm/huge_memory.c), that we'll handle separately later. Update the THP_SWAP documentation and sanity checks in mm_types.h and __split_huge_page_tail(). [[email protected]: stop using page->private on tail pages for THP_SWAP] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: David Hildenbrand <[email protected]> Acked-by: Catalin Marinas <[email protected]> [arm64] Reviewed-by: Yosry Ahmed <[email protected]> Cc: Dan Streetman <[email protected]> Cc: Hugh Dickins <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Peter Xu <[email protected]> Cc: Seth Jennings <[email protected]> Cc: Vitaly Wool <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent bad5a3a commit cfeed8f

File tree

8 files changed

+26
-28
lines changed

8 files changed

+26
-28
lines changed

arch/arm64/mm/mteswap.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ int mte_save_tags(struct page *page)
3333

3434
mte_save_page_tags(page_address(page), tag_storage);
3535

36-
/* page_private contains the swap entry.val set in do_swap_page */
37-
ret = xa_store(&mte_pages, page_private(page), tag_storage, GFP_KERNEL);
36+
/* lookup the swap entry.val from the page */
37+
ret = xa_store(&mte_pages, page_swap_entry(page).val, tag_storage,
38+
GFP_KERNEL);
3839
if (WARN(xa_is_err(ret), "Failed to store MTE tags")) {
3940
mte_free_tag_storage(tag_storage);
4041
return xa_err(ret);

include/linux/mm_types.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -322,11 +322,8 @@ struct folio {
322322
atomic_t _pincount;
323323
#ifdef CONFIG_64BIT
324324
unsigned int _folio_nr_pages;
325-
/* 4 byte gap here */
326-
/* private: the union with struct page is transitional */
327-
/* Fix THP_SWAP to not use tail->private */
328-
unsigned long _private_1;
329325
#endif
326+
/* private: the union with struct page is transitional */
330327
};
331328
struct page __page_1;
332329
};
@@ -347,9 +344,6 @@ struct folio {
347344
/* public: */
348345
struct list_head _deferred_list;
349346
/* private: the union with struct page is transitional */
350-
unsigned long _avail_2a;
351-
/* Fix THP_SWAP to not use tail->private */
352-
unsigned long _private_2a;
353347
};
354348
struct page __page_2;
355349
};
@@ -374,9 +368,6 @@ FOLIO_MATCH(memcg_data, memcg_data);
374368
offsetof(struct page, pg) + sizeof(struct page))
375369
FOLIO_MATCH(flags, _flags_1);
376370
FOLIO_MATCH(compound_head, _head_1);
377-
#ifdef CONFIG_64BIT
378-
FOLIO_MATCH(private, _private_1);
379-
#endif
380371
#undef FOLIO_MATCH
381372
#define FOLIO_MATCH(pg, fl) \
382373
static_assert(offsetof(struct folio, fl) == \
@@ -385,7 +376,6 @@ FOLIO_MATCH(flags, _flags_2);
385376
FOLIO_MATCH(compound_head, _head_2);
386377
FOLIO_MATCH(flags, _flags_2a);
387378
FOLIO_MATCH(compound_head, _head_2a);
388-
FOLIO_MATCH(private, _private_2a);
389379
#undef FOLIO_MATCH
390380

391381
/**

include/linux/swap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,15 @@ static inline swp_entry_t folio_swap_entry(struct folio *folio)
339339
return entry;
340340
}
341341

342+
static inline swp_entry_t page_swap_entry(struct page *page)
343+
{
344+
struct folio *folio = page_folio(page);
345+
swp_entry_t entry = folio_swap_entry(folio);
346+
347+
entry.val += folio_page_idx(folio, page);
348+
return entry;
349+
}
350+
342351
static inline void folio_set_swap_entry(struct folio *folio, swp_entry_t entry)
343352
{
344353
folio->private = (void *)entry.val;

mm/huge_memory.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2446,18 +2446,15 @@ static void __split_huge_page_tail(struct page *head, int tail,
24462446
page_tail->index = head->index + tail;
24472447

24482448
/*
2449-
* page->private should not be set in tail pages with the exception
2450-
* of swap cache pages that store the swp_entry_t in tail pages.
2451-
* Fix up and warn once if private is unexpectedly set.
2452-
*
2453-
* What of 32-bit systems, on which folio->_pincount overlays
2454-
* head[1].private? No problem: THP_SWAP is not enabled on 32-bit, and
2455-
* pincount must be 0 for folio_ref_freeze() to have succeeded.
2449+
* page->private should not be set in tail pages. Fix up and warn once
2450+
* if private is unexpectedly set.
24562451
*/
2457-
if (!folio_test_swapcache(page_folio(head))) {
2458-
VM_WARN_ON_ONCE_PAGE(page_tail->private != 0, page_tail);
2452+
if (unlikely(page_tail->private)) {
2453+
VM_WARN_ON_ONCE_PAGE(true, page_tail);
24592454
page_tail->private = 0;
24602455
}
2456+
if (PageSwapCache(head))
2457+
set_page_private(page_tail, (unsigned long)head->private + tail);
24612458

24622459
/* Page flags must be visible before we make the page non-compound. */
24632460
smp_wmb();

mm/memory.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3879,7 +3879,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf)
38793879
* changed.
38803880
*/
38813881
if (unlikely(!folio_test_swapcache(folio) ||
3882-
page_private(page) != entry.val))
3882+
page_swap_entry(page).val != entry.val))
38833883
goto out_page;
38843884

38853885
/*

mm/rmap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,7 @@ static bool try_to_unmap_one(struct folio *folio, struct vm_area_struct *vma,
16471647
*/
16481648
dec_mm_counter(mm, mm_counter(&folio->page));
16491649
} else if (folio_test_anon(folio)) {
1650-
swp_entry_t entry = { .val = page_private(subpage) };
1650+
swp_entry_t entry = page_swap_entry(subpage);
16511651
pte_t swp_pte;
16521652
/*
16531653
* Store the swap location in the pte.

mm/swap_state.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ int add_to_swap_cache(struct folio *folio, swp_entry_t entry,
100100

101101
folio_ref_add(folio, nr);
102102
folio_set_swapcache(folio);
103+
folio_set_swap_entry(folio, entry);
103104

104105
do {
105106
xas_lock_irq(&xas);
@@ -113,7 +114,6 @@ int add_to_swap_cache(struct folio *folio, swp_entry_t entry,
113114
if (shadowp)
114115
*shadowp = old;
115116
}
116-
set_page_private(folio_page(folio, i), entry.val + i);
117117
xas_store(&xas, folio);
118118
xas_next(&xas);
119119
}
@@ -154,9 +154,10 @@ void __delete_from_swap_cache(struct folio *folio,
154154
for (i = 0; i < nr; i++) {
155155
void *entry = xas_store(&xas, shadow);
156156
VM_BUG_ON_PAGE(entry != folio, entry);
157-
set_page_private(folio_page(folio, i), 0);
158157
xas_next(&xas);
159158
}
159+
entry.val = 0;
160+
folio_set_swap_entry(folio, entry);
160161
folio_clear_swapcache(folio);
161162
address_space->nrpages -= nr;
162163
__node_stat_mod_folio(folio, NR_FILE_PAGES, -nr);

mm/swapfile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3369,7 +3369,7 @@ struct swap_info_struct *swp_swap_info(swp_entry_t entry)
33693369

33703370
struct swap_info_struct *page_swap_info(struct page *page)
33713371
{
3372-
swp_entry_t entry = { .val = page_private(page) };
3372+
swp_entry_t entry = page_swap_entry(page);
33733373
return swp_swap_info(entry);
33743374
}
33753375

@@ -3384,7 +3384,7 @@ EXPORT_SYMBOL_GPL(swapcache_mapping);
33843384

33853385
pgoff_t __page_file_index(struct page *page)
33863386
{
3387-
swp_entry_t swap = { .val = page_private(page) };
3387+
swp_entry_t swap = page_swap_entry(page);
33883388
return swp_offset(swap);
33893389
}
33903390
EXPORT_SYMBOL_GPL(__page_file_index);

0 commit comments

Comments
 (0)