Commit:     c986d1e2a460cbce79d631c51519ae82c778c6c5
Parent:     f57b9b7b4f68e1723ca99381dc10c8bc07d6df14
Author:     Andrew Morton <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 16 23:30:34 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Oct 17 08:43:02 2007 -0700

    writeback: fix time ordering of the per superblock dirty inode lists 4
    When the kupdate function has tried to write back an expired inode it will
    then check to see whether some of the inode's pages are still dirty.
    This can happen when the filesystem decided to not write a page for some
    reason.  But it does _not_ occur due to redirtyings: a redirtying will set
    What we need to do here is to set I_DIRTY_PAGES to reflect reality and to 
    put the inode onto the _head_ of s_dirty for consideration on the next 
    pass, in five seconds time.
    Problem is, the code failed to modify the inode's timestamp when pushing the
    inode onto thehead of s_dirty.
    The patch:
    If there are no other inodes on s_dirty then we leave the inode's timestamp
    alone: it is already expired.
    If there _are_ other inodes on s_dirty then we arrange for this inode to get
    the same timestamp as the inode which is at the head of s_dirty, thus
    preserving the s_dirty ordering.  But we only need to do this if this inode
    purports to have been dirtied before the one at head-of-list.
    Cc: Mike Waychison <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
 fs/fs-writeback.c |   24 +++++++++++++++++++++++-
 1 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 66889b0..eb8dc1f 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -165,6 +165,28 @@ static void redirty_tail(struct inode *inode)
+ * Redirty an inode, but mark it as the very next-to-be-written inode on its
+ * superblock's dirty-inode list.
+ * We need to preserve s_dirty's reverse-time-orderedness, so we cheat by
+ * setting this inode's dirtied_when to the same value as that of the inode
+ * which is presently head-of-list, if present head-of-list is newer than this
+ * inode. (head-of-list is the least-recently-dirtied inode: the oldest one).
+ */
+static void redirty_head(struct inode *inode)
+       struct super_block *sb = inode->i_sb;
+       if (!list_empty(&sb->s_dirty)) {
+               struct inode *head_inode;
+               head_inode = list_entry(sb->s_dirty.prev, struct inode, i_list);
+               if (time_after(inode->dirtied_when, head_inode->dirtied_when))
+                       inode->dirtied_when = head_inode->dirtied_when;
+       }
+       list_move_tail(&inode->i_list, &sb->s_dirty);
  * Write a single inode's dirty pages and inode data out to disk.
  * If `wait' is set, wait on the writeout.
@@ -225,7 +247,7 @@ __sync_single_inode(struct inode *inode, struct 
writeback_control *wbc)
                                 * uncongested.
                                inode->i_state |= I_DIRTY_PAGES;
-                               list_move_tail(&inode->i_list, &sb->s_dirty);
+                               redirty_head(inode);
                        } else {
                                 * Otherwise fully redirty the inode so that
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

Reply via email to