diff options
Diffstat (limited to 'fs/xfs/xfs_file.c')
| -rw-r--r-- | fs/xfs/xfs_file.c | 64 | 
1 files changed, 36 insertions, 28 deletions
| diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ebdd0bd2b261..6526ef0e2a23 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -58,7 +58,7 @@ xfs_zero_range(  	xfs_off_t		count,  	bool			*did_zero)  { -	return iomap_zero_range(VFS_I(ip), pos, count, NULL, &xfs_iomap_ops); +	return iomap_zero_range(VFS_I(ip), pos, count, did_zero, &xfs_iomap_ops);  }  int @@ -237,11 +237,13 @@ xfs_file_dax_read(  	if (!count)  		return 0; /* skip atime */ -	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { -		if (iocb->ki_flags & IOCB_NOWAIT) +	if (iocb->ki_flags & IOCB_NOWAIT) { +		if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))  			return -EAGAIN; +	} else {  		xfs_ilock(ip, XFS_IOLOCK_SHARED);  	} +  	ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops);  	xfs_iunlock(ip, XFS_IOLOCK_SHARED); @@ -259,9 +261,10 @@ xfs_file_buffered_aio_read(  	trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); -	if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) { -		if (iocb->ki_flags & IOCB_NOWAIT) +	if (iocb->ki_flags & IOCB_NOWAIT) { +		if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))  			return -EAGAIN; +	} else {  		xfs_ilock(ip, XFS_IOLOCK_SHARED);  	}  	ret = generic_file_read_iter(iocb, to); @@ -377,8 +380,6 @@ restart:  	 */  	spin_lock(&ip->i_flags_lock);  	if (iocb->ki_pos > i_size_read(inode)) { -		bool	zero = false; -  		spin_unlock(&ip->i_flags_lock);  		if (!drained_dio) {  			if (*iolock == XFS_IOLOCK_SHARED) { @@ -399,7 +400,7 @@ restart:  			drained_dio = true;  			goto restart;  		} -		error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), &zero); +		error = xfs_zero_eof(ip, iocb->ki_pos, i_size_read(inode), NULL);  		if (error)  			return error;  	} else @@ -436,7 +437,6 @@ xfs_dio_write_end_io(  	struct inode		*inode = file_inode(iocb->ki_filp);  	struct xfs_inode	*ip = XFS_I(inode);  	loff_t			offset = iocb->ki_pos; -	bool			update_size = false;  	int			error = 0;  	trace_xfs_end_io_direct_write(ip, offset, size); @@ -447,6 +447,21 @@ xfs_dio_write_end_io(  	if (size <= 0)  		return size; +	if (flags & IOMAP_DIO_COW) { +		error = xfs_reflink_end_cow(ip, offset, size); +		if (error) +			return error; +	} + +	/* +	 * Unwritten conversion updates the in-core isize after extent +	 * conversion but before updating the on-disk size. Updating isize any +	 * earlier allows a racing dio read to find unwritten extents before +	 * they are converted. +	 */ +	if (flags & IOMAP_DIO_UNWRITTEN) +		return xfs_iomap_write_unwritten(ip, offset, size, true); +  	/*  	 * We need to update the in-core inode size here so that we don't end up  	 * with the on-disk inode size being outside the in-core inode size. We @@ -461,20 +476,11 @@ xfs_dio_write_end_io(  	spin_lock(&ip->i_flags_lock);  	if (offset + size > i_size_read(inode)) {  		i_size_write(inode, offset + size); -		update_size = true; -	} -	spin_unlock(&ip->i_flags_lock); - -	if (flags & IOMAP_DIO_COW) { -		error = xfs_reflink_end_cow(ip, offset, size); -		if (error) -			return error; -	} - -	if (flags & IOMAP_DIO_UNWRITTEN) -		error = xfs_iomap_write_unwritten(ip, offset, size); -	else if (update_size) +		spin_unlock(&ip->i_flags_lock);  		error = xfs_setfilesize(ip, offset, size); +	} else { +		spin_unlock(&ip->i_flags_lock); +	}  	return error;  } @@ -549,9 +555,10 @@ xfs_file_dio_aio_write(  		iolock = XFS_IOLOCK_SHARED;  	} -	if (!xfs_ilock_nowait(ip, iolock)) { -		if (iocb->ki_flags & IOCB_NOWAIT) +	if (iocb->ki_flags & IOCB_NOWAIT) { +		if (!xfs_ilock_nowait(ip, iolock))  			return -EAGAIN; +	} else {  		xfs_ilock(ip, iolock);  	} @@ -603,9 +610,10 @@ xfs_file_dax_write(  	size_t			count;  	loff_t			pos; -	if (!xfs_ilock_nowait(ip, iolock)) { -		if (iocb->ki_flags & IOCB_NOWAIT) +	if (iocb->ki_flags & IOCB_NOWAIT) { +		if (!xfs_ilock_nowait(ip, iolock))  			return -EAGAIN; +	} else {  		xfs_ilock(ip, iolock);  	} @@ -761,7 +769,7 @@ xfs_file_fallocate(  	enum xfs_prealloc_flags	flags = 0;  	uint			iolock = XFS_IOLOCK_EXCL;  	loff_t			new_size = 0; -	bool			do_file_insert = 0; +	bool			do_file_insert = false;  	if (!S_ISREG(inode->i_mode))  		return -EINVAL; @@ -822,7 +830,7 @@ xfs_file_fallocate(  			error = -EINVAL;  			goto out_unlock;  		} -		do_file_insert = 1; +		do_file_insert = true;  	} else {  		flags |= XFS_PREALLOC_SET; |