Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f0c6bcba authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Dave Chinner
Browse files

xfs: reorder zeroing and flushing sequence in truncate



Currently zeroing out blocks and waiting for writeout is a bit of a mess in
truncate.  This patch gives it a clear order in preparation for the iomap
path:

 (1) we first wait for any direct I/O to complete to prevent any races
     for it
 (2) we then perform the actual zeroing, and only use the truncate_page
     helpers for truncating down.  The truncate up case already is
     handled by the separate call to xfs_zero_eof.
 (3) only then we write back dirty data, as zeroing block may cause
     dirty pages when using either xfs_zero_eof or the new iomap
     infrastructure.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>

parent 3b3dce05
Loading
Loading
Loading
Loading
+19 −14
Original line number Diff line number Diff line
@@ -800,20 +800,35 @@ xfs_setattr_size(
	if (error)
		return error;

	/*
	 * Wait for all direct I/O to complete.
	 */
	inode_dio_wait(inode);

	/*
	 * File data changes must be complete before we start the transaction to
	 * modify the inode.  This needs to be done before joining the inode to
	 * the transaction because the inode cannot be unlocked once it is a
	 * part of the transaction.
	 *
	 * Start with zeroing any data block beyond EOF that we may expose on
	 * file extension.
	 * Start with zeroing any data beyond EOF that we may expose on file
	 * extension, or zeroing out the rest of the block on a downward
	 * truncate.
	 */
	if (newsize > oldsize) {
		error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing);
	} else {
		if (IS_DAX(inode)) {
			error = dax_truncate_page(inode, newsize,
					xfs_get_blocks_direct);
		} else {
			error = block_truncate_page(inode->i_mapping, newsize,
					xfs_get_blocks);
		}
	}

	if (error)
		return error;
	}

	/*
	 * We are going to log the inode size change in this transaction so
@@ -831,9 +846,6 @@ xfs_setattr_size(
			return error;
	}

	/* Now wait for all direct I/O to complete. */
	inode_dio_wait(inode);

	/*
	 * We've already locked out new page faults, so now we can safely remove
	 * pages from the page cache knowing they won't get refaulted until we
@@ -851,13 +863,6 @@ xfs_setattr_size(
	 * to hope that the caller sees ENOMEM and retries the truncate
	 * operation.
	 */
	if (IS_DAX(inode))
		error = dax_truncate_page(inode, newsize, xfs_get_blocks_direct);
	else
		error = block_truncate_page(inode->i_mapping, newsize,
					    xfs_get_blocks);
	if (error)
		return error;
	truncate_setsize(inode, newsize);

	error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp);