xfs: introduce a new xfs_inode_has_cow_data helper
authorChristoph Hellwig <hch@lst.de>
Tue, 17 Jul 2018 23:51:51 +0000 (16:51 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 30 Jul 2018 14:57:48 +0000 (07:57 -0700)
We have a few places that already check if an inode has actual data in
the COW fork to avoid work on reflink inodes that do not actually have
outstanding COW blocks.  There are a few more places that can avoid
working if doing the same check, so add a documented helper for this
condition and use it in all places where it makes sense.

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_aops.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_icache.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_reflink.c

index f4d3252236c1128e7ddb27c9be51ae5cfa6faa64..814100d27343f20a167a4fff93406a1f3a5511e8 100644 (file)
@@ -338,7 +338,7 @@ xfs_map_blocks(
        imap_valid = offset_fsb >= wpc->imap.br_startoff &&
                     offset_fsb < wpc->imap.br_startoff + wpc->imap.br_blockcount;
        if (imap_valid &&
-           (!xfs_is_reflink_inode(ip) || wpc->io_type == XFS_IO_COW))
+           (!xfs_inode_has_cow_data(ip) || wpc->io_type == XFS_IO_COW))
                return 0;
 
        if (XFS_FORCED_SHUTDOWN(mp))
@@ -363,7 +363,7 @@ xfs_map_blocks(
         * Check if this is offset is covered by a COW extents, and if yes use
         * it directly instead of looking up anything in the data fork.
         */
-       if (xfs_is_reflink_inode(ip) &&
+       if (xfs_inode_has_cow_data(ip) &&
            xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &imap) &&
            imap.br_startoff <= offset_fsb) {
                xfs_iunlock(ip, XFS_ILOCK_SHARED);
index c32ec17048f5c897ae040c766d79dfce27b75f38..412dc58ae54dc129e558e8a7b7b031ee726152ff 100644 (file)
@@ -1263,7 +1263,7 @@ xfs_prepare_shift(
         * we've flushed all the dirty data out to disk to avoid having
         * CoW extents at the wrong offsets.
         */
-       if (xfs_is_reflink_inode(ip)) {
+       if (xfs_inode_has_cow_data(ip)) {
                error = xfs_reflink_cancel_cow_range(ip, offset, NULLFILEOFF,
                                true);
                if (error)
index e5591f5ebe1562b4afe2db6174a13c9207ff9e63..245483cc282ba0032f5f0a16649d5b7dbd45cffb 100644 (file)
@@ -1697,14 +1697,13 @@ xfs_inode_clear_eofblocks_tag(
  */
 static bool
 xfs_prep_free_cowblocks(
-       struct xfs_inode        *ip,
-       struct xfs_ifork        *ifp)
+       struct xfs_inode        *ip)
 {
        /*
         * Just clear the tag if we have an empty cow fork or none at all. It's
         * possible the inode was fully unshared since it was originally tagged.
         */
-       if (!xfs_is_reflink_inode(ip) || !ifp->if_bytes) {
+       if (!xfs_inode_has_cow_data(ip)) {
                trace_xfs_inode_free_cowblocks_invalid(ip);
                xfs_inode_clear_cowblocks_tag(ip);
                return false;
@@ -1742,11 +1741,10 @@ xfs_inode_free_cowblocks(
        void                    *args)
 {
        struct xfs_eofblocks    *eofb = args;
-       struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
        int                     match;
        int                     ret = 0;
 
-       if (!xfs_prep_free_cowblocks(ip, ifp))
+       if (!xfs_prep_free_cowblocks(ip))
                return 0;
 
        if (eofb) {
@@ -1771,7 +1769,7 @@ xfs_inode_free_cowblocks(
         * Check again, nobody else should be able to dirty blocks or change
         * the reflink iflag now that we have the first two locks held.
         */
-       if (xfs_prep_free_cowblocks(ip, ifp))
+       if (xfs_prep_free_cowblocks(ip))
                ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, false);
 
        xfs_iunlock(ip, XFS_MMAPLOCK_EXCL);
index 54fcfdfc748cb413dbaf704c235d02f2c3d3b32f..5fc1815c2b626e140f6957dc425fb3c0ddba44f3 100644 (file)
@@ -1832,7 +1832,6 @@ xfs_inactive(
        xfs_inode_t     *ip)
 {
        struct xfs_mount        *mp;
-       struct xfs_ifork        *cow_ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
        int                     error;
        int                     truncate = 0;
 
@@ -1853,7 +1852,7 @@ xfs_inactive(
                return;
 
        /* Try to clean out the cow blocks if there are any. */
-       if (xfs_is_reflink_inode(ip) && cow_ifp->if_bytes > 0)
+       if (xfs_inode_has_cow_data(ip))
                xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF, true);
 
        if (VFS_I(ip)->i_nlink != 0) {
index a67efdac70a6f2febb379e876ea84d79eae58f14..79a3e61a6991836a6cce1037bf815a1c042c78b7 100644 (file)
@@ -198,6 +198,15 @@ static inline bool xfs_is_reflink_inode(struct xfs_inode *ip)
        return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
 }
 
+/*
+ * Check if an inode has any data in the COW fork.  This might be often false
+ * even for inodes with the reflink flag when there is no pending COW operation.
+ */
+static inline bool xfs_inode_has_cow_data(struct xfs_inode *ip)
+{
+       return ip->i_cowfp && ip->i_cowfp->if_bytes;
+}
+
 /*
  * In-core inode flags.
  */
index 68b6921dc3f6bc33f2bf683d9d31162046c13635..9a0a565262667e41a848f39c9f6d9cb9c13440b1 100644 (file)
@@ -478,7 +478,7 @@ xfs_reflink_cancel_cow_blocks(
        struct xfs_iext_cursor          icur;
        int                             error = 0;
 
-       if (!xfs_is_reflink_inode(ip))
+       if (!xfs_inode_has_cow_data(ip))
                return 0;
        if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got))
                return 0;