xfs
[Top] [All Lists]

[PATCH v2 block/for-linus] writeback: sync_inodes_sb() must write out I_

To: Jens Axboe <axboe@xxxxxxxxx>, Jan Kara <jack@xxxxxxxx>
Subject: [PATCH v2 block/for-linus] writeback: sync_inodes_sb() must write out I_DIRTY_TIME inodes and always call wait_sb_inodes()
From: Tejun Heo <tj@xxxxxxxxxx>
Date: Tue, 25 Aug 2015 14:11:52 -0400
Cc: Eryu Guan <eguan@xxxxxxxxxx>, xfs@xxxxxxxxxxx, axboe@xxxxxx, Dave Chinner <david@xxxxxxxxxxxxx>, linux-fsdevel@xxxxxxxxxxxxxxx, linux-kernel@xxxxxxxxxxxxxxx, kernel-team@xxxxxx
Delivered-to: xfs@xxxxxxxxxxx
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; bh=efqsTIFBLamhL93IRaz6TiaLzHv+OlNm9vGvb/RGqMI=; b=N+tL1MUejrb5JsJMJcYVYmRkfkA21iag1i/3q6D4UyRYV652x8+r/to7rak0oE/eUp bc5Ju8PWbCUXJ4Yzkf2M44v6GDq20B3oS2dR4QTVgnXA3EQpHOYfEBQUCdiCq6rZUV+B d7jjIUXTvFSZfNvU8YJEha8Ikd3lkjpaayt293XKl2M3fC1mwbAKVMa3lLL81dSo1v4+ 5h6IdhkuRA9f2SJkA99k0VY3kZHXwluHQm7XpZ79NjRM9aJzNc7OBm8G9qy2iBfqSSPf FCQTfdvm6Zc3Dla16EEgq3i8C8aUtX+ENhMmJicoXcUikcNfYn0HxMb7WPzox+0xAKW/ GKfA==
In-reply-to: <20150813224415.GG4496@xxxxxxxxxxxxxxx>
References: <20150812101204.GE17933@xxxxxxxxxxxxxxxxxxxxxxxxxx> <20150813004435.GN3902@dastard> <20150813224415.GG4496@xxxxxxxxxxxxxxx>
Sender: Tejun Heo <htejun@xxxxxxxxx>
User-agent: Mutt/1.5.23 (2014-03-12)
e79729123f63 ("writeback: don't issue wb_writeback_work if clean")
updated writeback path to avoid kicking writeback work items if there
are no inodes to be written out; unfortunately, the avoidance logic
was too aggressive and broke sync_inodes_sb().

* sync_inodes_sb() must write out I_DIRTY_TIME inodes but I_DIRTY_TIME
  inodes dont't contribute to bdi/wb_has_dirty_io() tests and were
  being skipped over.

* inodes are taken off wb->b_dirty/io/more_io lists after writeback
  starts on them.  sync_inodes_sb() skipping wait_sb_inodes() when
  bdi_has_dirty_io() breaks it by making it return while writebacks
  are in-flight.

This patch fixes the breakages by

* Removing bdi_has_dirty_io() shortcut from bdi_split_work_to_wbs().
  The callers are already testing the condition.

* Removing bdi_has_dirty_io() shortcut from sync_inodes_sb() so that
  it always calls into bdi_split_work_to_wbs() and wait_sb_inodes().

* Making bdi_split_work_to_wbs() consider the b_dirty_time list for
  WB_SYNC_ALL writebacks.

Kudos to Eryu, Dave and Jan for tracking down the issue.

Signed-off-by: Tejun Heo <tj@xxxxxxxxxx>
Fixes: e79729123f63 ("writeback: don't issue wb_writeback_work if clean")
Link: http://lkml.kernel.org/g/20150812101204.GE17933@xxxxxxxxxxxxxxxxxxxxxxxxxx
Reported-and-bisected-by: Eryu Guan <eguan@xxxxxxxxxx>
Cc: Dave Chinner <david@xxxxxxxxxxxxx>
Cc: Jan Kara <jack@xxxxxxxx>
Cc: Ted Ts'o <tytso@xxxxxxxxxx>
---
 fs/fs-writeback.c |   22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -844,14 +844,15 @@ static void bdi_split_work_to_wbs(struct
        struct wb_iter iter;
 
        might_sleep();
-
-       if (!bdi_has_dirty_io(bdi))
-               return;
 restart:
        rcu_read_lock();
        bdi_for_each_wb(wb, bdi, &iter, next_blkcg_id) {
-               if (!wb_has_dirty_io(wb) ||
-                   (skip_if_busy && writeback_in_progress(wb)))
+               /* SYNC_ALL writes out I_DIRTY_TIME too */
+               if (!wb_has_dirty_io(wb) &&
+                   (base_work->sync_mode == WB_SYNC_NONE ||
+                    list_empty(&wb->b_dirty_time)))
+                       continue;
+               if (skip_if_busy && writeback_in_progress(wb))
                        continue;
 
                base_work->nr_pages = wb_split_bdi_pages(wb, nr_pages);
@@ -899,8 +900,7 @@ static void bdi_split_work_to_wbs(struct
 {
        might_sleep();
 
-       if (bdi_has_dirty_io(bdi) &&
-           (!skip_if_busy || !writeback_in_progress(&bdi->wb))) {
+       if (!skip_if_busy || !writeback_in_progress(&bdi->wb)) {
                base_work->auto_free = 0;
                base_work->single_wait = 0;
                base_work->single_done = 0;
@@ -2275,8 +2275,12 @@ void sync_inodes_sb(struct super_block *
        };
        struct backing_dev_info *bdi = sb->s_bdi;
 
-       /* Nothing to do? */
-       if (!bdi_has_dirty_io(bdi) || bdi == &noop_backing_dev_info)
+       /*
+        * Can't skip on !bdi_has_dirty() because we should wait for !dirty
+        * inodes under writeback and I_DIRTY_TIME inodes ignored by
+        * bdi_has_dirty() need to be written out too.
+        */
+       if (bdi == &noop_backing_dev_info)
                return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 

<Prev in Thread] Current Thread [Next in Thread>