diff options
Diffstat (limited to 'fs/xfs/xfs_reflink.c')
-rw-r--r-- | fs/xfs/xfs_reflink.c | 23 |
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 | */ |
576 | int | 579 | int |
577 | xfs_reflink_cancel_cow_blocks( | 580 | xfs_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 | */ |
653 | int | 660 | int |
654 | xfs_reflink_cancel_cow_range( | 661 | xfs_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 | ||