mm: page_idle: convert page idle to use a folio

Firstly, make page_idle_get_page() return a folio, also rename it to
page_idle_get_folio(), then, use it to convert page_idle_bitmap_read() and
page_idle_bitmap_write() functions.

Link: https://lkml.kernel.org/r/20221230070849.63358-3-wangkefeng.wang@huawei.com
Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: SeongJae Park <sj@kernel.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Vishal Moola (Oracle) <vishal.moola@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Kefeng Wang 2022-12-30 15:08:43 +08:00 committed by Andrew Morton
parent becacb04fd
commit 5acc17fd35
1 changed files with 24 additions and 23 deletions

View File

@ -31,19 +31,22 @@
*
* This function tries to get a user memory page by pfn as described above.
*/
static struct page *page_idle_get_page(unsigned long pfn)
static struct folio *page_idle_get_folio(unsigned long pfn)
{
struct page *page = pfn_to_online_page(pfn);
struct folio *folio;
if (!page || !PageLRU(page) ||
!get_page_unless_zero(page))
if (!page || PageTail(page))
return NULL;
if (unlikely(!PageLRU(page))) {
put_page(page);
page = NULL;
folio = page_folio(page);
if (!folio_test_lru(folio) || !folio_try_get(folio))
return NULL;
if (unlikely(page_folio(page) != folio || !folio_test_lru(folio))) {
folio_put(folio);
folio = NULL;
}
return page;
return folio;
}
static bool page_idle_clear_pte_refs_one(struct folio *folio,
@ -83,10 +86,8 @@ static bool page_idle_clear_pte_refs_one(struct folio *folio,
return true;
}
static void page_idle_clear_pte_refs(struct page *page)
static void page_idle_clear_pte_refs(struct folio *folio)
{
struct folio *folio = page_folio(page);
/*
* Since rwc.try_lock is unused, rwc is effectively immutable, so we
* can make it static to save some cycles and stack.
@ -115,7 +116,7 @@ static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj,
loff_t pos, size_t count)
{
u64 *out = (u64 *)buf;
struct page *page;
struct folio *folio;
unsigned long pfn, end_pfn;
int bit;
@ -134,19 +135,19 @@ static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj,
bit = pfn % BITMAP_CHUNK_BITS;
if (!bit)
*out = 0ULL;
page = page_idle_get_page(pfn);
if (page) {
if (page_is_idle(page)) {
folio = page_idle_get_folio(pfn);
if (folio) {
if (folio_test_idle(folio)) {
/*
* The page might have been referenced via a
* pte, in which case it is not idle. Clear
* refs and recheck.
*/
page_idle_clear_pte_refs(page);
if (page_is_idle(page))
page_idle_clear_pte_refs(folio);
if (folio_test_idle(folio))
*out |= 1ULL << bit;
}
put_page(page);
folio_put(folio);
}
if (bit == BITMAP_CHUNK_BITS - 1)
out++;
@ -160,7 +161,7 @@ static ssize_t page_idle_bitmap_write(struct file *file, struct kobject *kobj,
loff_t pos, size_t count)
{
const u64 *in = (u64 *)buf;
struct page *page;
struct folio *folio;
unsigned long pfn, end_pfn;
int bit;
@ -178,11 +179,11 @@ static ssize_t page_idle_bitmap_write(struct file *file, struct kobject *kobj,
for (; pfn < end_pfn; pfn++) {
bit = pfn % BITMAP_CHUNK_BITS;
if ((*in >> bit) & 1) {
page = page_idle_get_page(pfn);
if (page) {
page_idle_clear_pte_refs(page);
set_page_idle(page);
put_page(page);
folio = page_idle_get_folio(pfn);
if (folio) {
page_idle_clear_pte_refs(folio);
folio_set_idle(folio);
folio_put(folio);
}
}
if (bit == BITMAP_CHUNK_BITS - 1)