xfs: dquot log reservations are too small
[cascardo/linux.git] / fs / xfs / xfs_trans_dquot.c
index fec75d0..db041a5 100644 (file)
@@ -103,8 +103,6 @@ xfs_trans_dup_dqinfo(
                return;
 
        xfs_trans_alloc_dqinfo(ntp);
-       oqa = otp->t_dqinfo->dqa_usrdquots;
-       nqa = ntp->t_dqinfo->dqa_usrdquots;
 
        /*
         * Because the quota blk reservation is carried forward,
@@ -113,7 +111,9 @@ xfs_trans_dup_dqinfo(
        if(otp->t_flags & XFS_TRANS_DQ_DIRTY)
                ntp->t_flags |= XFS_TRANS_DQ_DIRTY;
 
-       for (j = 0; j < 2; j++) {
+       for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
+               oqa = otp->t_dqinfo->dqs[j];
+               nqa = ntp->t_dqinfo->dqs[j];
                for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
                        if (oqa[i].qt_dquot == NULL)
                                break;
@@ -138,8 +138,6 @@ xfs_trans_dup_dqinfo(
                        oq->qt_ino_res = oq->qt_ino_res_used;
 
                }
-               oqa = otp->t_dqinfo->dqa_grpdquots;
-               nqa = ntp->t_dqinfo->dqa_grpdquots;
        }
 }
 
@@ -157,8 +155,7 @@ xfs_trans_mod_dquot_byino(
 
        if (!XFS_IS_QUOTA_RUNNING(mp) ||
            !XFS_IS_QUOTA_ON(mp) ||
-           ip->i_ino == mp->m_sb.sb_uquotino ||
-           ip->i_ino == mp->m_sb.sb_gquotino)
+           xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
                return;
 
        if (tp->t_dqinfo == NULL)
@@ -170,16 +167,18 @@ xfs_trans_mod_dquot_byino(
                (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
 }
 
-STATIC xfs_dqtrx_t *
+STATIC struct xfs_dqtrx *
 xfs_trans_get_dqtrx(
-       xfs_trans_t     *tp,
-       xfs_dquot_t     *dqp)
+       struct xfs_trans        *tp,
+       struct xfs_dquot        *dqp)
 {
-       int             i;
-       xfs_dqtrx_t     *qa;
+       int                     i;
+       struct xfs_dqtrx        *qa;
 
-       qa = XFS_QM_ISUDQ(dqp) ?
-               tp->t_dqinfo->dqa_usrdquots : tp->t_dqinfo->dqa_grpdquots;
+       if (XFS_QM_ISUDQ(dqp))
+               qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
+       else
+               qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
 
        for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
                if (qa[i].qt_dquot == NULL ||
@@ -292,11 +291,10 @@ xfs_trans_mod_dquot(
 
 
 /*
- * Given an array of dqtrx structures, lock all the dquots associated
- * and join them to the transaction, provided they have been modified.
- * We know that the highest number of dquots (of one type - usr OR grp),
- * involved in a transaction is 2 and that both usr and grp combined - 3.
- * So, we don't attempt to make this very generic.
+ * Given an array of dqtrx structures, lock all the dquots associated and join
+ * them to the transaction, provided they have been modified.  We know that the
+ * highest number of dquots of one type - usr, grp OR prj - involved in a
+ * transaction is 2 so we don't need to make this very generic.
  */
 STATIC void
 xfs_trans_dqlockedjoin(
@@ -339,12 +337,10 @@ xfs_trans_apply_dquot_deltas(
                return;
 
        ASSERT(tp->t_dqinfo);
-       qa = tp->t_dqinfo->dqa_usrdquots;
-       for (j = 0; j < 2; j++) {
-               if (qa[0].qt_dquot == NULL) {
-                       qa = tp->t_dqinfo->dqa_grpdquots;
+       for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
+               qa = tp->t_dqinfo->dqs[j];
+               if (qa[0].qt_dquot == NULL)
                        continue;
-               }
 
                /*
                 * Lock all of the dquots and join them to the transaction.
@@ -495,10 +491,6 @@ xfs_trans_apply_dquot_deltas(
                        ASSERT(dqp->q_res_rtbcount >=
                                be64_to_cpu(dqp->q_core.d_rtbcount));
                }
-               /*
-                * Do the group quotas next
-                */
-               qa = tp->t_dqinfo->dqa_grpdquots;
        }
 }
 
@@ -521,9 +513,9 @@ xfs_trans_unreserve_and_mod_dquots(
        if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY))
                return;
 
-       qa = tp->t_dqinfo->dqa_usrdquots;
+       for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
+               qa = tp->t_dqinfo->dqs[j];
 
-       for (j = 0; j < 2; j++) {
                for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
                        qtrx = &qa[i];
                        /*
@@ -565,7 +557,6 @@ xfs_trans_unreserve_and_mod_dquots(
                                xfs_dqunlock(dqp);
 
                }
-               qa = tp->t_dqinfo->dqa_grpdquots;
        }
 }
 
@@ -640,8 +631,8 @@ xfs_trans_dqresv(
        if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
            dqp->q_core.d_id &&
            ((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
-            (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&
-             (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {
+            (XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(dqp)) ||
+            (XFS_IS_PQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISPDQ(dqp)))) {
                if (nblks > 0) {
                        /*
                         * dquot is locked already. See if we'd go over the
@@ -748,15 +739,15 @@ error_return:
  */
 int
 xfs_trans_reserve_quota_bydquots(
-       xfs_trans_t     *tp,
-       xfs_mount_t     *mp,
-       xfs_dquot_t     *udqp,
-       xfs_dquot_t     *gdqp,
-       long            nblks,
-       long            ninos,
-       uint            flags)
+       struct xfs_trans        *tp,
+       struct xfs_mount        *mp,
+       struct xfs_dquot        *udqp,
+       struct xfs_dquot        *gdqp,
+       long                    nblks,
+       long                    ninos,
+       uint                    flags)
 {
-       int             resvd = 0, error;
+       int             error;
 
        if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
                return 0;
@@ -771,28 +762,24 @@ xfs_trans_reserve_quota_bydquots(
                                        (flags & ~XFS_QMOPT_ENOSPC));
                if (error)
                        return error;
-               resvd = 1;
        }
 
        if (gdqp) {
                error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
-               if (error) {
-                       /*
-                        * can't do it, so backout previous reservation
-                        */
-                       if (resvd) {
-                               flags |= XFS_QMOPT_FORCE_RES;
-                               xfs_trans_dqresv(tp, mp, udqp,
-                                                -nblks, -ninos, flags);
-                       }
-                       return error;
-               }
+               if (error)
+                       goto unwind_usr;
        }
 
        /*
         * Didn't change anything critical, so, no need to log
         */
        return 0;
+
+unwind_usr:
+       flags |= XFS_QMOPT_FORCE_RES;
+       if (udqp)
+               xfs_trans_dqresv(tp, mp, udqp, -nblks, -ninos, flags);
+       return error;
 }
 
 
@@ -816,8 +803,7 @@ xfs_trans_reserve_quota_nblks(
        if (XFS_IS_PQUOTA_ON(mp))
                flags |= XFS_QMOPT_ENOSPC;
 
-       ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
-       ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
+       ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
 
        ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==