diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 115 |
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 | */ | ||
4561 | int | ||
4562 | xfs_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 | } |
4880 | trim_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))))) { |