aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fs-writeback.c
diff options
context:
space:
mode:
authorAndrew Morton <akpm@linux-foundation.org>2007-10-17 02:30:37 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:02 -0400
commit65cb9b47e0ea568a7a38cce7773052a6ea093629 (patch)
tree9a53747f37c772cb882a7cbcd65879c36c5297fd /fs/fs-writeback.c
parentc6945e77e477103057b4a639b4b01596f5257861 (diff)
writeback: fix time ordering of the per superblock dirty inode lists 6
Recycling the previous changelog: When the writeback function is operating in writeback-for-flushing mode (as opposed to writeback-for-integrity) and it encounters an I_LOCKed inode, it will skip writing that inode. This is done for throughput and latency: move on to another inode rather than blocking for this one. Writeback skips this inode by moving it off s_io and onto s_dirty, so that writeback can proceed with the other inodes on s_io. However that inode movement can corrupt s_dirty's reverse-time-orderedness. Fix that by using the new redirty_tail(), which will update the refiled inode's dirtied_when field. Note: the behaviour in here is a bit rude: if kupdate happens to come across a locked inode then it will defer writeback of that inode for another 30 seconds. We'll address that in the next patch. Address that here. What we do is to move the skipped inode to the _head_ of s_dirty, immediately eligible for writeout again. Instead of deferring that writeout for another 30 seconds. One would think that this might cause a livelock: we keep on trying to write the same locked inode. But it won't because: a) if that was the case, it would _already_ be happening on the balance_dirty_pages codepath. Because balance_dirty_pages() doesn't care about inode timestamps. b) if we skipped this inode then we won't have done any writeback. The higher-level writeback paths will see that wbc.nr_to_write didn't change and they'll then back off and take a nap. Cc: Mike Waychison <mikew@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fs-writeback.c')
-rw-r--r--fs/fs-writeback.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 1b43cc9d9ebb..30d9383c87c3 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -308,7 +308,14 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
308 struct address_space *mapping = inode->i_mapping; 308 struct address_space *mapping = inode->i_mapping;
309 int ret; 309 int ret;
310 310
311 redirty_tail(inode); 311 /*
312 * We're skipping this inode because it's locked, and we're not
313 * doing writeback-for-data-integrity. Move it to the head of
314 * s_dirty so that writeback can proceed with the other inodes
315 * on s_io. We'll have another go at writing back this inode
316 * when the s_dirty iodes get moved back onto s_io.
317 */
318 redirty_head(inode);
312 319
313 /* 320 /*
314 * Even if we don't actually write the inode itself here, 321 * Even if we don't actually write the inode itself here,