[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: Nathan Scott <nathans@sgi.com>
This commit is contained in:
parent
764d1f89a5
commit
9a2a7de268
4 changed files with 54 additions and 47 deletions
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue