[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.

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux