mm/vmscan: Convert __remove_mapping() to take a folio
This removes a few hidden calls to compound_head(). Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
44
mm/vmscan.c
44
mm/vmscan.c
@ -1239,17 +1239,16 @@ static pageout_t pageout(struct page *page, struct address_space *mapping)
|
|||||||
* Same as remove_mapping, but if the page is removed from the mapping, it
|
* Same as remove_mapping, but if the page is removed from the mapping, it
|
||||||
* gets returned with a refcount of 0.
|
* gets returned with a refcount of 0.
|
||||||
*/
|
*/
|
||||||
static int __remove_mapping(struct address_space *mapping, struct page *page,
|
static int __remove_mapping(struct address_space *mapping, struct folio *folio,
|
||||||
bool reclaimed, struct mem_cgroup *target_memcg)
|
bool reclaimed, struct mem_cgroup *target_memcg)
|
||||||
{
|
{
|
||||||
struct folio *folio = page_folio(page);
|
|
||||||
int refcount;
|
int refcount;
|
||||||
void *shadow = NULL;
|
void *shadow = NULL;
|
||||||
|
|
||||||
BUG_ON(!PageLocked(page));
|
BUG_ON(!folio_test_locked(folio));
|
||||||
BUG_ON(mapping != page_mapping(page));
|
BUG_ON(mapping != folio_mapping(folio));
|
||||||
|
|
||||||
if (!PageSwapCache(page))
|
if (!folio_test_swapcache(folio))
|
||||||
spin_lock(&mapping->host->i_lock);
|
spin_lock(&mapping->host->i_lock);
|
||||||
xa_lock_irq(&mapping->i_pages);
|
xa_lock_irq(&mapping->i_pages);
|
||||||
/*
|
/*
|
||||||
@ -1277,23 +1276,23 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
|
|||||||
* Note that if SetPageDirty is always performed via set_page_dirty,
|
* Note that if SetPageDirty is always performed via set_page_dirty,
|
||||||
* and thus under the i_pages lock, then this ordering is not required.
|
* and thus under the i_pages lock, then this ordering is not required.
|
||||||
*/
|
*/
|
||||||
refcount = 1 + compound_nr(page);
|
refcount = 1 + folio_nr_pages(folio);
|
||||||
if (!page_ref_freeze(page, refcount))
|
if (!folio_ref_freeze(folio, refcount))
|
||||||
goto cannot_free;
|
goto cannot_free;
|
||||||
/* note: atomic_cmpxchg in page_ref_freeze provides the smp_rmb */
|
/* note: atomic_cmpxchg in page_ref_freeze provides the smp_rmb */
|
||||||
if (unlikely(PageDirty(page))) {
|
if (unlikely(folio_test_dirty(folio))) {
|
||||||
page_ref_unfreeze(page, refcount);
|
folio_ref_unfreeze(folio, refcount);
|
||||||
goto cannot_free;
|
goto cannot_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PageSwapCache(page)) {
|
if (folio_test_swapcache(folio)) {
|
||||||
swp_entry_t swap = { .val = page_private(page) };
|
swp_entry_t swap = folio_swap_entry(folio);
|
||||||
mem_cgroup_swapout(folio, swap);
|
mem_cgroup_swapout(folio, swap);
|
||||||
if (reclaimed && !mapping_exiting(mapping))
|
if (reclaimed && !mapping_exiting(mapping))
|
||||||
shadow = workingset_eviction(folio, target_memcg);
|
shadow = workingset_eviction(folio, target_memcg);
|
||||||
__delete_from_swap_cache(page, swap, shadow);
|
__delete_from_swap_cache(&folio->page, swap, shadow);
|
||||||
xa_unlock_irq(&mapping->i_pages);
|
xa_unlock_irq(&mapping->i_pages);
|
||||||
put_swap_page(page, swap);
|
put_swap_page(&folio->page, swap);
|
||||||
} else {
|
} else {
|
||||||
void (*freepage)(struct page *);
|
void (*freepage)(struct page *);
|
||||||
|
|
||||||
@ -1314,7 +1313,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
|
|||||||
* exceptional entries and shadow exceptional entries in the
|
* exceptional entries and shadow exceptional entries in the
|
||||||
* same address_space.
|
* same address_space.
|
||||||
*/
|
*/
|
||||||
if (reclaimed && page_is_file_lru(page) &&
|
if (reclaimed && folio_is_file_lru(folio) &&
|
||||||
!mapping_exiting(mapping) && !dax_mapping(mapping))
|
!mapping_exiting(mapping) && !dax_mapping(mapping))
|
||||||
shadow = workingset_eviction(folio, target_memcg);
|
shadow = workingset_eviction(folio, target_memcg);
|
||||||
__filemap_remove_folio(folio, shadow);
|
__filemap_remove_folio(folio, shadow);
|
||||||
@ -1324,14 +1323,14 @@ static int __remove_mapping(struct address_space *mapping, struct page *page,
|
|||||||
spin_unlock(&mapping->host->i_lock);
|
spin_unlock(&mapping->host->i_lock);
|
||||||
|
|
||||||
if (freepage != NULL)
|
if (freepage != NULL)
|
||||||
freepage(page);
|
freepage(&folio->page);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
cannot_free:
|
cannot_free:
|
||||||
xa_unlock_irq(&mapping->i_pages);
|
xa_unlock_irq(&mapping->i_pages);
|
||||||
if (!PageSwapCache(page))
|
if (!folio_test_swapcache(folio))
|
||||||
spin_unlock(&mapping->host->i_lock);
|
spin_unlock(&mapping->host->i_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1344,13 +1343,14 @@ cannot_free:
|
|||||||
*/
|
*/
|
||||||
int remove_mapping(struct address_space *mapping, struct page *page)
|
int remove_mapping(struct address_space *mapping, struct page *page)
|
||||||
{
|
{
|
||||||
if (__remove_mapping(mapping, page, false, NULL)) {
|
struct folio *folio = page_folio(page);
|
||||||
|
if (__remove_mapping(mapping, folio, false, NULL)) {
|
||||||
/*
|
/*
|
||||||
* Unfreezing the refcount with 1 rather than 2 effectively
|
* Unfreezing the refcount with 1 rather than 2 effectively
|
||||||
* drops the pagecache ref for us without requiring another
|
* drops the pagecache ref for us without requiring another
|
||||||
* atomic operation.
|
* atomic operation.
|
||||||
*/
|
*/
|
||||||
page_ref_unfreeze(page, 1);
|
folio_ref_unfreeze(folio, 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1532,14 +1532,16 @@ retry:
|
|||||||
while (!list_empty(page_list)) {
|
while (!list_empty(page_list)) {
|
||||||
struct address_space *mapping;
|
struct address_space *mapping;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
struct folio *folio;
|
||||||
enum page_references references = PAGEREF_RECLAIM;
|
enum page_references references = PAGEREF_RECLAIM;
|
||||||
bool dirty, writeback, may_enter_fs;
|
bool dirty, writeback, may_enter_fs;
|
||||||
unsigned int nr_pages;
|
unsigned int nr_pages;
|
||||||
|
|
||||||
cond_resched();
|
cond_resched();
|
||||||
|
|
||||||
page = lru_to_page(page_list);
|
folio = lru_to_folio(page_list);
|
||||||
list_del(&page->lru);
|
list_del(&folio->lru);
|
||||||
|
page = &folio->page;
|
||||||
|
|
||||||
if (!trylock_page(page))
|
if (!trylock_page(page))
|
||||||
goto keep;
|
goto keep;
|
||||||
@ -1892,7 +1894,7 @@ retry:
|
|||||||
*/
|
*/
|
||||||
count_vm_event(PGLAZYFREED);
|
count_vm_event(PGLAZYFREED);
|
||||||
count_memcg_page_event(page, PGLAZYFREED);
|
count_memcg_page_event(page, PGLAZYFREED);
|
||||||
} else if (!mapping || !__remove_mapping(mapping, page, true,
|
} else if (!mapping || !__remove_mapping(mapping, folio, true,
|
||||||
sc->target_mem_cgroup))
|
sc->target_mem_cgroup))
|
||||||
goto keep_locked;
|
goto keep_locked;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user