From: Christoph Lameter Add gfp_mask to add_to_swap add_to_swap does allocations with GFP_ATOMIC in order not to interfere with swapping. During migration we may have use add_to_swap extensively which may lead to out of memory errors. This patch makes add_to_swap take a parameter that specifies the gfp mask. The page migration code can then make add_to_swap use GFP_KERNEL. Signed-off-by: Hirokazu Takahashi Signed-off-by: Dave Hansen Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton --- include/linux/swap.h | 2 +- mm/swap_state.c | 4 ++-- mm/vmscan.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff -puN include/linux/swap.h~swapmig-add_to_swap-avoid-atomic-allocations include/linux/swap.h --- devel/include/linux/swap.h~swapmig-add_to_swap-avoid-atomic-allocations 2005-11-17 18:14:37.000000000 -0800 +++ devel-akpm/include/linux/swap.h 2005-11-17 18:14:37.000000000 -0800 @@ -231,7 +231,7 @@ extern int rw_swap_page_sync(int, swp_en extern struct address_space swapper_space; #define total_swapcache_pages swapper_space.nrpages extern void show_swap_cache_info(void); -extern int add_to_swap(struct page *); +extern int add_to_swap(struct page *, gfp_t); extern void __delete_from_swap_cache(struct page *); extern void delete_from_swap_cache(struct page *); extern int move_to_swap_cache(struct page *, swp_entry_t); diff -puN mm/swap_state.c~swapmig-add_to_swap-avoid-atomic-allocations mm/swap_state.c --- devel/mm/swap_state.c~swapmig-add_to_swap-avoid-atomic-allocations 2005-11-17 18:14:37.000000000 -0800 +++ devel-akpm/mm/swap_state.c 2005-11-17 18:14:37.000000000 -0800 @@ -142,7 +142,7 @@ void __delete_from_swap_cache(struct pag * Allocate swap space for the page and add the page to the * swap cache. Caller needs to hold the page lock. */ -int add_to_swap(struct page * page) +int add_to_swap(struct page * page, gfp_t gfp_mask) { swp_entry_t entry; int err; @@ -170,7 +170,7 @@ int add_to_swap(struct page * page) * Add it to the swap cache and mark it dirty */ err = __add_to_swap_cache(page, entry, - GFP_ATOMIC|__GFP_NOMEMALLOC|__GFP_NOWARN); + gfp_mask|__GFP_NOMEMALLOC|__GFP_NOWARN); switch (err) { case 0: /* Success */ diff -puN mm/vmscan.c~swapmig-add_to_swap-avoid-atomic-allocations mm/vmscan.c --- devel/mm/vmscan.c~swapmig-add_to_swap-avoid-atomic-allocations 2005-11-17 18:14:37.000000000 -0800 +++ devel-akpm/mm/vmscan.c 2005-11-17 18:14:37.000000000 -0800 @@ -456,7 +456,7 @@ static int shrink_list(struct list_head if (PageAnon(page) && !PageSwapCache(page)) { if (!sc->may_swap) goto keep_locked; - if (!add_to_swap(page)) + if (!add_to_swap(page, GFP_ATOMIC)) goto activate_locked; } #endif /* CONFIG_SWAP */ @@ -722,7 +722,7 @@ redo: } if (PageAnon(page) && !PageSwapCache(page)) { - if (!add_to_swap(page)) { + if (!add_to_swap(page, GFP_KERNEL)) { unlock_page(page); list_move(&page->lru, &failed); nr_failed++; _