xfs: unconditionally read all AGFs on mounts with perag reservation
[linux-2.6-microblaze.git] / fs / xfs / xfs_qm.c
index c134eb4..4bf949a 100644 (file)
@@ -787,7 +787,8 @@ xfs_qm_qino_alloc(
                return error;
 
        if (need_alloc) {
-               error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, ipp);
+               error = xfs_dir_ialloc(&init_user_ns, &tp, NULL, S_IFREG, 1, 0,
+                                      0, false, ipp);
                if (error) {
                        xfs_trans_cancel(tp);
                        return error;
@@ -991,7 +992,7 @@ xfs_qm_reset_dqcounts_buf(
         * trans_reserve. But, this gets called during quotacheck, and that
         * happens only at mount time which is single threaded.
         */
-       if (qip->i_d.di_nblocks == 0)
+       if (qip->i_nblocks == 0)
                return 0;
 
        map = kmem_alloc(XFS_DQITER_MAP_SIZE * sizeof(*map), 0);
@@ -1164,16 +1165,14 @@ xfs_qm_dqusage_adjust(
        if (XFS_IS_REALTIME_INODE(ip)) {
                struct xfs_ifork        *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 
-               if (!(ifp->if_flags & XFS_IFEXTENTS)) {
-                       error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
-                       if (error)
-                               goto error0;
-               }
+               error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
+               if (error)
+                       goto error0;
 
                xfs_bmap_count_leaves(ifp, &rtblks);
        }
 
-       nblks = (xfs_qcnt_t)ip->i_d.di_nblocks - rtblks;
+       nblks = (xfs_qcnt_t)ip->i_nblocks - rtblks;
 
        /*
         * Add the (disk blocks and inode) resources occupied by this
@@ -1715,7 +1714,7 @@ xfs_qm_vop_dqalloc(
        }
        if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(O_pdqpp);
-               if (ip->i_d.di_projid != prid) {
+               if (ip->i_projid != prid) {
                        xfs_iunlock(ip, lockflags);
                        error = xfs_qm_dqget(mp, prid,
                                        XFS_DQTYPE_PROJ, true, &pq);
@@ -1778,113 +1777,43 @@ xfs_qm_vop_chown(
        ASSERT(prevdq);
        ASSERT(prevdq != newdq);
 
-       xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
+       xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_nblocks));
        xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
 
        /* the sparkling new dquot */
-       xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
+       xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_nblocks);
        xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
 
        /*
-        * Take an extra reference, because the inode is going to keep
-        * this dquot pointer even after the trans_commit.
+        * Back when we made quota reservations for the chown, we reserved the
+        * ondisk blocks + delalloc blocks with the new dquot.  Now that we've
+        * switched the dquots, decrease the new dquot's block reservation
+        * (having already bumped up the real counter) so that we don't have
+        * any reservation to give back when we commit.
         */
-       *IO_olddq = xfs_qm_dqhold(newdq);
+       xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_RES_BLKS,
+                       -ip->i_delayed_blks);
 
-       return prevdq;
-}
-
-/*
- * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
- */
-int
-xfs_qm_vop_chown_reserve(
-       struct xfs_trans        *tp,
-       struct xfs_inode        *ip,
-       struct xfs_dquot        *udqp,
-       struct xfs_dquot        *gdqp,
-       struct xfs_dquot        *pdqp,
-       uint                    flags)
-{
-       struct xfs_mount        *mp = ip->i_mount;
-       uint64_t                delblks;
-       unsigned int            blkflags;
-       struct xfs_dquot        *udq_unres = NULL;
-       struct xfs_dquot        *gdq_unres = NULL;
-       struct xfs_dquot        *pdq_unres = NULL;
-       struct xfs_dquot        *udq_delblks = NULL;
-       struct xfs_dquot        *gdq_delblks = NULL;
-       struct xfs_dquot        *pdq_delblks = NULL;
-       int                     error;
-
-
-       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
-       ASSERT(XFS_IS_QUOTA_RUNNING(mp));
-
-       delblks = ip->i_delayed_blks;
-       blkflags = XFS_IS_REALTIME_INODE(ip) ?
-                       XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
-
-       if (XFS_IS_UQUOTA_ON(mp) && udqp &&
-           i_uid_read(VFS_I(ip)) != udqp->q_id) {
-               udq_delblks = udqp;
-               /*
-                * If there are delayed allocation blocks, then we have to
-                * unreserve those from the old dquot, and add them to the
-                * new dquot.
-                */
-               if (delblks) {
-                       ASSERT(ip->i_udquot);
-                       udq_unres = ip->i_udquot;
-               }
-       }
-       if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
-           i_gid_read(VFS_I(ip)) != gdqp->q_id) {
-               gdq_delblks = gdqp;
-               if (delblks) {
-                       ASSERT(ip->i_gdquot);
-                       gdq_unres = ip->i_gdquot;
-               }
-       }
-
-       if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
-           ip->i_d.di_projid != pdqp->q_id) {
-               pdq_delblks = pdqp;
-               if (delblks) {
-                       ASSERT(ip->i_pdquot);
-                       pdq_unres = ip->i_pdquot;
-               }
-       }
-
-       error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
-                               udq_delblks, gdq_delblks, pdq_delblks,
-                               ip->i_d.di_nblocks, 1, flags | blkflags);
-       if (error)
-               return error;
+       /*
+        * Give the incore reservation for delalloc blocks back to the old
+        * dquot.  We don't normally handle delalloc quota reservations
+        * transactionally, so just lock the dquot and subtract from the
+        * reservation.  Dirty the transaction because it's too late to turn
+        * back now.
+        */
+       tp->t_flags |= XFS_TRANS_DIRTY;
+       xfs_dqlock(prevdq);
+       ASSERT(prevdq->q_blk.reserved >= ip->i_delayed_blks);
+       prevdq->q_blk.reserved -= ip->i_delayed_blks;
+       xfs_dqunlock(prevdq);
 
        /*
-        * Do the delayed blks reservations/unreservations now. Since, these
-        * are done without the help of a transaction, if a reservation fails
-        * its previous reservations won't be automatically undone by trans
-        * code. So, we have to do it manually here.
+        * Take an extra reference, because the inode is going to keep
+        * this dquot pointer even after the trans_commit.
         */
-       if (delblks) {
-               /*
-                * Do the reservations first. Unreservation can't fail.
-                */
-               ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
-               ASSERT(udq_unres || gdq_unres || pdq_unres);
-               error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
-                           udq_delblks, gdq_delblks, pdq_delblks,
-                           (xfs_qcnt_t)delblks, 0, flags | blkflags);
-               if (error)
-                       return error;
-               xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
-                               udq_unres, gdq_unres, pdq_unres,
-                               -((xfs_qcnt_t)delblks), 0, blkflags);
-       }
+       *IO_olddq = xfs_qm_dqhold(newdq);
 
-       return 0;
+       return prevdq;
 }
 
 int
@@ -1946,7 +1875,7 @@ xfs_qm_vop_create_dqattach(
        }
        if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
                ASSERT(ip->i_pdquot == NULL);
-               ASSERT(ip->i_d.di_projid == pdqp->q_id);
+               ASSERT(ip->i_projid == pdqp->q_id);
 
                ip->i_pdquot = xfs_qm_dqhold(pdqp);
                xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1);