aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c115
1 files changed, 89 insertions, 26 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index cd01783a89d7..6f3276974555 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4238,7 +4238,7 @@ xfs_bmap_validate_ret(
4238 ASSERT(i == 0 || 4238 ASSERT(i == 0 ||
4239 mval[i - 1].br_startoff + mval[i - 1].br_blockcount == 4239 mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
4240 mval[i].br_startoff); 4240 mval[i].br_startoff);
4241 if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY)) 4241 if (flags & XFS_BMAPI_WRITE)
4242 ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && 4242 ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
4243 mval[i].br_startblock != HOLESTARTBLOCK); 4243 mval[i].br_startblock != HOLESTARTBLOCK);
4244 ASSERT(mval[i].br_state == XFS_EXT_NORM || 4244 ASSERT(mval[i].br_state == XFS_EXT_NORM ||
@@ -4556,6 +4556,90 @@ out_unreserve_quota:
4556} 4556}
4557 4557
4558/* 4558/*
4559 * Map file blocks to filesystem blocks, adding delayed allocations as needed.
4560 */
4561int
4562xfs_bmapi_delay(
4563 struct xfs_inode *ip, /* incore inode */
4564 xfs_fileoff_t bno, /* starting file offs. mapped */
4565 xfs_filblks_t len, /* length to map in file */
4566 struct xfs_bmbt_irec *mval, /* output: map values */
4567 int *nmap, /* i/o: mval size/count */
4568 int flags) /* XFS_BMAPI_... */
4569{
4570 struct xfs_mount *mp = ip->i_mount;
4571 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
4572 struct xfs_bmbt_irec got; /* current file extent record */
4573 struct xfs_bmbt_irec prev; /* previous file extent record */
4574 xfs_fileoff_t obno; /* old block number (offset) */
4575 xfs_fileoff_t end; /* end of mapped file region */
4576 xfs_extnum_t lastx; /* last useful extent number */
4577 int eof; /* we've hit the end of extents */
4578 int n = 0; /* current extent index */
4579 int error = 0;
4580
4581 ASSERT(*nmap >= 1);
4582 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
4583 ASSERT(!(flags & ~XFS_BMAPI_ENTIRE));
4584
4585 if (unlikely(XFS_TEST_ERROR(
4586 (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS &&
4587 XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE),
4588 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
4589 XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp);
4590 return XFS_ERROR(EFSCORRUPTED);
4591 }
4592
4593 if (XFS_FORCED_SHUTDOWN(mp))
4594 return XFS_ERROR(EIO);
4595
4596 XFS_STATS_INC(xs_blk_mapw);
4597
4598 if (!(ifp->if_flags & XFS_IFEXTENTS)) {
4599 error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK);
4600 if (error)
4601 return error;
4602 }
4603
4604 xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev);
4605 end = bno + len;
4606 obno = bno;
4607
4608 while (bno < end && n < *nmap) {
4609 if (eof || got.br_startoff > bno) {
4610 error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got,
4611 &prev, &lastx, eof);
4612 if (error) {
4613 if (n == 0) {
4614 *nmap = 0;
4615 return error;
4616 }
4617 break;
4618 }
4619 }
4620
4621 /* set up the extent map to return. */
4622 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
4623 xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
4624
4625 /* If we're done, stop now. */
4626 if (bno >= end || n >= *nmap)
4627 break;
4628
4629 /* Else go on to the next record. */
4630 prev = got;
4631 if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
4632 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
4633 else
4634 eof = 1;
4635 }
4636
4637 *nmap = n;
4638 return 0;
4639}
4640
4641
4642/*
4559 * Map file blocks to filesystem blocks. 4643 * Map file blocks to filesystem blocks.
4560 * File range is given by the bno/len pair. 4644 * File range is given by the bno/len pair.
4561 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) 4645 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set)
@@ -4663,7 +4747,6 @@ xfs_bmapi(
4663 */ 4747 */
4664 if ((flags & XFS_BMAPI_IGSTATE) && wr) /* if writing unwritten space */ 4748 if ((flags & XFS_BMAPI_IGSTATE) && wr) /* if writing unwritten space */
4665 wr = 0; /* no allocations are allowed */ 4749 wr = 0; /* no allocations are allowed */
4666 ASSERT(wr || !(flags & XFS_BMAPI_DELAY));
4667 logflags = 0; 4750 logflags = 0;
4668 nallocs = 0; 4751 nallocs = 0;
4669 cur = NULL; 4752 cur = NULL;
@@ -4698,8 +4781,7 @@ xfs_bmapi(
4698 if (eof && !wr) 4781 if (eof && !wr)
4699 got.br_startoff = end; 4782 got.br_startoff = end;
4700 inhole = eof || got.br_startoff > bno; 4783 inhole = eof || got.br_startoff > bno;
4701 wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) && 4784 wasdelay = wr && !inhole && isnullstartblock(got.br_startblock);
4702 isnullstartblock(got.br_startblock);
4703 /* 4785 /*
4704 * First, deal with the hole before the allocated space 4786 * First, deal with the hole before the allocated space
4705 * that we found, if any. 4787 * that we found, if any.
@@ -4727,20 +4809,7 @@ xfs_bmapi(
4727 aoff = bno; 4809 aoff = bno;
4728 } 4810 }
4729 minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1; 4811 minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4730 if (flags & XFS_BMAPI_DELAY) { 4812 {
4731 error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got,
4732 &prev, &lastx, eof);
4733 if (error) {
4734 if (n == 0) {
4735 *nmap = 0;
4736 ASSERT(cur == NULL);
4737 return error;
4738 }
4739 break;
4740 }
4741
4742 goto trim_extent;
4743 } else {
4744 /* 4813 /*
4745 * If first time, allocate and fill in 4814 * If first time, allocate and fill in
4746 * once-only bma fields. 4815 * once-only bma fields.
@@ -4851,14 +4920,8 @@ xfs_bmapi(
4851 ASSERT(got.br_startoff <= aoff); 4920 ASSERT(got.br_startoff <= aoff);
4852 ASSERT(got.br_startoff + got.br_blockcount >= 4921 ASSERT(got.br_startoff + got.br_blockcount >=
4853 aoff + alen); 4922 aoff + alen);
4854#ifdef DEBUG
4855 if (flags & XFS_BMAPI_DELAY) {
4856 ASSERT(isnullstartblock(got.br_startblock));
4857 ASSERT(startblockval(got.br_startblock) > 0);
4858 }
4859 ASSERT(got.br_state == XFS_EXT_NORM || 4923 ASSERT(got.br_state == XFS_EXT_NORM ||
4860 got.br_state == XFS_EXT_UNWRITTEN); 4924 got.br_state == XFS_EXT_UNWRITTEN);
4861#endif
4862 /* 4925 /*
4863 * Fall down into the found allocated space case. 4926 * Fall down into the found allocated space case.
4864 */ 4927 */
@@ -4877,7 +4940,7 @@ xfs_bmapi(
4877 n++; 4940 n++;
4878 continue; 4941 continue;
4879 } 4942 }
4880trim_extent: 4943
4881 /* Deal with the allocated space we found. */ 4944 /* Deal with the allocated space we found. */
4882 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); 4945 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
4883 4946
@@ -4887,7 +4950,7 @@ trim_extent:
4887 */ 4950 */
4888 if (wr && 4951 if (wr &&
4889 ((mval->br_state == XFS_EXT_UNWRITTEN && 4952 ((mval->br_state == XFS_EXT_UNWRITTEN &&
4890 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) || 4953 ((flags & XFS_BMAPI_PREALLOC) == 0)) ||
4891 (mval->br_state == XFS_EXT_NORM && 4954 (mval->br_state == XFS_EXT_NORM &&
4892 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) == 4955 ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) ==
4893 (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) { 4956 (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) {