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 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 | */ |
553 | int | 556 | int |
554 | xfs_reflink_cancel_cow_blocks( | 557 | xfs_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 | */ |
626 | int | 633 | int |
627 | xfs_reflink_cancel_cow_range( | 634 | xfs_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 | ||