]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
xfs: fill out the srcmap in iomap_begin
authorChristoph Hellwig <hch@lst.de>
Sat, 19 Oct 2019 16:09:44 +0000 (09:09 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 21 Oct 2019 16:04:58 +0000 (09:04 -0700)
Replace our local hacks to report the source block in the main iomap
with the proper scrmap reporting.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_iomap.c

index 38e0b1221d51b5a85d07130da268d3c0b3543123..08c0f0a369d70a5c5f66308173f79289c23e334d 100644 (file)
@@ -527,7 +527,8 @@ xfs_file_iomap_begin_delay(
        loff_t                  offset,
        loff_t                  count,
        unsigned                flags,
-       struct iomap            *iomap)
+       struct iomap            *iomap,
+       struct iomap            *srcmap)
 {
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
@@ -721,11 +722,13 @@ xfs_file_iomap_begin_delay(
 found_cow:
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        if (imap.br_startoff <= offset_fsb) {
-               /* ensure we only report blocks we have a reservation for */
-               xfs_trim_extent(&imap, cmap.br_startoff, cmap.br_blockcount);
-               return xfs_bmbt_to_iomap(ip, iomap, &imap, IOMAP_F_SHARED);
+               error = xfs_bmbt_to_iomap(ip, srcmap, &imap, 0);
+               if (error)
+                       return error;
+       } else {
+               xfs_trim_extent(&cmap, offset_fsb,
+                               imap.br_startoff - offset_fsb);
        }
-       xfs_trim_extent(&cmap, offset_fsb, imap.br_startoff - offset_fsb);
        return xfs_bmbt_to_iomap(ip, iomap, &cmap, IOMAP_F_SHARED);
 
 out_unlock:
@@ -933,7 +936,7 @@ xfs_file_iomap_begin(
 {
        struct xfs_inode        *ip = XFS_I(inode);
        struct xfs_mount        *mp = ip->i_mount;
-       struct xfs_bmbt_irec    imap;
+       struct xfs_bmbt_irec    imap, cmap;
        xfs_fileoff_t           offset_fsb, end_fsb;
        int                     nimaps = 1, error = 0;
        bool                    shared = false;
@@ -947,7 +950,7 @@ xfs_file_iomap_begin(
                        !IS_DAX(inode) && !xfs_get_extsz_hint(ip)) {
                /* Reserve delalloc blocks for regular writeback. */
                return xfs_file_iomap_begin_delay(inode, offset, length, flags,
-                               iomap);
+                               iomap, srcmap);
        }
 
        /*
@@ -987,9 +990,6 @@ xfs_file_iomap_begin(
         * been done up front, so we don't need to do them here.
         */
        if (xfs_is_cow_inode(ip)) {
-               struct xfs_bmbt_irec    cmap;
-               bool                    directio = (flags & IOMAP_DIRECT);
-
                /* if zeroing doesn't need COW allocation, then we are done. */
                if ((flags & IOMAP_ZERO) &&
                    !needs_cow_for_zeroing(&imap, nimaps))
@@ -997,23 +997,11 @@ xfs_file_iomap_begin(
 
                /* may drop and re-acquire the ilock */
                error = xfs_reflink_allocate_cow(ip, &imap, &cmap, &shared,
-                               &lockmode, directio);
+                               &lockmode, flags & IOMAP_DIRECT);
                if (error)
                        goto out_unlock;
-
-               /*
-                * For buffered writes we need to report the address of the
-                * previous block (if there was any) so that the higher level
-                * write code can perform read-modify-write operations; we
-                * won't need the CoW fork mapping until writeback.  For direct
-                * I/O, which must be block aligned, we need to report the
-                * newly allocated address.  If the data fork has a hole, copy
-                * the COW fork mapping to avoid allocating to the data fork.
-                */
-               if (shared &&
-                   (directio || imap.br_startblock == HOLESTARTBLOCK))
-                       imap = cmap;
-
+               if (shared)
+                       goto out_found_cow;
                end_fsb = imap.br_startoff + imap.br_blockcount;
                length = XFS_FSB_TO_B(mp, end_fsb) - offset;
        }
@@ -1074,6 +1062,17 @@ xfs_file_iomap_begin(
        trace_xfs_iomap_found(ip, offset, length, XFS_DATA_FORK, &imap);
        goto out_finish;
 
+out_found_cow:
+       xfs_iunlock(ip, lockmode);
+       length = XFS_FSB_TO_B(mp, cmap.br_startoff + cmap.br_blockcount);
+       trace_xfs_iomap_found(ip, offset, length - offset, XFS_COW_FORK, &cmap);
+       if (imap.br_startblock != HOLESTARTBLOCK) {
+               error = xfs_bmbt_to_iomap(ip, srcmap, &imap, 0);
+               if (error)
+                       return error;
+       }
+       return xfs_bmbt_to_iomap(ip, iomap, &cmap, IOMAP_F_SHARED);
+
 out_unlock:
        xfs_iunlock(ip, lockmode);
        return error;