aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-10-18 02:19:26 -0400
committerDave Chinner <david@fromorbit.com>2018-10-18 02:19:26 -0400
commit0365c5d6c3d4bcf17a1aa38719e48351932c62b6 (patch)
tree2332527e376682dbbb03617919b7e3c407db8bab /fs/xfs
parentdaa79baefc47293c753fed191d722f7ef605a303 (diff)
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_iomap.c44
1 files changed, 38 insertions, 6 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 6320aca39f39..9b572a1fbd42 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -62,6 +62,21 @@ xfs_bmbt_to_iomap(
62 iomap->dax_dev = xfs_find_daxdev_for_inode(VFS_I(ip)); 62 iomap->dax_dev = xfs_find_daxdev_for_inode(VFS_I(ip));
63} 63}
64 64
65static void
66xfs_hole_to_iomap(
67 struct xfs_inode *ip,
68 struct iomap *iomap,
69 xfs_fileoff_t offset_fsb,
70 xfs_fileoff_t end_fsb)
71{
72 iomap->addr = IOMAP_NULL_ADDR;
73 iomap->type = IOMAP_HOLE;
74 iomap->offset = XFS_FSB_TO_B(ip->i_mount, offset_fsb);
75 iomap->length = XFS_FSB_TO_B(ip->i_mount, end_fsb - offset_fsb);
76 iomap->bdev = xfs_find_bdev_for_inode(VFS_I(ip));
77 iomap->dax_dev = xfs_find_daxdev_for_inode(VFS_I(ip));
78}
79
65xfs_extlen_t 80xfs_extlen_t
66xfs_eof_alignment( 81xfs_eof_alignment(
67 struct xfs_inode *ip, 82 struct xfs_inode *ip,
@@ -502,6 +517,7 @@ xfs_file_iomap_begin_delay(
502 struct inode *inode, 517 struct inode *inode,
503 loff_t offset, 518 loff_t offset,
504 loff_t count, 519 loff_t count,
520 unsigned flags,
505 struct iomap *iomap) 521 struct iomap *iomap)
506{ 522{
507 struct xfs_inode *ip = XFS_I(inode); 523 struct xfs_inode *ip = XFS_I(inode);
@@ -538,13 +554,23 @@ xfs_file_iomap_begin_delay(
538 goto out_unlock; 554 goto out_unlock;
539 } 555 }
540 556
557 end_fsb = min(XFS_B_TO_FSB(mp, offset + count), maxbytes_fsb);
558
541 eof = !xfs_iext_lookup_extent(ip, ifp, offset_fsb, &icur, &got); 559 eof = !xfs_iext_lookup_extent(ip, ifp, offset_fsb, &icur, &got);
542 if (!eof && got.br_startoff <= offset_fsb) { 560 if (eof)
543 if (xfs_is_reflink_inode(ip)) { 561 got.br_startoff = end_fsb; /* fake hole until the end */
562
563 if (got.br_startoff <= offset_fsb) {
564 /*
565 * For reflink files we may need a delalloc reservation when
566 * overwriting shared extents. This includes zeroing of
567 * existing extents that contain data.
568 */
569 if (xfs_is_reflink_inode(ip) &&
570 ((flags & IOMAP_WRITE) ||
571 got.br_state != XFS_EXT_UNWRITTEN)) {
544 bool shared; 572 bool shared;
545 573
546 end_fsb = min(XFS_B_TO_FSB(mp, offset + count),
547 maxbytes_fsb);
548 xfs_trim_extent(&got, offset_fsb, end_fsb - offset_fsb); 574 xfs_trim_extent(&got, offset_fsb, end_fsb - offset_fsb);
549 error = xfs_reflink_reserve_cow(ip, &got, &shared); 575 error = xfs_reflink_reserve_cow(ip, &got, &shared);
550 if (error) 576 if (error)
@@ -555,6 +581,11 @@ xfs_file_iomap_begin_delay(
555 goto done; 581 goto done;
556 } 582 }
557 583
584 if (flags & IOMAP_ZERO) {
585 xfs_hole_to_iomap(ip, iomap, offset_fsb, got.br_startoff);
586 goto out_unlock;
587 }
588
558 error = xfs_qm_dqattach_locked(ip, false); 589 error = xfs_qm_dqattach_locked(ip, false);
559 if (error) 590 if (error)
560 goto out_unlock; 591 goto out_unlock;
@@ -1009,10 +1040,11 @@ xfs_file_iomap_begin(
1009 if (XFS_FORCED_SHUTDOWN(mp)) 1040 if (XFS_FORCED_SHUTDOWN(mp))
1010 return -EIO; 1041 return -EIO;
1011 1042
1012 if (((flags & (IOMAP_WRITE | IOMAP_DIRECT)) == IOMAP_WRITE) && 1043 if ((flags & (IOMAP_WRITE | IOMAP_ZERO)) && !(flags & IOMAP_DIRECT) &&
1013 !IS_DAX(inode) && !xfs_get_extsz_hint(ip)) { 1044 !IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
1014 /* Reserve delalloc blocks for regular writeback. */ 1045 /* Reserve delalloc blocks for regular writeback. */
1015 return xfs_file_iomap_begin_delay(inode, offset, length, iomap); 1046 return xfs_file_iomap_begin_delay(inode, offset, length, flags,
1047 iomap);
1016 } 1048 }
1017 1049
1018 /* 1050 /*