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 | ||
