aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-09-18 16:40:50 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:04 -0400
commit7e47a4efde33aa3f0cb901e086a75751c2269f04 (patch)
tree2ed47e82967b9b2655fc700bcc0fd5a375433fa2
parent1fd044d9c6735e669f0db025f18023e56a608130 (diff)
xfs: factor extent allocation out of xfs_bmapi
To further improve the readability of xfs_bmapi(), factor the extent allocation out into a separate function. This removes a large block of logic from the xfs_bmapi() code loop and makes it easier to see the operational logic flow for xfs_bmapi(). Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/xfs_bmap.c302
1 files changed, 162 insertions, 140 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index c9492e23447..311cbc1d64c 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4605,6 +4605,147 @@ xfs_bmapi_delay(
4605} 4605}
4606 4606
4607 4607
4608STATIC int
4609xfs_bmapi_allocate(
4610 struct xfs_bmalloca *bma,
4611 xfs_extnum_t *lastx,
4612 struct xfs_btree_cur **cur,
4613 xfs_fsblock_t *firstblock,
4614 struct xfs_bmap_free *flist,
4615 int flags,
4616 int *nallocs,
4617 int *logflags)
4618{
4619 struct xfs_mount *mp = bma->ip->i_mount;
4620 int whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
4621 XFS_ATTR_FORK : XFS_DATA_FORK;
4622 struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
4623 xfs_fsblock_t abno;
4624 xfs_extlen_t alen;
4625 xfs_fileoff_t aoff;
4626 int error;
4627 int rt;
4628
4629 rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip);
4630
4631 /*
4632 * For the wasdelay case, we could also just allocate the stuff asked
4633 * for in this bmap call but that wouldn't be as good.
4634 */
4635 if (bma->wasdel) {
4636 alen = (xfs_extlen_t)bma->gotp->br_blockcount;
4637 aoff = bma->gotp->br_startoff;
4638 if (*lastx != NULLEXTNUM && *lastx) {
4639 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx - 1),
4640 bma->prevp);
4641 }
4642 } else {
4643 alen = (xfs_extlen_t)XFS_FILBLKS_MIN(bma->alen, MAXEXTLEN);
4644 if (!bma->eof)
4645 alen = (xfs_extlen_t)XFS_FILBLKS_MIN(alen,
4646 bma->gotp->br_startoff - bma->off);
4647 aoff = bma->off;
4648 }
4649
4650 /*
4651 * Indicate if this is the first user data in the file, or just any
4652 * user data.
4653 */
4654 if (!(flags & XFS_BMAPI_METADATA)) {
4655 bma->userdata = (aoff == 0) ?
4656 XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
4657 }
4658
4659 /*
4660 * Fill in changeable bma fields.
4661 */
4662 bma->alen = alen;
4663 bma->off = aoff;
4664 bma->firstblock = *firstblock;
4665 bma->minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4666 bma->low = flist->xbf_low;
4667 bma->aeof = 0;
4668
4669 /*
4670 * Only want to do the alignment at the eof if it is userdata and
4671 * allocation length is larger than a stripe unit.
4672 */
4673 if (mp->m_dalign && alen >= mp->m_dalign &&
4674 !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
4675 error = xfs_bmap_isaeof(bma->ip, aoff, whichfork, &bma->aeof);
4676 if (error)
4677 return error;
4678 }
4679
4680 error = xfs_bmap_alloc(bma);
4681 if (error)
4682 return error;
4683
4684 /*
4685 * Copy out result fields.
4686 */
4687 abno = bma->rval;
4688 flist->xbf_low = bma->low;
4689 alen = bma->alen;
4690 aoff = bma->off;
4691 ASSERT(*firstblock == NULLFSBLOCK ||
4692 XFS_FSB_TO_AGNO(mp, *firstblock) ==
4693 XFS_FSB_TO_AGNO(mp, bma->firstblock) ||
4694 (flist->xbf_low &&
4695 XFS_FSB_TO_AGNO(mp, *firstblock) <
4696 XFS_FSB_TO_AGNO(mp, bma->firstblock)));
4697 *firstblock = bma->firstblock;
4698 if (*cur)
4699 (*cur)->bc_private.b.firstblock = *firstblock;
4700 if (abno == NULLFSBLOCK)
4701 return 0;
4702 if ((ifp->if_flags & XFS_IFBROOT) && !*cur) {
4703 (*cur) = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork);
4704 (*cur)->bc_private.b.firstblock = *firstblock;
4705 (*cur)->bc_private.b.flist = flist;
4706 }
4707 /*
4708 * Bump the number of extents we've allocated
4709 * in this call.
4710 */
4711 (*nallocs)++;
4712
4713 if (*cur)
4714 (*cur)->bc_private.b.flags =
4715 bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
4716
4717 bma->gotp->br_startoff = aoff;
4718 bma->gotp->br_startblock = abno;
4719 bma->gotp->br_blockcount = alen;
4720 bma->gotp->br_state = XFS_EXT_NORM;
4721
4722 /*
4723 * A wasdelay extent has been initialized, so shouldn't be flagged
4724 * as unwritten.
4725 */
4726 if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) &&
4727 xfs_sb_version_hasextflgbit(&mp->m_sb))
4728 bma->gotp->br_state = XFS_EXT_UNWRITTEN;
4729
4730 error = xfs_bmap_add_extent(bma->tp, bma->ip, lastx, cur, bma->gotp,
4731 firstblock, flist, logflags, whichfork);
4732 if (error)
4733 return error;
4734
4735 /*
4736 * Update our extent pointer, given that xfs_bmap_add_extent might
4737 * have merged it into one of the neighbouring ones.
4738 */
4739 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), bma->gotp);
4740
4741 ASSERT(bma->gotp->br_startoff <= aoff);
4742 ASSERT(bma->gotp->br_startoff + bma->gotp->br_blockcount >=
4743 aoff + alen);
4744 ASSERT(bma->gotp->br_state == XFS_EXT_NORM ||
4745 bma->gotp->br_state == XFS_EXT_UNWRITTEN);
4746 return 0;
4747}
4748
4608/* 4749/*
4609 * Map file blocks to filesystem blocks. 4750 * Map file blocks to filesystem blocks.
4610 * File range is given by the bno/len pair. 4751 * File range is given by the bno/len pair.
@@ -4632,9 +4773,6 @@ xfs_bmapi(
4632 int *nmap, /* i/o: mval size/count */ 4773 int *nmap, /* i/o: mval size/count */
4633 xfs_bmap_free_t *flist) /* i/o: list extents to free */ 4774 xfs_bmap_free_t *flist) /* i/o: list extents to free */
4634{ 4775{
4635 xfs_fsblock_t abno; /* allocated block number */
4636 xfs_extlen_t alen; /* allocated extent length */
4637 xfs_fileoff_t aoff; /* allocated file offset */
4638 xfs_bmalloca_t bma = { 0 }; /* args for xfs_bmap_alloc */ 4776 xfs_bmalloca_t bma = { 0 }; /* args for xfs_bmap_alloc */
4639 xfs_btree_cur_t *cur; /* bmap btree cursor */ 4777 xfs_btree_cur_t *cur; /* bmap btree cursor */
4640 xfs_fileoff_t end; /* end of mapped file region */ 4778 xfs_fileoff_t end; /* end of mapped file region */
@@ -4646,7 +4784,6 @@ xfs_bmapi(
4646 xfs_extnum_t lastx; /* last useful extent number */ 4784 xfs_extnum_t lastx; /* last useful extent number */
4647 int logflags; /* flags for transaction logging */ 4785 int logflags; /* flags for transaction logging */
4648 xfs_extlen_t minleft; /* min blocks left after allocation */ 4786 xfs_extlen_t minleft; /* min blocks left after allocation */
4649 xfs_extlen_t minlen; /* min allocation size */
4650 xfs_mount_t *mp; /* xfs mount structure */ 4787 xfs_mount_t *mp; /* xfs mount structure */
4651 int n; /* current extent index */ 4788 int n; /* current extent index */
4652 int nallocs; /* number of extents alloc'd */ 4789 int nallocs; /* number of extents alloc'd */
@@ -4737,7 +4874,13 @@ xfs_bmapi(
4737 n = 0; 4874 n = 0;
4738 end = bno + len; 4875 end = bno + len;
4739 obno = bno; 4876 obno = bno;
4740 bma.ip = NULL; 4877
4878 bma.tp = tp;
4879 bma.ip = ip;
4880 bma.prevp = &prev;
4881 bma.gotp = &got;
4882 bma.total = total;
4883 bma.userdata = 0;
4741 4884
4742 while (bno < end && n < *nmap) { 4885 while (bno < end && n < *nmap) {
4743 /* 4886 /*
@@ -4753,144 +4896,23 @@ xfs_bmapi(
4753 * that we found, if any. 4896 * that we found, if any.
4754 */ 4897 */
4755 if (wr && (inhole || wasdelay)) { 4898 if (wr && (inhole || wasdelay)) {
4756 /* 4899 bma.eof = eof;
4757 * For the wasdelay case, we could also just 4900 bma.conv = !!(flags & XFS_BMAPI_CONVERT);
4758 * allocate the stuff asked for in this bmap call 4901 bma.wasdel = wasdelay;
4759 * but that wouldn't be as good. 4902 bma.alen = len;
4760 */ 4903 bma.off = bno;
4761 if (wasdelay) { 4904 bma.minleft = minleft;
4762 alen = (xfs_extlen_t)got.br_blockcount; 4905
4763 aoff = got.br_startoff; 4906 error = xfs_bmapi_allocate(&bma, &lastx, &cur,
4764 if (lastx != NULLEXTNUM && lastx) { 4907 firstblock, flist, flags, &nallocs,
4765 ep = xfs_iext_get_ext(ifp, lastx - 1); 4908 &tmp_logflags);
4766 xfs_bmbt_get_all(ep, &prev);
4767 }
4768 } else {
4769 alen = (xfs_extlen_t)
4770 XFS_FILBLKS_MIN(len, MAXEXTLEN);
4771 if (!eof)
4772 alen = (xfs_extlen_t)
4773 XFS_FILBLKS_MIN(alen,
4774 got.br_startoff - bno);
4775 aoff = bno;
4776 }
4777 minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4778 {
4779 /*
4780 * If first time, allocate and fill in
4781 * once-only bma fields.
4782 */
4783 if (bma.ip == NULL) {
4784 bma.tp = tp;
4785 bma.ip = ip;
4786 bma.prevp = &prev;
4787 bma.gotp = &got;
4788 bma.total = total;
4789 bma.userdata = 0;
4790 }
4791 /* Indicate if this is the first user data
4792 * in the file, or just any user data.
4793 */
4794 if (!(flags & XFS_BMAPI_METADATA)) {
4795 bma.userdata = (aoff == 0) ?
4796 XFS_ALLOC_INITIAL_USER_DATA :
4797 XFS_ALLOC_USERDATA;
4798 }
4799 /*
4800 * Fill in changeable bma fields.
4801 */
4802 bma.eof = eof;
4803 bma.firstblock = *firstblock;
4804 bma.alen = alen;
4805 bma.off = aoff;
4806 bma.conv = !!(flags & XFS_BMAPI_CONVERT);
4807 bma.wasdel = wasdelay;
4808 bma.minlen = minlen;
4809 bma.low = flist->xbf_low;
4810 bma.minleft = minleft;
4811 /*
4812 * Only want to do the alignment at the
4813 * eof if it is userdata and allocation length
4814 * is larger than a stripe unit.
4815 */
4816 if (mp->m_dalign && alen >= mp->m_dalign &&
4817 (!(flags & XFS_BMAPI_METADATA)) &&
4818 (whichfork == XFS_DATA_FORK)) {
4819 if ((error = xfs_bmap_isaeof(ip, aoff,
4820 whichfork, &bma.aeof)))
4821 goto error0;
4822 } else
4823 bma.aeof = 0;
4824 /*
4825 * Call allocator.
4826 */
4827 if ((error = xfs_bmap_alloc(&bma)))
4828 goto error0;
4829 /*
4830 * Copy out result fields.
4831 */
4832 abno = bma.rval;
4833 if ((flist->xbf_low = bma.low))
4834 minleft = 0;
4835 alen = bma.alen;
4836 aoff = bma.off;
4837 ASSERT(*firstblock == NULLFSBLOCK ||
4838 XFS_FSB_TO_AGNO(mp, *firstblock) ==
4839 XFS_FSB_TO_AGNO(mp, bma.firstblock) ||
4840 (flist->xbf_low &&
4841 XFS_FSB_TO_AGNO(mp, *firstblock) <
4842 XFS_FSB_TO_AGNO(mp, bma.firstblock)));
4843 *firstblock = bma.firstblock;
4844 if (cur)
4845 cur->bc_private.b.firstblock =
4846 *firstblock;
4847 if (abno == NULLFSBLOCK)
4848 break;
4849 if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
4850 cur = xfs_bmbt_init_cursor(mp, tp,
4851 ip, whichfork);
4852 cur->bc_private.b.firstblock =
4853 *firstblock;
4854 cur->bc_private.b.flist = flist;
4855 }
4856 /*
4857 * Bump the number of extents we've allocated
4858 * in this call.
4859 */
4860 nallocs++;
4861 }
4862 if (cur)
4863 cur->bc_private.b.flags =
4864 wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0;
4865 got.br_startoff = aoff;
4866 got.br_startblock = abno;
4867 got.br_blockcount = alen;
4868 got.br_state = XFS_EXT_NORM; /* assume normal */
4869 /*
4870 * Determine state of extent, and the filesystem.
4871 * A wasdelay extent has been initialized, so
4872 * shouldn't be flagged as unwritten.
4873 */
4874 if (wr && xfs_sb_version_hasextflgbit(&mp->m_sb)) {
4875 if (!wasdelay && (flags & XFS_BMAPI_PREALLOC))
4876 got.br_state = XFS_EXT_UNWRITTEN;
4877 }
4878 error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &got,
4879 firstblock, flist, &tmp_logflags,
4880 whichfork);
4881 logflags |= tmp_logflags; 4909 logflags |= tmp_logflags;
4882 if (error) 4910 if (error)
4883 goto error0; 4911 goto error0;
4884 ep = xfs_iext_get_ext(ifp, lastx); 4912 if (flist && flist->xbf_low)
4885 xfs_bmbt_get_all(ep, &got); 4913 minleft = 0;
4886 ASSERT(got.br_startoff <= aoff); 4914 if (bma.rval == NULLFSBLOCK)
4887 ASSERT(got.br_startoff + got.br_blockcount >= 4915 break;
4888 aoff + alen);
4889 ASSERT(got.br_state == XFS_EXT_NORM ||
4890 got.br_state == XFS_EXT_UNWRITTEN);
4891 /*
4892 * Fall down into the found allocated space case.
4893 */
4894 } else if (inhole) { 4916 } else if (inhole) {
4895 /* 4917 /*
4896 * Reading in a hole. 4918 * Reading in a hole.