aboutsummaryrefslogtreecommitdiff
path: root/mm/vmscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 2cf5e9ece1a..3002a05e7ee 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1160,6 +1160,66 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
return ret;
}
+#ifdef CONFIG_PROCESS_RECLAIM
+static unsigned long shrink_page(struct page *page,
+ struct zone *zone,
+ struct scan_control *sc,
+ enum ttu_flags ttu_flags,
+ unsigned long *ret_nr_dirty,
+ unsigned long *ret_nr_writeback,
+ bool force_reclaim,
+ struct list_head *ret_pages)
+{
+ int reclaimed;
+ LIST_HEAD(page_list);
+ list_add(&page->lru, &page_list);
+
+ reclaimed = shrink_page_list(&page_list, zone, sc, ttu_flags,
+ ret_nr_dirty, ret_nr_writeback,
+ force_reclaim);
+ if (!reclaimed)
+ list_splice(&page_list, ret_pages);
+
+ return reclaimed;
+}
+
+unsigned long reclaim_pages_from_list(struct list_head *page_list)
+{
+ struct scan_control sc = {
+ .gfp_mask = GFP_KERNEL,
+ .priority = DEF_PRIORITY,
+ .may_writepage = 1,
+ .may_unmap = 1,
+ .may_swap = 1,
+ };
+
+ LIST_HEAD(ret_pages);
+ struct page *page;
+ unsigned long dummy1, dummy2, dummy3, dummy4, dummy5;
+ unsigned long nr_reclaimed = 0;
+
+ while (!list_empty(page_list)) {
+ page = lru_to_page(page_list);
+ list_del(&page->lru);
+
+ ClearPageActive(page);
+ nr_reclaimed += shrink_page(page, page_zone(page), &sc,
+ TTU_UNMAP|TTU_IGNORE_ACCESS,
+ &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, true);
+ }
+
+ while (!list_empty(&ret_pages)) {
+ page = lru_to_page(&ret_pages);
+ list_del(&page->lru);
+ dec_zone_page_state(page, NR_ISOLATED_ANON +
+ page_is_file_cache(page));
+ putback_lru_page(page);
+ }
+
+ return nr_reclaimed;
+}
+#endif
+
/*
* Attempt to remove the specified page from its LRU. Only take this page
* if it is of the appropriate PageActive status. Pages which are being