]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
[XFS] Make project quota enforcement return an error code consistent with
authorNathan Scott <nathans@sgi.com>
Fri, 31 Mar 2006 03:04:49 +0000 (13:04 +1000)
committerNathan Scott <nathans@sgi.com>
Fri, 31 Mar 2006 03:04:49 +0000 (13:04 +1000)
its use.

SGI-PV: 951300
SGI-Modid: xfs-linux-melb:xfs-kern:25633a

Signed-off-by: Nathan Scott <nathans@sgi.com>
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_trans_dquot.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_quota.h

index 73c1e5e80c077b6f580fada7979c9f8620edfd22..7fb5eca9bd5017df4ba44267ef496c7319b260f7 100644 (file)
@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve(
 {
        int             error;
        xfs_mount_t     *mp;
-       uint            delblks, blkflags;
+       uint            delblks, blkflags, prjflags = 0;
        xfs_dquot_t     *unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
        ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve(
                }
        }
        if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
-               if ((XFS_IS_GQUOTA_ON(ip->i_mount) &&
-                    ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) ||
-                   (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-                    ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
+               if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
+                    ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+                       prjflags = XFS_QMOPT_ENOSPC;
+
+               if (prjflags ||
+                   (XFS_IS_GQUOTA_ON(ip->i_mount) &&
+                    ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
                        delblksgdq = gdqp;
                        if (delblks) {
                                ASSERT(ip->i_gdquot);
@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve(
 
        if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
                                delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
-                               flags | blkflags)))
+                               flags | blkflags | prjflags)))
                return (error);
 
        /*
@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve(
                ASSERT(unresudq || unresgdq);
                if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
                                delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
-                               flags | blkflags)))
+                               flags | blkflags | prjflags)))
                        return (error);
                xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
                                unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
index d8e131ec0aa8ed520ddf2458f772b2361212825a..9168918db252fa3c55087f173c0c418da70f7b9e 100644 (file)
@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots(
        }
 }
 
+STATIC int
+xfs_quota_error(uint flags)
+{
+       if (flags & XFS_QMOPT_ENOSPC)
+               return ENOSPC;
+       return EDQUOT;
+}
+
 /*
  * This reserves disk blocks and inodes against a dquot.
  * Flags indicate if the dquot is to be locked here and also
  * if the blk reservation is for RT or regular blocks.
  * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
- * Returns EDQUOT if quota is exceeded.
  */
 STATIC int
 xfs_trans_dqresv(
@@ -666,19 +673,15 @@ xfs_trans_dqresv(
                         */
                        if (hardlimit > 0ULL &&
                             (hardlimit <= nblks + *resbcountp)) {
-                               error = EDQUOT;
+                               error = xfs_quota_error(flags);
                                goto error_return;
                        }
 
                        if (softlimit > 0ULL &&
                             (softlimit <= nblks + *resbcountp)) {
-                               /*
-                                * If timer or warnings has expired,
-                                * return EDQUOT
-                                */
                                if ((timer != 0 && get_seconds() > timer) ||
                                    (warns != 0 && warns >= warnlimit)) {
-                                       error = EDQUOT;
+                                       error = xfs_quota_error(flags);
                                        goto error_return;
                                }
                        }
@@ -695,16 +698,12 @@ xfs_trans_dqresv(
                        if (!softlimit)
                                softlimit = q->qi_isoftlimit;
                        if (hardlimit > 0ULL && count >= hardlimit) {
-                               error = EDQUOT;
+                               error = xfs_quota_error(flags);
                                goto error_return;
                        } else if (softlimit > 0ULL && count >= softlimit) {
-                               /*
-                                * If timer or warnings has expired,
-                                * return EDQUOT
-                                */
                                if ((timer != 0 && get_seconds() > timer) ||
                                     (warns != 0 && warns >= warnlimit)) {
-                                       error = EDQUOT;
+                                       error = xfs_quota_error(flags);
                                        goto error_return;
                                }
                        }
@@ -751,13 +750,14 @@ error_return:
 
 
 /*
- * Given dquot(s), make disk block and/or inode reservations against them.
+ * Given dquot(s), make disk block and/or inode reservations against them.
  * The fact that this does the reservation against both the usr and
- * grp quotas is important, because this follows a both-or-nothing
+ * grp/prj quotas is important, because this follows a both-or-nothing
  * approach.
  *
  * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
  *        XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
+ *        XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT.  Used by pquota.
  *        XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks
  *        XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
  * dquots are unlocked on return, if they were not locked by caller.
@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots(
        long            ninos,
        uint            flags)
 {
-       int             resvd;
+       int             resvd = 0, error;
 
-       if (! XFS_IS_QUOTA_ON(mp))
-               return (0);
+       if (!XFS_IS_QUOTA_ON(mp))
+               return 0;
 
        if (tp && tp->t_dqinfo == NULL)
                xfs_trans_alloc_dqinfo(tp);
 
        ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
-       resvd = 0;
 
        if (udqp) {
-               if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags))
-                       return (EDQUOT);
+               error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
+                                       (flags & ~XFS_QMOPT_ENOSPC));
+               if (error)
+                       return error;
                resvd = 1;
        }
 
        if (gdqp) {
-               if (xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags)) {
+               error = xfs_trans_dqresv(tp, mp, gdqp, nblks, ninos, flags);
+               if (error) {
                        /*
                         * can't do it, so backout previous reservation
                         */
@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots(
                                xfs_trans_dqresv(tp, mp, udqp,
                                                 -nblks, -ninos, flags);
                        }
-                       return (EDQUOT);
+                       return error;
                }
        }
 
        /*
         * Didn't change anything critical, so, no need to log
         */
-       return (0);
+       return 0;
 }
 
 
@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots(
  * Lock the dquot and change the reservation if we can.
  * This doesn't change the actual usage, just the reservation.
  * The inode sent in is locked.
- *
- * Returns 0 on success, EDQUOT or other errors otherwise
  */
 STATIC int
 xfs_trans_reserve_quota_nblks(
@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks(
        xfs_inode_t     *ip,
        long            nblks,
        long            ninos,
-       uint            type)
+       uint            flags)
 {
        int             error;
 
        if (!XFS_IS_QUOTA_ON(mp))
-               return (0);
+               return 0;
+       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_ISLOCKED_INODE_EXCL(ip));
        ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
-       ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS ||
-              (type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS);
+       ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+                               XFS_TRANS_DQ_RES_RTBLKS ||
+              (flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
+                               XFS_TRANS_DQ_RES_BLKS);
 
        /*
         * Reserve nblks against these dquots, with trans as the mediator.
@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks(
        error = xfs_trans_reserve_quota_bydquots(tp, mp,
                                                 ip->i_udquot, ip->i_gdquot,
                                                 nblks, ninos,
-                                                type);
-       return (error);
+                                                flags);
+       return error;
 }
 
 /*
index d384e489705f8eff50b900e07926f88db196bc13..26939d364bc47bbcff7d52bce28d06ac988939d1 100644 (file)
@@ -4719,18 +4719,17 @@ xfs_bmapi(
                                /*
                                 * Make a transaction-less quota reservation for
                                 * delayed allocation blocks. This number gets
-                                * adjusted later.
-                                * We return EDQUOT if we haven't allocated
-                                * blks already inside this loop;
+                                * adjusted later.  We return if we haven't
+                                * allocated blocks already inside this loop.
                                 */
-                               if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+                               if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
                                                mp, NULL, ip, (long)alen, 0,
                                                rt ? XFS_QMOPT_RES_RTBLKS :
-                                                    XFS_QMOPT_RES_REGBLKS)) {
+                                                    XFS_QMOPT_RES_REGBLKS))) {
                                        if (n == 0) {
                                                *nmap = 0;
                                                ASSERT(cur == NULL);
-                                               return XFS_ERROR(EDQUOT);
+                                               return error;
                                        }
                                        break;
                                }
index 4f6a034de7f7c2b5b4acee67c2efb5c66a0a4e67..7fbef974bce663323d24ca87c0fd9153250e78ac 100644 (file)
@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat {
 #define XFS_QMOPT_QUOTAOFF     0x0000080 /* quotas are being turned off */
 #define XFS_QMOPT_UMOUNTING    0x0000100 /* filesys is being unmounted */
 #define XFS_QMOPT_DOLOG                0x0000200 /* log buf changes (in quotacheck) */
-#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if necessary */
+#define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if needed */
 #define XFS_QMOPT_ILOCKED      0x0000800 /* inode is already locked (excl) */
-#define XFS_QMOPT_DQREPAIR     0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_DQREPAIR     0x0001000 /* repair dquot if damaged */
 #define XFS_QMOPT_GQUOTA       0x0002000 /* group dquot requested */
+#define XFS_QMOPT_ENOSPC       0x0004000 /* enospc instead of edquot (prj) */
 
 /*
  * flags to xfs_trans_mod_dquot to indicate which field needs to be