aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2015-03-25 00:12:53 -0400
committerDave Chinner <david@fromorbit.com>2015-03-25 00:12:53 -0400
commita448f8f1b744611fb1867ea811170cca2a9a6588 (patch)
tree288e292c7134d3d04ab1ef77cd7798a08276812c /fs/xfs
parent2b93681f593577df6fcb9af61947beaace071b74 (diff)
parenta904b1ca5751faf5ece8600e18cd3b674afcca1b (diff)
Merge branch 'fallocate-insert-range' into for-next
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c356
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h13
-rw-r--r--fs/xfs/xfs_bmap_util.c131
-rw-r--r--fs/xfs/xfs_bmap_util.h2
-rw-r--r--fs/xfs/xfs_file.c41
-rw-r--r--fs/xfs/xfs_trace.h1
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)++; 5570update_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
5564xfs_bmap_shift_extents( 5604xfs_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, &current_ext); 5702 gotp = xfs_iext_bno_to_ext(ifp, *next_fsb, &current_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 &current_ext, gotp, cur, &logflags); 5717 &current_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 */
5760STATIC int
5761xfs_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, &current_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
5886del_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
5898int
5899xfs_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
5935out:
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
169enum shift_direction {
170 SHIFT_LEFT = 0,
171 SHIFT_RIGHT,
172};
173
169#ifdef DEBUG 174#ifdef DEBUG
170void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, 175void 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);
212uint xfs_default_attroffset(struct xfs_inode *ip); 217uint xfs_default_attroffset(struct xfs_inode *ip);
213int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, 218int 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);
223int 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 */
1390int 1386int
1391xfs_collapse_file_space( 1387xfs_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
1492out: 1500out:
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 */
1517int
1518xfs_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 */
1547int
1548xfs_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);
64int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset, 64int xfs_collapse_file_space(struct xfs_inode *, xfs_off_t offset,
65 xfs_off_t len); 65 xfs_off_t len);
66int 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 */
68bool xfs_can_free_eofblocks(struct xfs_inode *ip, bool force); 70bool 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
825STATIC long 830STATIC long
826xfs_file_fallocate( 831xfs_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
915out_unlock: 952out_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);
664DEFINE_INODE_EVENT(xfs_free_file_space); 664DEFINE_INODE_EVENT(xfs_free_file_space);
665DEFINE_INODE_EVENT(xfs_zero_file_space); 665DEFINE_INODE_EVENT(xfs_zero_file_space);
666DEFINE_INODE_EVENT(xfs_collapse_file_space); 666DEFINE_INODE_EVENT(xfs_collapse_file_space);
667DEFINE_INODE_EVENT(xfs_insert_file_space);
667DEFINE_INODE_EVENT(xfs_readdir); 668DEFINE_INODE_EVENT(xfs_readdir);
668#ifdef CONFIG_XFS_POSIX_ACL 669#ifdef CONFIG_XFS_POSIX_ACL
669DEFINE_INODE_EVENT(xfs_get_acl); 670DEFINE_INODE_EVENT(xfs_get_acl);