diff options
author | Christoph Hellwig <hch@lst.de> | 2018-10-18 02:19:26 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2018-10-18 02:19:26 -0400 |
commit | 0365c5d6c3d4bcf17a1aa38719e48351932c62b6 (patch) | |
tree | 2332527e376682dbbb03617919b7e3c407db8bab /fs/xfs | |
parent | daa79baefc47293c753fed191d722f7ef605a303 (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.c | 44 |
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 | ||
65 | static void | ||
66 | xfs_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 | |||
65 | xfs_extlen_t | 80 | xfs_extlen_t |
66 | xfs_eof_alignment( | 81 | xfs_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 | /* |