The page reclaiming logic operates on a per-zone basis. This patch introduces a general try_to_free_pages_nozone() which just tries to free 32 pages from *every* zone. This function is only used from free_more_memory() in fs/buffer.c. When we're trying to grow buffers against a device for filesystem metadata. It seems to me that free_more_memory() simply is not needed - we're already retrying the allocation over in buffer.c, and it seems that this will do most everything which the call to try_to_free_pages() would do? ===================================== --- 2.4.19-pre4/fs/buffer.c~aa-120-try_to_free_pages_nozone Tue Mar 26 23:11:31 2002 +++ 2.4.19-pre4-akpm/fs/buffer.c Tue Mar 26 23:11:31 2002 @@ -727,12 +727,8 @@ void __invalidate_buffers(kdev_t dev, in static void free_more_memory(void) { - zone_t * zone = contig_page_data.node_zonelists[GFP_NOFS & GFP_ZONEMASK].zones[0]; - - balance_dirty(); wakeup_bdflush(); - try_to_free_pages(zone, GFP_NOFS, 0); - run_task_queue(&tq_disk); + try_to_free_pages_nozone(GFP_NOIO); current->policy |= SCHED_YIELD; __set_current_state(TASK_RUNNING); schedule(); --- 2.4.19-pre4/include/linux/swap.h~aa-120-try_to_free_pages_nozone Tue Mar 26 23:11:31 2002 +++ 2.4.19-pre4-akpm/include/linux/swap.h Tue Mar 26 23:11:31 2002 @@ -113,6 +113,7 @@ extern void swap_setup(void); extern wait_queue_head_t kswapd_wait; extern int FASTCALL(try_to_free_pages(zone_t *, unsigned int, unsigned int)); extern int vm_vfs_scan_ratio, vm_cache_scan_ratio, vm_lru_balance_ratio, vm_passes, vm_gfp_debug, vm_mapped_ratio; +extern int FASTCALL(try_to_free_pages_nozone(unsigned int)); /* linux/mm/page_io.c */ extern void rw_swap_page(int, struct page *); --- 2.4.19-pre4/mm/page_alloc.c~aa-120-try_to_free_pages_nozone Tue Mar 26 23:11:31 2002 +++ 2.4.19-pre4-akpm/mm/page_alloc.c Tue Mar 26 23:11:31 2002 @@ -510,6 +510,30 @@ unsigned int nr_free_highpages (void) } #endif +int try_to_free_pages_nozone(unsigned int gfp_mask) +{ + pg_data_t *pgdat = pgdat_list; + zonelist_t *zonelist; + zone_t **zonep; + int ret = 0; + unsigned long pf_free_pages; + + pf_free_pages = current->flags & PF_FREE_PAGES; + current->flags &= ~PF_FREE_PAGES; + + do { + zonelist = pgdat->node_zonelists + (gfp_mask & GFP_ZONEMASK); + zonep = zonelist->zones; + + ret |= try_to_free_pages(*zonep, gfp_mask, 0); + + pgdat = pgdat->node_next; + } while (pgdat); + + current->flags |= pf_free_pages; + return ret; +} + #define K(x) ((x) << (PAGE_SHIFT-10)) /*