Tests show that bdi_thresh may take minutes to ramp up on a typical desktop. The time should be improvable but cannot be eliminated totally. So when (background_thresh + dirty_thresh)/2 is reached and balance_dirty_pages() starts to throttle the task, it will suddenly find the (still low and ramping up) bdi_thresh is exceeded _excessively_. Here we definitely don't want to stall the task for one minute. So introduce an alternative way to break out of the loop when the bdi dirty/write pages has dropped by a reasonable amount. When dirty_background_ratio is set close to dirty_ratio, bdi_thresh may also be constantly exceeded due to the task_dirty_limit() gap. It will take at least 200ms before trying to break out. (pages_dirtied * 8) is used because in this situation pages_dirtied will typically be small numbers (eg. 3 pages) due to the fast back off logic. Signed-off-by: Wu Fengguang --- mm/page-writeback.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) --- linux-next.orig/mm/page-writeback.c 2010-09-09 15:51:38.000000000 +0800 +++ linux-next/mm/page-writeback.c 2010-09-12 13:10:02.000000000 +0800 @@ -463,6 +463,7 @@ static void balance_dirty_pages(struct a { long nr_reclaimable, bdi_nr_reclaimable; long nr_writeback, bdi_nr_writeback; + long bdi_prev_dirty3 = 0; unsigned long background_thresh; unsigned long dirty_thresh; unsigned long bdi_thresh; @@ -516,6 +517,20 @@ static void balance_dirty_pages(struct a bdi_nr_writeback = bdi_stat(bdi, BDI_WRITEBACK); } + /* + * bdi_thresh could get exceeded for long time: + * - bdi_thresh takes some time to ramp up from the initial 0 + * - users may set dirty_background_ratio close to dirty_ratio + * (at least 1/8 gap is preferred) + * So offer a complementary way to break out of the loop when + * enough bdi pages have been cleaned during our pause time. + */ + if (nr_reclaimable + nr_writeback <= dirty_thresh && + bdi_prev_dirty3 - (bdi_nr_reclaimable + bdi_nr_writeback) > + (long)pages_dirtied * 8) + break; + bdi_prev_dirty3 = bdi_nr_reclaimable + bdi_nr_writeback; + if (bdi_nr_reclaimable + bdi_nr_writeback <= bdi_thresh - bdi_thresh / DIRTY_SOFT_THROTTLE_RATIO) goto check_exceeded; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/