xfs: handle zeroing in xfs_file_iomap_begin_delay
We only need to allocate blocks for zeroing for reflink inodes, and for we currently have a special case for reflink files in the otherwise direct I/O path that I'd like to get rid of. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
parent
daa79baefc
commit
0365c5d6c3
|
@ -62,6 +62,21 @@ xfs_bmbt_to_iomap(
|
|||
iomap->dax_dev = xfs_find_daxdev_for_inode(VFS_I(ip));
|
||||
}
|
||||
|
||||
static void
|
||||
xfs_hole_to_iomap(
|
||||
struct xfs_inode *ip,
|
||||
struct iomap *iomap,
|
||||
xfs_fileoff_t offset_fsb,
|
||||
xfs_fileoff_t end_fsb)
|
||||
{
|
||||
iomap->addr = IOMAP_NULL_ADDR;
|
||||
iomap->type = IOMAP_HOLE;
|
||||
iomap->offset = XFS_FSB_TO_B(ip->i_mount, offset_fsb);
|
||||
iomap->length = XFS_FSB_TO_B(ip->i_mount, end_fsb - offset_fsb);
|
||||
iomap->bdev = xfs_find_bdev_for_inode(VFS_I(ip));
|
||||
iomap->dax_dev = xfs_find_daxdev_for_inode(VFS_I(ip));
|
||||
}
|
||||
|
||||
xfs_extlen_t
|
||||
xfs_eof_alignment(
|
||||
struct xfs_inode *ip,
|
||||
|
@ -502,6 +517,7 @@ xfs_file_iomap_begin_delay(
|
|||
struct inode *inode,
|
||||
loff_t offset,
|
||||
loff_t count,
|
||||
unsigned flags,
|
||||
struct iomap *iomap)
|
||||
{
|
||||
struct xfs_inode *ip = XFS_I(inode);
|
||||
|
@ -538,13 +554,23 @@ xfs_file_iomap_begin_delay(
|
|||
goto out_unlock;
|
||||
}
|
||||
|
||||
end_fsb = min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb);
|
||||
|
||||
eof = !xfs_iext_lookup_extent(ip, ifp, offset_fsb, &icur, &got);
|
||||
if (!eof && got.br_startoff <= offset_fsb) {
|
||||
if (xfs_is_reflink_inode(ip)) {
|
||||
if (eof)
|
||||
got.br_startoff = end_fsb; /* fake hole until the end */
|
||||
|
||||
if (got.br_startoff <= offset_fsb) {
|
||||
/*
|
||||
* For reflink files we may need a delalloc reservation when
|
||||
* overwriting shared extents. This includes zeroing of
|
||||
* existing extents that contain data.
|
||||
*/
|
||||
if (xfs_is_reflink_inode(ip) &&
|
||||
((flags & IOMAP_WRITE) ||
|
||||
got.br_state != XFS_EXT_UNWRITTEN)) {
|
||||
bool shared;
|
||||
|
||||
end_fsb = min(XFS_B_TO_FSB(mp, offset + count),
|
||||
maxbytes_fsb);
|
||||
xfs_trim_extent(&got, offset_fsb, end_fsb - offset_fsb);
|
||||
error = xfs_reflink_reserve_cow(ip, &got, &shared);
|
||||
if (error)
|
||||
|
@ -555,6 +581,11 @@ xfs_file_iomap_begin_delay(
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (flags & IOMAP_ZERO) {
|
||||
xfs_hole_to_iomap(ip, iomap, offset_fsb, got.br_startoff);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
error = xfs_qm_dqattach_locked(ip, false);
|
||||
if (error)
|
||||
goto out_unlock;
|
||||
|
@ -1009,10 +1040,11 @@ xfs_file_iomap_begin(
|
|||
if (XFS_FORCED_SHUTDOWN(mp))
|
||||
return -EIO;
|
||||
|
||||
if (((flags & (IOMAP_WRITE | IOMAP_DIRECT)) == IOMAP_WRITE) &&
|
||||
if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && !(flags & IOMAP_DIRECT) &&
|
||||
!IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
|
||||
/* Reserve delalloc blocks for regular writeback. */
|
||||
return xfs_file_iomap_begin_delay(inode, offset, length, iomap);
|
||||
return xfs_file_iomap_begin_delay(inode, offset, length, flags,
|
||||
iomap);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue