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.c127
1 files changed, 78 insertions, 49 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index de3162418663..6f5d283888aa 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -301,6 +301,19 @@ xfs_bmap_search_extents(
301 xfs_bmbt_irec_t *gotp, /* out: extent entry found */ 301 xfs_bmbt_irec_t *gotp, /* out: extent entry found */
302 xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */ 302 xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */
303 303
304/*
305 * Check the last inode extent to determine whether this allocation will result
306 * in blocks being allocated at the end of the file. When we allocate new data
307 * blocks at the end of the file which do not start at the previous data block,
308 * we will try to align the new blocks at stripe unit boundaries.
309 */
310STATIC int /* error */
311xfs_bmap_isaeof(
312 xfs_inode_t *ip, /* incore inode pointer */
313 xfs_fileoff_t off, /* file offset in fsblocks */
314 int whichfork, /* data or attribute fork */
315 char *aeof); /* return value */
316
304#ifdef XFS_BMAP_TRACE 317#ifdef XFS_BMAP_TRACE
305/* 318/*
306 * Add a bmap trace buffer entry. Base routine for the others. 319 * Add a bmap trace buffer entry. Base routine for the others.
@@ -4532,18 +4545,17 @@ xfs_bmapi(
4532 xfs_extlen_t alen; /* allocated extent length */ 4545 xfs_extlen_t alen; /* allocated extent length */
4533 xfs_fileoff_t aoff; /* allocated file offset */ 4546 xfs_fileoff_t aoff; /* allocated file offset */
4534 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */ 4547 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */
4535 char contig; /* allocation must be one extent */
4536 xfs_btree_cur_t *cur; /* bmap btree cursor */ 4548 xfs_btree_cur_t *cur; /* bmap btree cursor */
4537 char delay; /* this request is for delayed alloc */
4538 xfs_fileoff_t end; /* end of mapped file region */ 4549 xfs_fileoff_t end; /* end of mapped file region */
4539 int eof; /* we've hit the end of extent list */ 4550 int eof; /* we've hit the end of extent list */
4551 char contig; /* allocation must be one extent */
4552 char delay; /* this request is for delayed alloc */
4553 char exact; /* don't do all of wasdelayed extent */
4540 xfs_bmbt_rec_t *ep; /* extent list entry pointer */ 4554 xfs_bmbt_rec_t *ep; /* extent list entry pointer */
4541 int error; /* error return */ 4555 int error; /* error return */
4542 char exact; /* don't do all of wasdelayed extent */
4543 xfs_bmbt_irec_t got; /* current extent list record */ 4556 xfs_bmbt_irec_t got; /* current extent list record */
4544 xfs_ifork_t *ifp; /* inode fork pointer */ 4557 xfs_ifork_t *ifp; /* inode fork pointer */
4545 xfs_extlen_t indlen; /* indirect blocks length */ 4558 xfs_extlen_t indlen; /* indirect blocks length */
4546 char inhole; /* current location is hole in file */
4547 xfs_extnum_t lastx; /* last useful extent number */ 4559 xfs_extnum_t lastx; /* last useful extent number */
4548 int logflags; /* flags for transaction logging */ 4560 int logflags; /* flags for transaction logging */
4549 xfs_extlen_t minleft; /* min blocks left after allocation */ 4561 xfs_extlen_t minleft; /* min blocks left after allocation */
@@ -4554,13 +4566,15 @@ xfs_bmapi(
4554 xfs_extnum_t nextents; /* number of extents in file */ 4566 xfs_extnum_t nextents; /* number of extents in file */
4555 xfs_fileoff_t obno; /* old block number (offset) */ 4567 xfs_fileoff_t obno; /* old block number (offset) */
4556 xfs_bmbt_irec_t prev; /* previous extent list record */ 4568 xfs_bmbt_irec_t prev; /* previous extent list record */
4557 char stateless; /* ignore state flag set */
4558 int tmp_logflags; /* temp flags holder */ 4569 int tmp_logflags; /* temp flags holder */
4570 int whichfork; /* data or attr fork */
4571 char inhole; /* current location is hole in file */
4572 char stateless; /* ignore state flag set */
4559 char trim; /* output trimmed to match range */ 4573 char trim; /* output trimmed to match range */
4560 char userdata; /* allocating non-metadata */ 4574 char userdata; /* allocating non-metadata */
4561 char wasdelay; /* old extent was delayed */ 4575 char wasdelay; /* old extent was delayed */
4562 int whichfork; /* data or attr fork */
4563 char wr; /* this is a write request */ 4576 char wr; /* this is a write request */
4577 char rt; /* this is a realtime file */
4564 char rsvd; /* OK to allocate reserved blocks */ 4578 char rsvd; /* OK to allocate reserved blocks */
4565#ifdef DEBUG 4579#ifdef DEBUG
4566 xfs_fileoff_t orig_bno; /* original block number value */ 4580 xfs_fileoff_t orig_bno; /* original block number value */
@@ -4590,6 +4604,7 @@ xfs_bmapi(
4590 } 4604 }
4591 if (XFS_FORCED_SHUTDOWN(mp)) 4605 if (XFS_FORCED_SHUTDOWN(mp))
4592 return XFS_ERROR(EIO); 4606 return XFS_ERROR(EIO);
4607 rt = XFS_IS_REALTIME_INODE(ip);
4593 ifp = XFS_IFORK_PTR(ip, whichfork); 4608 ifp = XFS_IFORK_PTR(ip, whichfork);
4594 ASSERT(ifp->if_ext_max == 4609 ASSERT(ifp->if_ext_max ==
4595 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); 4610 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4694,9 +4709,16 @@ xfs_bmapi(
4694 } 4709 }
4695 minlen = contig ? alen : 1; 4710 minlen = contig ? alen : 1;
4696 if (delay) { 4711 if (delay) {
4697 indlen = (xfs_extlen_t) 4712 xfs_extlen_t extsz = 0;
4698 xfs_bmap_worst_indlen(ip, alen); 4713
4699 ASSERT(indlen > 0); 4714 /* Figure out the extent size, adjust alen */
4715 if (rt) {
4716 if (!(extsz = ip->i_d.di_extsize))
4717 extsz = mp->m_sb.sb_rextsize;
4718 alen = roundup(alen, extsz);
4719 extsz = alen / mp->m_sb.sb_rextsize;
4720 }
4721
4700 /* 4722 /*
4701 * Make a transaction-less quota reservation for 4723 * Make a transaction-less quota reservation for
4702 * delayed allocation blocks. This number gets 4724 * delayed allocation blocks. This number gets
@@ -4704,8 +4726,10 @@ xfs_bmapi(
4704 * We return EDQUOT if we haven't allocated 4726 * We return EDQUOT if we haven't allocated
4705 * blks already inside this loop; 4727 * blks already inside this loop;
4706 */ 4728 */
4707 if (XFS_TRANS_RESERVE_BLKQUOTA( 4729 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
4708 mp, NULL, ip, (long)alen)) { 4730 mp, NULL, ip, (long)alen, 0,
4731 rt ? XFS_QMOPT_RES_RTBLKS :
4732 XFS_QMOPT_RES_REGBLKS)) {
4709 if (n == 0) { 4733 if (n == 0) {
4710 *nmap = 0; 4734 *nmap = 0;
4711 ASSERT(cur == NULL); 4735 ASSERT(cur == NULL);
@@ -4718,40 +4742,34 @@ xfs_bmapi(
4718 * Split changing sb for alen and indlen since 4742 * Split changing sb for alen and indlen since
4719 * they could be coming from different places. 4743 * they could be coming from different places.
4720 */ 4744 */
4721 if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) { 4745 indlen = (xfs_extlen_t)
4722 xfs_extlen_t extsz; 4746 xfs_bmap_worst_indlen(ip, alen);
4723 xfs_extlen_t ralen; 4747 ASSERT(indlen > 0);
4724 if (!(extsz = ip->i_d.di_extsize))
4725 extsz = mp->m_sb.sb_rextsize;
4726 ralen = roundup(alen, extsz);
4727 ralen = ralen / mp->m_sb.sb_rextsize;
4728 if (xfs_mod_incore_sb(mp,
4729 XFS_SBS_FREXTENTS,
4730 -(ralen), rsvd)) {
4731 if (XFS_IS_QUOTA_ON(ip->i_mount))
4732 XFS_TRANS_UNRESERVE_BLKQUOTA(
4733 mp, NULL, ip,
4734 (long)alen);
4735 break;
4736 }
4737 } else {
4738 if (xfs_mod_incore_sb(mp,
4739 XFS_SBS_FDBLOCKS,
4740 -(alen), rsvd)) {
4741 if (XFS_IS_QUOTA_ON(ip->i_mount))
4742 XFS_TRANS_UNRESERVE_BLKQUOTA(
4743 mp, NULL, ip,
4744 (long)alen);
4745 break;
4746 }
4747 }
4748 4748
4749 if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, 4749 if (rt)
4750 -(indlen), rsvd)) { 4750 error = xfs_mod_incore_sb(mp,
4751 XFS_TRANS_UNRESERVE_BLKQUOTA( 4751 XFS_SBS_FREXTENTS,
4752 mp, NULL, ip, (long)alen); 4752 -(extsz), rsvd);
4753 else
4754 error = xfs_mod_incore_sb(mp,
4755 XFS_SBS_FDBLOCKS,
4756 -(alen), rsvd);
4757 if (!error)
4758 error = xfs_mod_incore_sb(mp,
4759 XFS_SBS_FDBLOCKS,
4760 -(indlen), rsvd);
4761
4762 if (error) {
4763 if (XFS_IS_QUOTA_ON(ip->i_mount))
4764 /* unreserve the blocks now */
4765 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
4766 mp, NULL, ip,
4767 (long)alen, 0, rt ?
4768 XFS_QMOPT_RES_RTBLKS :
4769 XFS_QMOPT_RES_REGBLKS);
4753 break; 4770 break;
4754 } 4771 }
4772
4755 ip->i_delayed_blks += alen; 4773 ip->i_delayed_blks += alen;
4756 abno = NULLSTARTBLOCK(indlen); 4774 abno = NULLSTARTBLOCK(indlen);
4757 } else { 4775 } else {
@@ -5376,13 +5394,24 @@ xfs_bunmapi(
5376 } 5394 }
5377 if (wasdel) { 5395 if (wasdel) {
5378 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); 5396 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
5379 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, 5397 /* Update realtim/data freespace, unreserve quota */
5380 (int)del.br_blockcount, rsvd); 5398 if (isrt) {
5381 /* Unreserve our quota space */ 5399 xfs_filblks_t rtexts;
5382 XFS_TRANS_RESERVE_QUOTA_NBLKS( 5400
5383 mp, NULL, ip, -((long)del.br_blockcount), 0, 5401 rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5384 isrt ? XFS_QMOPT_RES_RTBLKS : 5402 do_div(rtexts, mp->m_sb.sb_rextsize);
5403 xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
5404 (int)rtexts, rsvd);
5405 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
5406 -((long)del.br_blockcount), 0,
5407 XFS_QMOPT_RES_RTBLKS);
5408 } else {
5409 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
5410 (int)del.br_blockcount, rsvd);
5411 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
5412 -((long)del.br_blockcount), 0,
5385 XFS_QMOPT_RES_REGBLKS); 5413 XFS_QMOPT_RES_REGBLKS);
5414 }
5386 ip->i_delayed_blks -= del.br_blockcount; 5415 ip->i_delayed_blks -= del.br_blockcount;
5387 if (cur) 5416 if (cur)
5388 cur->bc_private.b.flags |= 5417 cur->bc_private.b.flags |=
@@ -5714,7 +5743,7 @@ unlock_and_return:
5714 * blocks at the end of the file which do not start at the previous data block, 5743 * blocks at the end of the file which do not start at the previous data block,
5715 * we will try to align the new blocks at stripe unit boundaries. 5744 * we will try to align the new blocks at stripe unit boundaries.
5716 */ 5745 */
5717int /* error */ 5746STATIC int /* error */
5718xfs_bmap_isaeof( 5747xfs_bmap_isaeof(
5719 xfs_inode_t *ip, /* incore inode pointer */ 5748 xfs_inode_t *ip, /* incore inode pointer */
5720 xfs_fileoff_t off, /* file offset in fsblocks */ 5749 xfs_fileoff_t off, /* file offset in fsblocks */