Skip to content

Commit 0e17733

Browse files
jankaragregkh
authored andcommitted
writeback: Fix data corruption on NFS
commit f9b0e05 upstream. 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. Fixes: 4f8ad65 Reported-and-tested-by: Dan Duval <[email protected]> Signed-off-by: Jan Kara <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 19519d5 commit 0e17733

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
@@ -510,13 +510,16 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb,
510510
}
511511
WARN_ON(inode->i_state & I_SYNC);
512512
/*
513-
* Skip inode if it is clean. We don't want to mess with writeback
514-
* lists in this function since flusher thread may be doing for example
515-
* sync in parallel and if we move the inode, it could get skipped. So
516-
* here we make sure inode is on some writeback list and leave it there
517-
* unless we have completely cleaned the inode.
513+
* Skip inode if it is clean and we have no outstanding writeback in
514+
* WB_SYNC_ALL mode. We don't want to mess with writeback lists in this
515+
* function since flusher thread may be doing for example sync in
516+
* parallel and if we move the inode, it could get skipped. So here we
517+
* make sure inode is on some writeback list and leave it there unless
518+
* we have completely cleaned the inode.
518519
*/
519-
if (!(inode->i_state & I_DIRTY))
520+
if (!(inode->i_state & I_DIRTY) &&
521+
(wbc->sync_mode != WB_SYNC_ALL ||
522+
!mapping_tagged(inode->i_mapping, PAGECACHE_TAG_WRITEBACK)))
520523
goto out;
521524
inode->i_state |= I_SYNC;
522525
spin_unlock(&inode->i_lock);

0 commit comments

Comments
 (0)