提交 c5295c6a 编写于 作者: D Dave Chinner 提交者: Darrick J. Wong

xfs: fix double ijoin in xfs_reflink_cancel_cow_range

xfs_reflink_cancel_cow_range joins an inode twice to the same
transaction.  This is not allowed, so fix it and document that the
callers of xfs_reflink_cancel_cow_blocks() must have already joined the
inode to the permanent transaction passed in.
Signed-Off-By: NDave Chinner <dchinner@redhat.com>
Reviewed-by: NChristoph Hellwig <hch@lst.de>
Reviewed-by: NBrian Foster <bfoster@redhat.com>
[darrick: edited the commit log to remove trace for nonexistent ASSERT]
Reviewed-by: NDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: NDarrick J. Wong <darrick.wong@oracle.com>
上级 3565b660
...@@ -552,6 +552,9 @@ xfs_reflink_trim_irec_to_next_cow( ...@@ -552,6 +552,9 @@ xfs_reflink_trim_irec_to_next_cow(
* *
* If cancel_real is true this function cancels all COW fork extents for the * If cancel_real is true this function cancels all COW fork extents for the
* inode; if cancel_real is false, real extents are not cleared. * inode; if cancel_real is false, real extents are not cleared.
*
* Caller must have already joined the inode to the current transaction. The
* inode will be joined to the transaction returned to the caller.
*/ */
int int
xfs_reflink_cancel_cow_blocks( xfs_reflink_cancel_cow_blocks(
...@@ -592,7 +595,6 @@ xfs_reflink_cancel_cow_blocks( ...@@ -592,7 +595,6 @@ xfs_reflink_cancel_cow_blocks(
if (error) if (error)
break; break;
} else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) { } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
xfs_trans_ijoin(*tpp, ip, 0);
xfs_defer_init(&dfops, &firstfsb); xfs_defer_init(&dfops, &firstfsb);
/* Free the CoW orphan record. */ /* Free the CoW orphan record. */
...@@ -1570,6 +1572,7 @@ xfs_reflink_clear_inode_flag( ...@@ -1570,6 +1572,7 @@ xfs_reflink_clear_inode_flag(
* We didn't find any shared blocks so turn off the reflink flag. * We didn't find any shared blocks so turn off the reflink flag.
* First, get rid of any leftover CoW mappings. * First, get rid of any leftover CoW mappings.
*/ */
xfs_trans_ijoin(*tpp, ip, 0);
error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true); error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true);
if (error) if (error)
return error; return error;
...@@ -1578,7 +1581,6 @@ xfs_reflink_clear_inode_flag( ...@@ -1578,7 +1581,6 @@ xfs_reflink_clear_inode_flag(
trace_xfs_reflink_unset_inode_flag(ip); trace_xfs_reflink_unset_inode_flag(ip);
ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
xfs_inode_clear_cowblocks_tag(ip); xfs_inode_clear_cowblocks_tag(ip);
xfs_trans_ijoin(*tpp, ip, 0);
xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
return error; return error;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册