This patch moves some LRU list handling code out of the swap-code. These can be used by memory-migration code. Signed-off-by: Hirokazu Takahashi Signed-off-by: Dave Hansen --- memhotplug-dave/include/linux/mm_inline.h | 58 ++++++++++++++++++++++++++++++ memhotplug-dave/mm/vmscan.c | 39 ++------------------ 2 files changed, 63 insertions(+), 34 deletions(-) diff -puN include/linux/mm_inline.h~AA-PM-01-steal_page_from_lru include/linux/mm_inline.h --- memhotplug/include/linux/mm_inline.h~AA-PM-01-steal_page_from_lru 2005-03-11 10:51:36.000000000 -0800 +++ memhotplug-dave/include/linux/mm_inline.h 2005-03-11 10:51:36.000000000 -0800 @@ -38,3 +38,61 @@ del_page_from_lru(struct zone *zone, str zone->nr_inactive--; } } + +static inline int +__steal_page_from_lru(struct zone *zone, struct page *page) +{ + if (!TestClearPageLRU(page)) + BUG(); + list_del(&page->lru); + if (get_page_testone(page)) { + /* + * It was already free! release_pages() or put_page() + * are about to remove it from the LRU and free it. So + * put the refcount back and put the page back on the + * LRU + */ + __put_page(page); + SetPageLRU(page); + if (PageActive(page)) + list_add(&page->lru, &zone->active_list); + else + list_add(&page->lru, &zone->inactive_list); + return 0; + } + if (PageActive(page)) + zone->nr_active--; + else + zone->nr_inactive--; + return 1; +} + +static inline int +steal_page_from_lru(struct zone *zone, struct page *page) +{ + int ret; + spin_lock_irq(&zone->lru_lock); + ret = __steal_page_from_lru(zone, page); + spin_unlock_irq(&zone->lru_lock); + return ret; +} + +static inline void +__putback_page_to_lru(struct zone *zone, struct page *page) +{ + if (TestSetPageLRU(page)) + BUG(); + if (PageActive(page)) + add_page_to_active_list(zone, page); + else + add_page_to_inactive_list(zone, page); +} + +static inline void +putback_page_to_lru(struct zone *zone, struct page *page) +{ + spin_lock_irq(&zone->lru_lock); + __putback_page_to_lru(zone, page); + spin_unlock_irq(&zone->lru_lock); +} + diff -puN mm/vmscan.c~AA-PM-01-steal_page_from_lru mm/vmscan.c --- memhotplug/mm/vmscan.c~AA-PM-01-steal_page_from_lru 2005-03-11 10:51:36.000000000 -0800 +++ memhotplug-dave/mm/vmscan.c 2005-03-11 10:51:36.000000000 -0800 @@ -565,23 +565,11 @@ static void shrink_cache(struct zone *zo prefetchw_prev_lru_page(page, &zone->inactive_list, flags); - - if (!TestClearPageLRU(page)) - BUG(); - list_del(&page->lru); - if (get_page_testone(page)) { - /* - * It is being freed elsewhere - */ - __put_page(page); - SetPageLRU(page); - list_add(&page->lru, &zone->inactive_list); + if (!__steal_page_from_lru(zone, page)) continue; - } list_add(&page->lru, &page_list); nr_taken++; } - zone->nr_inactive -= nr_taken; zone->pages_scanned += nr_scan; spin_unlock_irq(&zone->lru_lock); @@ -605,13 +593,10 @@ static void shrink_cache(struct zone *zo */ 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 (PageActive(page) && page_under_capture(page)) + ClearPageActive(page); + __putback_page_to_lru(zone, page); if (!pagevec_add(&pvec, page)) { spin_unlock_irq(&zone->lru_lock); __pagevec_release(&pvec); @@ -664,27 +649,13 @@ refill_inactive_zone(struct zone *zone, while (pgscanned < nr_pages && !list_empty(&zone->active_list)) { page = lru_to_page(&zone->active_list); prefetchw_prev_lru_page(page, &zone->active_list, flags); - if (!TestClearPageLRU(page)) - BUG(); - list_del(&page->lru); - if (get_page_testone(page)) { - /* - * It was already free! release_pages() or put_page() - * are about to remove it from the LRU and free it. So - * put the refcount back and put the page back on the - * LRU - */ - __put_page(page); - SetPageLRU(page); - list_add(&page->lru, &zone->active_list); - } else { + if (__steal_page_from_lru(zone, page)) { list_add(&page->lru, &l_hold); pgmoved++; } pgscanned++; } zone->pages_scanned += pgscanned; - zone->nr_active -= pgmoved; spin_unlock_irq(&zone->lru_lock); /* _