Merge tag 'idmapped-mounts-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / fs / xfs / xfs_qm.c
index 1b7b139..bfa4164 100644 (file)
@@ -1787,105 +1787,35 @@ xfs_qm_vop_chown(
        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