From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753673Ab0ILPzh (ORCPT ); Sun, 12 Sep 2010 11:55:37 -0400 Received: from mga09.intel.com ([134.134.136.24]:35314 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753361Ab0ILPzC (ORCPT ); Sun, 12 Sep 2010 11:55:02 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.56,355,1280732400"; d="scan'208";a="656512015" Message-Id: <20100912155203.206486412@intel.com> User-Agent: quilt/0.48-1 Date: Sun, 12 Sep 2010 23:49:49 +0800 From: Wu Fengguang To: linux-mm Cc: LKML , Wu Fengguang CC: Andrew Morton CC: "Theodore Ts'o" CC: Dave Chinner CC: Jan Kara CC: Peter Zijlstra CC: Mel Gorman CC: Rik van Riel CC: KOSAKI Motohiro CC: Chris Mason CC: Christoph Hellwig CC: Li Shaohua Subject: [PATCH 04/17] writeback: quit throttling when bdi dirty/writeback pages go down References: <20100912154945.758129106@intel.com> Content-Disposition: inline; filename=writeback-bdi-throttle-break.patch Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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;