aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-09-18 16:40:52 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:04 -0400
commitc0dc7828af6952643219292be29e482ef74cb261 (patch)
tree02f12935ec56f61a9ed396d1b902b21aaf4ffb3e /fs/xfs/xfs_bmap.c
parentb447fe5a05cbd01c4bf7fe2fa41cb9e99ce7e58e (diff)
xfs: rename xfs_bmapi to xfs_bmapi_write
Now that all the read-only users of xfs_bmapi have been converted to use xfs_bmapi_read(), we can remove all the read-only handling cases from xfs_bmapi(). Once this is done, rename xfs_bmapi to xfs_bmapi_write to reflect the fact it is for allocation only. This enables us to kill the XFS_BMAPI_WRITE flag as well. Also clean up xfs_bmapi_write to the style used in the newly added xfs_bmapi_read/delay functions. Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r--fs/xfs/xfs_bmap.c225
1 files changed, 94 insertions, 131 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index c2e49fd18bfd..595cc6311937 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4211,9 +4211,8 @@ xfs_bmap_validate_ret(
4211 ASSERT(i == 0 || 4211 ASSERT(i == 0 ||
4212 mval[i - 1].br_startoff + mval[i - 1].br_blockcount == 4212 mval[i - 1].br_startoff + mval[i - 1].br_blockcount ==
4213 mval[i].br_startoff); 4213 mval[i].br_startoff);
4214 if (flags & XFS_BMAPI_WRITE) 4214 ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK &&
4215 ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && 4215 mval[i].br_startblock != HOLESTARTBLOCK);
4216 mval[i].br_startblock != HOLESTARTBLOCK);
4217 ASSERT(mval[i].br_state == XFS_EXT_NORM || 4216 ASSERT(mval[i].br_state == XFS_EXT_NORM ||
4218 mval[i].br_state == XFS_EXT_UNWRITTEN); 4217 mval[i].br_state == XFS_EXT_UNWRITTEN);
4219 } 4218 }
@@ -4809,60 +4808,57 @@ xfs_bmapi_convert_unwritten(
4809} 4808}
4810 4809
4811/* 4810/*
4812 * Map file blocks to filesystem blocks. 4811 * Map file blocks to filesystem blocks, and allocate blocks or convert the
4813 * File range is given by the bno/len pair. 4812 * extent state if necessary. Details behaviour is controlled by the flags
4814 * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) 4813 * parameter. Only allocates blocks from a single allocation group, to avoid
4815 * into a hole or past eof. 4814 * locking problems.
4816 * Only allocates blocks from a single allocation group, 4815 *
4817 * to avoid locking problems.
4818 * The returned value in "firstblock" from the first call in a transaction 4816 * The returned value in "firstblock" from the first call in a transaction
4819 * must be remembered and presented to subsequent calls in "firstblock". 4817 * must be remembered and presented to subsequent calls in "firstblock".
4820 * An upper bound for the number of blocks to be allocated is supplied to 4818 * An upper bound for the number of blocks to be allocated is supplied to
4821 * the first call in "total"; if no allocation group has that many free 4819 * the first call in "total"; if no allocation group has that many free
4822 * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). 4820 * blocks then the call will fail (return NULLFSBLOCK in "firstblock").
4823 */ 4821 */
4824int /* error */ 4822int
4825xfs_bmapi( 4823xfs_bmapi_write(
4826 xfs_trans_t *tp, /* transaction pointer */ 4824 struct xfs_trans *tp, /* transaction pointer */
4827 xfs_inode_t *ip, /* incore inode */ 4825 struct xfs_inode *ip, /* incore inode */
4828 xfs_fileoff_t bno, /* starting file offs. mapped */ 4826 xfs_fileoff_t bno, /* starting file offs. mapped */
4829 xfs_filblks_t len, /* length to map in file */ 4827 xfs_filblks_t len, /* length to map in file */
4830 int flags, /* XFS_BMAPI_... */ 4828 int flags, /* XFS_BMAPI_... */
4831 xfs_fsblock_t *firstblock, /* first allocated block 4829 xfs_fsblock_t *firstblock, /* first allocated block
4832 controls a.g. for allocs */ 4830 controls a.g. for allocs */
4833 xfs_extlen_t total, /* total blocks needed */ 4831 xfs_extlen_t total, /* total blocks needed */
4834 xfs_bmbt_irec_t *mval, /* output: map values */ 4832 struct xfs_bmbt_irec *mval, /* output: map values */
4835 int *nmap, /* i/o: mval size/count */ 4833 int *nmap, /* i/o: mval size/count */
4836 xfs_bmap_free_t *flist) /* i/o: list extents to free */ 4834 struct xfs_bmap_free *flist) /* i/o: list extents to free */
4837{ 4835{
4838 xfs_bmalloca_t bma = { 0 }; /* args for xfs_bmap_alloc */ 4836 struct xfs_mount *mp = ip->i_mount;
4839 xfs_btree_cur_t *cur; /* bmap btree cursor */ 4837 struct xfs_ifork *ifp;
4840 xfs_fileoff_t end; /* end of mapped file region */ 4838 struct xfs_bmalloca bma = { 0 }; /* args for xfs_bmap_alloc */
4841 int eof; /* we've hit the end of extents */ 4839 struct xfs_btree_cur *cur; /* bmap btree cursor */
4842 xfs_bmbt_rec_host_t *ep; /* extent record pointer */ 4840 xfs_fileoff_t end; /* end of mapped file region */
4843 int error; /* error return */ 4841 int eof; /* after the end of extents */
4844 xfs_bmbt_irec_t got; /* current file extent record */ 4842 int error; /* error return */
4845 xfs_ifork_t *ifp; /* inode fork pointer */ 4843 struct xfs_bmbt_irec got; /* current file extent record */
4846 xfs_extnum_t lastx; /* last useful extent number */ 4844 xfs_extnum_t lastx; /* last useful extent number */
4847 int logflags; /* flags for transaction logging */ 4845 int logflags; /* flags for transaction logging */
4848 xfs_extlen_t minleft; /* min blocks left after allocation */ 4846 xfs_extlen_t minleft; /* min blocks left after allocation */
4849 xfs_mount_t *mp; /* xfs mount structure */ 4847 int n; /* current extent index */
4850 int n; /* current extent index */ 4848 int nallocs; /* number of extents alloc'd */
4851 int nallocs; /* number of extents alloc'd */ 4849 xfs_fileoff_t obno; /* old block number (offset) */
4852 xfs_fileoff_t obno; /* old block number (offset) */ 4850 struct xfs_bmbt_irec prev; /* previous file extent record */
4853 xfs_bmbt_irec_t prev; /* previous file extent record */ 4851 int tmp_logflags; /* temp flags holder */
4854 int tmp_logflags; /* temp flags holder */ 4852 int whichfork; /* data or attr fork */
4855 int whichfork; /* data or attr fork */ 4853 char inhole; /* current location is hole in file */
4856 char inhole; /* current location is hole in file */ 4854 char wasdelay; /* old extent was delayed */
4857 char wasdelay; /* old extent was delayed */ 4855
4858 char wr; /* this is a write request */
4859 char rt; /* this is a realtime file */
4860#ifdef DEBUG 4856#ifdef DEBUG
4861 xfs_fileoff_t orig_bno; /* original block number value */ 4857 xfs_fileoff_t orig_bno; /* original block number value */
4862 int orig_flags; /* original flags arg value */ 4858 int orig_flags; /* original flags arg value */
4863 xfs_filblks_t orig_len; /* original value of len arg */ 4859 xfs_filblks_t orig_len; /* original value of len arg */
4864 xfs_bmbt_irec_t *orig_mval; /* original value of mval */ 4860 struct xfs_bmbt_irec *orig_mval; /* original value of mval */
4865 int orig_nmap; /* original value of *nmap */ 4861 int orig_nmap; /* original value of *nmap */
4866 4862
4867 orig_bno = bno; 4863 orig_bno = bno;
4868 orig_len = len; 4864 orig_len = len;
@@ -4870,69 +4866,60 @@ xfs_bmapi(
4870 orig_mval = mval; 4866 orig_mval = mval;
4871 orig_nmap = *nmap; 4867 orig_nmap = *nmap;
4872#endif 4868#endif
4869
4873 ASSERT(*nmap >= 1); 4870 ASSERT(*nmap >= 1);
4874 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE)); 4871 ASSERT(*nmap <= XFS_BMAP_MAX_NMAP);
4872 ASSERT(!(flags & XFS_BMAPI_IGSTATE));
4873 ASSERT(tp != NULL);
4874
4875 whichfork = (flags & XFS_BMAPI_ATTRFORK) ? 4875 whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4876 XFS_ATTR_FORK : XFS_DATA_FORK; 4876 XFS_ATTR_FORK : XFS_DATA_FORK;
4877 mp = ip->i_mount; 4877
4878 if (unlikely(XFS_TEST_ERROR( 4878 if (unlikely(XFS_TEST_ERROR(
4879 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && 4879 (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
4880 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && 4880 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE &&
4881 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), 4881 XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL),
4882 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { 4882 mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) {
4883 XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp); 4883 XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp);
4884 return XFS_ERROR(EFSCORRUPTED); 4884 return XFS_ERROR(EFSCORRUPTED);
4885 } 4885 }
4886
4886 if (XFS_FORCED_SHUTDOWN(mp)) 4887 if (XFS_FORCED_SHUTDOWN(mp))
4887 return XFS_ERROR(EIO); 4888 return XFS_ERROR(EIO);
4888 rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); 4889
4889 ifp = XFS_IFORK_PTR(ip, whichfork); 4890 ifp = XFS_IFORK_PTR(ip, whichfork);
4890 ASSERT(ifp->if_ext_max == 4891 ASSERT(ifp->if_ext_max ==
4891 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); 4892 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
4892 if ((wr = (flags & XFS_BMAPI_WRITE)) != 0) 4893
4893 XFS_STATS_INC(xs_blk_mapw); 4894 XFS_STATS_INC(xs_blk_mapw);
4894 else 4895
4895 XFS_STATS_INC(xs_blk_mapr);
4896 /*
4897 * IGSTATE flag is used to combine extents which
4898 * differ only due to the state of the extents.
4899 * This technique is used from xfs_getbmap()
4900 * when the caller does not wish to see the
4901 * separation (which is the default).
4902 *
4903 * This technique is also used when writing a
4904 * buffer which has been partially written,
4905 * (usually by being flushed during a chunkread),
4906 * to ensure one write takes place. This also
4907 * prevents a change in the xfs inode extents at
4908 * this time, intentionally. This change occurs
4909 * on completion of the write operation, in
4910 * xfs_strat_comp(), where the xfs_bmapi() call
4911 * is transactioned, and the extents combined.
4912 */
4913 if ((flags & XFS_BMAPI_IGSTATE) && wr) /* if writing unwritten space */
4914 wr = 0; /* no allocations are allowed */
4915 logflags = 0; 4896 logflags = 0;
4916 nallocs = 0; 4897 nallocs = 0;
4917 cur = NULL; 4898 cur = NULL;
4899
4918 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { 4900 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
4919 ASSERT(wr && tp); 4901 error = xfs_bmap_local_to_extents(tp, ip, firstblock, total,
4920 if ((error = xfs_bmap_local_to_extents(tp, ip, 4902 &logflags, whichfork);
4921 firstblock, total, &logflags, whichfork))) 4903 if (error)
4922 goto error0; 4904 goto error0;
4923 } 4905 }
4924 if (wr && *firstblock == NULLFSBLOCK) { 4906
4907 if (*firstblock == NULLFSBLOCK) {
4925 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) 4908 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE)
4926 minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; 4909 minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1;
4927 else 4910 else
4928 minleft = 1; 4911 minleft = 1;
4929 } else 4912 } else {
4930 minleft = 0; 4913 minleft = 0;
4931 if (!(ifp->if_flags & XFS_IFEXTENTS) && 4914 }
4932 (error = xfs_iread_extents(tp, ip, whichfork))) 4915
4933 goto error0; 4916 if (!(ifp->if_flags & XFS_IFEXTENTS)) {
4934 ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, 4917 error = xfs_iread_extents(tp, ip, whichfork);
4935 &prev); 4918 if (error)
4919 goto error0;
4920 }
4921
4922 xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev);
4936 n = 0; 4923 n = 0;
4937 end = bno + len; 4924 end = bno + len;
4938 obno = bno; 4925 obno = bno;
@@ -4945,19 +4932,14 @@ xfs_bmapi(
4945 bma.userdata = 0; 4932 bma.userdata = 0;
4946 4933
4947 while (bno < end && n < *nmap) { 4934 while (bno < end && n < *nmap) {
4948 /*
4949 * Reading past eof, act as though there's a hole
4950 * up to end.
4951 */
4952 if (eof && !wr)
4953 got.br_startoff = end;
4954 inhole = eof || got.br_startoff > bno; 4935 inhole = eof || got.br_startoff > bno;
4955 wasdelay = wr && !inhole && isnullstartblock(got.br_startblock); 4936 wasdelay = !inhole && isnullstartblock(got.br_startblock);
4937
4956 /* 4938 /*
4957 * First, deal with the hole before the allocated space 4939 * First, deal with the hole before the allocated space
4958 * that we found, if any. 4940 * that we found, if any.
4959 */ 4941 */
4960 if (wr && (inhole || wasdelay)) { 4942 if (inhole || wasdelay) {
4961 bma.eof = eof; 4943 bma.eof = eof;
4962 bma.conv = !!(flags & XFS_BMAPI_CONVERT); 4944 bma.conv = !!(flags & XFS_BMAPI_CONVERT);
4963 bma.wasdel = wasdelay; 4945 bma.wasdel = wasdelay;
@@ -4975,36 +4957,20 @@ xfs_bmapi(
4975 minleft = 0; 4957 minleft = 0;
4976 if (bma.rval == NULLFSBLOCK) 4958 if (bma.rval == NULLFSBLOCK)
4977 break; 4959 break;
4978 } else if (inhole) {
4979 /*
4980 * Reading in a hole.
4981 */
4982 mval->br_startoff = bno;
4983 mval->br_startblock = HOLESTARTBLOCK;
4984 mval->br_blockcount =
4985 XFS_FILBLKS_MIN(len, got.br_startoff - bno);
4986 mval->br_state = XFS_EXT_NORM;
4987 bno += mval->br_blockcount;
4988 len -= mval->br_blockcount;
4989 mval++;
4990 n++;
4991 continue;
4992 } 4960 }
4993 4961
4994 /* Deal with the allocated space we found. */ 4962 /* Deal with the allocated space we found. */
4995 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); 4963 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
4996 4964
4997 /* Execute unwritten extent conversion if necessary */ 4965 /* Execute unwritten extent conversion if necessary */
4998 if (wr) { 4966 error = xfs_bmapi_convert_unwritten(&bma, mval, len, &lastx,
4999 error = xfs_bmapi_convert_unwritten(&bma, mval, len, 4967 &cur, firstblock, flist,
5000 &lastx, &cur, firstblock, flist, flags, 4968 flags, &tmp_logflags);
5001 &tmp_logflags); 4969 logflags |= tmp_logflags;
5002 logflags |= tmp_logflags; 4970 if (error == EAGAIN)
5003 if (error == EAGAIN) 4971 continue;
5004 continue; 4972 if (error)
5005 if (error) 4973 goto error0;
5006 goto error0;
5007 }
5008 4974
5009 /* update the extent map to return */ 4975 /* update the extent map to return */
5010 xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); 4976 xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags);
@@ -5016,24 +4982,22 @@ xfs_bmapi(
5016 */ 4982 */
5017 if (bno >= end || n >= *nmap || nallocs >= *nmap) 4983 if (bno >= end || n >= *nmap || nallocs >= *nmap)
5018 break; 4984 break;
5019 /* 4985
5020 * Else go on to the next record. 4986 /* Else go on to the next record. */
5021 */
5022 prev = got; 4987 prev = got;
5023 if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) { 4988 if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t))
5024 ep = xfs_iext_get_ext(ifp, lastx); 4989 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got);
5025 xfs_bmbt_get_all(ep, &got); 4990 else
5026 } else {
5027 eof = 1; 4991 eof = 1;
5028 }
5029 } 4992 }
5030 *nmap = n; 4993 *nmap = n;
4994
5031 /* 4995 /*
5032 * Transform from btree to extents, give it cur. 4996 * Transform from btree to extents, give it cur.
5033 */ 4997 */
5034 if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && 4998 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE &&
5035 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { 4999 XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) {
5036 ASSERT(wr && cur); 5000 ASSERT(cur);
5037 error = xfs_bmap_btree_to_extents(tp, ip, cur, 5001 error = xfs_bmap_btree_to_extents(tp, ip, cur,
5038 &tmp_logflags, whichfork); 5002 &tmp_logflags, whichfork);
5039 logflags |= tmp_logflags; 5003 logflags |= tmp_logflags;
@@ -5061,10 +5025,9 @@ error0:
5061 * detecting a case where the data is changed, there's an error, 5025 * detecting a case where the data is changed, there's an error,
5062 * and it's not logged so we don't shutdown when we should. 5026 * and it's not logged so we don't shutdown when we should.
5063 */ 5027 */
5064 if (logflags) { 5028 if (logflags)
5065 ASSERT(tp && wr);
5066 xfs_trans_log_inode(tp, ip, logflags); 5029 xfs_trans_log_inode(tp, ip, logflags);
5067 } 5030
5068 if (cur) { 5031 if (cur) {
5069 if (!error) { 5032 if (!error) {
5070 ASSERT(*firstblock == NULLFSBLOCK || 5033 ASSERT(*firstblock == NULLFSBLOCK ||