Fix the time ordering bug re-introduced by
writeback-fix-periodic-superblock-dirty-inode-flushing.patch.

It works by never move not-yet-expired dirty inodes from s_dirty to s_io,
*only to* move them back. The move-inodes-back-and-forth thing is a mess.

Cc: Ken Chen <[EMAIL PROTECTED]>
Cc: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Fengguang Wu <[EMAIL PROTECTED]>
---
 fs/fs-writeback.c |   40 ++++++++++++++++++++++------------------
 1 file changed, 22 insertions(+), 18 deletions(-)

--- linux-2.6.23-rc2-mm2.orig/fs/fs-writeback.c
+++ linux-2.6.23-rc2-mm2/fs/fs-writeback.c
@@ -172,6 +172,23 @@ static void requeue_io(struct inode *ino
 }
 
 /*
+ * Queue expired dirty inodes for io.
+ */
+static void queue_io(struct super_block *sb,
+                               unsigned long *older_than_this)
+{
+       while (!list_empty(&sb->s_dirty)) {
+               struct inode *inode = list_entry(sb->s_dirty.prev,
+                                               struct inode, i_list);
+               /* Was this inode dirtied too recently? */
+               if (older_than_this &&
+                       time_after(inode->dirtied_when, *older_than_this))
+                       break;
+               list_move(&inode->i_list, &sb->s_io);
+       }
+}
+
+/*
  * Write a single inode's dirty pages and inode data out to disk.
  * If `wait' is set, wait on the writeout.
  *
@@ -295,10 +312,10 @@ __writeback_single_inode(struct inode *i
 
                /*
                 * We're skipping this inode because it's locked, and we're not
-                * doing writeback-for-data-integrity.  Move it to the head of
-                * s_dirty so that writeback can proceed with the other inodes
-                * on s_io.  We'll have another go at writing back this inode
-                * when the s_dirty iodes get moved back onto s_io.
+                * doing writeback-for-data-integrity.  Move it to s_more_io so
+                * that writeback can proceed with the other inodes on s_io.
+                * We'll have another go at writing back this inode when we
+                * completed a full scan of s_io.
                 */
                requeue_io(inode);
 
@@ -362,10 +379,8 @@ __writeback_single_inode(struct inode *i
 static void
 sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
 {
-       const unsigned long start = jiffies;    /* livelock avoidance */
-
        if (!wbc->for_kupdate || list_empty(&sb->s_io))
-               list_splice_init(&sb->s_dirty, &sb->s_io);
+               queue_io(sb, wbc->older_than_this);
 
        while (!list_empty(&sb->s_io)) {
                struct inode *inode = list_entry(sb->s_io.prev,
@@ -406,17 +421,6 @@ sync_sb_inodes(struct super_block *sb, s
                        continue;               /* blockdev has wrong queue */
                }
 
-               /* Was this inode dirtied after sync_sb_inodes was called? */
-               if (time_after(inode->dirtied_when, start))
-                       break;
-
-               /* Was this inode dirtied too recently? */
-               if (wbc->older_than_this && time_after(inode->dirtied_when,
-                                               *wbc->older_than_this)) {
-                       list_splice_init(&sb->s_io, sb->s_dirty.prev);
-                       break;
-               }
-
                /* Is another pdflush already flushing this queue? */
                if (current_is_pdflush() && !writeback_acquire(bdi))
                        break;

-- 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to