Commit 9949c4ca authored by Dave Chinner's avatar Dave Chinner Committed by Ben Hutchings

xfs: xfs_setattr_size no longer races with page faults

commit 0f9160b4 upstream.

Now that truncate locks out new page faults, we no longer need to do
special writeback hacks in truncate to work around potential races
between page faults, page cache truncation and file size updates to
ensure we get write page faults for extending truncates on sub-page
block size filesystems. Hence we can remove the code in
xfs_setattr_size() that handles this and update the comments around
the code tha thandles page cache truncate and size updates to
reflect the new reality.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
[bwh: Backported to 3.16: we never had the previous hack, so just update the
 comment]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent 1c2ed395
...@@ -823,19 +823,21 @@ xfs_setattr_size( ...@@ -823,19 +823,21 @@ xfs_setattr_size(
inode_dio_wait(inode); inode_dio_wait(inode);
/* /*
* Do all the page cache truncate work outside the transaction context * We've already locked out new page faults, so now we can safely remove
* as the "lock" order is page lock->log space reservation. i.e. * pages from the page cache knowing they won't get refaulted until we
* locking pages inside the transaction can ABBA deadlock with * drop the XFS_MMAP_EXCL lock after the extent manipulations are
* writeback. We have to do the VFS inode size update before we truncate * complete. The truncate_setsize() call also cleans partial EOF page
* the pagecache, however, to avoid racing with page faults beyond the * PTEs on extending truncates and hence ensures sub-page block size
* new EOF they are not serialised against truncate operations except by * filesystems are correctly handled, too.
* page locks and size updates.
* *
* Hence we are in a situation where a truncate can fail with ENOMEM * We have to do all the page cache truncate work outside the
* from xfs_trans_reserve(), but having already truncated the in-memory * transaction context as the "lock" order is page lock->log space
* version of the file (i.e. made user visible changes). There's not * reservation as defined by extent allocation in the writeback path.
* much we can do about this, except to hope that the caller sees ENOMEM * Hence a truncate can fail with ENOMEM from xfs_trans_reserve(), but
* and retries the truncate operation. * having already truncated the in-memory version of the file (i.e. made
* user visible changes). There's not much we can do about this, except
* to hope that the caller sees ENOMEM and retries the truncate
* operation.
*/ */
error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks); error = -block_truncate_page(inode->i_mapping, newsize, xfs_get_blocks);
if (error) if (error)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment