diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 60 |
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 |