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(
{
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,
......
......@@ -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 @@ 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
* 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;
}
/*
......
......@@ -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;
}
......
......@@ -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
......
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