diff options
Diffstat (limited to 'fs/xfs/xfs_trans_dquot.c')
-rw-r--r-- | fs/xfs/xfs_trans_dquot.c | 122 |
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 | ||
173 | STATIC xfs_dqtrx_t * | 172 | STATIC struct xfs_dqtrx * |
174 | xfs_trans_get_dqtrx( | 173 | xfs_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 | */ |
301 | STATIC void | 305 | STATIC void |
302 | xfs_trans_dqlockedjoin( | 306 | xfs_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 | */ |
749 | int | 746 | int |
750 | xfs_trans_reserve_quota_bydquots( | 747 | xfs_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 | |||
791 | unwind_grp: | ||
792 | flags |= XFS_QMOPT_FORCE_RES; | ||
793 | if (gdqp) | ||
794 | xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags); | ||
795 | unwind_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 | ||