aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_reflink.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_reflink.c')
-rw-r--r--fs/xfs/xfs_reflink.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index eff070accf04..2252f163c38f 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -571,14 +571,18 @@ xfs_reflink_trim_irec_to_next_cow(
571} 571}
572 572
573/* 573/*
574 * Cancel all pending CoW reservations for some block range of an inode. 574 * Cancel CoW reservations for some block range of an inode.
575 *
576 * If cancel_real is true this function cancels all COW fork extents for the
577 * inode; if cancel_real is false, real extents are not cleared.
575 */ 578 */
576int 579int
577xfs_reflink_cancel_cow_blocks( 580xfs_reflink_cancel_cow_blocks(
578 struct xfs_inode *ip, 581 struct xfs_inode *ip,
579 struct xfs_trans **tpp, 582 struct xfs_trans **tpp,
580 xfs_fileoff_t offset_fsb, 583 xfs_fileoff_t offset_fsb,
581 xfs_fileoff_t end_fsb) 584 xfs_fileoff_t end_fsb,
585 bool cancel_real)
582{ 586{
583 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); 587 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
584 struct xfs_bmbt_irec got, prev, del; 588 struct xfs_bmbt_irec got, prev, del;
@@ -605,7 +609,7 @@ xfs_reflink_cancel_cow_blocks(
605 &idx, &got, &del); 609 &idx, &got, &del);
606 if (error) 610 if (error)
607 break; 611 break;
608 } else { 612 } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
609 xfs_trans_ijoin(*tpp, ip, 0); 613 xfs_trans_ijoin(*tpp, ip, 0);
610 xfs_defer_init(&dfops, &firstfsb); 614 xfs_defer_init(&dfops, &firstfsb);
611 615
@@ -648,13 +652,17 @@ xfs_reflink_cancel_cow_blocks(
648} 652}
649 653
650/* 654/*
651 * Cancel all pending CoW reservations for some byte range of an inode. 655 * Cancel CoW reservations for some byte range of an inode.
656 *
657 * If cancel_real is true this function cancels all COW fork extents for the
658 * inode; if cancel_real is false, real extents are not cleared.
652 */ 659 */
653int 660int
654xfs_reflink_cancel_cow_range( 661xfs_reflink_cancel_cow_range(
655 struct xfs_inode *ip, 662 struct xfs_inode *ip,
656 xfs_off_t offset, 663 xfs_off_t offset,
657 xfs_off_t count) 664 xfs_off_t count,
665 bool cancel_real)
658{ 666{
659 struct xfs_trans *tp; 667 struct xfs_trans *tp;
660 xfs_fileoff_t offset_fsb; 668 xfs_fileoff_t offset_fsb;
@@ -680,7 +688,8 @@ xfs_reflink_cancel_cow_range(
680 xfs_trans_ijoin(tp, ip, 0); 688 xfs_trans_ijoin(tp, ip, 0);
681 689
682 /* Scrape out the old CoW reservations */ 690 /* Scrape out the old CoW reservations */
683 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb); 691 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb,
692 cancel_real);
684 if (error) 693 if (error)
685 goto out_cancel; 694 goto out_cancel;
686 695
@@ -1686,7 +1695,7 @@ next:
1686 * We didn't find any shared blocks so turn off the reflink flag. 1695 * We didn't find any shared blocks so turn off the reflink flag.
1687 * First, get rid of any leftover CoW mappings. 1696 * First, get rid of any leftover CoW mappings.
1688 */ 1697 */
1689 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF); 1698 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true);
1690 if (error) 1699 if (error)
1691 return error; 1700 return error;
1692 1701