Skip to content

Commit 2d9b1d6

Browse files
committed
Merge tag 'xfs-4.16-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
Pull xfs fixes from Darrick Wong: - Fix some iomap locking problems - Don't allocate cow blocks when we're zeroing file data * tag 'xfs-4.16-fixes-3' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux: xfs: don't block on the ilock for RWF_NOWAIT xfs: don't start out with the exclusive ilock for direct I/O xfs: don't allocate COW blocks for zeroing holes or unwritten extents
2 parents a525df0 + ff3d8b9 commit 2d9b1d6

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

fs/xfs/xfs_iomap.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -955,15 +955,29 @@ static inline bool imap_needs_alloc(struct inode *inode,
955955
(IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN);
956956
}
957957

958+
static inline bool needs_cow_for_zeroing(struct xfs_bmbt_irec *imap, int nimaps)
959+
{
960+
return nimaps &&
961+
imap->br_startblock != HOLESTARTBLOCK &&
962+
imap->br_state != XFS_EXT_UNWRITTEN;
963+
}
964+
958965
static inline bool need_excl_ilock(struct xfs_inode *ip, unsigned flags)
959966
{
960967
/*
961-
* COW writes will allocate delalloc space, so we need to make sure
962-
* to take the lock exclusively here.
968+
* COW writes may allocate delalloc space or convert unwritten COW
969+
* extents, so we need to make sure to take the lock exclusively here.
963970
*/
964971
if (xfs_is_reflink_inode(ip) && (flags & (IOMAP_WRITE | IOMAP_ZERO)))
965972
return true;
966-
if ((flags & IOMAP_DIRECT) && (flags & IOMAP_WRITE))
973+
974+
/*
975+
* Extents not yet cached requires exclusive access, don't block.
976+
* This is an opencoded xfs_ilock_data_map_shared() to cater for the
977+
* non-blocking behaviour.
978+
*/
979+
if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
980+
!(ip->i_df.if_flags & XFS_IFEXTENTS))
967981
return true;
968982
return false;
969983
}
@@ -993,16 +1007,18 @@ xfs_file_iomap_begin(
9931007
return xfs_file_iomap_begin_delay(inode, offset, length, iomap);
9941008
}
9951009

996-
if (need_excl_ilock(ip, flags)) {
1010+
if (need_excl_ilock(ip, flags))
9971011
lockmode = XFS_ILOCK_EXCL;
998-
xfs_ilock(ip, XFS_ILOCK_EXCL);
999-
} else {
1000-
lockmode = xfs_ilock_data_map_shared(ip);
1001-
}
1012+
else
1013+
lockmode = XFS_ILOCK_SHARED;
10021014

1003-
if ((flags & IOMAP_NOWAIT) && !(ip->i_df.if_flags & XFS_IFEXTENTS)) {
1004-
error = -EAGAIN;
1005-
goto out_unlock;
1015+
if (flags & IOMAP_NOWAIT) {
1016+
if (!(ip->i_df.if_flags & XFS_IFEXTENTS))
1017+
return -EAGAIN;
1018+
if (!xfs_ilock_nowait(ip, lockmode))
1019+
return -EAGAIN;
1020+
} else {
1021+
xfs_ilock(ip, lockmode);
10061022
}
10071023

10081024
ASSERT(offset <= mp->m_super->s_maxbytes);
@@ -1024,7 +1040,9 @@ xfs_file_iomap_begin(
10241040
goto out_unlock;
10251041
}
10261042

1027-
if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) {
1043+
if (xfs_is_reflink_inode(ip) &&
1044+
((flags & IOMAP_WRITE) ||
1045+
((flags & IOMAP_ZERO) && needs_cow_for_zeroing(&imap, nimaps)))) {
10281046
if (flags & IOMAP_DIRECT) {
10291047
/*
10301048
* A reflinked inode will result in CoW alloc.

0 commit comments

Comments
 (0)