aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/quota/xfs_qm.c34
-rw-r--r--fs/xfs/quota/xfs_qm.h6
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h1
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c50
-rw-r--r--fs/xfs/xfs_bmap.c112
-rw-r--r--fs/xfs/xfs_iomap.c65
-rw-r--r--fs/xfs/xfs_quota.h11
-rw-r--r--fs/xfs/xfs_vnodeops.c5
8 files changed, 143 insertions, 141 deletions
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 3ea75972767c..3254cb7b87f4 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -1251,6 +1251,10 @@ xfs_qm_init_quotainfo(
1251 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ? 1251 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
1252 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) : 1252 INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
1253 XFS_QM_IWARNLIMIT; 1253 XFS_QM_IWARNLIMIT;
1254 qinf->qi_rtbwarnlimit =
1255 INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) ?
1256 INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) :
1257 XFS_QM_RTBWARNLIMIT;
1254 qinf->qi_bhardlimit = 1258 qinf->qi_bhardlimit =
1255 INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT); 1259 INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
1256 qinf->qi_bsoftlimit = 1260 qinf->qi_bsoftlimit =
@@ -1276,6 +1280,7 @@ xfs_qm_init_quotainfo(
1276 qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT; 1280 qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT;
1277 qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT; 1281 qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT;
1278 qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT; 1282 qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT;
1283 qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
1279 } 1284 }
1280 1285
1281 return (0); 1286 return (0);
@@ -2624,6 +2629,9 @@ xfs_qm_vop_chown(
2624 xfs_dquot_t *newdq) 2629 xfs_dquot_t *newdq)
2625{ 2630{
2626 xfs_dquot_t *prevdq; 2631 xfs_dquot_t *prevdq;
2632 uint bfield = XFS_IS_REALTIME_INODE(ip) ?
2633 XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
2634
2627 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 2635 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
2628 ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); 2636 ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
2629 2637
@@ -2632,20 +2640,12 @@ xfs_qm_vop_chown(
2632 ASSERT(prevdq); 2640 ASSERT(prevdq);
2633 ASSERT(prevdq != newdq); 2641 ASSERT(prevdq != newdq);
2634 2642
2635 xfs_trans_mod_dquot(tp, prevdq, 2643 xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
2636 XFS_TRANS_DQ_BCOUNT, 2644 xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
2637 -(ip->i_d.di_nblocks));
2638 xfs_trans_mod_dquot(tp, prevdq,
2639 XFS_TRANS_DQ_ICOUNT,
2640 -1);
2641 2645
2642 /* the sparkling new dquot */ 2646 /* the sparkling new dquot */
2643 xfs_trans_mod_dquot(tp, newdq, 2647 xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
2644 XFS_TRANS_DQ_BCOUNT, 2648 xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
2645 ip->i_d.di_nblocks);
2646 xfs_trans_mod_dquot(tp, newdq,
2647 XFS_TRANS_DQ_ICOUNT,
2648 1);
2649 2649
2650 /* 2650 /*
2651 * Take an extra reference, because the inode 2651 * Take an extra reference, because the inode
@@ -2673,7 +2673,7 @@ xfs_qm_vop_chown_reserve(
2673{ 2673{
2674 int error; 2674 int error;
2675 xfs_mount_t *mp; 2675 xfs_mount_t *mp;
2676 uint delblks; 2676 uint delblks, blkflags;
2677 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; 2677 xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
2678 2678
2679 ASSERT(XFS_ISLOCKED_INODE(ip)); 2679 ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2682,6 +2682,8 @@ xfs_qm_vop_chown_reserve(
2682 2682
2683 delblks = ip->i_delayed_blks; 2683 delblks = ip->i_delayed_blks;
2684 delblksudq = delblksgdq = unresudq = unresgdq = NULL; 2684 delblksudq = delblksgdq = unresudq = unresgdq = NULL;
2685 blkflags = XFS_IS_REALTIME_INODE(ip) ?
2686 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
2685 2687
2686 if (XFS_IS_UQUOTA_ON(mp) && udqp && 2688 if (XFS_IS_UQUOTA_ON(mp) && udqp &&
2687 ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) { 2689 ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) {
@@ -2711,7 +2713,7 @@ xfs_qm_vop_chown_reserve(
2711 2713
2712 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 2714 if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
2713 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, 2715 delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
2714 flags | XFS_QMOPT_RES_REGBLKS))) 2716 flags | blkflags)))
2715 return (error); 2717 return (error);
2716 2718
2717 /* 2719 /*
@@ -2728,11 +2730,11 @@ xfs_qm_vop_chown_reserve(
2728 ASSERT(unresudq || unresgdq); 2730 ASSERT(unresudq || unresgdq);
2729 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2731 if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
2730 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, 2732 delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
2731 flags | XFS_QMOPT_RES_REGBLKS))) 2733 flags | blkflags)))
2732 return (error); 2734 return (error);
2733 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2735 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
2734 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, 2736 unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
2735 XFS_QMOPT_RES_REGBLKS); 2737 blkflags);
2736 } 2738 }
2737 2739
2738 return (0); 2740 return (0);
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index 781968779540..b03eecf3b6cb 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -133,8 +133,9 @@ typedef struct xfs_quotainfo {
133 time_t qi_btimelimit; /* limit for blks timer */ 133 time_t qi_btimelimit; /* limit for blks timer */
134 time_t qi_itimelimit; /* limit for inodes timer */ 134 time_t qi_itimelimit; /* limit for inodes timer */
135 time_t qi_rtbtimelimit;/* limit for rt blks timer */ 135 time_t qi_rtbtimelimit;/* limit for rt blks timer */
136 xfs_qwarncnt_t qi_bwarnlimit; /* limit for num warnings */ 136 xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
137 xfs_qwarncnt_t qi_iwarnlimit; /* limit for num warnings */ 137 xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
138 xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
138 mutex_t qi_quotaofflock;/* to serialize quotaoff */ 139 mutex_t qi_quotaofflock;/* to serialize quotaoff */
139 xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */ 140 xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
140 uint qi_dqperchunk; /* # ondisk dqs in above chunk */ 141 uint qi_dqperchunk; /* # ondisk dqs in above chunk */
@@ -176,6 +177,7 @@ typedef struct xfs_dquot_acct {
176 177
177#define XFS_QM_BWARNLIMIT 5 178#define XFS_QM_BWARNLIMIT 5
178#define XFS_QM_IWARNLIMIT 5 179#define XFS_QM_IWARNLIMIT 5
180#define XFS_QM_RTBWARNLIMIT 5
179 181
180#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD)) 182#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD))
181#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock)) 183#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock))
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 472afd3570c6..bf413e70ec07 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -56,6 +56,7 @@
56#define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit) 56#define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit)
57#define XFS_QI_ITIMELIMIT(mp) ((mp)->m_quotainfo->qi_itimelimit) 57#define XFS_QI_ITIMELIMIT(mp) ((mp)->m_quotainfo->qi_itimelimit)
58#define XFS_QI_BWARNLIMIT(mp) ((mp)->m_quotainfo->qi_bwarnlimit) 58#define XFS_QI_BWARNLIMIT(mp) ((mp)->m_quotainfo->qi_bwarnlimit)
59#define XFS_QI_RTBWARNLIMIT(mp) ((mp)->m_quotainfo->qi_rtbwarnlimit)
59#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit) 60#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
60#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) 61#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
61 62
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 565efb73c233..3b99daf8a640 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -497,7 +497,7 @@ xfs_trans_apply_dquot_deltas(
497 * Adjust the RT reservation. 497 * Adjust the RT reservation.
498 */ 498 */
499 if (qtrx->qt_rtblk_res != 0) { 499 if (qtrx->qt_rtblk_res != 0) {
500 if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) { 500 if (qtrx->qt_rtblk_res != qtrx->qt_rtblk_res_used) {
501 if (qtrx->qt_rtblk_res > 501 if (qtrx->qt_rtblk_res >
502 qtrx->qt_rtblk_res_used) 502 qtrx->qt_rtblk_res_used)
503 dqp->q_res_rtbcount -= (xfs_qcnt_t) 503 dqp->q_res_rtbcount -= (xfs_qcnt_t)
@@ -530,12 +530,6 @@ xfs_trans_apply_dquot_deltas(
530 (xfs_qcnt_t)qtrx->qt_icount_delta; 530 (xfs_qcnt_t)qtrx->qt_icount_delta;
531 } 531 }
532 532
533
534#ifdef QUOTADEBUG
535 if (qtrx->qt_rtblk_res != 0)
536 cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
537 (int) qtrx->qt_rtblk_res, dqp);
538#endif
539 ASSERT(dqp->q_res_bcount >= 533 ASSERT(dqp->q_res_bcount >=
540 INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT)); 534 INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
541 ASSERT(dqp->q_res_icount >= 535 ASSERT(dqp->q_res_icount >=
@@ -636,7 +630,10 @@ xfs_trans_dqresv(
636 int error; 630 int error;
637 xfs_qcnt_t hardlimit; 631 xfs_qcnt_t hardlimit;
638 xfs_qcnt_t softlimit; 632 xfs_qcnt_t softlimit;
639 time_t btimer; 633 time_t timer;
634 xfs_qwarncnt_t warns;
635 xfs_qwarncnt_t warnlimit;
636 xfs_qcnt_t count;
640 xfs_qcnt_t *resbcountp; 637 xfs_qcnt_t *resbcountp;
641 xfs_quotainfo_t *q = mp->m_quotainfo; 638 xfs_quotainfo_t *q = mp->m_quotainfo;
642 639
@@ -651,7 +648,9 @@ xfs_trans_dqresv(
651 softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT); 648 softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
652 if (!softlimit) 649 if (!softlimit)
653 softlimit = q->qi_bsoftlimit; 650 softlimit = q->qi_bsoftlimit;
654 btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT); 651 timer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
652 warns = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT);
653 warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);
655 resbcountp = &dqp->q_res_bcount; 654 resbcountp = &dqp->q_res_bcount;
656 } else { 655 } else {
657 ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS); 656 ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
@@ -661,7 +660,9 @@ xfs_trans_dqresv(
661 softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT); 660 softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
662 if (!softlimit) 661 if (!softlimit)
663 softlimit = q->qi_rtbsoftlimit; 662 softlimit = q->qi_rtbsoftlimit;
664 btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT); 663 timer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
664 warns = INT_GET(dqp->q_core.d_rtbwarns, ARCH_CONVERT);
665 warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);
665 resbcountp = &dqp->q_res_rtbcount; 666 resbcountp = &dqp->q_res_rtbcount;
666 } 667 }
667 error = 0; 668 error = 0;
@@ -691,37 +692,36 @@ xfs_trans_dqresv(
691 * If timer or warnings has expired, 692 * If timer or warnings has expired,
692 * return EDQUOT 693 * return EDQUOT
693 */ 694 */
694 if ((btimer != 0 && get_seconds() > btimer) || 695 if ((timer != 0 && get_seconds() > timer) ||
695 (dqp->q_core.d_bwarns && 696 (warns != 0 && warns >= warnlimit)) {
696 INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
697 XFS_QI_BWARNLIMIT(dqp->q_mount))) {
698 error = EDQUOT; 697 error = EDQUOT;
699 goto error_return; 698 goto error_return;
700 } 699 }
701 } 700 }
702 } 701 }
703 if (ninos > 0) { 702 if (ninos > 0) {
704 hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT); 703 count = INT_GET(dqp->q_core.d_icount, ARCH_CONVERT);
704 timer = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT);
705 warns = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT);
706 warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);
707 hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit,
708 ARCH_CONVERT);
705 if (!hardlimit) 709 if (!hardlimit)
706 hardlimit = q->qi_ihardlimit; 710 hardlimit = q->qi_ihardlimit;
707 softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT); 711 softlimit = INT_GET(dqp->q_core.d_ino_softlimit,
712 ARCH_CONVERT);
708 if (!softlimit) 713 if (!softlimit)
709 softlimit = q->qi_isoftlimit; 714 softlimit = q->qi_isoftlimit;
710 if (hardlimit > 0ULL && 715 if (hardlimit > 0ULL && count >= hardlimit) {
711 INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
712 error = EDQUOT; 716 error = EDQUOT;
713 goto error_return; 717 goto error_return;
714 } else if (softlimit > 0ULL && 718 } else if (softlimit > 0ULL && count >= softlimit) {
715 INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
716 /* 719 /*
717 * If timer or warnings has expired, 720 * If timer or warnings has expired,
718 * return EDQUOT 721 * return EDQUOT
719 */ 722 */
720 if ((dqp->q_core.d_itimer && 723 if ((timer != 0 && get_seconds() > timer) ||
721 get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) || 724 (warns != 0 && warns >= warnlimit)) {
722 (dqp->q_core.d_iwarns &&
723 INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
724 XFS_QI_IWARNLIMIT(dqp->q_mount))) {
725 error = EDQUOT; 725 error = EDQUOT;
726 goto error_return; 726 goto error_return;
727 } 727 }
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index f6f5ad35734c..6f5d283888aa 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4545,18 +4545,17 @@ xfs_bmapi(
4545 xfs_extlen_t alen; /* allocated extent length */ 4545 xfs_extlen_t alen; /* allocated extent length */
4546 xfs_fileoff_t aoff; /* allocated file offset */ 4546 xfs_fileoff_t aoff; /* allocated file offset */
4547 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */ 4547 xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */
4548 char contig; /* allocation must be one extent */
4549 xfs_btree_cur_t *cur; /* bmap btree cursor */ 4548 xfs_btree_cur_t *cur; /* bmap btree cursor */
4550 char delay; /* this request is for delayed alloc */
4551 xfs_fileoff_t end; /* end of mapped file region */ 4549 xfs_fileoff_t end; /* end of mapped file region */
4552 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 */
4553 xfs_bmbt_rec_t *ep; /* extent list entry pointer */ 4554 xfs_bmbt_rec_t *ep; /* extent list entry pointer */
4554 int error; /* error return */ 4555 int error; /* error return */
4555 char exact; /* don't do all of wasdelayed extent */
4556 xfs_bmbt_irec_t got; /* current extent list record */ 4556 xfs_bmbt_irec_t got; /* current extent list record */
4557 xfs_ifork_t *ifp; /* inode fork pointer */ 4557 xfs_ifork_t *ifp; /* inode fork pointer */
4558 xfs_extlen_t indlen; /* indirect blocks length */ 4558 xfs_extlen_t indlen; /* indirect blocks length */
4559 char inhole; /* current location is hole in file */
4560 xfs_extnum_t lastx; /* last useful extent number */ 4559 xfs_extnum_t lastx; /* last useful extent number */
4561 int logflags; /* flags for transaction logging */ 4560 int logflags; /* flags for transaction logging */
4562 xfs_extlen_t minleft; /* min blocks left after allocation */ 4561 xfs_extlen_t minleft; /* min blocks left after allocation */
@@ -4567,13 +4566,15 @@ xfs_bmapi(
4567 xfs_extnum_t nextents; /* number of extents in file */ 4566 xfs_extnum_t nextents; /* number of extents in file */
4568 xfs_fileoff_t obno; /* old block number (offset) */ 4567 xfs_fileoff_t obno; /* old block number (offset) */
4569 xfs_bmbt_irec_t prev; /* previous extent list record */ 4568 xfs_bmbt_irec_t prev; /* previous extent list record */
4570 char stateless; /* ignore state flag set */
4571 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 */
4572 char trim; /* output trimmed to match range */ 4573 char trim; /* output trimmed to match range */
4573 char userdata; /* allocating non-metadata */ 4574 char userdata; /* allocating non-metadata */
4574 char wasdelay; /* old extent was delayed */ 4575 char wasdelay; /* old extent was delayed */
4575 int whichfork; /* data or attr fork */
4576 char wr; /* this is a write request */ 4576 char wr; /* this is a write request */
4577 char rt; /* this is a realtime file */
4577 char rsvd; /* OK to allocate reserved blocks */ 4578 char rsvd; /* OK to allocate reserved blocks */
4578#ifdef DEBUG 4579#ifdef DEBUG
4579 xfs_fileoff_t orig_bno; /* original block number value */ 4580 xfs_fileoff_t orig_bno; /* original block number value */
@@ -4603,6 +4604,7 @@ xfs_bmapi(
4603 } 4604 }
4604 if (XFS_FORCED_SHUTDOWN(mp)) 4605 if (XFS_FORCED_SHUTDOWN(mp))
4605 return XFS_ERROR(EIO); 4606 return XFS_ERROR(EIO);
4607 rt = XFS_IS_REALTIME_INODE(ip);
4606 ifp = XFS_IFORK_PTR(ip, whichfork); 4608 ifp = XFS_IFORK_PTR(ip, whichfork);
4607 ASSERT(ifp->if_ext_max == 4609 ASSERT(ifp->if_ext_max ==
4608 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); 4610 XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4707,9 +4709,16 @@ xfs_bmapi(
4707 } 4709 }
4708 minlen = contig ? alen : 1; 4710 minlen = contig ? alen : 1;
4709 if (delay) { 4711 if (delay) {
4710 indlen = (xfs_extlen_t) 4712 xfs_extlen_t extsz = 0;
4711 xfs_bmap_worst_indlen(ip, alen); 4713
4712 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
4713 /* 4722 /*
4714 * Make a transaction-less quota reservation for 4723 * Make a transaction-less quota reservation for
4715 * delayed allocation blocks. This number gets 4724 * delayed allocation blocks. This number gets
@@ -4717,8 +4726,10 @@ xfs_bmapi(
4717 * We return EDQUOT if we haven't allocated 4726 * We return EDQUOT if we haven't allocated
4718 * blks already inside this loop; 4727 * blks already inside this loop;
4719 */ 4728 */
4720 if (XFS_TRANS_RESERVE_BLKQUOTA( 4729 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
4721 mp, NULL, ip, (long)alen)) { 4730 mp, NULL, ip, (long)alen, 0,
4731 rt ? XFS_QMOPT_RES_RTBLKS :
4732 XFS_QMOPT_RES_REGBLKS)) {
4722 if (n == 0) { 4733 if (n == 0) {
4723 *nmap = 0; 4734 *nmap = 0;
4724 ASSERT(cur == NULL); 4735 ASSERT(cur == NULL);
@@ -4731,40 +4742,34 @@ xfs_bmapi(
4731 * Split changing sb for alen and indlen since 4742 * Split changing sb for alen and indlen since
4732 * they could be coming from different places. 4743 * they could be coming from different places.
4733 */ 4744 */
4734 if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) { 4745 indlen = (xfs_extlen_t)
4735 xfs_extlen_t extsz; 4746 xfs_bmap_worst_indlen(ip, alen);
4736 xfs_extlen_t ralen; 4747 ASSERT(indlen > 0);
4737 if (!(extsz = ip->i_d.di_extsize))
4738 extsz = mp->m_sb.sb_rextsize;
4739 ralen = roundup(alen, extsz);
4740 ralen = ralen / mp->m_sb.sb_rextsize;
4741 if (xfs_mod_incore_sb(mp,
4742 XFS_SBS_FREXTENTS,
4743 -(ralen), rsvd)) {
4744 if (XFS_IS_QUOTA_ON(ip->i_mount))
4745 XFS_TRANS_UNRESERVE_BLKQUOTA(
4746 mp, NULL, ip,
4747 (long)alen);
4748 break;
4749 }
4750 } else {
4751 if (xfs_mod_incore_sb(mp,
4752 XFS_SBS_FDBLOCKS,
4753 -(alen), rsvd)) {
4754 if (XFS_IS_QUOTA_ON(ip->i_mount))
4755 XFS_TRANS_UNRESERVE_BLKQUOTA(
4756 mp, NULL, ip,
4757 (long)alen);
4758 break;
4759 }
4760 }
4761 4748
4762 if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, 4749 if (rt)
4763 -(indlen), rsvd)) { 4750 error = xfs_mod_incore_sb(mp,
4764 XFS_TRANS_UNRESERVE_BLKQUOTA( 4751 XFS_SBS_FREXTENTS,
4765 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);
4766 break; 4770 break;
4767 } 4771 }
4772
4768 ip->i_delayed_blks += alen; 4773 ip->i_delayed_blks += alen;
4769 abno = NULLSTARTBLOCK(indlen); 4774 abno = NULLSTARTBLOCK(indlen);
4770 } else { 4775 } else {
@@ -5389,13 +5394,24 @@ xfs_bunmapi(
5389 } 5394 }
5390 if (wasdel) { 5395 if (wasdel) {
5391 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0); 5396 ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
5392 xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, 5397 /* Update realtim/data freespace, unreserve quota */
5393 (int)del.br_blockcount, rsvd); 5398 if (isrt) {
5394 /* Unreserve our quota space */ 5399 xfs_filblks_t rtexts;
5395 XFS_TRANS_RESERVE_QUOTA_NBLKS( 5400
5396 mp, NULL, ip, -((long)del.br_blockcount), 0, 5401 rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
5397 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,
5398 XFS_QMOPT_RES_REGBLKS); 5413 XFS_QMOPT_RES_REGBLKS);
5414 }
5399 ip->i_delayed_blks -= del.br_blockcount; 5415 ip->i_delayed_blks -= del.br_blockcount;
5400 if (cur) 5416 if (cur)
5401 cur->bc_private.b.flags |= 5417 cur->bc_private.b.flags |=
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 469e1a7939d4..2edd6769e5d3 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -385,15 +385,15 @@ xfs_iomap_write_direct(
385 int nimaps, maps; 385 int nimaps, maps;
386 int error; 386 int error;
387 int bmapi_flag; 387 int bmapi_flag;
388 int quota_flag;
388 int rt; 389 int rt;
389 xfs_trans_t *tp; 390 xfs_trans_t *tp;
390 xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp; 391 xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
391 xfs_bmap_free_t free_list; 392 xfs_bmap_free_t free_list;
392 int aeof; 393 int aeof;
393 xfs_filblks_t datablocks; 394 xfs_filblks_t datablocks, qblocks, resblks;
394 int committed; 395 int committed;
395 int numrtextents; 396 int numrtextents;
396 uint resblks;
397 397
398 /* 398 /*
399 * Make sure that the dquots are there. This doesn't hold 399 * Make sure that the dquots are there. This doesn't hold
@@ -419,7 +419,6 @@ xfs_iomap_write_direct(
419 xfs_fileoff_t map_last_fsb; 419 xfs_fileoff_t map_last_fsb;
420 420
421 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff; 421 map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
422
423 if (map_last_fsb < last_fsb) { 422 if (map_last_fsb < last_fsb) {
424 last_fsb = map_last_fsb; 423 last_fsb = map_last_fsb;
425 count_fsb = last_fsb - offset_fsb; 424 count_fsb = last_fsb - offset_fsb;
@@ -428,56 +427,47 @@ xfs_iomap_write_direct(
428 } 427 }
429 428
430 /* 429 /*
431 * determine if reserving space on 430 * Determine if reserving space on the data or realtime partition.
432 * the data or realtime partition.
433 */ 431 */
434 if ((rt = XFS_IS_REALTIME_INODE(ip))) { 432 if ((rt = XFS_IS_REALTIME_INODE(ip))) {
435 int sbrtextsize, iprtextsize; 433 xfs_extlen_t extsz;
436 434
437 sbrtextsize = mp->m_sb.sb_rextsize; 435 if (!(extsz = ip->i_d.di_extsize))
438 iprtextsize = 436 extsz = mp->m_sb.sb_rextsize;
439 ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize; 437 numrtextents = qblocks = (count_fsb + extsz - 1);
440 numrtextents = (count_fsb + iprtextsize - 1); 438 do_div(numrtextents, mp->m_sb.sb_rextsize);
441 do_div(numrtextents, sbrtextsize); 439 quota_flag = XFS_QMOPT_RES_RTBLKS;
442 datablocks = 0; 440 datablocks = 0;
443 } else { 441 } else {
444 datablocks = count_fsb; 442 datablocks = qblocks = count_fsb;
443 quota_flag = XFS_QMOPT_RES_REGBLKS;
445 numrtextents = 0; 444 numrtextents = 0;
446 } 445 }
447 446
448 /* 447 /*
449 * allocate and setup the transaction 448 * Allocate and setup the transaction
450 */ 449 */
451 xfs_iunlock(ip, XFS_ILOCK_EXCL); 450 xfs_iunlock(ip, XFS_ILOCK_EXCL);
452 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); 451 tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
453
454 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks); 452 resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
455
456 error = xfs_trans_reserve(tp, resblks, 453 error = xfs_trans_reserve(tp, resblks,
457 XFS_WRITE_LOG_RES(mp), numrtextents, 454 XFS_WRITE_LOG_RES(mp), numrtextents,
458 XFS_TRANS_PERM_LOG_RES, 455 XFS_TRANS_PERM_LOG_RES,
459 XFS_WRITE_LOG_COUNT); 456 XFS_WRITE_LOG_COUNT);
460 457
461 /* 458 /*
462 * check for running out of space 459 * Check for running out of space, note: need lock to return
463 */ 460 */
464 if (error) 461 if (error)
465 /*
466 * Free the transaction structure.
467 */
468 xfs_trans_cancel(tp, 0); 462 xfs_trans_cancel(tp, 0);
469
470 xfs_ilock(ip, XFS_ILOCK_EXCL); 463 xfs_ilock(ip, XFS_ILOCK_EXCL);
471
472 if (error) 464 if (error)
473 goto error_out; /* Don't return in above if .. trans .., 465 goto error_out;
474 need lock to return */
475 466
476 if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) { 467 if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
477 error = (EDQUOT); 468 error = (EDQUOT);
478 goto error1; 469 goto error1;
479 } 470 }
480 nimaps = 1;
481 471
482 bmapi_flag = XFS_BMAPI_WRITE; 472 bmapi_flag = XFS_BMAPI_WRITE;
483 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); 473 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -487,31 +477,29 @@ xfs_iomap_write_direct(
487 bmapi_flag |= XFS_BMAPI_PREALLOC; 477 bmapi_flag |= XFS_BMAPI_PREALLOC;
488 478
489 /* 479 /*
490 * issue the bmapi() call to allocate the blocks 480 * Issue the bmapi() call to allocate the blocks
491 */ 481 */
492 XFS_BMAP_INIT(&free_list, &firstfsb); 482 XFS_BMAP_INIT(&free_list, &firstfsb);
483 nimaps = 1;
493 imapp = &imap[0]; 484 imapp = &imap[0];
494 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, 485 error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
495 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list); 486 bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
496 if (error) { 487 if (error)
497 goto error0; 488 goto error0;
498 }
499 489
500 /* 490 /*
501 * complete the transaction 491 * Complete the transaction
502 */ 492 */
503
504 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed); 493 error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
505 if (error) { 494 if (error)
506 goto error0; 495 goto error0;
507 }
508
509 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL); 496 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
510 if (error) { 497 if (error)
511 goto error_out; 498 goto error_out;
512 }
513 499
514 /* copy any maps to caller's array and return any error. */ 500 /*
501 * Copy any maps to caller's array and return any error.
502 */
515 if (nimaps == 0) { 503 if (nimaps == 0) {
516 error = (ENOSPC); 504 error = (ENOSPC);
517 goto error_out; 505 goto error_out;
@@ -530,10 +518,11 @@ xfs_iomap_write_direct(
530 } 518 }
531 return 0; 519 return 0;
532 520
533 error0: /* Cancel bmap, unlock inode, and cancel trans */ 521error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
534 xfs_bmap_cancel(&free_list); 522 xfs_bmap_cancel(&free_list);
523 XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
535 524
536 error1: /* Just cancel transaction */ 525error1: /* Just cancel transaction */
537 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT); 526 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
538 *nmaps = 0; /* nothing set-up here */ 527 *nmaps = 0; /* nothing set-up here */
539 528
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 341cb4604c66..7134576ae7fa 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -352,15 +352,8 @@ typedef struct xfs_dqtrxops {
352#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \ 352#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
353 XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots) 353 XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
354 354
355#define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \ 355#define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, flags) \
356 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \ 356 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), -(ninos), flags)
357 XFS_QMOPT_RES_REGBLKS)
358#define XFS_TRANS_RESERVE_BLKQUOTA_FORCE(mp, tp, ip, nblks) \
359 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
360 XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES)
361#define XFS_TRANS_UNRESERVE_BLKQUOTA(mp, tp, ip, nblks) \
362 XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), 0, \
363 XFS_QMOPT_RES_REGBLKS)
364#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \ 357#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
365 XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \ 358 XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \
366 f | XFS_QMOPT_RES_REGBLKS) 359 f | XFS_QMOPT_RES_REGBLKS)
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index d64ebcfa0b6c..1377c868f3f4 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -4175,9 +4175,8 @@ retry:
4175 break; 4175 break;
4176 } 4176 }
4177 xfs_ilock(ip, XFS_ILOCK_EXCL); 4177 xfs_ilock(ip, XFS_ILOCK_EXCL);
4178 error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, 4178 error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
4179 ip->i_udquot, ip->i_gdquot, resblks, 0, rt ? 4179 ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
4180 XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
4181 if (error) 4180 if (error)
4182 goto error1; 4181 goto error1;
4183 4182