Patch "xfs: fix eofblocks race with file extending async dio writes" has been added to the 4.9-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
xfs: fix eofblocks race with file extending async dio writes
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
xfs-fix-eofblocks-race-with-file-extending-async-dio-writes.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
e4229d6b0bc9280f29624faf170cf76a9f1ca60eMon Sep 17 00:00:00 2001
From: Brian Foster <[email protected]>
Date: Fri, 27 Jan 2017 23:22:57 -0800
Subject: xfs: fix eofblocks race with file extending async dio writes
From: Brian Foster <[email protected]>
commit e4229d6b0bc9280f29624faf170cf76a9f1ca60e upstream.
It's possible for post-eof blocks to end up being used for direct I/O writes. dio write performs an upfront unwritten extent allocation, sends the dio and then updates the inode size (if necessary) on write completion. If a file release occurs while a file extending dio write is in flight, it is possible to mistake the post-eof blocks for speculative preallocation and incorrectly truncate them from the inode. This means that the resulting dio write completion can discover a hole and allocate new blocks rather than perform unwritten extent conversion.
This requires a strange mix of I/O and is thus not likely to reproduce in real world workloads. It is intermittently reproduced by generic/299. The error manifests as an assert failure due to transaction overrun because the aforementioned write completion transaction has only reserved enough blocks for btree operations:
XFS: Assertion failed: tp->t_blk_res_used <= tp->t_blk_res, \ file: fs/xfs//xfs_trans.c, line: 309
The root cause is that xfs_free_eofblocks() uses i_size to truncate post-eof blocks from the inode, but async, file extending direct writes do not update i_size until write completion, long after inode locks are dropped. Therefore, xfs_free_eofblocks() effectively truncates the inode to the incorrect size.
Update xfs_free_eofblocks() to serialize against dio similar to how extending writes are serialized against i_size updates before post-eof block zeroing. Specifically, wait on dio while under the iolock. This ensures that dio write completions have updated i_size before post-eof blocks are processed.
--- fs/xfs/xfs_bmap_util.c | 3 +++ 1 file changed, 3 insertions(+)
fs/xfs/xfs_bmap_util.c +3 -0
@@ -959,6 +959,9 @@ xfs_free_eofblocks(if (error)return error; +/* wait on dio to ensure i_size has settled */ +inode_dio_wait (VFS_I (ip)); + error =xfs_trans_alloc (mp, &M_RES (mp)->tr_itruncate,0 ,0 ,0 , &tp);if (error) {
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/xfs-use-iomap-new-flag-for-newly-allocated-delalloc-blocks.patch queue-4.9/xfs-handle-indlen-shortage-on-delalloc-extent-merge.patch queue-4.9/xfs-reject-all-unaligned-direct-writes-to-reflinked-files.patch queue-4.9/xfs-don-t-fail-xfs_extent_busy-allocation.patch queue-4.9/xfs-sync-eofblocks-scans-under-iolock-are-livelock-prone.patch queue-4.9/xfs-pull-up-iolock-from-xfs_free_eofblocks.patch queue-4.9/xfs-split-indlen-reservations-fairly-when-under-reserved.patch queue-4.9/xfs-fix-eofblocks-race-with-file-extending-async-dio-writes.patch queue-4.9/xfs-fix-uninitialized-variable-in-_reflink_convert_cow.patch queue-4.9/xfs-don-t-reserve-blocks-for-right-shift-transactions.patch