diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 8d23b0b3871744a9fad98f3fcbdf5470083fb20d..08b9f83b645e6a1a33b07a489805c6da4bd45c2e 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -140,6 +140,30 @@ static int write_inode(struct inode *inode, int sync) return 0; } +/* + * Redirty an inode: set its when-it-was dirtied timestamp and move it to the + * furthest end of its superblock's dirty-inode list. + * + * Before stamping the inode's ->dirtied_when, we check to see whether it is + * already the most-recently-dirtied inode on the s_dirty list. If that is + * the case then the inode must have been redirtied while it was being written + * out and we don't reset its dirtied_when. + */ +static void redirty_tail(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + + if (!list_empty(&sb->s_dirty)) { + struct inode *tail_inode; + + tail_inode = list_entry(sb->s_dirty.next, struct inode, i_list); + if (!time_after_eq(inode->dirtied_when, + tail_inode->dirtied_when)) + inode->dirtied_when = jiffies; + } + list_move(&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. @@ -219,7 +243,7 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc) * Someone redirtied the inode while were writing back * the pages. */ - list_move(&inode->i_list, &sb->s_dirty); + redirty_tail(inode); } else if (atomic_read(&inode->i_count)) { /* * The inode is clean, inuse