Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=2e6883bdf49abd0e7f0d9b6297fc3be7ebb2250b
Commit:     2e6883bdf49abd0e7f0d9b6297fc3be7ebb2250b
Parent:     1f7decf6d9f06dac008b8d66935c0c3b18e564f9
Author:     Fengguang Wu <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 23:30:43 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Oct 17 08:43:02 2007 -0700

    writeback: introduce writeback_control.more_io to indicate more io
    
    After making dirty a 100M file, the normal behavior is to start the 
writeback
    for all data after 30s delays.  But sometimes the following happens instead:
    
        - after 30s:    ~4M
        - after 5s:     ~4M
        - after 5s:     all remaining 92M
    
    Some analyze shows that the internal io dispatch queues goes like this:
    
                s_io            s_more_io
                -------------------------
        1)      100M,1K         0
        2)      1K              96M
        3)      0               96M
    
    1) initial state with a 100M file and a 1K file
    2) 4M written, nr_to_write <= 0, so write more
    3) 1K written, nr_to_write > 0, no more writes(BUG)
    
    nr_to_write > 0 in (3) fools the upper layer to think that data have all 
been
    written out.  The big dirty file is actually still sitting in s_more_io.  We
    cannot simply splice s_more_io back to s_io as soon as s_io becomes empty, 
and
    let the loop in generic_sync_sb_inodes() continue: this may starve newly
    expired inodes in s_dirty.  It is also not an option to draw inodes from 
both
    s_more_io and s_dirty, an let the loop go on: this might lead to live locks,
    and might also starve other superblocks in sync time(well kupdate may still
    starve some superblocks, that's another bug).
    
    We have to return when a full scan of s_io completes.  So nr_to_write > 0 
does
    not necessarily mean that "all data are written".  This patch introduces a
    flag writeback_control.more_io to indicate this situation.  With it the big
    dirty file no longer has to wait for the next kupdate invocation 5s later.
    
    Cc: David Chinner <[EMAIL PROTECTED]>
    Cc: Ken Chen <[EMAIL PROTECTED]>
    Signed-off-by: Fengguang Wu <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/fs-writeback.c         |    2 ++
 include/linux/writeback.h |    1 +
 mm/page-writeback.c       |    9 ++++++---
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 414df43..71c158a 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -473,6 +473,8 @@ sync_sb_inodes(struct super_block *sb, struct 
writeback_control *wbc)
                if (wbc->nr_to_write <= 0)
                        break;
        }
+       if (!list_empty(&sb->s_more_io))
+               wbc->more_io = 1;
        return;         /* Leave any unwritten inodes on s_io */
 }
 
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 52be879..1200868 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -62,6 +62,7 @@ struct writeback_control {
        unsigned for_reclaim:1;         /* Invoked from the page allocator */
        unsigned for_writepages:1;      /* This is a writepages() call */
        unsigned range_cyclic:1;        /* range_start is cyclic */
+       unsigned more_io:1;             /* more io to be dispatched */
 };
 
 /*
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 3348521..bcdbbf6 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -553,6 +553,7 @@ static void background_writeout(unsigned long _min_pages)
                        global_page_state(NR_UNSTABLE_NFS) < background_thresh
                                && min_pages <= 0)
                        break;
+               wbc.more_io = 0;
                wbc.encountered_congestion = 0;
                wbc.nr_to_write = MAX_WRITEBACK_PAGES;
                wbc.pages_skipped = 0;
@@ -560,8 +561,9 @@ static void background_writeout(unsigned long _min_pages)
                min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
                if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
                        /* Wrote less than expected */
-                       congestion_wait(WRITE, HZ/10);
-                       if (!wbc.encountered_congestion)
+                       if (wbc.encountered_congestion || wbc.more_io)
+                               congestion_wait(WRITE, HZ/10);
+                       else
                                break;
                }
        }
@@ -626,11 +628,12 @@ static void wb_kupdate(unsigned long arg)
                        global_page_state(NR_UNSTABLE_NFS) +
                        (inodes_stat.nr_inodes - inodes_stat.nr_unused);
        while (nr_to_write > 0) {
+               wbc.more_io = 0;
                wbc.encountered_congestion = 0;
                wbc.nr_to_write = MAX_WRITEBACK_PAGES;
                writeback_inodes(&wbc);
                if (wbc.nr_to_write > 0) {
-                       if (wbc.encountered_congestion)
+                       if (wbc.encountered_congestion || wbc.more_io)
                                congestion_wait(WRITE, HZ/10);
                        else
                                break;  /* All the old data is written */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to