xfs: move the dio write relocking out of xfs_ilock_for_iomap
About half of xfs_ilock_for_iomap deals with a special case for direct I/O writes to COW files that need to take the ilock exclusively. Move this code into the one callers that cares and simplify xfs_ilock_for_iomap. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
This commit is contained in:
parent
0c7fcdb6d0
commit
8626b67acf
@ -717,53 +717,30 @@ imap_needs_cow(
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extents not yet cached requires exclusive access, don't block for
|
||||
* IOMAP_NOWAIT.
|
||||
*
|
||||
* This is basically an opencoded xfs_ilock_data_map_shared() call, but with
|
||||
* support for IOMAP_NOWAIT.
|
||||
*/
|
||||
static int
|
||||
xfs_ilock_for_iomap(
|
||||
struct xfs_inode *ip,
|
||||
unsigned flags,
|
||||
unsigned *lockmode)
|
||||
{
|
||||
unsigned int mode = *lockmode;
|
||||
bool is_write = flags & (IOMAP_WRITE | IOMAP_ZERO);
|
||||
|
||||
/*
|
||||
* COW writes may allocate delalloc space or convert unwritten COW
|
||||
* extents, so we need to make sure to take the lock exclusively here.
|
||||
*/
|
||||
if (xfs_is_cow_inode(ip) && is_write)
|
||||
mode = XFS_ILOCK_EXCL;
|
||||
|
||||
/*
|
||||
* Extents not yet cached requires exclusive access, don't block. This
|
||||
* is an opencoded xfs_ilock_data_map_shared() call but with
|
||||
* non-blocking behaviour.
|
||||
*/
|
||||
if (xfs_need_iread_extents(&ip->i_df)) {
|
||||
if (flags & IOMAP_NOWAIT)
|
||||
return -EAGAIN;
|
||||
mode = XFS_ILOCK_EXCL;
|
||||
}
|
||||
|
||||
relock:
|
||||
if (flags & IOMAP_NOWAIT) {
|
||||
if (!xfs_ilock_nowait(ip, mode))
|
||||
if (xfs_need_iread_extents(&ip->i_df))
|
||||
return -EAGAIN;
|
||||
if (!xfs_ilock_nowait(ip, *lockmode))
|
||||
return -EAGAIN;
|
||||
} else {
|
||||
xfs_ilock(ip, mode);
|
||||
if (xfs_need_iread_extents(&ip->i_df))
|
||||
*lockmode = XFS_ILOCK_EXCL;
|
||||
xfs_ilock(ip, *lockmode);
|
||||
}
|
||||
|
||||
/*
|
||||
* The reflink iflag could have changed since the earlier unlocked
|
||||
* check, so if we got ILOCK_SHARED for a write and but we're now a
|
||||
* reflink inode we have to switch to ILOCK_EXCL and relock.
|
||||
*/
|
||||
if (mode == XFS_ILOCK_SHARED && is_write && xfs_is_cow_inode(ip)) {
|
||||
xfs_iunlock(ip, mode);
|
||||
mode = XFS_ILOCK_EXCL;
|
||||
goto relock;
|
||||
}
|
||||
|
||||
*lockmode = mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -801,7 +778,7 @@ xfs_direct_write_iomap_begin(
|
||||
int nimaps = 1, error = 0;
|
||||
bool shared = false;
|
||||
u16 iomap_flags = 0;
|
||||
unsigned int lockmode = XFS_ILOCK_SHARED;
|
||||
unsigned int lockmode;
|
||||
u64 seq;
|
||||
|
||||
ASSERT(flags & (IOMAP_WRITE | IOMAP_ZERO));
|
||||
@ -817,10 +794,30 @@ xfs_direct_write_iomap_begin(
|
||||
if (offset + length > i_size_read(inode))
|
||||
iomap_flags |= IOMAP_F_DIRTY;
|
||||
|
||||
/*
|
||||
* COW writes may allocate delalloc space or convert unwritten COW
|
||||
* extents, so we need to make sure to take the lock exclusively here.
|
||||
*/
|
||||
if (xfs_is_cow_inode(ip))
|
||||
lockmode = XFS_ILOCK_EXCL;
|
||||
else
|
||||
lockmode = XFS_ILOCK_SHARED;
|
||||
|
||||
relock:
|
||||
error = xfs_ilock_for_iomap(ip, flags, &lockmode);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* The reflink iflag could have changed since the earlier unlocked
|
||||
* check, check if it again and relock if needed.
|
||||
*/
|
||||
if (xfs_is_cow_inode(ip) && lockmode == XFS_ILOCK_SHARED) {
|
||||
xfs_iunlock(ip, lockmode);
|
||||
lockmode = XFS_ILOCK_EXCL;
|
||||
goto relock;
|
||||
}
|
||||
|
||||
error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap,
|
||||
&nimaps, 0);
|
||||
if (error)
|
||||
|
Loading…
Reference in New Issue
Block a user