From: Martin Hicks The patches introduce two different ways to free up page cache from a node: manually through a syscall and automatically through flag modifiers to a mempolicy. Currently if a job is started and there is page cache lying around on a particular node then allocations will spill onto remote nodes and page cache won't be reclaimed until the whole system is short on memory. This can result in a signficiant performance hit for HPC applications that planned on that memory being allocated locally. Just a refactoring patch that sticks a list of pages back onto the appropriate LRU lists. This is used to return pages to the LRU lists after processing them outside the LRU lock. Signed-off-by: Martin Hicks Signed-off-by: Andrew Morton --- mm/vmscan.c | 62 ++++++++++++++++++++++++++++++++++++------------------------ 1 files changed, 38 insertions(+), 24 deletions(-) diff -puN mm/vmscan.c~vm-merge_lru_pages mm/vmscan.c --- 25/mm/vmscan.c~vm-merge_lru_pages Wed Apr 27 16:37:37 2005 +++ 25-akpm/mm/vmscan.c Wed Apr 27 16:37:37 2005 @@ -605,20 +605,50 @@ static int isolate_lru_pages(int nr_to_s } /* + * This is the opposite of isolate_lru_pages(). It puts the + * pages in @list back onto the lru lists in @zone. + */ +void merge_lru_pages(struct zone *zone, struct list_head *list) +{ + struct page *page; + struct pagevec pvec; + + BUG_ON(zone == NULL); + BUG_ON(list == NULL); + + pagevec_init(&pvec, 1); + + while (!list_empty(list)) { + page = lru_to_page(list); + if (TestSetPageLRU(page)) + BUG(); + list_del(&page->lru); + if (PageActive(page)) + add_page_to_active_list(zone, page); + else + add_page_to_inactive_list(zone, page); + if (!pagevec_add(&pvec, page)) { + spin_unlock_irq(&zone->lru_lock); + __pagevec_release(&pvec); + spin_lock_irq(&zone->lru_lock); + } + } + spin_unlock_irq(&zone->lru_lock); + pagevec_release(&pvec); + spin_lock_irq(&zone->lru_lock); +} + +/* * shrink_cache() adds the number of pages reclaimed to sc->nr_reclaimed */ static void shrink_cache(struct zone *zone, struct scan_control *sc) { LIST_HEAD(page_list); - struct pagevec pvec; int max_scan = sc->nr_to_scan; - pagevec_init(&pvec, 1); - lru_add_drain(); spin_lock_irq(&zone->lru_lock); while (max_scan > 0) { - struct page *page; int nr_taken; int nr_scan; int nr_freed; @@ -631,7 +661,7 @@ static void shrink_cache(struct zone *zo spin_unlock_irq(&zone->lru_lock); if (nr_taken == 0) - goto done; + return; max_scan -= nr_scan; if (current_is_kswapd()) @@ -644,29 +674,13 @@ static void shrink_cache(struct zone *zo mod_page_state_zone(zone, pgsteal, nr_freed); sc->nr_to_reclaim -= nr_freed; - spin_lock_irq(&zone->lru_lock); /* * Put back any unfreeable pages. */ - while (!list_empty(&page_list)) { - page = lru_to_page(&page_list); - if (TestSetPageLRU(page)) - BUG(); - list_del(&page->lru); - if (PageActive(page)) - add_page_to_active_list(zone, page); - else - add_page_to_inactive_list(zone, page); - if (!pagevec_add(&pvec, page)) { - spin_unlock_irq(&zone->lru_lock); - __pagevec_release(&pvec); - spin_lock_irq(&zone->lru_lock); - } - } - } + spin_lock_irq(&zone->lru_lock); + merge_lru_pages(zone, &page_list); + } spin_unlock_irq(&zone->lru_lock); -done: - pagevec_release(&pvec); } /* _