From 2bc85a5a38c5f0c2ea31a5fb2bd81ea20054a666 Mon Sep 17 00:00:00 2001 From: Charan Teja Reddy Date: Mon, 28 Jun 2021 16:00:03 +0530 Subject: [PATCH] ANDROID: mm: add reclaim_shmem_address_space() for faster reclaims Add the functionality that allow users of shmem to reclaim its pages without going through the kswapd/direct reclaim path. An example usecase is: Say that device allocates a larger amount of shmem pages and shares it with hardware. To faster reclaims such pages, drivers can register the shrinkers and call reclaim_shmem_address_space(). This commit is a squash of changes that contains all the fixes in the reclaim_shmem_address_space() API. Bug: 201263305 Bug: 263340150 Change-Id: I03d2c3b9610612af977f89ddeabb63b8e9e50918 Signed-off-by: Charan Teja Reddy Signed-off-by: Charan Teja Kalla (cherry picked from commit 81102cdb3d594c164676eef4afec4b3c48b55392) [georgi: Replace page_isolate_lru() with folio_isolate_lru()] Signed-off-by: Georgi Djakov --- include/linux/mm.h | 1 + mm/shmem.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h index 61fff5d34ed5..a633bf7c0bcd 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4072,6 +4072,7 @@ unsigned long wp_shared_mapping_range(struct address_space *mapping, #endif extern int sysctl_nr_trim_pages; +extern int reclaim_shmem_address_space(struct address_space *mapping); #ifdef CONFIG_PRINTK void mem_dump_obj(void *object); diff --git a/mm/shmem.c b/mm/shmem.c index c5adb987b23c..2c14c2af117f 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "swap.h" static struct vfsmount *shm_mnt __ro_after_init; @@ -5369,3 +5370,41 @@ struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, return page; } EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp); + +int reclaim_shmem_address_space(struct address_space *mapping) +{ +#ifdef CONFIG_SHMEM + pgoff_t start = 0; + struct page *page; + LIST_HEAD(page_list); + XA_STATE(xas, &mapping->i_pages, start); + + if (!shmem_mapping(mapping)) + return -EINVAL; + + lru_add_drain(); + + rcu_read_lock(); + xas_for_each(&xas, page, ULONG_MAX) { + if (xas_retry(&xas, page)) + continue; + if (xa_is_value(page)) + continue; + if (!folio_isolate_lru(page_folio(page))) + continue; + + list_add(&page->lru, &page_list); + + if (need_resched()) { + xas_pause(&xas); + cond_resched_rcu(); + } + } + rcu_read_unlock(); + + return reclaim_pages(&page_list); +#else + return 0; +#endif +} +EXPORT_SYMBOL_GPL(reclaim_shmem_address_space);