diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 66889b06d00f697fac67bbab8c48b1d8325fe134..eb8dc1f227756995dcc928c18713b6bb12b744f9 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -164,6 +164,28 @@ static void redirty_tail(struct inode *inode) list_move(&inode->i_list, &sb->s_dirty); } +/* + * 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