[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;
|
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(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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(
|
||||||
|
|
||||||
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(
|
||||||
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(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
||||||
*/
|
*/
|
||||||
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(
|
||||||
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(
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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(
|
||||||
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(
|
||||||
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(
|
||||||
* 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(
|
||||||
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(
|
||||||
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(
|
||||||
/*
|
/*
|
||||||
* 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 {
|
||||||
#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
|
||||||
|
|
Loading…
Reference in a new issue