Commit 9a2a7de2 authored by Nathan Scott's avatar Nathan Scott

[XFS] Make project quota enforcement return an error code consistent with

its use.

SGI-PV: 951300
SGI-Modid: xfs-linux-melb:xfs-kern:25633a
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 764d1f89
...@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve( ...@@ -2624,7 +2624,7 @@ xfs_qm_vop_chown_reserve(
{ {
int error; int error;
xfs_mount_t *mp; xfs_mount_t *mp;
uint delblks, blkflags; uint delblks, blkflags, prjflags = 0;
xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq; xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
ASSERT(XFS_ISLOCKED_INODE(ip)); ASSERT(XFS_ISLOCKED_INODE(ip));
...@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve( ...@@ -2650,10 +2650,13 @@ xfs_qm_vop_chown_reserve(
} }
} }
if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
if ((XFS_IS_GQUOTA_ON(ip->i_mount) && if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) || ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
(XFS_IS_PQUOTA_ON(ip->i_mount) && prjflags = XFS_QMOPT_ENOSPC;
ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
if (prjflags ||
(XFS_IS_GQUOTA_ON(ip->i_mount) &&
ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
delblksgdq = gdqp; delblksgdq = gdqp;
if (delblks) { if (delblks) {
ASSERT(ip->i_gdquot); ASSERT(ip->i_gdquot);
...@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve( ...@@ -2664,7 +2667,7 @@ xfs_qm_vop_chown_reserve(
if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
delblksudq, delblksgdq, ip->i_d.di_nblocks, 1, delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
flags | blkflags))) flags | blkflags | prjflags)))
return (error); return (error);
/* /*
...@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve( ...@@ -2681,7 +2684,7 @@ xfs_qm_vop_chown_reserve(
ASSERT(unresudq || unresgdq); ASSERT(unresudq || unresgdq);
if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0, delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
flags | blkflags))) flags | blkflags | prjflags)))
return (error); return (error);
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0, unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
......
...@@ -595,12 +595,19 @@ xfs_trans_unreserve_and_mod_dquots( ...@@ -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. * This reserves disk blocks and inodes against a dquot.
* Flags indicate if the dquot is to be locked here and also * Flags indicate if the dquot is to be locked here and also
* if the blk reservation is for RT or regular blocks. * if the blk reservation is for RT or regular blocks.
* Sending in XFS_QMOPT_FORCE_RES flag skips the quota check. * Sending in XFS_QMOPT_FORCE_RES flag skips the quota check.
* Returns EDQUOT if quota is exceeded.
*/ */
STATIC int STATIC int
xfs_trans_dqresv( xfs_trans_dqresv(
...@@ -666,19 +673,15 @@ xfs_trans_dqresv( ...@@ -666,19 +673,15 @@ xfs_trans_dqresv(
*/ */
if (hardlimit > 0ULL && if (hardlimit > 0ULL &&
(hardlimit <= nblks + *resbcountp)) { (hardlimit <= nblks + *resbcountp)) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} }
if (softlimit > 0ULL && if (softlimit > 0ULL &&
(softlimit <= nblks + *resbcountp)) { (softlimit <= nblks + *resbcountp)) {
/*
* If timer or warnings has expired,
* return EDQUOT
*/
if ((timer != 0 && get_seconds() > timer) || if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) { (warns != 0 && warns >= warnlimit)) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} }
} }
...@@ -695,16 +698,12 @@ xfs_trans_dqresv( ...@@ -695,16 +698,12 @@ xfs_trans_dqresv(
if (!softlimit) if (!softlimit)
softlimit = q->qi_isoftlimit; softlimit = q->qi_isoftlimit;
if (hardlimit > 0ULL && count >= hardlimit) { if (hardlimit > 0ULL && count >= hardlimit) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} else if (softlimit > 0ULL && count >= softlimit) { } else if (softlimit > 0ULL && count >= softlimit) {
/*
* If timer or warnings has expired,
* return EDQUOT
*/
if ((timer != 0 && get_seconds() > timer) || if ((timer != 0 && get_seconds() > timer) ||
(warns != 0 && warns >= warnlimit)) { (warns != 0 && warns >= warnlimit)) {
error = EDQUOT; error = xfs_quota_error(flags);
goto error_return; goto error_return;
} }
} }
...@@ -751,13 +750,14 @@ xfs_trans_dqresv( ...@@ -751,13 +750,14 @@ xfs_trans_dqresv(
/* /*
* Given a 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 * 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. * approach.
* *
* flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked.
* XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. * 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_BLKS reserves regular disk blocks
* XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks
* dquots are unlocked on return, if they were not locked by caller. * dquots are unlocked on return, if they were not locked by caller.
...@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots( ...@@ -772,25 +772,27 @@ xfs_trans_reserve_quota_bydquots(
long ninos, long ninos,
uint flags) uint flags)
{ {
int resvd; int resvd = 0, error;
if (! XFS_IS_QUOTA_ON(mp)) if (!XFS_IS_QUOTA_ON(mp))
return (0); return 0;
if (tp && tp->t_dqinfo == NULL) if (tp && tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp); xfs_trans_alloc_dqinfo(tp);
ASSERT(flags & XFS_QMOPT_RESBLK_MASK); ASSERT(flags & XFS_QMOPT_RESBLK_MASK);
resvd = 0;
if (udqp) { if (udqp) {
if (xfs_trans_dqresv(tp, mp, udqp, nblks, ninos, flags)) error = xfs_trans_dqresv(tp, mp, udqp, nblks, ninos,
return (EDQUOT); (flags & ~XFS_QMOPT_ENOSPC));
if (error)
return error;
resvd = 1; resvd = 1;
} }
if (gdqp) { 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 * can't do it, so backout previous reservation
*/ */
...@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots( ...@@ -799,14 +801,14 @@ xfs_trans_reserve_quota_bydquots(
xfs_trans_dqresv(tp, mp, udqp, xfs_trans_dqresv(tp, mp, udqp,
-nblks, -ninos, flags); -nblks, -ninos, flags);
} }
return (EDQUOT); return error;
} }
} }
/* /*
* Didn't change anything critical, so, no need to log * Didn't change anything critical, so, no need to log
*/ */
return (0); return 0;
} }
...@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots( ...@@ -814,8 +816,6 @@ xfs_trans_reserve_quota_bydquots(
* Lock the dquot and change the reservation if we can. * Lock the dquot and change the reservation if we can.
* This doesn't change the actual usage, just the reservation. * This doesn't change the actual usage, just the reservation.
* The inode sent in is locked. * The inode sent in is locked.
*
* Returns 0 on success, EDQUOT or other errors otherwise
*/ */
STATIC int STATIC int
xfs_trans_reserve_quota_nblks( xfs_trans_reserve_quota_nblks(
...@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks( ...@@ -824,20 +824,24 @@ xfs_trans_reserve_quota_nblks(
xfs_inode_t *ip, xfs_inode_t *ip,
long nblks, long nblks,
long ninos, long ninos,
uint type) uint flags)
{ {
int error; int error;
if (!XFS_IS_QUOTA_ON(mp)) 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_uquotino);
ASSERT(ip->i_ino != mp->m_sb.sb_gquotino); ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount)); ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
ASSERT((type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_RTBLKS || ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
(type & ~XFS_QMOPT_FORCE_RES) == XFS_TRANS_DQ_RES_BLKS); 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. * Reserve nblks against these dquots, with trans as the mediator.
...@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks( ...@@ -845,8 +849,8 @@ xfs_trans_reserve_quota_nblks(
error = xfs_trans_reserve_quota_bydquots(tp, mp, error = xfs_trans_reserve_quota_bydquots(tp, mp,
ip->i_udquot, ip->i_gdquot, ip->i_udquot, ip->i_gdquot,
nblks, ninos, nblks, ninos,
type); flags);
return (error); return error;
} }
/* /*
......
...@@ -4719,18 +4719,17 @@ xfs_bmapi( ...@@ -4719,18 +4719,17 @@ xfs_bmapi(
/* /*
* Make a transaction-less quota reservation for * Make a transaction-less quota reservation for
* delayed allocation blocks. This number gets * delayed allocation blocks. This number gets
* adjusted later. * adjusted later. We return if we haven't
* We return EDQUOT if we haven't allocated * allocated blocks already inside this loop.
* blks already inside this loop;
*/ */
if (XFS_TRANS_RESERVE_QUOTA_NBLKS( if ((error = XFS_TRANS_RESERVE_QUOTA_NBLKS(
mp, NULL, ip, (long)alen, 0, mp, NULL, ip, (long)alen, 0,
rt ? XFS_QMOPT_RES_RTBLKS : rt ? XFS_QMOPT_RES_RTBLKS :
XFS_QMOPT_RES_REGBLKS)) { XFS_QMOPT_RES_REGBLKS))) {
if (n == 0) { if (n == 0) {
*nmap = 0; *nmap = 0;
ASSERT(cur == NULL); ASSERT(cur == NULL);
return XFS_ERROR(EDQUOT); return error;
} }
break; break;
} }
......
...@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat { ...@@ -196,10 +196,11 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */ #define XFS_QMOPT_QUOTAOFF 0x0000080 /* quotas are being turned off */
#define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */ #define XFS_QMOPT_UMOUNTING 0x0000100 /* filesys is being unmounted */
#define XFS_QMOPT_DOLOG 0x0000200 /* log buf changes (in quotacheck) */ #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_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_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 * flags to xfs_trans_mod_dquot to indicate which field needs to be
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment