[PATCH 086/119] xfs: cancel CoW reservations and clear inode reflink flag when freeing blocks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When we're freeing blocks (truncate, punch, etc.), clear all CoW
reservations in the range being freed.  If the file block count
drops to zero, also clear the inode reflink flag.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 fs/xfs/xfs_bmap_util.c |   34 ++++++++++++++++++++++++++++++++++
 fs/xfs/xfs_inode.c     |   13 +++++++++++++
 2 files changed, 47 insertions(+)


diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 79225fb..9285111 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1147,6 +1147,32 @@ xfs_zero_remaining_bytes(
 	return error;
 }
 
+STATIC int
+xfs_free_cow_space(
+	struct xfs_inode	*ip,
+	struct xfs_trans	**tpp,
+	xfs_fileoff_t		startoffset_fsb,
+	xfs_fileoff_t		endoffset_fsb)
+{
+	int			error;
+
+	/* Remove any pending CoW reservations. */
+	error = xfs_reflink_cancel_cow_blocks(ip, tpp, startoffset_fsb,
+			endoffset_fsb);
+	if (error)
+		goto out;
+
+	/*
+	 * Clear the reflink flag if we freed everything.
+	 */
+	if (ip->i_d.di_nblocks == 0) {
+		ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
+		xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
+	}
+out:
+	return error;
+}
+
 int
 xfs_free_file_space(
 	struct xfs_inode	*ip,
@@ -1294,6 +1320,14 @@ xfs_free_file_space(
 		if (error)
 			goto error0;
 
+		/* Remove CoW reservations and inode flag if applicable. */
+		if (done && xfs_is_reflink_inode(ip)) {
+			error = xfs_free_cow_space(ip, &tp, startoffset_fsb,
+					endoffset_fsb);
+			if (error)
+				goto error0;
+		}
+
 		error = xfs_trans_commit(tp);
 		xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	}
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index e08eaea..b8d3c4f 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -49,6 +49,7 @@
 #include "xfs_trans_priv.h"
 #include "xfs_log.h"
 #include "xfs_bmap_btree.h"
+#include "xfs_reflink.h"
 
 kmem_zone_t *xfs_inode_zone;
 
@@ -1586,6 +1587,18 @@ xfs_itruncate_extents(
 			goto out;
 	}
 
+	/* Remove all pending CoW reservations. */
+	error = xfs_reflink_cancel_cow_blocks(ip, &tp, first_unmap_block,
+			last_block);
+	if (error)
+		goto out;
+
+	/*
+	 * Clear the reflink flag if we truncated everything.
+	 */
+	if (ip->i_d.di_nblocks == 0 && xfs_is_reflink_inode(ip))
+		ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
+
 	/*
 	 * Always re-log the inode so that our permanent transaction can keep
 	 * on rolling it forward in the log.

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux