aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_trans_dquot.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_trans_dquot.c')
-rw-r--r--fs/xfs/xfs_trans_dquot.c122
1 files changed, 63 insertions, 59 deletions
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index fec75d023703..61407a847b86 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -103,8 +103,6 @@ xfs_trans_dup_dqinfo(
103 return; 103 return;
104 104
105 xfs_trans_alloc_dqinfo(ntp); 105 xfs_trans_alloc_dqinfo(ntp);
106 oqa = otp->t_dqinfo->dqa_usrdquots;
107 nqa = ntp->t_dqinfo->dqa_usrdquots;
108 106
109 /* 107 /*
110 * Because the quota blk reservation is carried forward, 108 * Because the quota blk reservation is carried forward,
@@ -113,7 +111,9 @@ xfs_trans_dup_dqinfo(
113 if(otp->t_flags & XFS_TRANS_DQ_DIRTY) 111 if(otp->t_flags & XFS_TRANS_DQ_DIRTY)
114 ntp->t_flags |= XFS_TRANS_DQ_DIRTY; 112 ntp->t_flags |= XFS_TRANS_DQ_DIRTY;
115 113
116 for (j = 0; j < 2; j++) { 114 for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
115 oqa = otp->t_dqinfo->dqs[j];
116 nqa = ntp->t_dqinfo->dqs[j];
117 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { 117 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
118 if (oqa[i].qt_dquot == NULL) 118 if (oqa[i].qt_dquot == NULL)
119 break; 119 break;
@@ -138,8 +138,6 @@ xfs_trans_dup_dqinfo(
138 oq->qt_ino_res = oq->qt_ino_res_used; 138 oq->qt_ino_res = oq->qt_ino_res_used;
139 139
140 } 140 }
141 oqa = otp->t_dqinfo->dqa_grpdquots;
142 nqa = ntp->t_dqinfo->dqa_grpdquots;
143 } 141 }
144} 142}
145 143
@@ -157,8 +155,7 @@ xfs_trans_mod_dquot_byino(
157 155
158 if (!XFS_IS_QUOTA_RUNNING(mp) || 156 if (!XFS_IS_QUOTA_RUNNING(mp) ||
159 !XFS_IS_QUOTA_ON(mp) || 157 !XFS_IS_QUOTA_ON(mp) ||
160 ip->i_ino == mp->m_sb.sb_uquotino || 158 xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
161 ip->i_ino == mp->m_sb.sb_gquotino)
162 return; 159 return;
163 160
164 if (tp->t_dqinfo == NULL) 161 if (tp->t_dqinfo == NULL)
@@ -166,20 +163,28 @@ xfs_trans_mod_dquot_byino(
166 163
167 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) 164 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
168 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); 165 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
169 if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot) 166 if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)
170 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); 167 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
168 if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot)
169 (void) xfs_trans_mod_dquot(tp, ip->i_pdquot, field, delta);
171} 170}
172 171
173STATIC xfs_dqtrx_t * 172STATIC struct xfs_dqtrx *
174xfs_trans_get_dqtrx( 173xfs_trans_get_dqtrx(
175 xfs_trans_t *tp, 174 struct xfs_trans *tp,
176 xfs_dquot_t *dqp) 175 struct xfs_dquot *dqp)
177{ 176{
178 int i; 177 int i;
179 xfs_dqtrx_t *qa; 178 struct xfs_dqtrx *qa;
180 179
181 qa = XFS_QM_ISUDQ(dqp) ? 180 if (XFS_QM_ISUDQ(dqp))
182 tp->t_dqinfo->dqa_usrdquots : tp->t_dqinfo->dqa_grpdquots; 181 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
182 else if (XFS_QM_ISGDQ(dqp))
183 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
184 else if (XFS_QM_ISPDQ(dqp))
185 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ];
186 else
187 return NULL;
183 188
184 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { 189 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
185 if (qa[i].qt_dquot == NULL || 190 if (qa[i].qt_dquot == NULL ||
@@ -292,11 +297,10 @@ xfs_trans_mod_dquot(
292 297
293 298
294/* 299/*
295 * Given an array of dqtrx structures, lock all the dquots associated 300 * Given an array of dqtrx structures, lock all the dquots associated and join
296 * and join them to the transaction, provided they have been modified. 301 * them to the transaction, provided they have been modified. We know that the
297 * We know that the highest number of dquots (of one type - usr OR grp), 302 * highest number of dquots of one type - usr, grp OR prj - involved in a
298 * involved in a transaction is 2 and that both usr and grp combined - 3. 303 * transaction is 2 so we don't need to make this very generic.
299 * So, we don't attempt to make this very generic.
300 */ 304 */
301STATIC void 305STATIC void
302xfs_trans_dqlockedjoin( 306xfs_trans_dqlockedjoin(
@@ -339,12 +343,10 @@ xfs_trans_apply_dquot_deltas(
339 return; 343 return;
340 344
341 ASSERT(tp->t_dqinfo); 345 ASSERT(tp->t_dqinfo);
342 qa = tp->t_dqinfo->dqa_usrdquots; 346 for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
343 for (j = 0; j < 2; j++) { 347 qa = tp->t_dqinfo->dqs[j];
344 if (qa[0].qt_dquot == NULL) { 348 if (qa[0].qt_dquot == NULL)
345 qa = tp->t_dqinfo->dqa_grpdquots;
346 continue; 349 continue;
347 }
348 350
349 /* 351 /*
350 * Lock all of the dquots and join them to the transaction. 352 * Lock all of the dquots and join them to the transaction.
@@ -495,10 +497,6 @@ xfs_trans_apply_dquot_deltas(
495 ASSERT(dqp->q_res_rtbcount >= 497 ASSERT(dqp->q_res_rtbcount >=
496 be64_to_cpu(dqp->q_core.d_rtbcount)); 498 be64_to_cpu(dqp->q_core.d_rtbcount));
497 } 499 }
498 /*
499 * Do the group quotas next
500 */
501 qa = tp->t_dqinfo->dqa_grpdquots;
502 } 500 }
503} 501}
504 502
@@ -521,9 +519,9 @@ xfs_trans_unreserve_and_mod_dquots(
521 if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY)) 519 if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY))
522 return; 520 return;
523 521
524 qa = tp->t_dqinfo->dqa_usrdquots; 522 for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
523 qa = tp->t_dqinfo->dqs[j];
525 524
526 for (j = 0; j < 2; j++) {
527 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { 525 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
528 qtrx = &qa[i]; 526 qtrx = &qa[i];
529 /* 527 /*
@@ -565,7 +563,6 @@ xfs_trans_unreserve_and_mod_dquots(
565 xfs_dqunlock(dqp); 563 xfs_dqunlock(dqp);
566 564
567 } 565 }
568 qa = tp->t_dqinfo->dqa_grpdquots;
569 } 566 }
570} 567}
571 568
@@ -640,8 +637,8 @@ xfs_trans_dqresv(
640 if ((flags & XFS_QMOPT_FORCE_RES) == 0 && 637 if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
641 dqp->q_core.d_id && 638 dqp->q_core.d_id &&
642 ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) || 639 ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
643 (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) && 640 (XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(dqp)) ||
644 (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) { 641 (XFS_IS_PQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISPDQ(dqp)))) {
645 if (nblks > 0) { 642 if (nblks > 0) {
646 /* 643 /*
647 * dquot is locked already. See if we'd go over the 644 * dquot is locked already. See if we'd go over the
@@ -736,8 +733,8 @@ error_return:
736 733
737/* 734/*
738 * Given dquot(s), make disk block and/or inode reservations against them. 735 * Given dquot(s), make disk block and/or inode reservations against them.
739 * The fact that this does the reservation against both the usr and 736 * The fact that this does the reservation against user, group and
740 * grp/prj quotas is important, because this follows a both-or-nothing 737 * project quotas is important, because this follows a all-or-nothing
741 * approach. 738 * approach.
742 * 739 *
743 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. 740 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
@@ -748,15 +745,16 @@ error_return:
748 */ 745 */
749int 746int
750xfs_trans_reserve_quota_bydquots( 747xfs_trans_reserve_quota_bydquots(
751 xfs_trans_t *tp, 748 struct xfs_trans *tp,
752 xfs_mount_t *mp, 749 struct xfs_mount *mp,
753 xfs_dquot_t *udqp, 750 struct xfs_dquot *udqp,
754 xfs_dquot_t *gdqp, 751 struct xfs_dquot *gdqp,
755 long nblks, 752 struct xfs_dquot *pdqp,
756 long ninos, 753 long nblks,
757 uint flags) 754 long ninos,
755 uint flags)
758{ 756{
759 int resvd = 0, error; 757 int error;
760 758
761 if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp)) 759 if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
762 return 0; 760 return 0;
@@ -771,28 +769,34 @@ xfs_trans_reserve_quota_bydquots(
771 (flags & ~XFS_QMOPT_ENOSPC)); 769 (flags & ~XFS_QMOPT_ENOSPC));
772 if (error) 770 if (error)
773 return error; 771 return error;
774 resvd = 1;
775 } 772 }
776 773
777 if (gdqp) { 774 if (gdqp) {
778 error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags); 775 error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
779 if (error) { 776 if (error)
780 /* 777 goto unwind_usr;
781 * can't do it, so backout previous reservation 778 }
782 */ 779
783 if (resvd) { 780 if (pdqp) {
784 flags |= XFS_QMOPT_FORCE_RES; 781 error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
785 xfs_trans_dqresv(tp, mp, udqp, 782 if (error)
786 -nblks, -ninos, flags); 783 goto unwind_grp;
787 }
788 return error;
789 }
790 } 784 }
791 785
792 /* 786 /*
793 * Didn't change anything critical, so, no need to log 787 * Didn't change anything critical, so, no need to log
794 */ 788 */
795 return 0; 789 return 0;
790
791unwind_grp:
792 flags |= XFS_QMOPT_FORCE_RES;
793 if (gdqp)
794 xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags);
795unwind_usr:
796 flags |= XFS_QMOPT_FORCE_RES;
797 if (udqp)
798 xfs_trans_dqresv(tp, mp, udqp, -nblks, -ninos, flags);
799 return error;
796} 800}
797 801
798 802
@@ -816,8 +820,7 @@ xfs_trans_reserve_quota_nblks(
816 if (XFS_IS_PQUOTA_ON(mp)) 820 if (XFS_IS_PQUOTA_ON(mp))
817 flags |= XFS_QMOPT_ENOSPC; 821 flags |= XFS_QMOPT_ENOSPC;
818 822
819 ASSERT(ip->i_ino != mp->m_sb.sb_uquotino); 823 ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
820 ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
821 824
822 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 825 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
823 ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) == 826 ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
@@ -830,6 +833,7 @@ xfs_trans_reserve_quota_nblks(
830 */ 833 */
831 return xfs_trans_reserve_quota_bydquots(tp, mp, 834 return xfs_trans_reserve_quota_bydquots(tp, mp,
832 ip->i_udquot, ip->i_gdquot, 835 ip->i_udquot, ip->i_gdquot,
836 ip->i_pdquot,
833 nblks, ninos, flags); 837 nblks, ninos, flags);
834} 838}
835 839