From: Magnus Damm This patch reduces the amount of work done by __isolate_lru_page() and puts it in isolate_lru_page() instead. The patch reverts the isolate_lru_pages() parameter and return value modification too. Number of assembly lines occupied by isolate_lru_pages(): linux-2.6.14: 67 linux-2.6.14-mm2: 115 linux-2.6.14-mm2-slim: 71 (this patch) Signed-off-by: Magnus Damm Cc: Christoph Lameter Signed-off-by: Andrew Morton --- include/linux/mm_inline.h | 29 ++++++++++++----------------- mm/vmscan.c | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 32 deletions(-) diff -puN include/linux/mm_inline.h~swap-migration-v5-lru-operations-inline-shrinkage include/linux/mm_inline.h --- devel/include/linux/mm_inline.h~swap-migration-v5-lru-operations-inline-shrinkage 2005-11-22 22:30:26.000000000 -0800 +++ devel-akpm/include/linux/mm_inline.h 2005-11-22 22:30:26.000000000 -0800 @@ -44,24 +44,19 @@ del_page_from_lru(struct zone *zone, str * * - zone->lru_lock must be held */ -static inline int __isolate_lru_page(struct zone *zone, struct page *page) +static inline int __isolate_lru_page(struct page *page) { - if (TestClearPageLRU(page)) { - if (get_page_testone(page)) { - /* - * It is being freed elsewhere - */ - __put_page(page); - SetPageLRU(page); - return -ENOENT; - } else { - if (PageActive(page)) - del_page_from_active_list(zone, page); - else - del_page_from_inactive_list(zone, page); - return 1; - } + if (unlikely(!TestClearPageLRU(page))) + return 0; + + if (get_page_testone(page)) { + /* + * It is being freed elsewhere + */ + __put_page(page); + SetPageLRU(page); + return -ENOENT; } - return 0; + return 1; } diff -puN mm/vmscan.c~swap-migration-v5-lru-operations-inline-shrinkage mm/vmscan.c --- devel/mm/vmscan.c~swap-migration-v5-lru-operations-inline-shrinkage 2005-11-22 22:30:26.000000000 -0800 +++ devel-akpm/mm/vmscan.c 2005-11-22 22:30:26.000000000 -0800 @@ -584,27 +584,29 @@ keep: * * Appropriate locks must be held before calling this function. * - * @zone: The zone where lru_lock is held. * @nr_to_scan: The number of pages to look through on the list. * @src: The LRU list to pull pages off. * @dst: The temp list to put pages on to. + * @scanned: The number of pages that were scanned. * - * returns the number of pages that were scanned. + * returns how many pages were moved onto *@dst. */ -static int isolate_lru_pages(struct zone *zone, int nr_to_scan, - struct list_head *src, struct list_head *dst) +static int isolate_lru_pages(int nr_to_scan, struct list_head *src, + struct list_head *dst, int *scanned) { + int nr_taken = 0; struct page *page; - int scanned = 0; + int scan = 0; - while (scanned++ < nr_to_scan && !list_empty(src)) { + while (scan++ < nr_to_scan && !list_empty(src)) { page = lru_to_page(src); prefetchw_prev_lru_page(page, src, flags); - switch (__isolate_lru_page(zone, page)) { + switch (__isolate_lru_page(page)) { case 1: /* Succeeded to isolate page */ - list_add(&page->lru, dst); + list_move(&page->lru, dst); + nr_taken++; break; case -ENOENT: /* Not possible to isolate */ @@ -615,7 +617,8 @@ static int isolate_lru_pages(struct zone } } - return scanned; + *scanned = scan; + return nr_taken; } static void lru_add_drain_per_cpu(void *dummy) @@ -640,7 +643,13 @@ int isolate_lru_page(struct page *page) redo: spin_lock_irq(&zone->lru_lock); - rc = __isolate_lru_page(zone, page); + rc = __isolate_lru_page(page); + if (rc == 1) { + if (PageActive(page)) + del_page_from_active_list(zone, page); + else + del_page_from_inactive_list(zone, page); + } spin_unlock_irq(&zone->lru_lock); if (rc == 0) { /* @@ -669,15 +678,18 @@ static void shrink_cache(struct zone *zo spin_lock_irq(&zone->lru_lock); while (max_scan > 0) { struct page *page; + int nr_taken; int nr_scan; int nr_freed; - nr_scan = isolate_lru_pages(zone, sc->swap_cluster_max, - &zone->inactive_list, &page_list); + nr_taken = isolate_lru_pages(sc->swap_cluster_max, + &zone->inactive_list, + &page_list, &nr_scan); + zone->nr_inactive -= nr_taken; zone->pages_scanned += nr_scan; spin_unlock_irq(&zone->lru_lock); - if (list_empty(&page_list)) + if (nr_taken == 0) goto done; max_scan -= nr_scan; @@ -786,9 +798,10 @@ refill_inactive_zone(struct zone *zone, lru_add_drain(); spin_lock_irq(&zone->lru_lock); - pgscanned = isolate_lru_pages(zone, nr_pages, - &zone->active_list, &l_hold); + pgmoved = isolate_lru_pages(nr_pages, &zone->active_list, + &l_hold, &pgscanned); zone->pages_scanned += pgscanned; + zone->nr_active -= pgmoved; spin_unlock_irq(&zone->lru_lock); /* _