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 da6d08fb359c..4a84c5ea266d 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -548,14 +548,18 @@ xfs_reflink_trim_irec_to_next_cow(
548} 548}
549 549
550/* 550/*
551 * Cancel all pending CoW reservations for some block range of an inode. 551 * Cancel CoW reservations for some block range of an inode.
552 *
553 * If cancel_real is true this function cancels all COW fork extents for the
554 * inode; if cancel_real is false, real extents are not cleared.
552 */ 555 */
553int 556int
554xfs_reflink_cancel_cow_blocks( 557xfs_reflink_cancel_cow_blocks(
555 struct xfs_inode *ip, 558 struct xfs_inode *ip,
556 struct xfs_trans **tpp, 559 struct xfs_trans **tpp,
557 xfs_fileoff_t offset_fsb, 560 xfs_fileoff_t offset_fsb,
558 xfs_fileoff_t end_fsb) 561 xfs_fileoff_t end_fsb,
562 bool cancel_real)
559{ 563{
560 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); 564 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
561 struct xfs_bmbt_irec got, del; 565 struct xfs_bmbt_irec got, del;
@@ -579,7 +583,7 @@ xfs_reflink_cancel_cow_blocks(
579 &idx, &got, &del); 583 &idx, &got, &del);
580 if (error) 584 if (error)
581 break; 585 break;
582 } else { 586 } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
583 xfs_trans_ijoin(*tpp, ip, 0); 587 xfs_trans_ijoin(*tpp, ip, 0);
584 xfs_defer_init(&dfops, &firstfsb); 588 xfs_defer_init(&dfops, &firstfsb);
585 589
@@ -621,13 +625,17 @@ xfs_reflink_cancel_cow_blocks(
621} 625}
622 626
623/* 627/*
624 * Cancel all pending CoW reservations for some byte range of an inode. 628 * Cancel CoW reservations for some byte range of an inode.
629 *
630 * If cancel_real is true this function cancels all COW fork extents for the
631 * inode; if cancel_real is false, real extents are not cleared.
625 */ 632 */
626int 633int
627xfs_reflink_cancel_cow_range( 634xfs_reflink_cancel_cow_range(
628 struct xfs_inode *ip, 635 struct xfs_inode *ip,
629 xfs_off_t offset, 636 xfs_off_t offset,
630 xfs_off_t count) 637 xfs_off_t count,
638 bool cancel_real)
631{ 639{
632 struct xfs_trans *tp; 640 struct xfs_trans *tp;
633 xfs_fileoff_t offset_fsb; 641 xfs_fileoff_t offset_fsb;
@@ -653,7 +661,8 @@ xfs_reflink_cancel_cow_range(
653 xfs_trans_ijoin(tp, ip, 0); 661 xfs_trans_ijoin(tp, ip, 0);
654 662
655 /* Scrape out the old CoW reservations */ 663 /* Scrape out the old CoW reservations */
656 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb); 664 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb,
665 cancel_real);
657 if (error) 666 if (error)
658 goto out_cancel; 667 goto out_cancel;
659 668
@@ -1450,7 +1459,7 @@ next:
1450 * We didn't find any shared blocks so turn off the reflink flag. 1459 * We didn't find any shared blocks so turn off the reflink flag.
1451 * First, get rid of any leftover CoW mappings. 1460 * First, get rid of any leftover CoW mappings.
1452 */ 1461 */
1453 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF); 1462 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true);
1454 if (error) 1463 if (error)
1455 return error; 1464 return error;
1456 1465