aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <david@fromorbit.com>2014-09-23 01:51:14 -0400
committerDave Chinner <david@fromorbit.com>2014-09-23 01:51:14 -0400
commitf6d31f4b0462898896ba68e491662958ce37d095 (patch)
tree6655823e16402769f61fc20edb730b9c7c84a82a /fs/xfs
parenta4241aebe924136d6838fd516da6daa727fcd728 (diff)
parent8b5279e33f241a074a9c8649bba8f77a2167b798 (diff)
Merge branch 'xfs-shift-extents-rework' into for-next
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c365
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h7
-rw-r--r--fs/xfs/xfs_aops.c16
-rw-r--r--fs/xfs/xfs_bmap_util.c54
4 files changed, 289 insertions, 153 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 86df952d3e24..79c981984dca 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -5404,22 +5404,223 @@ error0:
5404} 5404}
5405 5405
5406/* 5406/*
5407 * Determine whether an extent shift can be accomplished by a merge with the
5408 * extent that precedes the target hole of the shift.
5409 */
5410STATIC bool
5411xfs_bmse_can_merge(
5412 struct xfs_bmbt_irec *left, /* preceding extent */
5413 struct xfs_bmbt_irec *got, /* current extent to shift */
5414 xfs_fileoff_t shift) /* shift fsb */
5415{
5416 xfs_fileoff_t startoff;
5417
5418 startoff = got->br_startoff - shift;
5419
5420 /*
5421 * The extent, once shifted, must be adjacent in-file and on-disk with
5422 * the preceding extent.
5423 */
5424 if ((left->br_startoff + left->br_blockcount != startoff) ||
5425 (left->br_startblock + left->br_blockcount != got->br_startblock) ||
5426 (left->br_state != got->br_state) ||
5427 (left->br_blockcount + got->br_blockcount > MAXEXTLEN))
5428 return false;
5429
5430 return true;
5431}
5432
5433/*
5434 * A bmap extent shift adjusts the file offset of an extent to fill a preceding
5435 * hole in the file. If an extent shift would result in the extent being fully
5436 * adjacent to the extent that currently precedes the hole, we can merge with
5437 * the preceding extent rather than do the shift.
5438 *
5439 * This function assumes the caller has verified a shift-by-merge is possible
5440 * with the provided extents via xfs_bmse_can_merge().
5441 */
5442STATIC int
5443xfs_bmse_merge(
5444 struct xfs_inode *ip,
5445 int whichfork,
5446 xfs_fileoff_t shift, /* shift fsb */
5447 int current_ext, /* idx of gotp */
5448 struct xfs_bmbt_rec_host *gotp, /* extent to shift */
5449 struct xfs_bmbt_rec_host *leftp, /* preceding extent */
5450 struct xfs_btree_cur *cur,
5451 int *logflags) /* output */
5452{
5453 struct xfs_ifork *ifp;
5454 struct xfs_bmbt_irec got;
5455 struct xfs_bmbt_irec left;
5456 xfs_filblks_t blockcount;
5457 int error, i;
5458
5459 ifp = XFS_IFORK_PTR(ip, whichfork);
5460 xfs_bmbt_get_all(gotp, &got);
5461 xfs_bmbt_get_all(leftp, &left);
5462 blockcount = left.br_blockcount + got.br_blockcount;
5463
5464 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
5465 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
5466 ASSERT(xfs_bmse_can_merge(&left, &got, shift));
5467
5468 /*
5469 * Merge the in-core extents. Note that the host record pointers and
5470 * current_ext index are invalid once the extent has been removed via
5471 * xfs_iext_remove().
5472 */
5473 xfs_bmbt_set_blockcount(leftp, blockcount);
5474 xfs_iext_remove(ip, current_ext, 1, 0);
5475
5476 /*
5477 * Update the on-disk extent count, the btree if necessary and log the
5478 * inode.
5479 */
5480 XFS_IFORK_NEXT_SET(ip, whichfork,
5481 XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
5482 *logflags |= XFS_ILOG_CORE;
5483 if (!cur) {
5484 *logflags |= XFS_ILOG_DEXT;
5485 return 0;
5486 }
5487
5488 /* lookup and remove the extent to merge */
5489 error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock,
5490 got.br_blockcount, &i);
5491 if (error)
5492 goto out_error;
5493 XFS_WANT_CORRUPTED_GOTO(i == 1, out_error);
5494
5495 error = xfs_btree_delete(cur, &i);
5496 if (error)
5497 goto out_error;
5498 XFS_WANT_CORRUPTED_GOTO(i == 1, out_error);
5499
5500 /* lookup and update size of the previous extent */
5501 error = xfs_bmbt_lookup_eq(cur, left.br_startoff, left.br_startblock,
5502 left.br_blockcount, &i);
5503 if (error)
5504 goto out_error;
5505 XFS_WANT_CORRUPTED_GOTO(i == 1, out_error);
5506
5507 left.br_blockcount = blockcount;
5508
5509 error = xfs_bmbt_update(cur, left.br_startoff, left.br_startblock,
5510 left.br_blockcount, left.br_state);
5511 if (error)
5512 goto out_error;
5513
5514 return 0;
5515
5516out_error:
5517 return error;
5518}
5519
5520/*
5521 * Shift a single extent.
5522 */
5523STATIC int
5524xfs_bmse_shift_one(
5525 struct xfs_inode *ip,
5526 int whichfork,
5527 xfs_fileoff_t offset_shift_fsb,
5528 int *current_ext,
5529 struct xfs_bmbt_rec_host *gotp,
5530 struct xfs_btree_cur *cur,
5531 int *logflags)
5532{
5533 struct xfs_ifork *ifp;
5534 xfs_fileoff_t startoff;
5535 struct xfs_bmbt_rec_host *leftp;
5536 struct xfs_bmbt_irec got;
5537 struct xfs_bmbt_irec left;
5538 int error;
5539 int i;
5540
5541 ifp = XFS_IFORK_PTR(ip, whichfork);
5542
5543 xfs_bmbt_get_all(gotp, &got);
5544 startoff = got.br_startoff - offset_shift_fsb;
5545
5546 /* delalloc extents should be prevented by caller */
5547 XFS_WANT_CORRUPTED_GOTO(!isnullstartblock(got.br_startblock),
5548 out_error);
5549
5550 /*
5551 * If this is the first extent in the file, make sure there's enough
5552 * room at the start of the file and jump right to the shift as there's
5553 * no left extent to merge.
5554 */
5555 if (*current_ext == 0) {
5556 if (got.br_startoff < offset_shift_fsb)
5557 return -EINVAL;
5558 goto shift_extent;
5559 }
5560
5561 /* grab the left extent and check for a large enough hole */
5562 leftp = xfs_iext_get_ext(ifp, *current_ext - 1);
5563 xfs_bmbt_get_all(leftp, &left);
5564
5565 if (startoff < left.br_startoff + left.br_blockcount)
5566 return -EINVAL;
5567
5568 /* check whether to merge the extent or shift it down */
5569 if (!xfs_bmse_can_merge(&left, &got, offset_shift_fsb))
5570 goto shift_extent;
5571
5572 return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, *current_ext,
5573 gotp, leftp, cur, logflags);
5574
5575shift_extent:
5576 /*
5577 * Increment the extent index for the next iteration, update the start
5578 * offset of the in-core extent and update the btree if applicable.
5579 */
5580 (*current_ext)++;
5581 xfs_bmbt_set_startoff(gotp, startoff);
5582 *logflags |= XFS_ILOG_CORE;
5583 if (!cur) {
5584 *logflags |= XFS_ILOG_DEXT;
5585 return 0;
5586 }
5587
5588 error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock,
5589 got.br_blockcount, &i);
5590 if (error)
5591 return error;
5592 XFS_WANT_CORRUPTED_GOTO(i == 1, out_error);
5593
5594 got.br_startoff = startoff;
5595 error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock,
5596 got.br_blockcount, got.br_state);
5597 if (error)
5598 return error;
5599
5600 return 0;
5601
5602out_error:
5603 return error;
5604}
5605
5606/*
5407 * Shift extent records to the left to cover a hole. 5607 * Shift extent records to the left to cover a hole.
5408 * 5608 *
5409 * The maximum number of extents to be shifted in a single operation 5609 * The maximum number of extents to be shifted in a single operation is
5410 * is @num_exts, and @current_ext keeps track of the current extent 5610 * @num_exts. @start_fsb specifies the file offset to start the shift and the
5411 * index we have shifted. @offset_shift_fsb is the length by which each 5611 * file offset where we've left off is returned in @next_fsb. @offset_shift_fsb
5412 * extent is shifted. If there is no hole to shift the extents 5612 * is the length by which each extent is shifted. If there is no hole to shift
5413 * into, this will be considered invalid operation and we abort immediately. 5613 * the extents into, this will be considered invalid operation and we abort
5614 * immediately.
5414 */ 5615 */
5415int 5616int
5416xfs_bmap_shift_extents( 5617xfs_bmap_shift_extents(
5417 struct xfs_trans *tp, 5618 struct xfs_trans *tp,
5418 struct xfs_inode *ip, 5619 struct xfs_inode *ip,
5419 int *done,
5420 xfs_fileoff_t start_fsb, 5620 xfs_fileoff_t start_fsb,
5421 xfs_fileoff_t offset_shift_fsb, 5621 xfs_fileoff_t offset_shift_fsb,
5422 xfs_extnum_t *current_ext, 5622 int *done,
5623 xfs_fileoff_t *next_fsb,
5423 xfs_fsblock_t *firstblock, 5624 xfs_fsblock_t *firstblock,
5424 struct xfs_bmap_free *flist, 5625 struct xfs_bmap_free *flist,
5425 int num_exts) 5626 int num_exts)
@@ -5427,16 +5628,13 @@ xfs_bmap_shift_extents(
5427 struct xfs_btree_cur *cur = NULL; 5628 struct xfs_btree_cur *cur = NULL;
5428 struct xfs_bmbt_rec_host *gotp; 5629 struct xfs_bmbt_rec_host *gotp;
5429 struct xfs_bmbt_irec got; 5630 struct xfs_bmbt_irec got;
5430 struct xfs_bmbt_irec left;
5431 struct xfs_mount *mp = ip->i_mount; 5631 struct xfs_mount *mp = ip->i_mount;
5432 struct xfs_ifork *ifp; 5632 struct xfs_ifork *ifp;
5433 xfs_extnum_t nexts = 0; 5633 xfs_extnum_t nexts = 0;
5434 xfs_fileoff_t startoff; 5634 xfs_extnum_t current_ext;
5435 int error = 0; 5635 int error = 0;
5436 int i;
5437 int whichfork = XFS_DATA_FORK; 5636 int whichfork = XFS_DATA_FORK;
5438 int logflags = 0; 5637 int logflags = 0;
5439 xfs_filblks_t blockcount = 0;
5440 int total_extents; 5638 int total_extents;
5441 5639
5442 if (unlikely(XFS_TEST_ERROR( 5640 if (unlikely(XFS_TEST_ERROR(
@@ -5451,7 +5649,8 @@ xfs_bmap_shift_extents(
5451 if (XFS_FORCED_SHUTDOWN(mp)) 5649 if (XFS_FORCED_SHUTDOWN(mp))
5452 return -EIO; 5650 return -EIO;
5453 5651
5454 ASSERT(current_ext != NULL); 5652 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
5653 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
5455 5654
5456 ifp = XFS_IFORK_PTR(ip, whichfork); 5655 ifp = XFS_IFORK_PTR(ip, whichfork);
5457 if (!(ifp->if_flags & XFS_IFEXTENTS)) { 5656 if (!(ifp->if_flags & XFS_IFEXTENTS)) {
@@ -5461,23 +5660,6 @@ xfs_bmap_shift_extents(
5461 return error; 5660 return error;
5462 } 5661 }
5463 5662
5464 /*
5465 * If *current_ext is 0, we would need to lookup the extent
5466 * from where we would start shifting and store it in gotp.
5467 */
5468 if (!*current_ext) {
5469 gotp = xfs_iext_bno_to_ext(ifp, start_fsb, current_ext);
5470 /*
5471 * gotp can be null in 2 cases: 1) if there are no extents
5472 * or 2) start_fsb lies in a hole beyond which there are
5473 * no extents. Either way, we are done.
5474 */
5475 if (!gotp) {
5476 *done = 1;
5477 return 0;
5478 }
5479 }
5480
5481 if (ifp->if_flags & XFS_IFBROOT) { 5663 if (ifp->if_flags & XFS_IFBROOT) {
5482 cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); 5664 cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
5483 cur->bc_private.b.firstblock = *firstblock; 5665 cur->bc_private.b.firstblock = *firstblock;
@@ -5486,112 +5668,46 @@ xfs_bmap_shift_extents(
5486 } 5668 }
5487 5669
5488 /* 5670 /*
5671 * Look up the extent index for the fsb where we start shifting. We can
5672 * henceforth iterate with current_ext as extent list changes are locked
5673 * out via ilock.
5674 *
5675 * gotp can be null in 2 cases: 1) if there are no extents or 2)
5676 * start_fsb lies in a hole beyond which there are no extents. Either
5677 * way, we are done.
5678 */
5679 gotp = xfs_iext_bno_to_ext(ifp, start_fsb, &current_ext);
5680 if (!gotp) {
5681 *done = 1;
5682 goto del_cursor;
5683 }
5684
5685 /*
5489 * There may be delalloc extents in the data fork before the range we 5686 * There may be delalloc extents in the data fork before the range we
5490 * are collapsing out, so we cannot 5687 * are collapsing out, so we cannot use the count of real extents here.
5491 * use the count of real extents here. Instead we have to calculate it 5688 * Instead we have to calculate it from the incore fork.
5492 * from the incore fork.
5493 */ 5689 */
5494 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); 5690 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
5495 while (nexts++ < num_exts && *current_ext < total_extents) { 5691 while (nexts++ < num_exts && current_ext < total_extents) {
5496 5692 error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb,
5497 gotp = xfs_iext_get_ext(ifp, *current_ext); 5693 &current_ext, gotp, cur, &logflags);
5498 xfs_bmbt_get_all(gotp, &got);
5499 startoff = got.br_startoff - offset_shift_fsb;
5500
5501 /*
5502 * Before shifting extent into hole, make sure that the hole
5503 * is large enough to accomodate the shift.
5504 */
5505 if (*current_ext) {
5506 xfs_bmbt_get_all(xfs_iext_get_ext(ifp,
5507 *current_ext - 1), &left);
5508
5509 if (startoff < left.br_startoff + left.br_blockcount)
5510 error = -EINVAL;
5511 } else if (offset_shift_fsb > got.br_startoff) {
5512 /*
5513 * When first extent is shifted, offset_shift_fsb
5514 * should be less than the stating offset of
5515 * the first extent.
5516 */
5517 error = -EINVAL;
5518 }
5519
5520 if (error) 5694 if (error)
5521 goto del_cursor; 5695 goto del_cursor;
5522 5696
5523 if (cur) { 5697 /* update total extent count and grab the next record */
5524 error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
5525 got.br_startblock,
5526 got.br_blockcount,
5527 &i);
5528 if (error)
5529 goto del_cursor;
5530 XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
5531 }
5532
5533 /* Check if we can merge 2 adjacent extents */
5534 if (*current_ext &&
5535 left.br_startoff + left.br_blockcount == startoff &&
5536 left.br_startblock + left.br_blockcount ==
5537 got.br_startblock &&
5538 left.br_state == got.br_state &&
5539 left.br_blockcount + got.br_blockcount <= MAXEXTLEN) {
5540 blockcount = left.br_blockcount +
5541 got.br_blockcount;
5542 xfs_iext_remove(ip, *current_ext, 1, 0);
5543 logflags |= XFS_ILOG_CORE;
5544 if (cur) {
5545 error = xfs_btree_delete(cur, &i);
5546 if (error)
5547 goto del_cursor;
5548 XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
5549 } else {
5550 logflags |= XFS_ILOG_DEXT;
5551 }
5552 XFS_IFORK_NEXT_SET(ip, whichfork,
5553 XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
5554 gotp = xfs_iext_get_ext(ifp, --*current_ext);
5555 xfs_bmbt_get_all(gotp, &got);
5556
5557 /* Make cursor point to the extent we will update */
5558 if (cur) {
5559 error = xfs_bmbt_lookup_eq(cur, got.br_startoff,
5560 got.br_startblock,
5561 got.br_blockcount,
5562 &i);
5563 if (error)
5564 goto del_cursor;
5565 XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
5566 }
5567
5568 xfs_bmbt_set_blockcount(gotp, blockcount);
5569 got.br_blockcount = blockcount;
5570 } else {
5571 /* We have to update the startoff */
5572 xfs_bmbt_set_startoff(gotp, startoff);
5573 got.br_startoff = startoff;
5574 }
5575
5576 logflags |= XFS_ILOG_CORE;
5577 if (cur) {
5578 error = xfs_bmbt_update(cur, got.br_startoff,
5579 got.br_startblock,
5580 got.br_blockcount,
5581 got.br_state);
5582 if (error)
5583 goto del_cursor;
5584 } else {
5585 logflags |= XFS_ILOG_DEXT;
5586 }
5587
5588 (*current_ext)++;
5589 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); 5698 total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
5699 if (current_ext >= total_extents)
5700 break;
5701 gotp = xfs_iext_get_ext(ifp, current_ext);
5590 } 5702 }
5591 5703
5592 /* Check if we are done */ 5704 /* Check if we are done */
5593 if (*current_ext == total_extents) 5705 if (current_ext == total_extents) {
5594 *done = 1; 5706 *done = 1;
5707 } else if (next_fsb) {
5708 xfs_bmbt_get_all(gotp, &got);
5709 *next_fsb = got.br_startoff;
5710 }
5595 5711
5596del_cursor: 5712del_cursor:
5597 if (cur) 5713 if (cur)
@@ -5600,5 +5716,6 @@ del_cursor:
5600 5716
5601 if (logflags) 5717 if (logflags)
5602 xfs_trans_log_inode(tp, ip, logflags); 5718 xfs_trans_log_inode(tp, ip, logflags);
5719
5603 return error; 5720 return error;
5604} 5721}
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index b879ca56a64c..44db6db86402 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -178,9 +178,8 @@ int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx,
178 xfs_extnum_t num); 178 xfs_extnum_t num);
179uint xfs_default_attroffset(struct xfs_inode *ip); 179uint xfs_default_attroffset(struct xfs_inode *ip);
180int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, 180int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip,
181 int *done, xfs_fileoff_t start_fsb, 181 xfs_fileoff_t start_fsb, xfs_fileoff_t offset_shift_fsb,
182 xfs_fileoff_t offset_shift_fsb, xfs_extnum_t *current_ext, 182 int *done, xfs_fileoff_t *next_fsb, xfs_fsblock_t *firstblock,
183 xfs_fsblock_t *firstblock, struct xfs_bmap_free *flist, 183 struct xfs_bmap_free *flist, int num_exts);
184 int num_exts);
185 184
186#endif /* __XFS_BMAP_H__ */ 185#endif /* __XFS_BMAP_H__ */
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index b984647c24db..2f502537a39c 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -434,10 +434,22 @@ xfs_start_page_writeback(
434{ 434{
435 ASSERT(PageLocked(page)); 435 ASSERT(PageLocked(page));
436 ASSERT(!PageWriteback(page)); 436 ASSERT(!PageWriteback(page));
437 if (clear_dirty) 437
438 /*
439 * if the page was not fully cleaned, we need to ensure that the higher
440 * layers come back to it correctly. That means we need to keep the page
441 * dirty, and for WB_SYNC_ALL writeback we need to ensure the
442 * PAGECACHE_TAG_TOWRITE index mark is not removed so another attempt to
443 * write this page in this writeback sweep will be made.
444 */
445 if (clear_dirty) {
438 clear_page_dirty_for_io(page); 446 clear_page_dirty_for_io(page);
439 set_page_writeback(page); 447 set_page_writeback(page);
448 } else
449 set_page_writeback_keepwrite(page);
450
440 unlock_page(page); 451 unlock_page(page);
452
441 /* If no buffers on the page are to be written, finish it here */ 453 /* If no buffers on the page are to be written, finish it here */
442 if (!buffers) 454 if (!buffers)
443 end_page_writeback(page); 455 end_page_writeback(page);
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 1707980f9a4b..809ae7d395c3 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1205,6 +1205,7 @@ xfs_free_file_space(
1205 xfs_bmap_free_t free_list; 1205 xfs_bmap_free_t free_list;
1206 xfs_bmbt_irec_t imap; 1206 xfs_bmbt_irec_t imap;
1207 xfs_off_t ioffset; 1207 xfs_off_t ioffset;
1208 xfs_off_t iendoffset;
1208 xfs_extlen_t mod=0; 1209 xfs_extlen_t mod=0;
1209 xfs_mount_t *mp; 1210 xfs_mount_t *mp;
1210 int nimap; 1211 int nimap;
@@ -1233,12 +1234,13 @@ xfs_free_file_space(
1233 inode_dio_wait(VFS_I(ip)); 1234 inode_dio_wait(VFS_I(ip));
1234 1235
1235 rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); 1236 rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE);
1236 ioffset = offset & ~(rounding - 1); 1237 ioffset = round_down(offset, rounding);
1237 error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, 1238 iendoffset = round_up(offset + len, rounding) - 1;
1238 ioffset, -1); 1239 error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ioffset,
1240 iendoffset);
1239 if (error) 1241 if (error)
1240 goto out; 1242 goto out;
1241 truncate_pagecache_range(VFS_I(ip), ioffset, -1); 1243 truncate_pagecache_range(VFS_I(ip), ioffset, iendoffset);
1242 1244
1243 /* 1245 /*
1244 * Need to zero the stuff we're not freeing, on disk. 1246 * Need to zero the stuff we're not freeing, on disk.
@@ -1456,41 +1458,47 @@ xfs_collapse_file_space(
1456 struct xfs_mount *mp = ip->i_mount; 1458 struct xfs_mount *mp = ip->i_mount;
1457 struct xfs_trans *tp; 1459 struct xfs_trans *tp;
1458 int error; 1460 int error;
1459 xfs_extnum_t current_ext = 0;
1460 struct xfs_bmap_free free_list; 1461 struct xfs_bmap_free free_list;
1461 xfs_fsblock_t first_block; 1462 xfs_fsblock_t first_block;
1462 int committed; 1463 int committed;
1463 xfs_fileoff_t start_fsb; 1464 xfs_fileoff_t start_fsb;
1465 xfs_fileoff_t next_fsb;
1464 xfs_fileoff_t shift_fsb; 1466 xfs_fileoff_t shift_fsb;
1465 1467
1466 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); 1468 ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL));
1467 1469
1468 trace_xfs_collapse_file_space(ip); 1470 trace_xfs_collapse_file_space(ip);
1469 1471
1470 start_fsb = XFS_B_TO_FSB(mp, offset + len); 1472 next_fsb = XFS_B_TO_FSB(mp, offset + len);
1471 shift_fsb = XFS_B_TO_FSB(mp, len); 1473 shift_fsb = XFS_B_TO_FSB(mp, len);
1472 1474
1473 /* 1475 error = xfs_free_file_space(ip, offset, len);
1474 * Writeback the entire file and force remove any post-eof blocks. The
1475 * writeback prevents changes to the extent list via concurrent
1476 * writeback and the eofblocks trim prevents the extent shift algorithm
1477 * from running into a post-eof delalloc extent.
1478 *
1479 * XXX: This is a temporary fix until the extent shift loop below is
1480 * converted to use offsets and lookups within the ILOCK rather than
1481 * carrying around the index into the extent list for the next
1482 * iteration.
1483 */
1484 error = filemap_write_and_wait(VFS_I(ip)->i_mapping);
1485 if (error) 1476 if (error)
1486 return error; 1477 return error;
1478
1479 /*
1480 * Trim eofblocks to avoid shifting uninitialized post-eof preallocation
1481 * into the accessible region of the file.
1482 */
1487 if (xfs_can_free_eofblocks(ip, true)) { 1483 if (xfs_can_free_eofblocks(ip, true)) {
1488 error = xfs_free_eofblocks(mp, ip, false); 1484 error = xfs_free_eofblocks(mp, ip, false);
1489 if (error) 1485 if (error)
1490 return error; 1486 return error;
1491 } 1487 }
1492 1488
1493 error = xfs_free_file_space(ip, offset, len); 1489 /*
1490 * Writeback and invalidate cache for the remainder of the file as we're
1491 * about to shift down every extent from the collapse range to EOF. The
1492 * free of the collapse range above might have already done some of
1493 * this, but we shouldn't rely on it to do anything outside of the range
1494 * that was freed.
1495 */
1496 error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
1497 offset + len, -1);
1498 if (error)
1499 return error;
1500 error = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
1501 (offset + len) >> PAGE_CACHE_SHIFT, -1);
1494 if (error) 1502 if (error)
1495 return error; 1503 return error;
1496 1504
@@ -1525,10 +1533,10 @@ xfs_collapse_file_space(
1525 * We are using the write transaction in which max 2 bmbt 1533 * We are using the write transaction in which max 2 bmbt
1526 * updates are allowed 1534 * updates are allowed
1527 */ 1535 */
1528 error = xfs_bmap_shift_extents(tp, ip, &done, start_fsb, 1536 start_fsb = next_fsb;
1529 shift_fsb, &current_ext, 1537 error = xfs_bmap_shift_extents(tp, ip, start_fsb, shift_fsb,
1530 &first_block, &free_list, 1538 &done, &next_fsb, &first_block, &free_list,
1531 XFS_BMAP_MAX_SHIFT_EXTENTS); 1539 XFS_BMAP_MAX_SHIFT_EXTENTS);
1532 if (error) 1540 if (error)
1533 goto out; 1541 goto out;
1534 1542