writeback: stop background writeback when below background threshold
authorWu Fengguang <fengguang.wu@intel.com>
Wed, 23 Sep 2009 12:33:40 +0000 (20:33 +0800)
committerJens Axboe <jens.axboe@oracle.com>
Fri, 25 Sep 2009 16:08:24 +0000 (18:08 +0200)
Treat bdi_start_writeback(0) as a special request to do background write,
and stop such work when we are below the background dirty threshold.

Also simplify the (nr_pages <= 0) checks. Since we already pass in
nr_pages=LONG_MAX for WB_SYNC_ALL and background writes, we don't
need to worry about it being decreased to zero.

Reported-by: Richard Kennedy <richard@rsk.demon.co.uk>
CC: Jan Kara <jack@suse.cz>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Wu Fengguang <fengguang.wu@intel.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
fs/fs-writeback.c
mm/page-writeback.c

index c59d673..476be9b 100644 (file)
@@ -41,8 +41,9 @@ struct wb_writeback_args {
        long nr_pages;
        struct super_block *sb;
        enum writeback_sync_modes sync_mode;
-       int for_kupdate;
-       int range_cyclic;
+       int for_kupdate:1;
+       int range_cyclic:1;
+       int for_background:1;
 };
 
 /*
@@ -257,6 +258,15 @@ void bdi_start_writeback(struct backing_dev_info *bdi, long nr_pages)
                .range_cyclic   = 1,
        };
 
+       /*
+        * We treat @nr_pages=0 as the special case to do background writeback,
+        * ie. to sync pages until the background dirty threshold is reached.
+        */
+       if (!nr_pages) {
+               args.nr_pages = LONG_MAX;
+               args.for_background = 1;
+       }
+
        bdi_alloc_queue_work(bdi, &args);
 }
 
@@ -720,20 +730,16 @@ static long wb_writeback(struct bdi_writeback *wb,
 
        for (;;) {
                /*
-                * Don't flush anything for non-integrity writeback where
-                * no nr_pages was given
+                * Stop writeback when nr_pages has been consumed
                 */
-               if (!args->for_kupdate && args->nr_pages <= 0 &&
-                    args->sync_mode == WB_SYNC_NONE)
+               if (args->nr_pages <= 0)
                        break;
 
                /*
-                * If no specific pages were given and this is just a
-                * periodic background writeout and we are below the
-                * background dirty threshold, don't do anything
+                * For background writeout, stop when we are below the
+                * background dirty threshold
                 */
-               if (args->for_kupdate && args->nr_pages <= 0 &&
-                   !over_bground_thresh())
+               if (args->for_background && !over_bground_thresh())
                        break;
 
                wbc.more_io = 0;
index cbd4cba..3c78fc3 100644 (file)
@@ -593,10 +593,10 @@ static void balance_dirty_pages(struct address_space *mapping,
         * background_thresh, to keep the amount of dirty memory low.
         */
        if ((laptop_mode && pages_written) ||
-           (!laptop_mode && ((nr_writeback = global_page_state(NR_FILE_DIRTY)
-                                         + global_page_state(NR_UNSTABLE_NFS))
+           (!laptop_mode && ((global_page_state(NR_FILE_DIRTY)
+                              + global_page_state(NR_UNSTABLE_NFS))
                                          > background_thresh)))
-               bdi_start_writeback(bdi, nr_writeback);
+               bdi_start_writeback(bdi, 0);
 }
 
 void set_page_dirty_balance(struct page *page, int page_mkwrite)