Skip to content

Commit f9b0e05

Browse files
jankaraFengguang Wu
authored andcommitted
writeback: Fix data corruption on NFS
Commit 4f8ad65 "writeback: Refactor writeback_single_inode()" added a condition to skip clean inode. However this is wrong in WB_SYNC_ALL mode because there we also want to wait for outstanding writeback on possibly clean inode. This was causing occasional data corruption issues on NFS because it uses sync_inode() to make sure all outstanding writes are flushed to the server before truncating the inode and with sync_inode() returning prematurely file was sometimes extended back by an outstanding write after it was truncated. So modify the test to also check for pages under writeback in WB_SYNC_ALL mode. CC: [email protected] # >= 3.5 Fixes: 4f8ad65 Reported-and-tested-by: Dan Duval <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent 374b105 commit f9b0e05

File tree

1 file changed

+9
-6
lines changed

1 file changed

+9
-6
lines changed

fs/fs-writeback.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -516,13 +516,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
516516
}
517517
WARN_ON(inode->i_state & I_SYNC);
518518
/*
519-
* Skip inode if it is clean. We don't want to mess with writeback
520-
* lists in this function since flusher thread may be doing for example
521-
* sync in parallel and if we move the inode, it could get skipped. So
522-
* here we make sure inode is on some writeback list and leave it there
523-
* unless we have completely cleaned the inode.
519+
* Skip inode if it is clean and we have no outstanding writeback in
520+
* WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
521+
* function since flusher thread may be doing for example sync in
522+
* parallel and if we move the inode, it could get skipped. So here we
523+
* make sure inode is on some writeback list and leave it there unless
524+
* we have completely cleaned the inode.
524525
*/
525-
if (!(inode->i_state & I_DIRTY))
526+
if (!(inode->i_state & I_DIRTY) &&
527+
(wbc->sync_mode != WB_SYNC_ALL ||
528+
!mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
526529
goto out;
527530
inode->i_state |= I_SYNC;
528531
spin_unlock(&inode->i_lock);

0 commit comments

Comments
 (0)