From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from aserp1040.oracle.com ([141.146.126.69]:48624 "EHLO aserp1040.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755273AbcFQB1K (ORCPT ); Thu, 16 Jun 2016 21:27:10 -0400 Subject: [PATCH 086/119] xfs: cancel CoW reservations and clear inode reflink flag when freeing blocks From: "Darrick J. Wong" To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:03 -0700 Message-ID: <146612682326.12839.16807060939543436332.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-fsdevel-owner@vger.kernel.org List-ID: 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 --- 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.