Index: linux-2.6.20-rc4/fs/buffer.c =================================================================== --- linux-2.6.20-rc4.orig/fs/buffer.c 2007-01-08 17:12:57.453866209 -0600 +++ linux-2.6.20-rc4/fs/buffer.c 2007-01-08 17:16:19.783968674 -0600 @@ -357,7 +357,7 @@ static void free_more_memory(void) struct zone **zones; pg_data_t *pgdat; - wakeup_pdflush(1024); + wakeup_pdflush(1024, &node_online_map); yield(); for_each_online_pgdat(pgdat) { Index: linux-2.6.20-rc4/fs/sync.c =================================================================== --- linux-2.6.20-rc4.orig/fs/sync.c 2007-01-08 17:12:57.462656080 -0600 +++ linux-2.6.20-rc4/fs/sync.c 2007-01-08 17:16:19.794711846 -0600 @@ -21,9 +21,9 @@ * sync everything. Start out by waking pdflush, because that writes back * all queues in parallel. */ -static void do_sync(unsigned long wait) +static void do_sync(unsigned long wait, nodemask_t *unused) { - wakeup_pdflush(0); + wakeup_pdflush(0, &node_online_map); sync_inodes(0); /* All mappings, inodes and their blockdevs */ DQUOT_SYNC(NULL); sync_supers(); /* Write the superblocks */ @@ -38,13 +38,13 @@ static void do_sync(unsigned long wait) asmlinkage long sys_sync(void) { - do_sync(1); + do_sync(1, &node_online_map); return 0; } void emergency_sync(void) { - pdflush_operation(do_sync, 0); + pdflush_operation(do_sync, 0, &node_online_map); } /* Index: linux-2.6.20-rc4/include/linux/writeback.h =================================================================== --- linux-2.6.20-rc4.orig/include/linux/writeback.h 2007-01-08 17:14:40.822738464 -0600 +++ linux-2.6.20-rc4/include/linux/writeback.h 2007-01-08 17:16:19.812291584 -0600 @@ -84,7 +84,7 @@ static inline void wait_on_inode(struct /* * mm/page-writeback.c */ -int wakeup_pdflush(long nr_pages); +int wakeup_pdflush(long nr_pages, nodemask_t *nodes); void laptop_io_completion(void); void laptop_sync_completion(void); void throttle_vm_writeout(void); @@ -112,7 +112,8 @@ balance_dirty_pages_ratelimited(struct a balance_dirty_pages_ratelimited_nr(mapping, 1); } -int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0); +int pdflush_operation(void (*fn)(unsigned long, nodemask_t *nodes), + unsigned long arg0, nodemask_t *nodes); extern int generic_writepages(struct address_space *mapping, struct writeback_control *wbc); int do_writepages(struct address_space *mapping, struct writeback_control *wbc); Index: linux-2.6.20-rc4/mm/page-writeback.c =================================================================== --- linux-2.6.20-rc4.orig/mm/page-writeback.c 2007-01-08 17:16:18.195932393 -0600 +++ linux-2.6.20-rc4/mm/page-writeback.c 2007-01-08 17:18:01.156542578 -0600 @@ -101,7 +101,7 @@ EXPORT_SYMBOL(laptop_mode); /* End of sysctl-exported parameters */ -static void background_writeout(unsigned long _min_pages); +static void background_writeout(unsigned long _min_pages, nodemask_t *nodes); struct dirty_limits { long thresh_background; @@ -155,7 +155,7 @@ get_dirty_limits(struct dirty_limits *dl high_memory = 0; nr_mapped = 0; wbc->masked = 1; - for_each_node_mask(node, wbc->nodeset) { + for_each_node_mask(node, *wbc->nodes) { if (!node_online(node)) continue; dl->nr_dirty += node_page_state(node, NR_FILE_DIRTY); @@ -291,7 +291,8 @@ static void balance_dirty_pages(struct a */ if ((laptop_mode && pages_written) || (!laptop_mode && (nr_reclaimable > dl.thresh_background))) - pdflush_operation(background_writeout, 0); + pdflush_operation(background_writeout, 0, + &cpuset_current_mems_allowed); } void set_page_dirty_balance(struct page *page) @@ -370,7 +371,7 @@ void throttle_vm_writeout(void) * writeback at least _min_pages, and keep writing until the amount of dirty * memory is less than the background threshold, or until we're all clean. */ -static void background_writeout(unsigned long _min_pages) +static void background_writeout(unsigned long _min_pages, nodemask_t *nodes) { long min_pages = _min_pages; struct writeback_control wbc = { @@ -380,7 +381,7 @@ static void background_writeout(unsigned .nr_to_write = 0, .nonblocking = 1, .range_cyclic = 1, - .nodeset = nodes_of_interest + .nodes = nodes }; for ( ; ; ) { @@ -409,12 +410,12 @@ static void background_writeout(unsigned * the whole world. Returns 0 if a pdflush thread was dispatched. Returns * -1 if all pdflush threads were busy. */ -int wakeup_pdflush(long nr_pages) +int wakeup_pdflush(long nr_pages, nodemask_t *nodes) { if (nr_pages == 0) nr_pages = global_page_state(NR_FILE_DIRTY) + global_page_state(NR_UNSTABLE_NFS); - return pdflush_operation(background_writeout, nr_pages); + return pdflush_operation(background_writeout, nr_pages, nodes); } static void wb_timer_fn(unsigned long unused); @@ -438,7 +439,7 @@ static DEFINE_TIMER(laptop_mode_wb_timer * older_than_this takes precedence over nr_to_write. So we'll only write back * all dirty pages if they are all attached to "old" mappings. */ -static void wb_kupdate(unsigned long arg) +static void wb_kupdate(unsigned long arg, nodemask_t *unused) { unsigned long oldest_jif; unsigned long start_jif; @@ -498,18 +499,18 @@ int dirty_writeback_centisecs_handler(ct static void wb_timer_fn(unsigned long unused) { - if (pdflush_operation(wb_kupdate, 0) < 0) + if (pdflush_operation(wb_kupdate, 0, &node_online_map) < 0) mod_timer(&wb_timer, jiffies + HZ); /* delay 1 second */ } -static void laptop_flush(unsigned long unused) +static void laptop_flush(unsigned long unused, nodemask_t *unused2) { sys_sync(); } static void laptop_timer_fn(unsigned long unused) { - pdflush_operation(laptop_flush, 0); + pdflush_operation(laptop_flush, 0, &node_online_map); } /* Index: linux-2.6.20-rc4/mm/pdflush.c =================================================================== --- linux-2.6.20-rc4.orig/mm/pdflush.c 2007-01-08 17:12:57.500745519 -0600 +++ linux-2.6.20-rc4/mm/pdflush.c 2007-01-08 17:17:23.838669795 -0600 @@ -83,10 +83,11 @@ static unsigned long last_empty_jifs; */ struct pdflush_work { struct task_struct *who; /* The thread */ - void (*fn)(unsigned long); /* A callback function */ + void (*fn)(unsigned long, nodemask_t *); /* A callback function */ unsigned long arg0; /* An argument to the callback */ struct list_head list; /* On pdflush_list, when idle */ unsigned long when_i_went_to_sleep; + nodemask_t nodes; /* running on Which node? */ }; static int __pdflush(struct pdflush_work *my_work) @@ -123,7 +124,7 @@ static int __pdflush(struct pdflush_work } spin_unlock_irq(&pdflush_lock); - (*my_work->fn)(my_work->arg0); + (*my_work->fn)(my_work->arg0, &my_work->nodes); /* * Thread creation: For how long have there been zero @@ -197,8 +198,8 @@ static int pdflush(void *dummy) * Returns zero if it indeed managed to find a worker thread, and passed your * payload to it. */ -int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0, - nodemask_t nodes) +int pdflush_operation(void (*fn)(unsigned long, nodemask_t *), + unsigned long arg0, nodemask_t *nodes) { unsigned long flags; int ret = 0; @@ -218,6 +219,7 @@ int pdflush_operation(void (*fn)(unsigne last_empty_jifs = jiffies; pdf->fn = fn; pdf->arg0 = arg0; + pdf->nodes = *nodes; wake_up_process(pdf->who); spin_unlock_irqrestore(&pdflush_lock, flags); } Index: linux-2.6.20-rc4/mm/vmscan.c =================================================================== --- linux-2.6.20-rc4.orig/mm/vmscan.c 2007-01-08 17:12:57.512465346 -0600 +++ linux-2.6.20-rc4/mm/vmscan.c 2007-01-08 17:16:19.852334319 -0600 @@ -1065,7 +1065,14 @@ unsigned long try_to_free_pages(struct z */ if (total_scanned > sc.swap_cluster_max + sc.swap_cluster_max / 2) { - wakeup_pdflush(laptop_mode ? 0 : total_scanned); + nodemask_t nodes = NODE_MASK_NONE; + + /* + * Writeout only makes sense if its flushing inodes + * with pages on the current node + */ + node_set(numa_node_id(), nodes); + wakeup_pdflush(laptop_mode ? 0 : total_scanned, &nodes); sc.may_writepage = 1; } Index: linux-2.6.20-rc4/fs/super.c =================================================================== --- linux-2.6.20-rc4.orig/fs/super.c 2007-01-08 17:12:57.473399255 -0600 +++ linux-2.6.20-rc4/fs/super.c 2007-01-08 17:16:19.865030796 -0600 @@ -618,7 +618,7 @@ int do_remount_sb(struct super_block *sb return 0; } -static void do_emergency_remount(unsigned long foo) +static void do_emergency_remount(unsigned long foo, nodemask_t *bar) { struct super_block *sb; @@ -646,7 +646,7 @@ static void do_emergency_remount(unsigne void emergency_remount(void) { - pdflush_operation(do_emergency_remount, 0); + pdflush_operation(do_emergency_remount, 0, &node_online_map); } /*