diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 127 |
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 | */ | ||
310 | STATIC int /* error */ | ||
311 | xfs_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 | */ |
5717 | int /* error */ | 5746 | STATIC int /* error */ |
5718 | xfs_bmap_isaeof( | 5747 | xfs_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 */ |