On Thu, 2007-11-15 at 20:40 +0100, Peter Zijlstra wrote: > As for the highmem part, that was due to buffer cache, and unfortunately > that is still true. Although maybe we can do something smart with the > per-bdi stuff.
Something like this ought to do I guess. Although my mapping_is_buffercache() is the ugliest thing. I'm sure that can be done better. Uncompiled, untested Not-Signed-off-by: Peter Zijlstra <[EMAIL PROTECTED]> --- mm/page-writeback.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) Index: linux-2.6/mm/page-writeback.c =================================================================== --- linux-2.6.orig/mm/page-writeback.c +++ linux-2.6/mm/page-writeback.c @@ -280,27 +280,28 @@ static unsigned long highmem_dirtyable_m #endif } -static unsigned long determine_dirtyable_memory(void) +static unsigned long determine_dirtyable_memory(int highmem) { unsigned long x; x = global_page_state(NR_FREE_PAGES) + global_page_state(NR_INACTIVE) + global_page_state(NR_ACTIVE); - x -= highmem_dirtyable_memory(x); + if (!highmem) + x -= highmem_dirtyable_memory(x); return x + 1; /* Ensure that we never return 0 */ } static void get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, - struct backing_dev_info *bdi) + struct backing_dev_info *bdi, int highmem) { int background_ratio; /* Percentages */ int dirty_ratio; int unmapped_ratio; long background; long dirty; - unsigned long available_memory = determine_dirtyable_memory(); + unsigned long available_memory = determine_dirtyable_memory(highmem); struct task_struct *tsk; unmapped_ratio = 100 - ((global_page_state(NR_FILE_MAPPED) + @@ -346,6 +347,16 @@ get_dirty_limits(long *pbackground, long } } +static inline int mapping_is_buffercache(struct address_space *mapping) +{ + struct super_block *sb = mapping->host->i_sb; + + if (sb && sb->s_bdev && sb->s_bdev->bd_inode->i_mapping != mapping) + return 0; + + return 1; +} + /* * balance_dirty_pages() must be called by processes which are generating dirty * data. It looks at the number of dirty pages in the machine and will force @@ -364,6 +375,7 @@ static void balance_dirty_pages(struct a unsigned long write_chunk = sync_writeback_pages(); struct backing_dev_info *bdi = mapping->backing_dev_info; + int highmem = !mapping_is_buffercache(mapping); for (;;) { struct writeback_control wbc = { @@ -375,7 +387,7 @@ static void balance_dirty_pages(struct a }; get_dirty_limits(&background_thresh, &dirty_thresh, - &bdi_thresh, bdi); + &bdi_thresh, bdi, highmem); bdi_nr_reclaimable = bdi_stat(bdi, BDI_RECLAIMABLE); bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK); if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh) @@ -394,7 +406,7 @@ static void balance_dirty_pages(struct a writeback_inodes(&wbc); pages_written += write_chunk - wbc.nr_to_write; get_dirty_limits(&background_thresh, &dirty_thresh, - &bdi_thresh, bdi); + &bdi_thresh, bdi, highmem); } /* @@ -503,7 +515,7 @@ void throttle_vm_writeout(gfp_t gfp_mask long dirty_thresh; for ( ; ; ) { - get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL); + get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL, 1); /* * Boost the allowable dirty threshold a bit for page @@ -546,7 +558,7 @@ static void background_writeout(unsigned long background_thresh; long dirty_thresh; - get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL); + get_dirty_limits(&background_thresh, &dirty_thresh, NULL, NULL, 1); if (global_page_state(NR_FILE_DIRTY) + global_page_state(NR_UNSTABLE_NFS) < background_thresh && min_pages <= 0) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/