Commit 2d9b1d69 authored by Linus Torvalds's avatar Linus Torvalds

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
parents a525df05 ff3d8b9c
...@@ -955,15 +955,29 @@ static inline bool imap_needs_alloc(struct inode *inode, ...@@ -955,15 +955,29 @@ static inline bool imap_needs_alloc(struct inode *inode,
(IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN); (IS_DAX(inode) && imap->br_state == XFS_EXT_UNWRITTEN);
} }
static inline bool needs_cow_for_zeroing(struct xfs_bmbt_irec *imap, int nimaps)
{
return nimaps &&
imap->br_startblock != HOLESTARTBLOCK &&
imap->br_state != XFS_EXT_UNWRITTEN;
}
static inline bool need_excl_ilock(struct xfs_inode *ip, unsigned flags) static inline bool need_excl_ilock(struct xfs_inode *ip, unsigned flags)
{ {
/* /*
* COW writes will allocate delalloc space, so we need to make sure * COW writes may allocate delalloc space or convert unwritten COW
* to take the lock exclusively here. * extents, so we need to make sure to take the lock exclusively here.
*/ */
if (xfs_is_reflink_inode(ip) && (flags & (IOMAP_WRITE | IOMAP_ZERO))) if (xfs_is_reflink_inode(ip) && (flags & (IOMAP_WRITE | IOMAP_ZERO)))
return true; return true;
if ((flags & IOMAP_DIRECT) && (flags & IOMAP_WRITE))
/*
* Extents not yet cached requires exclusive access, don't block.
* This is an opencoded xfs_ilock_data_map_shared() to cater for the
* non-blocking behaviour.
*/
if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE &&
!(ip->i_df.if_flags & XFS_IFEXTENTS))
return true; return true;
return false; return false;
} }
...@@ -993,16 +1007,18 @@ xfs_file_iomap_begin( ...@@ -993,16 +1007,18 @@ xfs_file_iomap_begin(
return xfs_file_iomap_begin_delay(inode, offset, length, iomap); return xfs_file_iomap_begin_delay(inode, offset, length, iomap);
} }
if (need_excl_ilock(ip, flags)) { if (need_excl_ilock(ip, flags))
lockmode = XFS_ILOCK_EXCL; lockmode = XFS_ILOCK_EXCL;
xfs_ilock(ip, XFS_ILOCK_EXCL); else
} else { lockmode = XFS_ILOCK_SHARED;
lockmode = xfs_ilock_data_map_shared(ip);
}
if ((flags & IOMAP_NOWAIT) && !(ip->i_df.if_flags & XFS_IFEXTENTS)) { if (flags & IOMAP_NOWAIT) {
error = -EAGAIN; if (!(ip->i_df.if_flags & XFS_IFEXTENTS))
goto out_unlock; return -EAGAIN;
if (!xfs_ilock_nowait(ip, lockmode))
return -EAGAIN;
} else {
xfs_ilock(ip, lockmode);
} }
ASSERT(offset <= mp->m_super->s_maxbytes); ASSERT(offset <= mp->m_super->s_maxbytes);
...@@ -1024,7 +1040,9 @@ xfs_file_iomap_begin( ...@@ -1024,7 +1040,9 @@ xfs_file_iomap_begin(
goto out_unlock; goto out_unlock;
} }
if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && xfs_is_reflink_inode(ip)) { if (xfs_is_reflink_inode(ip) &&
((flags & IOMAP_WRITE) ||
((flags & IOMAP_ZERO) && needs_cow_for_zeroing(&imap, nimaps)))) {
if (flags & IOMAP_DIRECT) { if (flags & IOMAP_DIRECT) {
/* /*
* A reflinked inode will result in CoW alloc. * A reflinked inode will result in CoW alloc.
......
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