Skip to content

Commit 2df1bd9

Browse files
weiny2gregkh
authored andcommitted
mm/swap: fix release_pages() when releasing devmap pages
[ Upstream commit c5d6c45 ] release_pages() is an optimized version of a loop around put_page(). Unfortunately for devmap pages the logic is not entirely correct in release_pages(). This is because device pages can be more than type MEMORY_DEVICE_PUBLIC. There are in fact 4 types, private, public, FS DAX, and PCI P2PDMA. Some of these have specific needs to "put" the page while others do not. This logic to handle any special needs is contained in put_devmap_managed_page(). Therefore all devmap pages should be processed by this function where we can contain the correct logic for a page put. Handle all device type pages within release_pages() by calling put_devmap_managed_page() on all devmap pages. If put_devmap_managed_page() returns true the page has been put and we continue with the next page. A false return of put_devmap_managed_page() means the page did not require special processing and should fall to "normal" processing. This was found via code inspection while determining if release_pages() and the new put_user_pages() could be interchangeable.[1] [1] https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Cc: Jérôme Glisse <[email protected]> Cc: Michal Hocko <[email protected]> Reviewed-by: Dan Williams <[email protected]> Reviewed-by: John Hubbard <[email protected]> Signed-off-by: Ira Weiny <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 7891d8a commit 2df1bd9

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

mm/swap.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -740,15 +740,20 @@ void release_pages(struct page **pages, int nr)
740740
if (is_huge_zero_page(page))
741741
continue;
742742

743-
/* Device public page can not be huge page */
744-
if (is_device_public_page(page)) {
743+
if (is_zone_device_page(page)) {
745744
if (locked_pgdat) {
746745
spin_unlock_irqrestore(&locked_pgdat->lru_lock,
747746
flags);
748747
locked_pgdat = NULL;
749748
}
750-
put_devmap_managed_page(page);
751-
continue;
749+
/*
750+
* ZONE_DEVICE pages that return 'false' from
751+
* put_devmap_managed_page() do not require special
752+
* processing, and instead, expect a call to
753+
* put_page_testzero().
754+
*/
755+
if (put_devmap_managed_page(page))
756+
continue;
752757
}
753758

754759
page = compound_head(page);

0 commit comments

Comments
 (0)