aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-09-18 16:40:47 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:04 -0400
commitb64dfe4e180ab5047c59bcbe379538eb23be4d8e (patch)
tree1c159801e7c7c0f947c0edd572e8ec26baf42ada /fs/xfs
parent5b777ad517ee75d3bb8d67c142d808822e46601b (diff)
xfs: factor delalloc reservations out of xfs_bmapi
Move the reservation of delayed allocations, and addition of delalloc regions to the extent trees into a new helper function. For now this adds some twisted goto logic to xfs_bmapi, but that will be cleaned up in the following patches. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_bmap.c202
1 files changed, 118 insertions, 84 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index fd06bf17d09..cd01783a89d 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4441,6 +4441,120 @@ xfs_bmapi_read(
4441 return 0; 4441 return 0;
4442} 4442}
4443 4443
4444STATIC int
4445xfs_bmapi_reserve_delalloc(
4446 struct xfs_inode *ip,
4447 xfs_fileoff_t aoff,
4448 xfs_filblks_t len,
4449 struct xfs_bmbt_irec *got,
4450 struct xfs_bmbt_irec *prev,
4451 xfs_extnum_t *lastx,
4452 int eof)
4453{
4454 struct xfs_mount *mp = ip->i_mount;
4455 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
4456 xfs_extlen_t alen;
4457 xfs_extlen_t indlen;
4458 xfs_fsblock_t firstblock = NULLFSBLOCK;
4459 struct xfs_btree_cur *cur = NULL;
4460 int tmp_logflags = 0;
4461 char rt = XFS_IS_REALTIME_INODE(ip);
4462 xfs_extlen_t extsz;
4463 int error;
4464
4465 alen = XFS_FILBLKS_MIN(len, MAXEXTLEN);
4466 if (!eof)
4467 alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff);
4468
4469 /* Figure out the extent size, adjust alen */
4470 extsz = xfs_get_extsz_hint(ip);
4471 if (extsz) {
4472 /*
4473 * Make sure we don't exceed a single extent length when we
4474 * align the extent by reducing length we are going to
4475 * allocate by the maximum amount extent size aligment may
4476 * require.
4477 */
4478 alen = XFS_FILBLKS_MIN(len, MAXEXTLEN - (2 * extsz - 1));
4479 error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof,
4480 1, 0, &aoff, &alen);
4481 ASSERT(!error);
4482 }
4483
4484 if (rt)
4485 extsz = alen / mp->m_sb.sb_rextsize;
4486
4487 /*
4488 * Make a transaction-less quota reservation for delayed allocation
4489 * blocks. This number gets adjusted later. We return if we haven't
4490 * allocated blocks already inside this loop.
4491 */
4492 error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0,
4493 rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
4494 if (error)
4495 return error;
4496
4497 /*
4498 * Split changing sb for alen and indlen since they could be coming
4499 * from different places.
4500 */
4501 indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen);
4502 ASSERT(indlen > 0);
4503
4504 if (rt) {
4505 error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
4506 -((int64_t)extsz), 0);
4507 } else {
4508 error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
4509 -((int64_t)alen), 0);
4510 }
4511
4512 if (error)
4513 goto out_unreserve_quota;
4514
4515 error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS,
4516 -((int64_t)indlen), 0);
4517 if (error)
4518 goto out_unreserve_blocks;
4519
4520
4521 ip->i_delayed_blks += alen;
4522
4523 got->br_startoff = aoff;
4524 got->br_startblock = nullstartblock(indlen);
4525 got->br_blockcount = alen;
4526 got->br_state = XFS_EXT_NORM;
4527
4528 error = xfs_bmap_add_extent(NULL, ip, lastx, &cur, got, &firstblock,
4529 NULL, &tmp_logflags, XFS_DATA_FORK);
4530 ASSERT(!error);
4531 ASSERT(!tmp_logflags);
4532 ASSERT(!cur);
4533
4534 /*
4535 * Update our extent pointer, given that xfs_bmap_add_extent might
4536 * have merged it into one of the neighbouring ones.
4537 */
4538 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got);
4539
4540 ASSERT(got->br_startoff <= aoff);
4541 ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen);
4542 ASSERT(isnullstartblock(got->br_startblock));
4543 ASSERT(got->br_state == XFS_EXT_NORM);
4544 return 0;
4545
4546out_unreserve_blocks:
4547 if (rt)
4548 xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0);
4549 else
4550 xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0);
4551out_unreserve_quota:
4552 if (XFS_IS_QUOTA_ON(mp))
4553 xfs_trans_unreserve_quota_nblks(NULL, ip, alen, 0, rt ?
4554 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
4555 return error;
4556}
4557
4444/* 4558/*
4445 * Map file blocks to filesystem blocks. 4559 * Map file blocks to filesystem blocks.
4446 * File range is given by the bno/len pair. 4560 * File range is given by the bno/len pair.
@@ -4479,7 +4593,6 @@ xfs_bmapi(
4479 int error; /* error return */ 4593 int error; /* error return */
4480 xfs_bmbt_irec_t got; /* current file extent record */ 4594 xfs_bmbt_irec_t got; /* current file extent record */
4481 xfs_ifork_t *ifp; /* inode fork pointer */ 4595 xfs_ifork_t *ifp; /* inode fork pointer */
4482 xfs_extlen_t indlen; /* indirect blocks length */
4483 xfs_extnum_t lastx; /* last useful extent number */ 4596 xfs_extnum_t lastx; /* last useful extent number */
4484 int logflags; /* flags for transaction logging */ 4597 int logflags; /* flags for transaction logging */
4485 xfs_extlen_t minleft; /* min blocks left after allocation */ 4598 xfs_extlen_t minleft; /* min blocks left after allocation */
@@ -4615,43 +4728,8 @@ xfs_bmapi(
4615 } 4728 }
4616 minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1; 4729 minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1;
4617 if (flags & XFS_BMAPI_DELAY) { 4730 if (flags & XFS_BMAPI_DELAY) {
4618 xfs_extlen_t extsz; 4731 error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got,
4619 4732 &prev, &lastx, eof);
4620 /* Figure out the extent size, adjust alen */
4621 extsz = xfs_get_extsz_hint(ip);
4622 if (extsz) {
4623 /*
4624 * make sure we don't exceed a single
4625 * extent length when we align the
4626 * extent by reducing length we are
4627 * going to allocate by the maximum
4628 * amount extent size aligment may
4629 * require.
4630 */
4631 alen = XFS_FILBLKS_MIN(len,
4632 MAXEXTLEN - (2 * extsz - 1));
4633 error = xfs_bmap_extsize_align(mp,
4634 &got, &prev, extsz,
4635 rt, eof,
4636 flags&XFS_BMAPI_DELAY,
4637 flags&XFS_BMAPI_CONVERT,
4638 &aoff, &alen);
4639 ASSERT(!error);
4640 }
4641
4642 if (rt)
4643 extsz = alen / mp->m_sb.sb_rextsize;
4644
4645 /*
4646 * Make a transaction-less quota reservation for
4647 * delayed allocation blocks. This number gets
4648 * adjusted later. We return if we haven't
4649 * allocated blocks already inside this loop.
4650 */
4651 error = xfs_trans_reserve_quota_nblks(
4652 NULL, ip, (long)alen, 0,
4653 rt ? XFS_QMOPT_RES_RTBLKS :
4654 XFS_QMOPT_RES_REGBLKS);
4655 if (error) { 4733 if (error) {
4656 if (n == 0) { 4734 if (n == 0) {
4657 *nmap = 0; 4735 *nmap = 0;
@@ -4661,51 +4739,7 @@ xfs_bmapi(
4661 break; 4739 break;
4662 } 4740 }
4663 4741
4664 /* 4742 goto trim_extent;
4665 * Split changing sb for alen and indlen since
4666 * they could be coming from different places.
4667 */
4668 indlen = (xfs_extlen_t)
4669 xfs_bmap_worst_indlen(ip, alen);
4670 ASSERT(indlen > 0);
4671
4672 if (rt) {
4673 error = xfs_mod_incore_sb(mp,
4674 XFS_SBS_FREXTENTS,
4675 -((int64_t)extsz), 0);
4676 } else {
4677 error = xfs_icsb_modify_counters(mp,
4678 XFS_SBS_FDBLOCKS,
4679 -((int64_t)alen), 0);
4680 }
4681 if (!error) {
4682 error = xfs_icsb_modify_counters(mp,
4683 XFS_SBS_FDBLOCKS,
4684 -((int64_t)indlen), 0);
4685 if (error && rt)
4686 xfs_mod_incore_sb(mp,
4687 XFS_SBS_FREXTENTS,
4688 (int64_t)extsz, 0);
4689 else if (error)
4690 xfs_icsb_modify_counters(mp,
4691 XFS_SBS_FDBLOCKS,
4692 (int64_t)alen, 0);
4693 }
4694
4695 if (error) {
4696 if (XFS_IS_QUOTA_ON(mp))
4697 /* unreserve the blocks now */
4698 (void)
4699 xfs_trans_unreserve_quota_nblks(
4700 NULL, ip,
4701 (long)alen, 0, rt ?
4702 XFS_QMOPT_RES_RTBLKS :
4703 XFS_QMOPT_RES_REGBLKS);
4704 break;
4705 }
4706
4707 ip->i_delayed_blks += alen;
4708 abno = nullstartblock(indlen);
4709 } else { 4743 } else {
4710 /* 4744 /*
4711 * If first time, allocate and fill in 4745 * If first time, allocate and fill in
@@ -4843,7 +4877,7 @@ xfs_bmapi(
4843 n++; 4877 n++;
4844 continue; 4878 continue;
4845 } 4879 }
4846 4880trim_extent:
4847 /* Deal with the allocated space we found. */ 4881 /* Deal with the allocated space we found. */
4848 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); 4882 xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags);
4849 4883