diff options
author | Dave Chinner <david@fromorbit.com> | 2015-03-25 00:12:53 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2015-03-25 00:12:53 -0400 |
commit | a448f8f1b744611fb1867ea811170cca2a9a6588 (patch) | |
tree | 288e292c7134d3d04ab1ef77cd7798a08276812c /fs/xfs | |
parent | 2b93681f593577df6fcb9af61947beaace071b74 (diff) | |
parent | a904b1ca5751faf5ece8600e18cd3b674afcca1b (diff) |
Merge branch 'fallocate-insert-range' into for-next
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 356 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.h | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 131 | ||||
-rw-r--r-- | fs/xfs/xfs_bmap_util.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 41 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 1 |
6 files changed, 461 insertions, 83 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index b872e9cedb69..aeffeaaac0ec 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -5486,52 +5486,92 @@ xfs_bmse_shift_one( | |||
5486 | int *current_ext, | 5486 | int *current_ext, |
5487 | struct xfs_bmbt_rec_host *gotp, | 5487 | struct xfs_bmbt_rec_host *gotp, |
5488 | struct xfs_btree_cur *cur, | 5488 | struct xfs_btree_cur *cur, |
5489 | int *logflags) | 5489 | int *logflags, |
5490 | enum shift_direction direction) | ||
5490 | { | 5491 | { |
5491 | struct xfs_ifork *ifp; | 5492 | struct xfs_ifork *ifp; |
5492 | struct xfs_mount *mp; | 5493 | struct xfs_mount *mp; |
5493 | xfs_fileoff_t startoff; | 5494 | xfs_fileoff_t startoff; |
5494 | struct xfs_bmbt_rec_host *leftp; | 5495 | struct xfs_bmbt_rec_host *adj_irecp; |
5495 | struct xfs_bmbt_irec got; | 5496 | struct xfs_bmbt_irec got; |
5496 | struct xfs_bmbt_irec left; | 5497 | struct xfs_bmbt_irec adj_irec; |
5497 | int error; | 5498 | int error; |
5498 | int i; | 5499 | int i; |
5500 | int total_extents; | ||
5499 | 5501 | ||
5500 | mp = ip->i_mount; | 5502 | mp = ip->i_mount; |
5501 | ifp = XFS_IFORK_PTR(ip, whichfork); | 5503 | ifp = XFS_IFORK_PTR(ip, whichfork); |
5504 | total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | ||
5502 | 5505 | ||
5503 | xfs_bmbt_get_all(gotp, &got); | 5506 | xfs_bmbt_get_all(gotp, &got); |
5504 | startoff = got.br_startoff - offset_shift_fsb; | ||
5505 | 5507 | ||
5506 | /* delalloc extents should be prevented by caller */ | 5508 | /* delalloc extents should be prevented by caller */ |
5507 | XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock)); | 5509 | XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock)); |
5508 | 5510 | ||
5509 | /* | 5511 | if (direction == SHIFT_LEFT) { |
5510 | * Check for merge if we've got an extent to the left, otherwise make | 5512 | startoff = got.br_startoff - offset_shift_fsb; |
5511 | * sure there's enough room at the start of the file for the shift. | 5513 | |
5512 | */ | 5514 | /* |
5513 | if (*current_ext) { | 5515 | * Check for merge if we've got an extent to the left, |
5514 | /* grab the left extent and check for a large enough hole */ | 5516 | * otherwise make sure there's enough room at the start |
5515 | leftp = xfs_iext_get_ext(ifp, *current_ext - 1); | 5517 | * of the file for the shift. |
5516 | xfs_bmbt_get_all(leftp, &left); | 5518 | */ |
5519 | if (!*current_ext) { | ||
5520 | if (got.br_startoff < offset_shift_fsb) | ||
5521 | return -EINVAL; | ||
5522 | goto update_current_ext; | ||
5523 | } | ||
5524 | /* | ||
5525 | * grab the left extent and check for a large | ||
5526 | * enough hole. | ||
5527 | */ | ||
5528 | adj_irecp = xfs_iext_get_ext(ifp, *current_ext - 1); | ||
5529 | xfs_bmbt_get_all(adj_irecp, &adj_irec); | ||
5517 | 5530 | ||
5518 | if (startoff < left.br_startoff + left.br_blockcount) | 5531 | if (startoff < |
5532 | adj_irec.br_startoff + adj_irec.br_blockcount) | ||
5519 | return -EINVAL; | 5533 | return -EINVAL; |
5520 | 5534 | ||
5521 | /* check whether to merge the extent or shift it down */ | 5535 | /* check whether to merge the extent or shift it down */ |
5522 | if (xfs_bmse_can_merge(&left, &got, offset_shift_fsb)) { | 5536 | if (xfs_bmse_can_merge(&adj_irec, &got, |
5537 | offset_shift_fsb)) { | ||
5523 | return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, | 5538 | return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, |
5524 | *current_ext, gotp, leftp, cur, | 5539 | *current_ext, gotp, adj_irecp, |
5525 | logflags); | 5540 | cur, logflags); |
5526 | } | 5541 | } |
5527 | } else if (got.br_startoff < offset_shift_fsb) | 5542 | } else { |
5528 | return -EINVAL; | 5543 | startoff = got.br_startoff + offset_shift_fsb; |
5529 | 5544 | /* nothing to move if this is the last extent */ | |
5545 | if (*current_ext >= (total_extents - 1)) | ||
5546 | goto update_current_ext; | ||
5547 | /* | ||
5548 | * If this is not the last extent in the file, make sure there | ||
5549 | * is enough room between current extent and next extent for | ||
5550 | * accommodating the shift. | ||
5551 | */ | ||
5552 | adj_irecp = xfs_iext_get_ext(ifp, *current_ext + 1); | ||
5553 | xfs_bmbt_get_all(adj_irecp, &adj_irec); | ||
5554 | if (startoff + got.br_blockcount > adj_irec.br_startoff) | ||
5555 | return -EINVAL; | ||
5556 | /* | ||
5557 | * Unlike a left shift (which involves a hole punch), | ||
5558 | * a right shift does not modify extent neighbors | ||
5559 | * in any way. We should never find mergeable extents | ||
5560 | * in this scenario. Check anyways and warn if we | ||
5561 | * encounter two extents that could be one. | ||
5562 | */ | ||
5563 | if (xfs_bmse_can_merge(&got, &adj_irec, offset_shift_fsb)) | ||
5564 | WARN_ON_ONCE(1); | ||
5565 | } | ||
5530 | /* | 5566 | /* |
5531 | * Increment the extent index for the next iteration, update the start | 5567 | * Increment the extent index for the next iteration, update the start |
5532 | * offset of the in-core extent and update the btree if applicable. | 5568 | * offset of the in-core extent and update the btree if applicable. |
5533 | */ | 5569 | */ |
5534 | (*current_ext)++; | 5570 | update_current_ext: |
5571 | if (direction == SHIFT_LEFT) | ||
5572 | (*current_ext)++; | ||
5573 | else | ||
5574 | (*current_ext)--; | ||
5535 | xfs_bmbt_set_startoff(gotp, startoff); | 5575 | xfs_bmbt_set_startoff(gotp, startoff); |
5536 | *logflags |= XFS_ILOG_CORE; | 5576 | *logflags |= XFS_ILOG_CORE; |
5537 | if (!cur) { | 5577 | if (!cur) { |
@@ -5547,14 +5587,14 @@ xfs_bmse_shift_one( | |||
5547 | 5587 | ||
5548 | got.br_startoff = startoff; | 5588 | got.br_startoff = startoff; |
5549 | return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, | 5589 | return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, |
5550 | got.br_blockcount, got.br_state); | 5590 | got.br_blockcount, got.br_state); |
5551 | } | 5591 | } |
5552 | 5592 | ||
5553 | /* | 5593 | /* |
5554 | * Shift extent records to the left to cover a hole. | 5594 | * Shift extent records to the left/right to cover/create a hole. |
5555 | * | 5595 | * |
5556 | * The maximum number of extents to be shifted in a single operation is | 5596 | * The maximum number of extents to be shifted in a single operation is |
5557 | * @num_exts. @start_fsb specifies the file offset to start the shift and the | 5597 | * @num_exts. @stop_fsb specifies the file offset at which to stop shift and the |
5558 | * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb | 5598 | * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb |
5559 | * is the length by which each extent is shifted. If there is no hole to shift | 5599 | * is the length by which each extent is shifted. If there is no hole to shift |
5560 | * the extents into, this will be considered invalid operation and we abort | 5600 | * the extents into, this will be considered invalid operation and we abort |
@@ -5564,12 +5604,13 @@ int | |||
5564 | xfs_bmap_shift_extents( | 5604 | xfs_bmap_shift_extents( |
5565 | struct xfs_trans *tp, | 5605 | struct xfs_trans *tp, |
5566 | struct xfs_inode *ip, | 5606 | struct xfs_inode *ip, |
5567 | xfs_fileoff_t start_fsb, | 5607 | xfs_fileoff_t *next_fsb, |
5568 | xfs_fileoff_t offset_shift_fsb, | 5608 | xfs_fileoff_t offset_shift_fsb, |
5569 | int *done, | 5609 | int *done, |
5570 | xfs_fileoff_t *next_fsb, | 5610 | xfs_fileoff_t stop_fsb, |
5571 | xfs_fsblock_t *firstblock, | 5611 | xfs_fsblock_t *firstblock, |
5572 | struct xfs_bmap_free *flist, | 5612 | struct xfs_bmap_free *flist, |
5613 | enum shift_direction direction, | ||
5573 | int num_exts) | 5614 | int num_exts) |
5574 | { | 5615 | { |
5575 | struct xfs_btree_cur *cur = NULL; | 5616 | struct xfs_btree_cur *cur = NULL; |
@@ -5579,10 +5620,11 @@ xfs_bmap_shift_extents( | |||
5579 | struct xfs_ifork *ifp; | 5620 | struct xfs_ifork *ifp; |
5580 | xfs_extnum_t nexts = 0; | 5621 | xfs_extnum_t nexts = 0; |
5581 | xfs_extnum_t current_ext; | 5622 | xfs_extnum_t current_ext; |
5623 | xfs_extnum_t total_extents; | ||
5624 | xfs_extnum_t stop_extent; | ||
5582 | int error = 0; | 5625 | int error = 0; |
5583 | int whichfork = XFS_DATA_FORK; | 5626 | int whichfork = XFS_DATA_FORK; |
5584 | int logflags = 0; | 5627 | int logflags = 0; |
5585 | int total_extents; | ||
5586 | 5628 | ||
5587 | if (unlikely(XFS_TEST_ERROR( | 5629 | if (unlikely(XFS_TEST_ERROR( |
5588 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | 5630 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && |
@@ -5598,6 +5640,8 @@ xfs_bmap_shift_extents( | |||
5598 | 5640 | ||
5599 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | 5641 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); |
5600 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 5642 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
5643 | ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT); | ||
5644 | ASSERT(*next_fsb != NULLFSBLOCK || direction == SHIFT_RIGHT); | ||
5601 | 5645 | ||
5602 | ifp = XFS_IFORK_PTR(ip, whichfork); | 5646 | ifp = XFS_IFORK_PTR(ip, whichfork); |
5603 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | 5647 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { |
@@ -5615,43 +5659,83 @@ xfs_bmap_shift_extents( | |||
5615 | } | 5659 | } |
5616 | 5660 | ||
5617 | /* | 5661 | /* |
5662 | * There may be delalloc extents in the data fork before the range we | ||
5663 | * are collapsing out, so we cannot use the count of real extents here. | ||
5664 | * Instead we have to calculate it from the incore fork. | ||
5665 | */ | ||
5666 | total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | ||
5667 | if (total_extents == 0) { | ||
5668 | *done = 1; | ||
5669 | goto del_cursor; | ||
5670 | } | ||
5671 | |||
5672 | /* | ||
5673 | * In case of first right shift, we need to initialize next_fsb | ||
5674 | */ | ||
5675 | if (*next_fsb == NULLFSBLOCK) { | ||
5676 | gotp = xfs_iext_get_ext(ifp, total_extents - 1); | ||
5677 | xfs_bmbt_get_all(gotp, &got); | ||
5678 | *next_fsb = got.br_startoff; | ||
5679 | if (stop_fsb > *next_fsb) { | ||
5680 | *done = 1; | ||
5681 | goto del_cursor; | ||
5682 | } | ||
5683 | } | ||
5684 | |||
5685 | /* Lookup the extent index at which we have to stop */ | ||
5686 | if (direction == SHIFT_RIGHT) { | ||
5687 | gotp = xfs_iext_bno_to_ext(ifp, stop_fsb, &stop_extent); | ||
5688 | /* Make stop_extent exclusive of shift range */ | ||
5689 | stop_extent--; | ||
5690 | } else | ||
5691 | stop_extent = total_extents; | ||
5692 | |||
5693 | /* | ||
5618 | * Look up the extent index for the fsb where we start shifting. We can | 5694 | * Look up the extent index for the fsb where we start shifting. We can |
5619 | * henceforth iterate with current_ext as extent list changes are locked | 5695 | * henceforth iterate with current_ext as extent list changes are locked |
5620 | * out via ilock. | 5696 | * out via ilock. |
5621 | * | 5697 | * |
5622 | * gotp can be null in 2 cases: 1) if there are no extents or 2) | 5698 | * gotp can be null in 2 cases: 1) if there are no extents or 2) |
5623 | * start_fsb lies in a hole beyond which there are no extents. Either | 5699 | * *next_fsb lies in a hole beyond which there are no extents. Either |
5624 | * way, we are done. | 5700 | * way, we are done. |
5625 | */ | 5701 | */ |
5626 | gotp = xfs_iext_bno_to_ext(ifp, start_fsb, ¤t_ext); | 5702 | gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, ¤t_ext); |
5627 | if (!gotp) { | 5703 | if (!gotp) { |
5628 | *done = 1; | 5704 | *done = 1; |
5629 | goto del_cursor; | 5705 | goto del_cursor; |
5630 | } | 5706 | } |
5631 | 5707 | ||
5632 | /* | 5708 | /* some sanity checking before we finally start shifting extents */ |
5633 | * There may be delalloc extents in the data fork before the range we | 5709 | if ((direction == SHIFT_LEFT && current_ext >= stop_extent) || |
5634 | * are collapsing out, so we cannot use the count of real extents here. | 5710 | (direction == SHIFT_RIGHT && current_ext <= stop_extent)) { |
5635 | * Instead we have to calculate it from the incore fork. | 5711 | error = -EIO; |
5636 | */ | 5712 | goto del_cursor; |
5637 | total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | 5713 | } |
5638 | while (nexts++ < num_exts && current_ext < total_extents) { | 5714 | |
5715 | while (nexts++ < num_exts) { | ||
5639 | error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, | 5716 | error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, |
5640 | ¤t_ext, gotp, cur, &logflags); | 5717 | ¤t_ext, gotp, cur, &logflags, |
5718 | direction); | ||
5641 | if (error) | 5719 | if (error) |
5642 | goto del_cursor; | 5720 | goto del_cursor; |
5721 | /* | ||
5722 | * If there was an extent merge during the shift, the extent | ||
5723 | * count can change. Update the total and grade the next record. | ||
5724 | */ | ||
5725 | if (direction == SHIFT_LEFT) { | ||
5726 | total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | ||
5727 | stop_extent = total_extents; | ||
5728 | } | ||
5643 | 5729 | ||
5644 | /* update total extent count and grab the next record */ | 5730 | if (current_ext == stop_extent) { |
5645 | total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | 5731 | *done = 1; |
5646 | if (current_ext >= total_extents) | 5732 | *next_fsb = NULLFSBLOCK; |
5647 | break; | 5733 | break; |
5734 | } | ||
5648 | gotp = xfs_iext_get_ext(ifp, current_ext); | 5735 | gotp = xfs_iext_get_ext(ifp, current_ext); |
5649 | } | 5736 | } |
5650 | 5737 | ||
5651 | /* Check if we are done */ | 5738 | if (!*done) { |
5652 | if (current_ext == total_extents) { | ||
5653 | *done = 1; | ||
5654 | } else if (next_fsb) { | ||
5655 | xfs_bmbt_get_all(gotp, &got); | 5739 | xfs_bmbt_get_all(gotp, &got); |
5656 | *next_fsb = got.br_startoff; | 5740 | *next_fsb = got.br_startoff; |
5657 | } | 5741 | } |
@@ -5666,3 +5750,189 @@ del_cursor: | |||
5666 | 5750 | ||
5667 | return error; | 5751 | return error; |
5668 | } | 5752 | } |
5753 | |||
5754 | /* | ||
5755 | * Splits an extent into two extents at split_fsb block such that it is | ||
5756 | * the first block of the current_ext. @current_ext is a target extent | ||
5757 | * to be split. @split_fsb is a block where the extents is split. | ||
5758 | * If split_fsb lies in a hole or the first block of extents, just return 0. | ||
5759 | */ | ||
5760 | STATIC int | ||
5761 | xfs_bmap_split_extent_at( | ||
5762 | struct xfs_trans *tp, | ||
5763 | struct xfs_inode *ip, | ||
5764 | xfs_fileoff_t split_fsb, | ||
5765 | xfs_fsblock_t *firstfsb, | ||
5766 | struct xfs_bmap_free *free_list) | ||
5767 | { | ||
5768 | int whichfork = XFS_DATA_FORK; | ||
5769 | struct xfs_btree_cur *cur = NULL; | ||
5770 | struct xfs_bmbt_rec_host *gotp; | ||
5771 | struct xfs_bmbt_irec got; | ||
5772 | struct xfs_bmbt_irec new; /* split extent */ | ||
5773 | struct xfs_mount *mp = ip->i_mount; | ||
5774 | struct xfs_ifork *ifp; | ||
5775 | xfs_fsblock_t gotblkcnt; /* new block count for got */ | ||
5776 | xfs_extnum_t current_ext; | ||
5777 | int error = 0; | ||
5778 | int logflags = 0; | ||
5779 | int i = 0; | ||
5780 | |||
5781 | if (unlikely(XFS_TEST_ERROR( | ||
5782 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | ||
5783 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), | ||
5784 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | ||
5785 | XFS_ERROR_REPORT("xfs_bmap_split_extent_at", | ||
5786 | XFS_ERRLEVEL_LOW, mp); | ||
5787 | return -EFSCORRUPTED; | ||
5788 | } | ||
5789 | |||
5790 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
5791 | return -EIO; | ||
5792 | |||
5793 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
5794 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
5795 | /* Read in all the extents */ | ||
5796 | error = xfs_iread_extents(tp, ip, whichfork); | ||
5797 | if (error) | ||
5798 | return error; | ||
5799 | } | ||
5800 | |||
5801 | /* | ||
5802 | * gotp can be null in 2 cases: 1) if there are no extents | ||
5803 | * or 2) split_fsb lies in a hole beyond which there are | ||
5804 | * no extents. Either way, we are done. | ||
5805 | */ | ||
5806 | gotp = xfs_iext_bno_to_ext(ifp, split_fsb, ¤t_ext); | ||
5807 | if (!gotp) | ||
5808 | return 0; | ||
5809 | |||
5810 | xfs_bmbt_get_all(gotp, &got); | ||
5811 | |||
5812 | /* | ||
5813 | * Check split_fsb lies in a hole or the start boundary offset | ||
5814 | * of the extent. | ||
5815 | */ | ||
5816 | if (got.br_startoff >= split_fsb) | ||
5817 | return 0; | ||
5818 | |||
5819 | gotblkcnt = split_fsb - got.br_startoff; | ||
5820 | new.br_startoff = split_fsb; | ||
5821 | new.br_startblock = got.br_startblock + gotblkcnt; | ||
5822 | new.br_blockcount = got.br_blockcount - gotblkcnt; | ||
5823 | new.br_state = got.br_state; | ||
5824 | |||
5825 | if (ifp->if_flags & XFS_IFBROOT) { | ||
5826 | cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); | ||
5827 | cur->bc_private.b.firstblock = *firstfsb; | ||
5828 | cur->bc_private.b.flist = free_list; | ||
5829 | cur->bc_private.b.flags = 0; | ||
5830 | error = xfs_bmbt_lookup_eq(cur, got.br_startoff, | ||
5831 | got.br_startblock, | ||
5832 | got.br_blockcount, | ||
5833 | &i); | ||
5834 | if (error) | ||
5835 | goto del_cursor; | ||
5836 | XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor); | ||
5837 | } | ||
5838 | |||
5839 | xfs_bmbt_set_blockcount(gotp, gotblkcnt); | ||
5840 | got.br_blockcount = gotblkcnt; | ||
5841 | |||
5842 | logflags = XFS_ILOG_CORE; | ||
5843 | if (cur) { | ||
5844 | error = xfs_bmbt_update(cur, got.br_startoff, | ||
5845 | got.br_startblock, | ||
5846 | got.br_blockcount, | ||
5847 | got.br_state); | ||
5848 | if (error) | ||
5849 | goto del_cursor; | ||
5850 | } else | ||
5851 | logflags |= XFS_ILOG_DEXT; | ||
5852 | |||
5853 | /* Add new extent */ | ||
5854 | current_ext++; | ||
5855 | xfs_iext_insert(ip, current_ext, 1, &new, 0); | ||
5856 | XFS_IFORK_NEXT_SET(ip, whichfork, | ||
5857 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); | ||
5858 | |||
5859 | if (cur) { | ||
5860 | error = xfs_bmbt_lookup_eq(cur, new.br_startoff, | ||
5861 | new.br_startblock, new.br_blockcount, | ||
5862 | &i); | ||
5863 | if (error) | ||
5864 | goto del_cursor; | ||
5865 | XFS_WANT_CORRUPTED_GOTO(mp, i == 0, del_cursor); | ||
5866 | cur->bc_rec.b.br_state = new.br_state; | ||
5867 | |||
5868 | error = xfs_btree_insert(cur, &i); | ||
5869 | if (error) | ||
5870 | goto del_cursor; | ||
5871 | XFS_WANT_CORRUPTED_GOTO(mp, i == 1, del_cursor); | ||
5872 | } | ||
5873 | |||
5874 | /* | ||
5875 | * Convert to a btree if necessary. | ||
5876 | */ | ||
5877 | if (xfs_bmap_needs_btree(ip, whichfork)) { | ||
5878 | int tmp_logflags; /* partial log flag return val */ | ||
5879 | |||
5880 | ASSERT(cur == NULL); | ||
5881 | error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list, | ||
5882 | &cur, 0, &tmp_logflags, whichfork); | ||
5883 | logflags |= tmp_logflags; | ||
5884 | } | ||
5885 | |||
5886 | del_cursor: | ||
5887 | if (cur) { | ||
5888 | cur->bc_private.b.allocated = 0; | ||
5889 | xfs_btree_del_cursor(cur, | ||
5890 | error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); | ||
5891 | } | ||
5892 | |||
5893 | if (logflags) | ||
5894 | xfs_trans_log_inode(tp, ip, logflags); | ||
5895 | return error; | ||
5896 | } | ||
5897 | |||
5898 | int | ||
5899 | xfs_bmap_split_extent( | ||
5900 | struct xfs_inode *ip, | ||
5901 | xfs_fileoff_t split_fsb) | ||
5902 | { | ||
5903 | struct xfs_mount *mp = ip->i_mount; | ||
5904 | struct xfs_trans *tp; | ||
5905 | struct xfs_bmap_free free_list; | ||
5906 | xfs_fsblock_t firstfsb; | ||
5907 | int committed; | ||
5908 | int error; | ||
5909 | |||
5910 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); | ||
5911 | error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, | ||
5912 | XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); | ||
5913 | if (error) { | ||
5914 | xfs_trans_cancel(tp, 0); | ||
5915 | return error; | ||
5916 | } | ||
5917 | |||
5918 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
5919 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
5920 | |||
5921 | xfs_bmap_init(&free_list, &firstfsb); | ||
5922 | |||
5923 | error = xfs_bmap_split_extent_at(tp, ip, split_fsb, | ||
5924 | &firstfsb, &free_list); | ||
5925 | if (error) | ||
5926 | goto out; | ||
5927 | |||
5928 | error = xfs_bmap_finish(&tp, &free_list, &committed); | ||
5929 | if (error) | ||
5930 | goto out; | ||
5931 | |||
5932 | return xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
5933 | |||
5934 | |||
5935 | out: | ||
5936 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | ||
5937 | return error; | ||
5938 | } | ||
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index b9d8a499d2c4..6aaa0c1c7200 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h | |||
@@ -166,6 +166,11 @@ static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) | |||
166 | */ | 166 | */ |
167 | #define XFS_BMAP_MAX_SHIFT_EXTENTS 1 | 167 | #define XFS_BMAP_MAX_SHIFT_EXTENTS 1 |
168 | 168 | ||
169 | enum shift_direction { | ||
170 | SHIFT_LEFT = 0, | ||
171 | SHIFT_RIGHT, | ||
172 | }; | ||
173 | |||
169 | #ifdef DEBUG | 174 | #ifdef DEBUG |
170 | void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, | 175 | void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, |
171 | int whichfork, unsigned long caller_ip); | 176 | int whichfork, unsigned long caller_ip); |
@@ -211,8 +216,10 @@ int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, | |||
211 | xfs_extnum_t num); | 216 | xfs_extnum_t num); |
212 | uint xfs_default_attroffset(struct xfs_inode *ip); | 217 | uint xfs_default_attroffset(struct xfs_inode *ip); |
213 | int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, | 218 | int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, |
214 | xfs_fileoff_t start_fsb, xfs_fileoff_t offset_shift_fsb, | 219 | xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, |
215 | int *done, xfs_fileoff_t *next_fsb, xfs_fsblock_t *firstblock, | 220 | int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, |
216 | struct xfs_bmap_free *flist, int num_exts); | 221 | struct xfs_bmap_free *flist, enum shift_direction direction, |
222 | int num_exts); | ||
223 | int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); | ||
217 | 224 | ||
218 | #endif /* __XFS_BMAP_H__ */ | 225 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 7efa23e72a90..1bd539321799 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -1376,22 +1376,19 @@ out: | |||
1376 | } | 1376 | } |
1377 | 1377 | ||
1378 | /* | 1378 | /* |
1379 | * xfs_collapse_file_space() | 1379 | * @next_fsb will keep track of the extent currently undergoing shift. |
1380 | * This routine frees disk space and shift extent for the given file. | 1380 | * @stop_fsb will keep track of the extent at which we have to stop. |
1381 | * The first thing we do is to free data blocks in the specified range | 1381 | * If we are shifting left, we will start with block (offset + len) and |
1382 | * by calling xfs_free_file_space(). It would also sync dirty data | 1382 | * shift each extent till last extent. |
1383 | * and invalidate page cache over the region on which collapse range | 1383 | * If we are shifting right, we will start with last extent inside file space |
1384 | * is working. And Shift extent records to the left to cover a hole. | 1384 | * and continue until we reach the block corresponding to offset. |
1385 | * RETURNS: | ||
1386 | * 0 on success | ||
1387 | * errno on error | ||
1388 | * | ||
1389 | */ | 1385 | */ |
1390 | int | 1386 | int |
1391 | xfs_collapse_file_space( | 1387 | xfs_shift_file_space( |
1392 | struct xfs_inode *ip, | 1388 | struct xfs_inode *ip, |
1393 | xfs_off_t offset, | 1389 | xfs_off_t offset, |
1394 | xfs_off_t len) | 1390 | xfs_off_t len, |
1391 | enum shift_direction direction) | ||
1395 | { | 1392 | { |
1396 | int done = 0; | 1393 | int done = 0; |
1397 | struct xfs_mount *mp = ip->i_mount; | 1394 | struct xfs_mount *mp = ip->i_mount; |
@@ -1400,21 +1397,26 @@ xfs_collapse_file_space( | |||
1400 | struct xfs_bmap_free free_list; | 1397 | struct xfs_bmap_free free_list; |
1401 | xfs_fsblock_t first_block; | 1398 | xfs_fsblock_t first_block; |
1402 | int committed; | 1399 | int committed; |
1403 | xfs_fileoff_t start_fsb; | 1400 | xfs_fileoff_t stop_fsb; |
1404 | xfs_fileoff_t next_fsb; | 1401 | xfs_fileoff_t next_fsb; |
1405 | xfs_fileoff_t shift_fsb; | 1402 | xfs_fileoff_t shift_fsb; |
1406 | 1403 | ||
1407 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | 1404 | ASSERT(direction == SHIFT_LEFT || direction == SHIFT_RIGHT); |
1408 | 1405 | ||
1409 | trace_xfs_collapse_file_space(ip); | 1406 | if (direction == SHIFT_LEFT) { |
1407 | next_fsb = XFS_B_TO_FSB(mp, offset + len); | ||
1408 | stop_fsb = XFS_B_TO_FSB(mp, VFS_I(ip)->i_size); | ||
1409 | } else { | ||
1410 | /* | ||
1411 | * If right shift, delegate the work of initialization of | ||
1412 | * next_fsb to xfs_bmap_shift_extent as it has ilock held. | ||
1413 | */ | ||
1414 | next_fsb = NULLFSBLOCK; | ||
1415 | stop_fsb = XFS_B_TO_FSB(mp, offset); | ||
1416 | } | ||
1410 | 1417 | ||
1411 | next_fsb = XFS_B_TO_FSB(mp, offset + len); | ||
1412 | shift_fsb = XFS_B_TO_FSB(mp, len); | 1418 | shift_fsb = XFS_B_TO_FSB(mp, len); |
1413 | 1419 | ||
1414 | error = xfs_free_file_space(ip, offset, len); | ||
1415 | if (error) | ||
1416 | return error; | ||
1417 | |||
1418 | /* | 1420 | /* |
1419 | * Trim eofblocks to avoid shifting uninitialized post-eof preallocation | 1421 | * Trim eofblocks to avoid shifting uninitialized post-eof preallocation |
1420 | * into the accessible region of the file. | 1422 | * into the accessible region of the file. |
@@ -1427,20 +1429,28 @@ xfs_collapse_file_space( | |||
1427 | 1429 | ||
1428 | /* | 1430 | /* |
1429 | * Writeback and invalidate cache for the remainder of the file as we're | 1431 | * Writeback and invalidate cache for the remainder of the file as we're |
1430 | * about to shift down every extent from the collapse range to EOF. The | 1432 | * about to shift down every extent from offset to EOF. |
1431 | * free of the collapse range above might have already done some of | ||
1432 | * this, but we shouldn't rely on it to do anything outside of the range | ||
1433 | * that was freed. | ||
1434 | */ | 1433 | */ |
1435 | error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, | 1434 | error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, |
1436 | offset + len, -1); | 1435 | offset, -1); |
1437 | if (error) | 1436 | if (error) |
1438 | return error; | 1437 | return error; |
1439 | error = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, | 1438 | error = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping, |
1440 | (offset + len) >> PAGE_CACHE_SHIFT, -1); | 1439 | offset >> PAGE_CACHE_SHIFT, -1); |
1441 | if (error) | 1440 | if (error) |
1442 | return error; | 1441 | return error; |
1443 | 1442 | ||
1443 | /* | ||
1444 | * The extent shiting code works on extent granularity. So, if | ||
1445 | * stop_fsb is not the starting block of extent, we need to split | ||
1446 | * the extent at stop_fsb. | ||
1447 | */ | ||
1448 | if (direction == SHIFT_RIGHT) { | ||
1449 | error = xfs_bmap_split_extent(ip, stop_fsb); | ||
1450 | if (error) | ||
1451 | return error; | ||
1452 | } | ||
1453 | |||
1444 | while (!error && !done) { | 1454 | while (!error && !done) { |
1445 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); | 1455 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); |
1446 | /* | 1456 | /* |
@@ -1464,7 +1474,7 @@ xfs_collapse_file_space( | |||
1464 | if (error) | 1474 | if (error) |
1465 | goto out; | 1475 | goto out; |
1466 | 1476 | ||
1467 | xfs_trans_ijoin(tp, ip, 0); | 1477 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
1468 | 1478 | ||
1469 | xfs_bmap_init(&free_list, &first_block); | 1479 | xfs_bmap_init(&free_list, &first_block); |
1470 | 1480 | ||
@@ -1472,10 +1482,9 @@ xfs_collapse_file_space( | |||
1472 | * We are using the write transaction in which max 2 bmbt | 1482 | * We are using the write transaction in which max 2 bmbt |
1473 | * updates are allowed | 1483 | * updates are allowed |
1474 | */ | 1484 | */ |
1475 | start_fsb = next_fsb; | 1485 | error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb, |
1476 | error = xfs_bmap_shift_extents(tp, ip, start_fsb, shift_fsb, | 1486 | &done, stop_fsb, &first_block, &free_list, |
1477 | &done, &next_fsb, &first_block, &free_list, | 1487 | direction, XFS_BMAP_MAX_SHIFT_EXTENTS); |
1478 | XFS_BMAP_MAX_SHIFT_EXTENTS); | ||
1479 | if (error) | 1488 | if (error) |
1480 | goto out; | 1489 | goto out; |
1481 | 1490 | ||
@@ -1484,18 +1493,70 @@ xfs_collapse_file_space( | |||
1484 | goto out; | 1493 | goto out; |
1485 | 1494 | ||
1486 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 1495 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
1487 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1488 | } | 1496 | } |
1489 | 1497 | ||
1490 | return error; | 1498 | return error; |
1491 | 1499 | ||
1492 | out: | 1500 | out: |
1493 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); | 1501 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); |
1494 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
1495 | return error; | 1502 | return error; |
1496 | } | 1503 | } |
1497 | 1504 | ||
1498 | /* | 1505 | /* |
1506 | * xfs_collapse_file_space() | ||
1507 | * This routine frees disk space and shift extent for the given file. | ||
1508 | * The first thing we do is to free data blocks in the specified range | ||
1509 | * by calling xfs_free_file_space(). It would also sync dirty data | ||
1510 | * and invalidate page cache over the region on which collapse range | ||
1511 | * is working. And Shift extent records to the left to cover a hole. | ||
1512 | * RETURNS: | ||
1513 | * 0 on success | ||
1514 | * errno on error | ||
1515 | * | ||
1516 | */ | ||
1517 | int | ||
1518 | xfs_collapse_file_space( | ||
1519 | struct xfs_inode *ip, | ||
1520 | xfs_off_t offset, | ||
1521 | xfs_off_t len) | ||
1522 | { | ||
1523 | int error; | ||
1524 | |||
1525 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | ||
1526 | trace_xfs_collapse_file_space(ip); | ||
1527 | |||
1528 | error = xfs_free_file_space(ip, offset, len); | ||
1529 | if (error) | ||
1530 | return error; | ||
1531 | |||
1532 | return xfs_shift_file_space(ip, offset, len, SHIFT_LEFT); | ||
1533 | } | ||
1534 | |||
1535 | /* | ||
1536 | * xfs_insert_file_space() | ||
1537 | * This routine create hole space by shifting extents for the given file. | ||
1538 | * The first thing we do is to sync dirty data and invalidate page cache | ||
1539 | * over the region on which insert range is working. And split an extent | ||
1540 | * to two extents at given offset by calling xfs_bmap_split_extent. | ||
1541 | * And shift all extent records which are laying between [offset, | ||
1542 | * last allocated extent] to the right to reserve hole range. | ||
1543 | * RETURNS: | ||
1544 | * 0 on success | ||
1545 | * errno on error | ||
1546 | */ | ||
1547 | int | ||
1548 | xfs_insert_file_space( | ||
1549 | struct xfs_inode *ip, | ||
1550 | loff_t offset, | ||
1551 | loff_t len) | ||
1552 | { | ||
1553 | ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); | ||
1554 | trace_xfs_insert_file_space(ip); | ||
1555 | |||
1556 | return xfs_shift_file_space(ip, offset, len, SHIFT_RIGHT); | ||
1557 | } | ||
1558 | |||
1559 | /* | ||
1499 | * We need to check that the format of the data fork in the temporary inode is | 1560 | * We need to check that the format of the data fork in the temporary inode is |
1500 | * valid for the target inode before doing the swap. This is not a problem with | 1561 | * valid for the target inode before doing the swap. This is not a problem with |
1501 | * attr1 because of the fixed fork offset, but attr2 has a dynamically sized | 1562 | * attr1 because of the fixed fork offset, but attr2 has a dynamically sized |
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 736429a72a12..af97d9a1dfb4 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h | |||
@@ -63,6 +63,8 @@ int xfs_zero_file_space(struct xfs_inode *ip, xfs_off_t offset, | |||
63 | xfs_off_t len); | 63 | xfs_off_t len); |
64 | int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset, | 64 | int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset, |
65 | xfs_off_t len); | 65 | xfs_off_t len); |
66 | int xfs_insert_file_space(struct xfs_inode *, xfs_off_t offset, | ||
67 | xfs_off_t len); | ||
66 | 68 | ||
67 | /* EOF block manipulation functions */ | 69 | /* EOF block manipulation functions */ |
68 | bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); | 70 | bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index b101e80f2862..dc5f609bea88 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -822,6 +822,11 @@ xfs_file_write_iter( | |||
822 | return ret; | 822 | return ret; |
823 | } | 823 | } |
824 | 824 | ||
825 | #define XFS_FALLOC_FL_SUPPORTED \ | ||
826 | (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ | ||
827 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE | \ | ||
828 | FALLOC_FL_INSERT_RANGE) | ||
829 | |||
825 | STATIC long | 830 | STATIC long |
826 | xfs_file_fallocate( | 831 | xfs_file_fallocate( |
827 | struct file *file, | 832 | struct file *file, |
@@ -835,11 +840,11 @@ xfs_file_fallocate( | |||
835 | enum xfs_prealloc_flags flags = 0; | 840 | enum xfs_prealloc_flags flags = 0; |
836 | uint iolock = XFS_IOLOCK_EXCL; | 841 | uint iolock = XFS_IOLOCK_EXCL; |
837 | loff_t new_size = 0; | 842 | loff_t new_size = 0; |
843 | bool do_file_insert = 0; | ||
838 | 844 | ||
839 | if (!S_ISREG(inode->i_mode)) | 845 | if (!S_ISREG(inode->i_mode)) |
840 | return -EINVAL; | 846 | return -EINVAL; |
841 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | | 847 | if (mode & ~XFS_FALLOC_FL_SUPPORTED) |
842 | FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE)) | ||
843 | return -EOPNOTSUPP; | 848 | return -EOPNOTSUPP; |
844 | 849 | ||
845 | xfs_ilock(ip, iolock); | 850 | xfs_ilock(ip, iolock); |
@@ -876,6 +881,27 @@ xfs_file_fallocate( | |||
876 | error = xfs_collapse_file_space(ip, offset, len); | 881 | error = xfs_collapse_file_space(ip, offset, len); |
877 | if (error) | 882 | if (error) |
878 | goto out_unlock; | 883 | goto out_unlock; |
884 | } else if (mode & FALLOC_FL_INSERT_RANGE) { | ||
885 | unsigned blksize_mask = (1 << inode->i_blkbits) - 1; | ||
886 | |||
887 | new_size = i_size_read(inode) + len; | ||
888 | if (offset & blksize_mask || len & blksize_mask) { | ||
889 | error = -EINVAL; | ||
890 | goto out_unlock; | ||
891 | } | ||
892 | |||
893 | /* check the new inode size does not wrap through zero */ | ||
894 | if (new_size > inode->i_sb->s_maxbytes) { | ||
895 | error = -EFBIG; | ||
896 | goto out_unlock; | ||
897 | } | ||
898 | |||
899 | /* Offset should be less than i_size */ | ||
900 | if (offset >= i_size_read(inode)) { | ||
901 | error = -EINVAL; | ||
902 | goto out_unlock; | ||
903 | } | ||
904 | do_file_insert = 1; | ||
879 | } else { | 905 | } else { |
880 | flags |= XFS_PREALLOC_SET; | 906 | flags |= XFS_PREALLOC_SET; |
881 | 907 | ||
@@ -910,8 +936,19 @@ xfs_file_fallocate( | |||
910 | iattr.ia_valid = ATTR_SIZE; | 936 | iattr.ia_valid = ATTR_SIZE; |
911 | iattr.ia_size = new_size; | 937 | iattr.ia_size = new_size; |
912 | error = xfs_setattr_size(ip, &iattr); | 938 | error = xfs_setattr_size(ip, &iattr); |
939 | if (error) | ||
940 | goto out_unlock; | ||
913 | } | 941 | } |
914 | 942 | ||
943 | /* | ||
944 | * Perform hole insertion now that the file size has been | ||
945 | * updated so that if we crash during the operation we don't | ||
946 | * leave shifted extents past EOF and hence losing access to | ||
947 | * the data that is contained within them. | ||
948 | */ | ||
949 | if (do_file_insert) | ||
950 | error = xfs_insert_file_space(ip, offset, len); | ||
951 | |||
915 | out_unlock: | 952 | out_unlock: |
916 | xfs_iunlock(ip, iolock); | 953 | xfs_iunlock(ip, iolock); |
917 | return error; | 954 | return error; |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index a302738d224d..b2a45cc9eceb 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -664,6 +664,7 @@ DEFINE_INODE_EVENT(xfs_alloc_file_space); | |||
664 | DEFINE_INODE_EVENT(xfs_free_file_space); | 664 | DEFINE_INODE_EVENT(xfs_free_file_space); |
665 | DEFINE_INODE_EVENT(xfs_zero_file_space); | 665 | DEFINE_INODE_EVENT(xfs_zero_file_space); |
666 | DEFINE_INODE_EVENT(xfs_collapse_file_space); | 666 | DEFINE_INODE_EVENT(xfs_collapse_file_space); |
667 | DEFINE_INODE_EVENT(xfs_insert_file_space); | ||
667 | DEFINE_INODE_EVENT(xfs_readdir); | 668 | DEFINE_INODE_EVENT(xfs_readdir); |
668 | #ifdef CONFIG_XFS_POSIX_ACL | 669 | #ifdef CONFIG_XFS_POSIX_ACL |
669 | DEFINE_INODE_EVENT(xfs_get_acl); | 670 | DEFINE_INODE_EVENT(xfs_get_acl); |