Commit c8ad20ff authored by Nathan Scott's avatar Nathan Scott

[XFS] Add support for project quota, based on Dan Knappes earlier work.

SGI-PV: 932952
SGI-Modid: xfs-linux:xfs-kern:22805a
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent 8401e963
...@@ -230,8 +230,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh) ...@@ -230,8 +230,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
* field (see the QCMD macro in quota.h). These macros help keep the * field (see the QCMD macro in quota.h). These macros help keep the
* code portable - they are not visible from the syscall interface. * code portable - they are not visible from the syscall interface.
*/ */
#define Q_XSETGQLIM XQM_CMD(0x8) /* set groups disk limits */ #define Q_XSETGQLIM XQM_CMD(8) /* set groups disk limits */
#define Q_XGETGQUOTA XQM_CMD(0x9) /* get groups disk limits */ #define Q_XGETGQUOTA XQM_CMD(9) /* get groups disk limits */
#define Q_XSETPQLIM XQM_CMD(10) /* set projects disk limits */
#define Q_XGETPQUOTA XQM_CMD(11) /* get projects disk limits */
/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */ /* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
/* we may well need to fine-tune this if it ever becomes an issue. */ /* we may well need to fine-tune this if it ever becomes an issue. */
......
...@@ -701,7 +701,8 @@ linvfs_getxquota( ...@@ -701,7 +701,8 @@ linvfs_getxquota(
struct vfs *vfsp = LINVFS_GET_VFS(sb); struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error, getmode; int error, getmode;
getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA; getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
return -error; return -error;
} }
...@@ -716,7 +717,8 @@ linvfs_setxquota( ...@@ -716,7 +717,8 @@ linvfs_setxquota(
struct vfs *vfsp = LINVFS_GET_VFS(sb); struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error, setmode; int error, setmode;
setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM; setmode = (type == USRQUOTA) ? Q_XSETQLIM :
((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
return -error; return -error;
} }
......
...@@ -399,9 +399,9 @@ xfs_qm_init_dquot_blk( ...@@ -399,9 +399,9 @@ xfs_qm_init_dquot_blk(
for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++) for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
xfs_qm_dqinit_core(curid, type, d); xfs_qm_dqinit_core(curid, type, d);
xfs_trans_dquot_buf(tp, bp, xfs_trans_dquot_buf(tp, bp,
type & XFS_DQ_USER ? (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF :
XFS_BLI_UDQUOT_BUF : ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF :
XFS_BLI_GDQUOT_BUF); XFS_BLI_GDQUOT_BUF)));
xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1); xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
} }
...@@ -482,8 +482,7 @@ xfs_qm_dqalloc( ...@@ -482,8 +482,7 @@ xfs_qm_dqalloc(
* the entire thing. * the entire thing.
*/ */
xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT), xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP), dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
bp);
if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) { if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
goto error1; goto error1;
...@@ -613,8 +612,7 @@ xfs_qm_dqtobp( ...@@ -613,8 +612,7 @@ xfs_qm_dqtobp(
/* /*
* A simple sanity check in case we got a corrupted dquot... * A simple sanity check in case we got a corrupted dquot...
*/ */
if (xfs_qm_dqcheck(ddq, id, if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
"dqtobp")) { "dqtobp")) {
if (!(flags & XFS_QMOPT_DQREPAIR)) { if (!(flags & XFS_QMOPT_DQREPAIR)) {
...@@ -891,8 +889,8 @@ int ...@@ -891,8 +889,8 @@ int
xfs_qm_dqget( xfs_qm_dqget(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_inode_t *ip, /* locked inode (optional) */ xfs_inode_t *ip, /* locked inode (optional) */
xfs_dqid_t id, /* gid or uid, depending on type */ xfs_dqid_t id, /* uid/projid/gid depending on type */
uint type, /* UDQUOT or GDQUOT */ uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
{ {
...@@ -903,7 +901,9 @@ xfs_qm_dqget( ...@@ -903,7 +901,9 @@ xfs_qm_dqget(
ASSERT(XFS_IS_QUOTA_RUNNING(mp)); ASSERT(XFS_IS_QUOTA_RUNNING(mp));
if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) || if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
(! XFS_IS_PQUOTA_ON(mp) && type == XFS_DQ_PROJ) ||
(! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) { (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
printk("XQM: ESRCH1\n");
return (ESRCH); return (ESRCH);
} }
h = XFS_DQ_HASH(mp, id, type); h = XFS_DQ_HASH(mp, id, type);
...@@ -921,7 +921,9 @@ xfs_qm_dqget( ...@@ -921,7 +921,9 @@ xfs_qm_dqget(
again: again:
#ifdef DEBUG #ifdef DEBUG
ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP); ASSERT(type == XFS_DQ_USER ||
type == XFS_DQ_PROJ ||
type == XFS_DQ_GROUP);
if (ip) { if (ip) {
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
if (type == XFS_DQ_USER) if (type == XFS_DQ_USER)
...@@ -979,6 +981,7 @@ xfs_qm_dqget( ...@@ -979,6 +981,7 @@ xfs_qm_dqget(
&dqp))) { &dqp))) {
if (ip) if (ip)
xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_ilock(ip, XFS_ILOCK_EXCL);
if (error == ESRCH) printk("XQM: ESRCH2\n");
return (error); return (error);
} }
...@@ -1004,6 +1007,7 @@ xfs_qm_dqget( ...@@ -1004,6 +1007,7 @@ xfs_qm_dqget(
if (! XFS_IS_DQTYPE_ON(mp, type)) { if (! XFS_IS_DQTYPE_ON(mp, type)) {
/* inode stays locked on return */ /* inode stays locked on return */
xfs_qm_dqdestroy(dqp); xfs_qm_dqdestroy(dqp);
printk("XQM: ESRCH3\n");
return XFS_ERROR(ESRCH); return XFS_ERROR(ESRCH);
} }
/* /*
...@@ -1244,8 +1248,8 @@ xfs_qm_dqflush( ...@@ -1244,8 +1248,8 @@ xfs_qm_dqflush(
return (error); return (error);
} }
if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN, if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT),
"dqflush (incore copy)")) { 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE); xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
return XFS_ERROR(EIO); return XFS_ERROR(EIO);
} }
...@@ -1397,7 +1401,8 @@ xfs_dqlock2( ...@@ -1397,7 +1401,8 @@ xfs_dqlock2(
{ {
if (d1 && d2) { if (d1 && d2) {
ASSERT(d1 != d2); ASSERT(d1 != d2);
if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) { if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) >
INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
xfs_dqlock(d2); xfs_dqlock(d2);
xfs_dqlock(d1); xfs_dqlock(d1);
} else { } else {
...@@ -1520,8 +1525,7 @@ xfs_qm_dqprint(xfs_dquot_t *dqp) ...@@ -1520,8 +1525,7 @@ xfs_qm_dqprint(xfs_dquot_t *dqp)
cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
cmn_err(CE_DEBUG, "---- dquotID = %d", cmn_err(CE_DEBUG, "---- dquotID = %d",
(int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
cmn_err(CE_DEBUG, "---- type = %s", cmn_err(CE_DEBUG, "---- type = %s", DQFLAGTO_TYPESTR(dqp));
XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount); cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount);
cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno); cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno);
cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset); cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset);
......
...@@ -114,26 +114,19 @@ typedef struct xfs_dquot { ...@@ -114,26 +114,19 @@ typedef struct xfs_dquot {
#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++)
/* /*
* Quota Accounting flags * Quota Accounting/Enforcement flags
*/ */
#define XFS_ALL_QUOTA_ACCT (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT) #define XFS_ALL_QUOTA_ACCT \
#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD) (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD) #define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
#define XFS_ALL_QUOTA_ACTV (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE) #define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
#define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD)
#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT) #define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT) #define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT) #define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
/*
* Quota Limit Enforcement flags
*/
#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
#define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD)
#define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD)
#ifdef DEBUG #ifdef DEBUG
static inline int static inline int
XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
...@@ -167,6 +160,8 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) ...@@ -167,6 +160,8 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp))
#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY)
#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
#define XFS_QM_ISPDQ(dqp) ((dqp)->dq_flags & XFS_DQ_PROJ)
#define XFS_QM_ISGDQ(dqp) ((dqp)->dq_flags & XFS_DQ_GROUP)
#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo) #define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo)
#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \ #define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \
XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
...@@ -174,7 +169,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) ...@@ -174,7 +169,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \ #define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
(XFS_IS_UQUOTA_ON((d)->q_mount)) : \ (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
(XFS_IS_GQUOTA_ON((d)->q_mount)))) (XFS_IS_OQUOTA_ON((d)->q_mount))))
#ifdef XFS_DQUOT_TRACE #ifdef XFS_DQUOT_TRACE
/* /*
......
...@@ -310,9 +310,9 @@ xfs_qm_mount_quotainit( ...@@ -310,9 +310,9 @@ xfs_qm_mount_quotainit(
uint flags) uint flags)
{ {
/* /*
* User or group quotas has to be on. * User, projects or group quotas has to be on.
*/ */
ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)); ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
/* /*
* Initialize the flags in the mount structure. From this point * Initialize the flags in the mount structure. From this point
...@@ -330,7 +330,11 @@ xfs_qm_mount_quotainit( ...@@ -330,7 +330,11 @@ xfs_qm_mount_quotainit(
if (flags & XFSMNT_GQUOTA) { if (flags & XFSMNT_GQUOTA) {
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
if (flags & XFSMNT_GQUOTAENF) if (flags & XFSMNT_GQUOTAENF)
mp->m_qflags |= XFS_GQUOTA_ENFD; mp->m_qflags |= XFS_OQUOTA_ENFD;
} else if (flags & XFSMNT_PQUOTA) {
mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
if (flags & XFSMNT_PQUOTAENF)
mp->m_qflags |= XFS_OQUOTA_ENFD;
} }
} }
...@@ -363,11 +367,11 @@ xfs_qm_mount_quotas( ...@@ -363,11 +367,11 @@ xfs_qm_mount_quotas(
/* /*
* If a file system had quotas running earlier, but decided to * If a file system had quotas running earlier, but decided to
* mount without -o quota/uquota/gquota options, revoke the * mount without -o uquota/pquota/gquota options, revoke the
* quotachecked license, and bail out. * quotachecked license, and bail out.
*/ */
if (! XFS_IS_QUOTA_ON(mp) && if (! XFS_IS_QUOTA_ON(mp) &&
(mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) { (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
mp->m_qflags = 0; mp->m_qflags = 0;
goto write_changes; goto write_changes;
} }
...@@ -619,7 +623,7 @@ xfs_qm_detach_gdquots( ...@@ -619,7 +623,7 @@ xfs_qm_detach_gdquots(
STATIC int STATIC int
xfs_qm_dqpurge_int( xfs_qm_dqpurge_int(
xfs_mount_t *mp, xfs_mount_t *mp,
uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */ uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
{ {
xfs_dquot_t *dqp; xfs_dquot_t *dqp;
uint dqtype; uint dqtype;
...@@ -631,6 +635,7 @@ xfs_qm_dqpurge_int( ...@@ -631,6 +635,7 @@ xfs_qm_dqpurge_int(
return (0); return (0);
dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0; dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0; dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
xfs_qm_mplist_lock(mp); xfs_qm_mplist_lock(mp);
...@@ -740,11 +745,11 @@ xfs_qm_dqattach_one( ...@@ -740,11 +745,11 @@ xfs_qm_dqattach_one(
/* /*
* udqhint is the i_udquot field in inode, and is non-NULL only * udqhint is the i_udquot field in inode, and is non-NULL only
* when the type arg is XFS_DQ_GROUP. Its purpose is to save a * when the type arg is group/project. Its purpose is to save a
* lookup by dqid (xfs_qm_dqget) by caching a group dquot inside * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
* the user dquot. * the user dquot.
*/ */
ASSERT(!udqhint || type == XFS_DQ_GROUP); ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
if (udqhint && !dolock) if (udqhint && !dolock)
xfs_dqlock(udqhint); xfs_dqlock(udqhint);
...@@ -903,8 +908,8 @@ xfs_qm_dqattach_grouphint( ...@@ -903,8 +908,8 @@ xfs_qm_dqattach_grouphint(
/* /*
* Given a locked inode, attach dquot(s) to it, taking UQUOTAON / GQUOTAON * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
* in to account. * into account.
* If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
* If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
* much made this code a complete mess, but it has been pretty useful. * much made this code a complete mess, but it has been pretty useful.
...@@ -943,8 +948,13 @@ xfs_qm_dqattach( ...@@ -943,8 +948,13 @@ xfs_qm_dqattach(
nquotas++; nquotas++;
} }
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
if (XFS_IS_GQUOTA_ON(mp)) { if (XFS_IS_OQUOTA_ON(mp)) {
error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, error = XFS_IS_GQUOTA_ON(mp) ?
xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
flags & XFS_QMOPT_DQALLOC,
flags & XFS_QMOPT_DQLOCK,
ip->i_udquot, &ip->i_gdquot) :
xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
flags & XFS_QMOPT_DQALLOC, flags & XFS_QMOPT_DQALLOC,
flags & XFS_QMOPT_DQLOCK, flags & XFS_QMOPT_DQLOCK,
ip->i_udquot, &ip->i_gdquot); ip->i_udquot, &ip->i_gdquot);
...@@ -995,7 +1005,7 @@ xfs_qm_dqattach( ...@@ -995,7 +1005,7 @@ xfs_qm_dqattach(
} }
if (XFS_IS_UQUOTA_ON(mp)) if (XFS_IS_UQUOTA_ON(mp))
ASSERT(ip->i_udquot); ASSERT(ip->i_udquot);
if (XFS_IS_GQUOTA_ON(mp)) if (XFS_IS_OQUOTA_ON(mp))
ASSERT(ip->i_gdquot); ASSERT(ip->i_gdquot);
} }
#endif #endif
...@@ -1024,13 +1034,13 @@ xfs_qm_dqdetach( ...@@ -1024,13 +1034,13 @@ xfs_qm_dqdetach(
ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino); ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino); ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
if (ip->i_udquot)
xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
if (ip->i_udquot) { if (ip->i_udquot) {
xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
xfs_qm_dqrele(ip->i_udquot); xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL; ip->i_udquot = NULL;
} }
if (ip->i_gdquot) { if (ip->i_gdquot) {
xfs_dqtrace_entry_ino(ip->i_gdquot, "DQDETTACH", ip);
xfs_qm_dqrele(ip->i_gdquot); xfs_qm_dqrele(ip->i_gdquot);
ip->i_gdquot = NULL; ip->i_gdquot = NULL;
} }
...@@ -1208,8 +1218,9 @@ xfs_qm_init_quotainfo( ...@@ -1208,8 +1218,9 @@ xfs_qm_init_quotainfo(
* and group quotas, at least not at this point. * and group quotas, at least not at this point.
*/ */
error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0, error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
(XFS_IS_UQUOTA_RUNNING(mp)) ? XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER :
XFS_DQ_USER : XFS_DQ_GROUP, (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
XFS_DQ_PROJ),
XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN, XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
&dqp); &dqp);
if (! error) { if (! error) {
...@@ -1372,13 +1383,20 @@ xfs_qm_dqget_noattach( ...@@ -1372,13 +1383,20 @@ xfs_qm_dqget_noattach(
ASSERT(udqp); ASSERT(udqp);
} }
if (XFS_IS_GQUOTA_ON(mp)) { if (XFS_IS_OQUOTA_ON(mp)) {
ASSERT(ip->i_gdquot == NULL); ASSERT(ip->i_gdquot == NULL);
if (udqp) if (udqp)
xfs_dqunlock(udqp); xfs_dqunlock(udqp);
if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_gid, XFS_DQ_GROUP, error = XFS_IS_GQUOTA_ON(mp) ?
xfs_qm_dqget(mp, ip,
ip->i_d.di_gid, XFS_DQ_GROUP,
XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN, XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
&gdqp))) { &gdqp) :
xfs_qm_dqget(mp, ip,
ip->i_d.di_projid, XFS_DQ_PROJ,
XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
&gdqp);
if (error) {
if (udqp) if (udqp)
xfs_qm_dqrele(udqp); xfs_qm_dqrele(udqp);
ASSERT(error != ESRCH); ASSERT(error != ESRCH);
...@@ -1547,11 +1565,14 @@ xfs_qm_dqiter_bufs( ...@@ -1547,11 +1565,14 @@ xfs_qm_dqiter_bufs(
int error; int error;
int notcommitted; int notcommitted;
int incr; int incr;
int type;
ASSERT(blkcnt > 0); ASSERT(blkcnt > 0);
notcommitted = 0; notcommitted = 0;
incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ? incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt; XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
(flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
error = 0; error = 0;
/* /*
...@@ -1570,9 +1591,7 @@ xfs_qm_dqiter_bufs( ...@@ -1570,9 +1591,7 @@ xfs_qm_dqiter_bufs(
if (error) if (error)
break; break;
(void) xfs_qm_reset_dqcounts(mp, bp, firstid, (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
flags & XFS_QMOPT_UQUOTA ?
XFS_DQ_USER : XFS_DQ_GROUP);
xfs_bdwrite(mp, bp); xfs_bdwrite(mp, bp);
/* /*
* goto the next block. * goto the next block.
...@@ -1584,7 +1603,7 @@ xfs_qm_dqiter_bufs( ...@@ -1584,7 +1603,7 @@ xfs_qm_dqiter_bufs(
} }
/* /*
* Iterate over all allocated USR/GRP dquots in the system, calling a * Iterate over all allocated USR/GRP/PRJ dquots in the system, calling a
* caller supplied function for every chunk of dquots that we find. * caller supplied function for every chunk of dquots that we find.
*/ */
STATIC int STATIC int
...@@ -1855,7 +1874,7 @@ xfs_qm_dqusage_adjust( ...@@ -1855,7 +1874,7 @@ xfs_qm_dqusage_adjust(
xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks); xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
xfs_qm_dqput(udqp); xfs_qm_dqput(udqp);
} }
if (XFS_IS_GQUOTA_ON(mp)) { if (XFS_IS_OQUOTA_ON(mp)) {
ASSERT(gdqp); ASSERT(gdqp);
xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks); xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
xfs_qm_dqput(gdqp); xfs_qm_dqput(gdqp);
...@@ -1904,7 +1923,7 @@ xfs_qm_quotacheck( ...@@ -1904,7 +1923,7 @@ xfs_qm_quotacheck(
cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
/* /*
* First we go thru all the dquots on disk, USR and GRP, and reset * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
* their counters to zero. We need a clean slate. * their counters to zero. We need a clean slate.
* We don't log our changes till later. * We don't log our changes till later.
*/ */
...@@ -1915,9 +1934,10 @@ xfs_qm_quotacheck( ...@@ -1915,9 +1934,10 @@ xfs_qm_quotacheck(
} }
if ((gip = XFS_QI_GQIP(mp))) { if ((gip = XFS_QI_GQIP(mp))) {
if ((error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA))) if ((error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA)))
goto error_return; goto error_return;
flags |= XFS_GQUOTA_CHKD; flags |= XFS_OQUOTA_CHKD;
} }
do { do {
...@@ -1944,7 +1964,7 @@ xfs_qm_quotacheck( ...@@ -1944,7 +1964,7 @@ xfs_qm_quotacheck(
if (error) { if (error) {
xfs_qm_dqpurge_all(mp, xfs_qm_dqpurge_all(mp,
XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA| XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
XFS_QMOPT_QUOTAOFF); XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
goto error_return; goto error_return;
} }
/* /*
...@@ -1967,7 +1987,7 @@ xfs_qm_quotacheck( ...@@ -1967,7 +1987,7 @@ xfs_qm_quotacheck(
* quotachecked status, since we won't be doing accounting for * quotachecked status, since we won't be doing accounting for
* that type anymore. * that type anymore.
*/ */
mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD); mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
mp->m_qflags |= flags; mp->m_qflags |= flags;
XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++"); XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++");
...@@ -2019,7 +2039,7 @@ xfs_qm_init_quotainos( ...@@ -2019,7 +2039,7 @@ xfs_qm_init_quotainos(
0, 0, &uip, 0))) 0, 0, &uip, 0)))
return XFS_ERROR(error); return XFS_ERROR(error);
} }
if (XFS_IS_GQUOTA_ON(mp) && if (XFS_IS_OQUOTA_ON(mp) &&
mp->m_sb.sb_gquotino != NULLFSINO) { mp->m_sb.sb_gquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_gquotino > 0); ASSERT(mp->m_sb.sb_gquotino > 0);
if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
...@@ -2049,10 +2069,12 @@ xfs_qm_init_quotainos( ...@@ -2049,10 +2069,12 @@ xfs_qm_init_quotainos(
flags &= ~XFS_QMOPT_SBVERSION; flags &= ~XFS_QMOPT_SBVERSION;
} }
if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) { if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
if ((error = xfs_qm_qino_alloc(mp, &gip, flags |= (XFS_IS_GQUOTA_ON(mp) ?
sbflags | XFS_SB_GQUOTINO, XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
flags | XFS_QMOPT_GQUOTA))) { error = xfs_qm_qino_alloc(mp, &gip,
sbflags | XFS_SB_GQUOTINO, flags);
if (error) {
if (uip) if (uip)
VN_RELE(XFS_ITOV(uip)); VN_RELE(XFS_ITOV(uip));
...@@ -2458,6 +2480,7 @@ xfs_qm_vop_dqalloc( ...@@ -2458,6 +2480,7 @@ xfs_qm_vop_dqalloc(
xfs_inode_t *ip, xfs_inode_t *ip,
uid_t uid, uid_t uid,
gid_t gid, gid_t gid,
prid_t prid,
uint flags, uint flags,
xfs_dquot_t **O_udqpp, xfs_dquot_t **O_udqpp,
xfs_dquot_t **O_gdqpp) xfs_dquot_t **O_gdqpp)
...@@ -2489,8 +2512,7 @@ xfs_qm_vop_dqalloc( ...@@ -2489,8 +2512,7 @@ xfs_qm_vop_dqalloc(
} }
uq = gq = NULL; uq = gq = NULL;
if ((flags & XFS_QMOPT_UQUOTA) && if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
XFS_IS_UQUOTA_ON(mp)) {
if (ip->i_d.di_uid != uid) { if (ip->i_d.di_uid != uid) {
/* /*
* What we need is the dquot that has this uid, and * What we need is the dquot that has this uid, and
...@@ -2528,8 +2550,7 @@ xfs_qm_vop_dqalloc( ...@@ -2528,8 +2550,7 @@ xfs_qm_vop_dqalloc(
xfs_dqunlock(uq); xfs_dqunlock(uq);
} }
} }
if ((flags & XFS_QMOPT_GQUOTA) && if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
XFS_IS_GQUOTA_ON(mp)) {
if (ip->i_d.di_gid != gid) { if (ip->i_d.di_gid != gid) {
xfs_iunlock(ip, lockflags); xfs_iunlock(ip, lockflags);
if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid, if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
...@@ -2552,6 +2573,29 @@ xfs_qm_vop_dqalloc( ...@@ -2552,6 +2573,29 @@ xfs_qm_vop_dqalloc(
XFS_DQHOLD(gq); XFS_DQHOLD(gq);
xfs_dqunlock(gq); xfs_dqunlock(gq);
} }
} else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
if (ip->i_d.di_projid != prid) {
xfs_iunlock(ip, lockflags);
if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
XFS_DQ_PROJ,
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
&gq))) {
if (uq)
xfs_qm_dqrele(uq);
ASSERT(error != ENOENT);
return (error);
}
xfs_dqunlock(gq);
lockflags = XFS_ILOCK_SHARED;
xfs_ilock(ip, lockflags);
} else {
ASSERT(ip->i_gdquot);
gq = ip->i_gdquot;
xfs_dqlock(gq);
XFS_DQHOLD(gq);
xfs_dqunlock(gq);
}
} }
if (uq) if (uq)
xfs_dqtrace_entry_ino(uq, "DQALLOC", ip); xfs_dqtrace_entry_ino(uq, "DQALLOC", ip);
...@@ -2617,7 +2661,7 @@ xfs_qm_vop_chown( ...@@ -2617,7 +2661,7 @@ xfs_qm_vop_chown(
} }
/* /*
* Quota reservations for setattr(AT_UID|AT_GID). * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
*/ */
int int
xfs_qm_vop_chown_reserve( xfs_qm_vop_chown_reserve(
...@@ -2652,14 +2696,18 @@ xfs_qm_vop_chown_reserve( ...@@ -2652,14 +2696,18 @@ xfs_qm_vop_chown_reserve(
unresudq = ip->i_udquot; unresudq = ip->i_udquot;
} }
} }
if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
ip->i_d.di_gid != INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) { if ((XFS_IS_GQUOTA_ON(ip->i_mount) && ip->i_d.di_gid !=
INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) ||
(XFS_IS_PQUOTA_ON(ip->i_mount) && ip->i_d.di_projid !=
INT_GET(gdqp->q_core.d_id, ARCH_CONVERT))) {
delblksgdq = gdqp; delblksgdq = gdqp;
if (delblks) { if (delblks) {
ASSERT(ip->i_gdquot); ASSERT(ip->i_gdquot);
unresgdq = ip->i_gdquot; unresgdq = ip->i_gdquot;
} }
} }
}
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,
......
/* /*
* Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as * under the terms of version 2 of the GNU General Public License as
...@@ -202,7 +202,7 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); ...@@ -202,7 +202,7 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
/* vop stuff */ /* vop stuff */
extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
uid_t, gid_t, uint, uid_t, gid_t, prid_t, uint,
xfs_dquot_t **, xfs_dquot_t **); xfs_dquot_t **, xfs_dquot_t **);
extern void xfs_qm_vop_dqattach_and_dqmod_newinode( extern void xfs_qm_vop_dqattach_and_dqmod_newinode(
xfs_trans_t *, xfs_inode_t *, xfs_trans_t *, xfs_inode_t *,
......
...@@ -71,10 +71,13 @@ ...@@ -71,10 +71,13 @@
#define MNTOPT_NOQUOTA "noquota" /* no quotas */ #define MNTOPT_NOQUOTA "noquota" /* no quotas */
#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */ #define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */ #define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */ #define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */ #define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */ #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ #define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
STATIC int STATIC int
...@@ -109,6 +112,14 @@ xfs_qm_parseargs( ...@@ -109,6 +112,14 @@ xfs_qm_parseargs(
args->flags |= XFSMNT_UQUOTA; args->flags |= XFSMNT_UQUOTA;
args->flags &= ~XFSMNT_UQUOTAENF; args->flags &= ~XFSMNT_UQUOTAENF;
referenced = 1; referenced = 1;
} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
!strcmp(this_char, MNTOPT_PRJQUOTA)) {
args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
referenced = 1;
} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
args->flags |= XFSMNT_PQUOTA;
args->flags &= ~XFSMNT_PQUOTAENF;
referenced = 1;
} else if (!strcmp(this_char, MNTOPT_GQUOTA) || } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
!strcmp(this_char, MNTOPT_GRPQUOTA)) { !strcmp(this_char, MNTOPT_GRPQUOTA)) {
args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
...@@ -127,6 +138,12 @@ xfs_qm_parseargs( ...@@ -127,6 +138,12 @@ xfs_qm_parseargs(
*this_char++ = ','; *this_char++ = ',';
} }
if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
cmn_err(CE_WARN,
"XFS: cannot mount with both project and group quota");
return XFS_ERROR(EINVAL);
}
PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
if (!error && !referenced) if (!error && !referenced)
bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
...@@ -148,13 +165,19 @@ xfs_qm_showargs( ...@@ -148,13 +165,19 @@ xfs_qm_showargs(
seq_puts(m, "," MNTOPT_UQUOTANOENF); seq_puts(m, "," MNTOPT_UQUOTANOENF);
} }
if (mp->m_qflags & XFS_PQUOTA_ACCT) {
(mp->m_qflags & XFS_OQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_PRJQUOTA) :
seq_puts(m, "," MNTOPT_PQUOTANOENF);
}
if (mp->m_qflags & XFS_GQUOTA_ACCT) { if (mp->m_qflags & XFS_GQUOTA_ACCT) {
(mp->m_qflags & XFS_GQUOTA_ENFD) ? (mp->m_qflags & XFS_OQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_GRPQUOTA) : seq_puts(m, "," MNTOPT_GRPQUOTA) :
seq_puts(m, "," MNTOPT_GQUOTANOENF); seq_puts(m, "," MNTOPT_GQUOTANOENF);
} }
if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
seq_puts(m, "," MNTOPT_NOQUOTA); seq_puts(m, "," MNTOPT_NOQUOTA);
PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
...@@ -171,7 +194,7 @@ xfs_qm_mount( ...@@ -171,7 +194,7 @@ xfs_qm_mount(
struct xfs_mount *mp = XFS_VFSTOM(vfsp); struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error; int error;
if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)) if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
xfs_qm_mount_quotainit(mp, args->flags); xfs_qm_mount_quotainit(mp, args->flags);
PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
return error; return error;
...@@ -255,16 +278,17 @@ xfs_qm_newmount( ...@@ -255,16 +278,17 @@ xfs_qm_newmount(
uint *quotaflags) uint *quotaflags)
{ {
uint quotaondisk; uint quotaondisk;
uint uquotaondisk = 0, gquotaondisk = 0; uint uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
*quotaflags = 0; *quotaflags = 0;
*needquotamount = B_FALSE; *needquotamount = B_FALSE;
quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
if (quotaondisk) { if (quotaondisk) {
uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT; uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT; gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
} }
...@@ -277,13 +301,16 @@ xfs_qm_newmount( ...@@ -277,13 +301,16 @@ xfs_qm_newmount(
if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
(!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
(pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
(!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) ||
(gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
(!gquotaondisk && XFS_IS_GQUOTA_ON(mp))) && (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) &&
xfs_dev_is_read_only(mp, "changing quota state")) { xfs_dev_is_read_only(mp, "changing quota state")) {
cmn_err(CE_WARN, cmn_err(CE_WARN,
"XFS: please mount with%s%s%s.", "XFS: please mount with%s%s%s%s.",
(!quotaondisk ? "out quota" : ""), (!quotaondisk ? "out quota" : ""),
(uquotaondisk ? " usrquota" : ""), (uquotaondisk ? " usrquota" : ""),
(pquotaondisk ? " prjquota" : ""),
(gquotaondisk ? " grpquota" : "")); (gquotaondisk ? " grpquota" : ""));
return XFS_ERROR(EPERM); return XFS_ERROR(EPERM);
} }
......
...@@ -118,34 +118,35 @@ xfs_qm_quotactl( ...@@ -118,34 +118,35 @@ xfs_qm_quotactl(
* The following commands are valid even when quotaoff. * The following commands are valid even when quotaoff.
*/ */
switch (cmd) { switch (cmd) {
case Q_XQUOTARM:
/* /*
* truncate quota files. quota must be off. * Truncate quota files. quota must be off.
*/ */
case Q_XQUOTARM:
if (XFS_IS_QUOTA_ON(mp) || addr == NULL) if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
return XFS_ERROR(EINVAL); return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY) if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS); return XFS_ERROR(EROFS);
return (xfs_qm_scall_trunc_qfiles(mp, return (xfs_qm_scall_trunc_qfiles(mp,
xfs_qm_import_qtype_flags(*(uint *)addr))); xfs_qm_import_qtype_flags(*(uint *)addr)));
case Q_XGETQSTAT:
/* /*
* Get quota status information. * Get quota status information.
*/ */
case Q_XGETQSTAT:
return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
case Q_XQUOTAON:
/* /*
* QUOTAON for root f/s and quota enforcement on others.. * QUOTAON - enabling quota enforcement.
* Quota accounting for non-root f/s's must be turned on * Quota accounting must be turned on at mount time.
* at mount time.
*/ */
case Q_XQUOTAON:
if (addr == NULL) if (addr == NULL)
return XFS_ERROR(EINVAL); return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY) if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS); return XFS_ERROR(EROFS);
return (xfs_qm_scall_quotaon(mp, return (xfs_qm_scall_quotaon(mp,
xfs_qm_import_flags(*(uint *)addr))); xfs_qm_import_flags(*(uint *)addr)));
case Q_XQUOTAOFF: case Q_XQUOTAOFF:
if (vfsp->vfs_flag & VFS_RDONLY) if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS); return XFS_ERROR(EROFS);
...@@ -167,41 +168,38 @@ xfs_qm_quotactl( ...@@ -167,41 +168,38 @@ xfs_qm_quotactl(
B_FALSE); B_FALSE);
break; break;
/*
* Defaults to XFS_GETUQUOTA.
*/
case Q_XGETQUOTA: case Q_XGETQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr); (fs_disk_quota_t *)addr);
break; break;
/* case Q_XGETGQUOTA:
* Set limits, both hard and soft. Defaults to Q_SETUQLIM. error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
*/ (fs_disk_quota_t *)addr);
break;
case Q_XGETPQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
(fs_disk_quota_t *)addr);
break;
case Q_XSETQLIM: case Q_XSETQLIM:
if (vfsp->vfs_flag & VFS_RDONLY) if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS); return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr); (fs_disk_quota_t *)addr);
break; break;
case Q_XSETGQLIM: case Q_XSETGQLIM:
if (vfsp->vfs_flag & VFS_RDONLY) if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS); return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr); (fs_disk_quota_t *)addr);
break; break;
case Q_XSETPQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
case Q_XGETGQUOTA: return XFS_ERROR(EROFS);
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
(fs_disk_quota_t *)addr); (fs_disk_quota_t *)addr);
break; break;
/*
* Quotas are entirely undefined after quotaoff in XFS quotas.
* For instance, there's no way to set limits when quotaoff.
*/
default: default:
error = XFS_ERROR(EINVAL); error = XFS_ERROR(EINVAL);
break; break;
...@@ -286,8 +284,12 @@ xfs_qm_scall_quotaoff( ...@@ -286,8 +284,12 @@ xfs_qm_scall_quotaoff(
} }
if (flags & XFS_GQUOTA_ACCT) { if (flags & XFS_GQUOTA_ACCT) {
dqtype |= XFS_QMOPT_GQUOTA; dqtype |= XFS_QMOPT_GQUOTA;
flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
inactivate_flags |= XFS_GQUOTA_ACTIVE; inactivate_flags |= XFS_GQUOTA_ACTIVE;
} else if (flags & XFS_PQUOTA_ACCT) {
dqtype |= XFS_QMOPT_PQUOTA;
flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
inactivate_flags |= XFS_PQUOTA_ACTIVE;
} }
/* /*
...@@ -364,7 +366,8 @@ xfs_qm_scall_quotaoff( ...@@ -364,7 +366,8 @@ xfs_qm_scall_quotaoff(
/* /*
* If quotas is completely disabled, close shop. * If quotas is completely disabled, close shop.
*/ */
if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) { if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
mutex_unlock(&(XFS_QI_QOFFLOCK(mp))); mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
xfs_qm_destroy_quotainfo(mp); xfs_qm_destroy_quotainfo(mp);
return (0); return (0);
...@@ -378,7 +381,7 @@ xfs_qm_scall_quotaoff( ...@@ -378,7 +381,7 @@ xfs_qm_scall_quotaoff(
XFS_PURGE_INODE(XFS_QI_UQIP(mp)); XFS_PURGE_INODE(XFS_QI_UQIP(mp));
XFS_QI_UQIP(mp) = NULL; XFS_QI_UQIP(mp) = NULL;
} }
if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) { if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
XFS_PURGE_INODE(XFS_QI_GQIP(mp)); XFS_PURGE_INODE(XFS_QI_GQIP(mp));
XFS_QI_GQIP(mp) = NULL; XFS_QI_GQIP(mp) = NULL;
} }
...@@ -411,7 +414,8 @@ xfs_qm_scall_trunc_qfiles( ...@@ -411,7 +414,8 @@ xfs_qm_scall_trunc_qfiles(
} }
} }
if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) { if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
mp->m_sb.sb_gquotino != NULLFSINO) {
error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0); error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
if (! error) { if (! error) {
(void) xfs_truncate_file(mp, qip); (void) xfs_truncate_file(mp, qip);
...@@ -468,9 +472,13 @@ xfs_qm_scall_quotaon( ...@@ -468,9 +472,13 @@ xfs_qm_scall_quotaon(
(mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 && (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
(flags & XFS_UQUOTA_ENFD)) (flags & XFS_UQUOTA_ENFD))
|| ||
((flags & XFS_PQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
(flags & XFS_OQUOTA_ENFD))
||
((flags & XFS_GQUOTA_ACCT) == 0 && ((flags & XFS_GQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 && (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
(flags & XFS_GQUOTA_ENFD))) { (flags & XFS_OQUOTA_ENFD))) {
qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n", qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
flags, mp->m_sb.sb_qflags); flags, mp->m_sb.sb_qflags);
return XFS_ERROR(EINVAL); return XFS_ERROR(EINVAL);
...@@ -504,6 +512,10 @@ xfs_qm_scall_quotaon( ...@@ -504,6 +512,10 @@ xfs_qm_scall_quotaon(
*/ */
if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) != if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
(mp->m_qflags & XFS_UQUOTA_ACCT)) || (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
(mp->m_qflags & XFS_PQUOTA_ACCT)) ||
((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
(mp->m_qflags & XFS_GQUOTA_ACCT)) ||
(flags & XFS_ALL_QUOTA_ENFD) == 0) (flags & XFS_ALL_QUOTA_ENFD) == 0)
return (0); return (0);
...@@ -521,7 +533,6 @@ xfs_qm_scall_quotaon( ...@@ -521,7 +533,6 @@ xfs_qm_scall_quotaon(
} }
/* /*
* Return quota status information, such as uquota-off, enforcements, etc. * Return quota status information, such as uquota-off, enforcements, etc.
*/ */
...@@ -930,16 +941,24 @@ STATIC uint ...@@ -930,16 +941,24 @@ STATIC uint
xfs_qm_import_qtype_flags( xfs_qm_import_qtype_flags(
uint uflags) uint uflags)
{ {
uint oflags = 0;
/* /*
* Can't be both at the same time. * Can't be more than one, or none.
*/ */
if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
(XFS_GROUP_QUOTA | XFS_USER_QUOTA)) || (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0)) ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
(XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
(XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
return (0); return (0);
return (uflags & XFS_USER_QUOTA) ? oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
XFS_DQ_USER : XFS_DQ_GROUP; oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
return oflags;
} }
STATIC uint STATIC uint
...@@ -947,14 +966,19 @@ xfs_qm_export_qtype_flags( ...@@ -947,14 +966,19 @@ xfs_qm_export_qtype_flags(
uint flags) uint flags)
{ {
/* /*
* Can't be both at the same time. * Can't be more than one, or none.
*/ */
ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) !=
(XFS_GROUP_QUOTA | XFS_USER_QUOTA)); (XFS_PROJ_QUOTA | XFS_USER_QUOTA));
ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0); ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) !=
(XFS_PROJ_QUOTA | XFS_GROUP_QUOTA));
ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) !=
(XFS_USER_QUOTA | XFS_GROUP_QUOTA));
ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0);
return (flags & XFS_DQ_USER) ? return (flags & XFS_DQ_USER) ?
XFS_USER_QUOTA : XFS_GROUP_QUOTA; XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
} }
STATIC uint STATIC uint
...@@ -965,12 +989,14 @@ xfs_qm_import_flags( ...@@ -965,12 +989,14 @@ xfs_qm_import_flags(
if (uflags & XFS_QUOTA_UDQ_ACCT) if (uflags & XFS_QUOTA_UDQ_ACCT)
flags |= XFS_UQUOTA_ACCT; flags |= XFS_UQUOTA_ACCT;
if (uflags & XFS_QUOTA_PDQ_ACCT)
flags |= XFS_PQUOTA_ACCT;
if (uflags & XFS_QUOTA_GDQ_ACCT) if (uflags & XFS_QUOTA_GDQ_ACCT)
flags |= XFS_GQUOTA_ACCT; flags |= XFS_GQUOTA_ACCT;
if (uflags & XFS_QUOTA_UDQ_ENFD) if (uflags & XFS_QUOTA_UDQ_ENFD)
flags |= XFS_UQUOTA_ENFD; flags |= XFS_UQUOTA_ENFD;
if (uflags & XFS_QUOTA_GDQ_ENFD) if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
flags |= XFS_GQUOTA_ENFD; flags |= XFS_OQUOTA_ENFD;
return (flags); return (flags);
} }
...@@ -984,12 +1010,16 @@ xfs_qm_export_flags( ...@@ -984,12 +1010,16 @@ xfs_qm_export_flags(
uflags = 0; uflags = 0;
if (flags & XFS_UQUOTA_ACCT) if (flags & XFS_UQUOTA_ACCT)
uflags |= XFS_QUOTA_UDQ_ACCT; uflags |= XFS_QUOTA_UDQ_ACCT;
if (flags & XFS_PQUOTA_ACCT)
uflags |= XFS_QUOTA_PDQ_ACCT;
if (flags & XFS_GQUOTA_ACCT) if (flags & XFS_GQUOTA_ACCT)
uflags |= XFS_QUOTA_GDQ_ACCT; uflags |= XFS_QUOTA_GDQ_ACCT;
if (flags & XFS_UQUOTA_ENFD) if (flags & XFS_UQUOTA_ENFD)
uflags |= XFS_QUOTA_UDQ_ENFD; uflags |= XFS_QUOTA_UDQ_ENFD;
if (flags & XFS_GQUOTA_ENFD) if (flags & (XFS_OQUOTA_ENFD)) {
uflags |= XFS_QUOTA_GDQ_ENFD; uflags |= (flags & XFS_GQUOTA_ACCT) ?
XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;
}
return (uflags); return (uflags);
} }
...@@ -1070,7 +1100,7 @@ xfs_qm_dqrele_all_inodes( ...@@ -1070,7 +1100,7 @@ xfs_qm_dqrele_all_inodes(
xfs_qm_dqrele(ip->i_udquot); xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL; ip->i_udquot = NULL;
} }
if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) { if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
xfs_qm_dqrele(ip->i_gdquot); xfs_qm_dqrele(ip->i_gdquot);
ip->i_gdquot = NULL; ip->i_gdquot = NULL;
} }
...@@ -1160,7 +1190,6 @@ xfs_qm_dqtest_print( ...@@ -1160,7 +1190,6 @@ xfs_qm_dqtest_print(
{ {
cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
cmn_err(CE_DEBUG, "---- type = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount); cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount);
cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)",
d->d_bcount, (int)d->d_bcount); d->d_bcount, (int)d->d_bcount);
...@@ -1231,7 +1260,7 @@ xfs_dqtest_cmp2( ...@@ -1231,7 +1260,7 @@ xfs_dqtest_cmp2(
#ifdef QUOTADEBUG #ifdef QUOTADEBUG
if (!err) { if (!err) {
cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount); d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
} }
#endif #endif
return (err); return (err);
...@@ -1287,6 +1316,7 @@ STATIC void ...@@ -1287,6 +1316,7 @@ STATIC void
xfs_qm_internalqcheck_get_dquots( xfs_qm_internalqcheck_get_dquots(
xfs_mount_t *mp, xfs_mount_t *mp,
xfs_dqid_t uid, xfs_dqid_t uid,
xfs_dqid_t projid,
xfs_dqid_t gid, xfs_dqid_t gid,
xfs_dqtest_t **ud, xfs_dqtest_t **ud,
xfs_dqtest_t **gd) xfs_dqtest_t **gd)
...@@ -1295,6 +1325,8 @@ xfs_qm_internalqcheck_get_dquots( ...@@ -1295,6 +1325,8 @@ xfs_qm_internalqcheck_get_dquots(
xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud); xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
if (XFS_IS_GQUOTA_ON(mp)) if (XFS_IS_GQUOTA_ON(mp))
xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd); xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
else if (XFS_IS_PQUOTA_ON(mp))
xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
} }
...@@ -1362,13 +1394,14 @@ xfs_qm_internalqcheck_adjust( ...@@ -1362,13 +1394,14 @@ xfs_qm_internalqcheck_adjust(
} }
xfs_qm_internalqcheck_get_dquots(mp, xfs_qm_internalqcheck_get_dquots(mp,
(xfs_dqid_t) ip->i_d.di_uid, (xfs_dqid_t) ip->i_d.di_uid,
(xfs_dqid_t) ip->i_d.di_projid,
(xfs_dqid_t) ip->i_d.di_gid, (xfs_dqid_t) ip->i_d.di_gid,
&ud, &gd); &ud, &gd);
if (XFS_IS_UQUOTA_ON(mp)) { if (XFS_IS_UQUOTA_ON(mp)) {
ASSERT(ud); ASSERT(ud);
xfs_qm_internalqcheck_dqadjust(ip, ud); xfs_qm_internalqcheck_dqadjust(ip, ud);
} }
if (XFS_IS_GQUOTA_ON(mp)) { if (XFS_IS_OQUOTA_ON(mp)) {
ASSERT(gd); ASSERT(gd);
xfs_qm_internalqcheck_dqadjust(ip, gd); xfs_qm_internalqcheck_dqadjust(ip, gd);
} }
......
...@@ -102,7 +102,8 @@ static inline int XQMISLCKD(struct xfs_dqhash *h) ...@@ -102,7 +102,8 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
(xfs_Gqm->qm_grp_dqhtable + \ (xfs_Gqm->qm_grp_dqhtable + \
XFS_DQ_HASHVAL(mp, id))) XFS_DQ_HASHVAL(mp, id)))
#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \ #define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \
XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp)) XFS_IS_UQUOTA_ON(mp) : \
XFS_IS_OQUOTA_ON(mp))
#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \ #define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
!dqp->q_core.d_blk_hardlimit && \ !dqp->q_core.d_blk_hardlimit && \
!dqp->q_core.d_blk_softlimit && \ !dqp->q_core.d_blk_softlimit && \
...@@ -180,7 +181,8 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \ ...@@ -180,7 +181,8 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
IRELE(ip); IRELE(ip);
#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \ #define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
(((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : "???")) (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
(((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
#define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY") #define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
#endif /* __XFS_QUOTA_PRIV_H__ */ #endif /* __XFS_QUOTA_PRIV_H__ */
...@@ -207,12 +207,10 @@ xfs_trans_mod_dquot_byino( ...@@ -207,12 +207,10 @@ xfs_trans_mod_dquot_byino(
if (tp->t_dqinfo == NULL) if (tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp); xfs_trans_alloc_dqinfo(tp);
if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) { if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
(void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
} if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
(void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
}
} }
STATIC xfs_dqtrx_t * STATIC xfs_dqtrx_t *
......
...@@ -80,7 +80,7 @@ typedef struct xfs_buf_log_format_t { ...@@ -80,7 +80,7 @@ typedef struct xfs_buf_log_format_t {
* user or group dquots and may require special recovery handling. * user or group dquots and may require special recovery handling.
*/ */
#define XFS_BLI_UDQUOT_BUF 0x4 #define XFS_BLI_UDQUOT_BUF 0x4
/* #define XFS_BLI_PDQUOT_BUF 0x8 */ #define XFS_BLI_PDQUOT_BUF 0x8
#define XFS_BLI_GDQUOT_BUF 0x10 #define XFS_BLI_GDQUOT_BUF 0x10
#define XFS_BLI_CHUNK 128 #define XFS_BLI_CHUNK 128
......
...@@ -1964,7 +1964,8 @@ xlog_recover_do_reg_buffer( ...@@ -1964,7 +1964,8 @@ xlog_recover_do_reg_buffer(
* probably a good thing to do for other buf types also. * probably a good thing to do for other buf types also.
*/ */
error = 0; error = 0;
if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { if (buf_f->blf_flags &
(XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
error = xfs_qm_dqcheck((xfs_disk_dquot_t *) error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
item->ri_buf[i].i_addr, item->ri_buf[i].i_addr,
-1, 0, XFS_QMOPT_DOWARN, -1, 0, XFS_QMOPT_DOWARN,
...@@ -2030,6 +2031,7 @@ xfs_qm_dqcheck( ...@@ -2030,6 +2031,7 @@ xfs_qm_dqcheck(
} }
if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER && if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER &&
INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_PROJ &&
INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) { INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) {
if (flags & XFS_QMOPT_DOWARN) if (flags & XFS_QMOPT_DOWARN)
cmn_err(CE_ALERT, cmn_err(CE_ALERT,
...@@ -2135,6 +2137,8 @@ xlog_recover_do_dquot_buffer( ...@@ -2135,6 +2137,8 @@ xlog_recover_do_dquot_buffer(
type = 0; type = 0;
if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF) if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
type |= XFS_DQ_USER; type |= XFS_DQ_USER;
if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
type |= XFS_DQ_PROJ;
if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF) if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
type |= XFS_DQ_GROUP; type |= XFS_DQ_GROUP;
/* /*
...@@ -2247,7 +2251,8 @@ xlog_recover_do_buffer_trans( ...@@ -2247,7 +2251,8 @@ xlog_recover_do_buffer_trans(
error = 0; error = 0;
if (flags & XFS_BLI_INODE_BUF) { if (flags & XFS_BLI_INODE_BUF) {
error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
} else if (flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) { } else if (flags &
(XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
} else { } else {
xlog_recover_do_reg_buffer(mp, item, bp, buf_f); xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
...@@ -2619,7 +2624,7 @@ xlog_recover_do_dquot_trans( ...@@ -2619,7 +2624,7 @@ xlog_recover_do_dquot_trans(
* This type of quotas was turned off, so ignore this record. * This type of quotas was turned off, so ignore this record.
*/ */
type = INT_GET(recddq->d_flags, ARCH_CONVERT) & type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
(XFS_DQ_USER | XFS_DQ_GROUP); (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
ASSERT(type); ASSERT(type);
if (log->l_quotaoffs_flag & type) if (log->l_quotaoffs_flag & type)
return (0); return (0);
......
...@@ -141,7 +141,7 @@ typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint); ...@@ -141,7 +141,7 @@ typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint);
typedef void (*xfs_dqdetach_t)(struct xfs_inode *); typedef void (*xfs_dqdetach_t)(struct xfs_inode *);
typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint); typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *, typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *,
struct xfs_inode *, uid_t, gid_t, uint, struct xfs_inode *, uid_t, gid_t, prid_t, uint,
struct xfs_dquot **, struct xfs_dquot **); struct xfs_dquot **, struct xfs_dquot **);
typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *, typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
struct xfs_dquot *, struct xfs_dquot *); struct xfs_dquot *, struct xfs_dquot *);
...@@ -185,8 +185,8 @@ typedef struct xfs_qmops { ...@@ -185,8 +185,8 @@ typedef struct xfs_qmops {
(*(mp)->m_qm_ops.xfs_dqdetach)(ip) (*(mp)->m_qm_ops.xfs_dqdetach)(ip)
#define XFS_QM_DQPURGEALL(mp, fl) \ #define XFS_QM_DQPURGEALL(mp, fl) \
(*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl) (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \ #define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
(*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2) (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \ #define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
(*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2) (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
#define XFS_QM_DQVOPRENAME(mp, ip) \ #define XFS_QM_DQVOPRENAME(mp, ip) \
......
...@@ -96,7 +96,7 @@ typedef struct xfs_dqblk { ...@@ -96,7 +96,7 @@ typedef struct xfs_dqblk {
* flags for q_flags field in the dquot. * flags for q_flags field in the dquot.
*/ */
#define XFS_DQ_USER 0x0001 /* a user quota */ #define XFS_DQ_USER 0x0001 /* a user quota */
/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */ #define XFS_DQ_PROJ 0x0002 /* project quota */
#define XFS_DQ_GROUP 0x0004 /* a group quota */ #define XFS_DQ_GROUP 0x0004 /* a group quota */
#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */ #define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */
#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */ #define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */
...@@ -104,6 +104,8 @@ typedef struct xfs_dqblk { ...@@ -104,6 +104,8 @@ typedef struct xfs_dqblk {
#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */ #define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */
#define XFS_DQ_MARKER 0x0080 /* sentinel */ #define XFS_DQ_MARKER 0x0080 /* sentinel */
#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
/* /*
* In the worst case, when both user and group quotas are on, * In the worst case, when both user and group quotas are on,
* we can have a max of three dquots changing in a single transaction. * we can have a max of three dquots changing in a single transaction.
...@@ -124,7 +126,7 @@ typedef struct xfs_dqblk { ...@@ -124,7 +126,7 @@ typedef struct xfs_dqblk {
typedef struct xfs_dq_logformat { typedef struct xfs_dq_logformat {
__uint16_t qlf_type; /* dquot log item type */ __uint16_t qlf_type; /* dquot log item type */
__uint16_t qlf_size; /* size of this item */ __uint16_t qlf_size; /* size of this item */
xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */ xfs_dqid_t qlf_id; /* usr/grp/proj id : 32 bits */
__int64_t qlf_blkno; /* blkno of dquot buffer */ __int64_t qlf_blkno; /* blkno of dquot buffer */
__int32_t qlf_len; /* len of dquot buffer */ __int32_t qlf_len; /* len of dquot buffer */
__uint32_t qlf_boffset; /* off of dquot in buffer */ __uint32_t qlf_boffset; /* off of dquot in buffer */
...@@ -152,9 +154,9 @@ typedef struct xfs_qoff_logformat { ...@@ -152,9 +154,9 @@ typedef struct xfs_qoff_logformat {
#define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */ #define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */
#define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */ #define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */
#define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */ #define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */
#define XFS_PQUOTA_ACCT 0x0008 /* (IRIX) project quota accounting ON */ #define XFS_PQUOTA_ACCT 0x0008 /* project quota accounting ON */
#define XFS_GQUOTA_ENFD 0x0010 /* group quota limits enforced */ #define XFS_OQUOTA_ENFD 0x0010 /* other (grp/prj) quota limits enforced */
#define XFS_GQUOTA_CHKD 0x0020 /* quotacheck run on grp quotas */ #define XFS_OQUOTA_CHKD 0x0020 /* quotacheck run on other (grp/prj) quotas */
#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */ #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
/* /*
...@@ -162,17 +164,22 @@ typedef struct xfs_qoff_logformat { ...@@ -162,17 +164,22 @@ typedef struct xfs_qoff_logformat {
* are in the process of getting turned off. These flags are in m_qflags but * are in the process of getting turned off. These flags are in m_qflags but
* never in sb_qflags. * never in sb_qflags.
*/ */
#define XFS_UQUOTA_ACTIVE 0x0080 /* uquotas are being turned off */ #define XFS_UQUOTA_ACTIVE 0x0100 /* uquotas are being turned off */
#define XFS_GQUOTA_ACTIVE 0x0100 /* gquotas are being turned off */ #define XFS_PQUOTA_ACTIVE 0x0200 /* pquotas are being turned off */
#define XFS_GQUOTA_ACTIVE 0x0400 /* gquotas are being turned off */
/* /*
* Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
* quota will be not be switched off as long as that inode lock is held. * quota will be not be switched off as long as that inode lock is held.
*/ */
#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \ #define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
XFS_GQUOTA_ACTIVE)) XFS_GQUOTA_ACTIVE | \
XFS_PQUOTA_ACTIVE))
#define XFS_IS_OQUOTA_ON(mp) ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
XFS_PQUOTA_ACTIVE))
#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE) #define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE) #define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
/* /*
* Flags to tell various functions what to do. Not all of these are meaningful * Flags to tell various functions what to do. Not all of these are meaningful
...@@ -182,7 +189,7 @@ typedef struct xfs_qoff_logformat { ...@@ -182,7 +189,7 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */ #define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */
#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */
#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */
#define XFS_QMOPT_GQUOTA 0x0000008 /* group dquot requested */ #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */
#define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */ #define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */
#define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */ #define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */
#define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */ #define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */
...@@ -192,6 +199,7 @@ typedef struct xfs_qoff_logformat { ...@@ -192,6 +199,7 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */ #define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */
#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 */
/* /*
* 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
...@@ -231,7 +239,8 @@ typedef struct xfs_qoff_logformat { ...@@ -231,7 +239,8 @@ typedef struct xfs_qoff_logformat {
#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT #define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
#define XFS_QMOPT_QUOTALL (XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA) #define XFS_QMOPT_QUOTALL \
(XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) #define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -246,21 +255,33 @@ typedef struct xfs_qoff_logformat { ...@@ -246,21 +255,33 @@ typedef struct xfs_qoff_logformat {
*/ */
#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ #define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
(ip)->i_udquot == NULL) || \ (ip)->i_udquot == NULL) || \
(XFS_IS_GQUOTA_ON(mp) && \ (XFS_IS_OQUOTA_ON(mp) && \
(ip)->i_gdquot == NULL)) (ip)->i_gdquot == NULL))
#define XFS_QM_NEED_QUOTACHECK(mp) ((XFS_IS_UQUOTA_ON(mp) && \ #define XFS_QM_NEED_QUOTACHECK(mp) \
(mp->m_sb.sb_qflags & \ ((XFS_IS_UQUOTA_ON(mp) && \
XFS_UQUOTA_CHKD) == 0) || \ (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
(XFS_IS_GQUOTA_ON(mp) && \ (XFS_IS_GQUOTA_ON(mp) && \
(mp->m_sb.sb_qflags & \ ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
XFS_GQUOTA_CHKD) == 0)) (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
(XFS_IS_PQUOTA_ON(mp) && \
((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
(mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ #define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD) XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
XFS_GQUOTA_ACCT)
#define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \ #define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
XFS_GQUOTA_ACTIVE) XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
/* /*
......
...@@ -976,6 +976,7 @@ xfs_trans_dquot_buf( ...@@ -976,6 +976,7 @@ xfs_trans_dquot_buf(
ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
ASSERT(type == XFS_BLI_UDQUOT_BUF || ASSERT(type == XFS_BLI_UDQUOT_BUF ||
type == XFS_BLI_PDQUOT_BUF ||
type == XFS_BLI_GDQUOT_BUF); type == XFS_BLI_GDQUOT_BUF);
bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
......
...@@ -428,7 +428,7 @@ xfs_truncate_file( ...@@ -428,7 +428,7 @@ xfs_truncate_file(
if (ip->i_ino != mp->m_sb.sb_uquotino) if (ip->i_ino != mp->m_sb.sb_uquotino)
ASSERT(ip->i_udquot); ASSERT(ip->i_udquot);
} }
if (XFS_IS_GQUOTA_ON(mp)) { if (XFS_IS_OQUOTA_ON(mp)) {
if (ip->i_ino != mp->m_sb.sb_gquotino) if (ip->i_ino != mp->m_sb.sb_gquotino)
ASSERT(ip->i_gdquot); ASSERT(ip->i_gdquot);
} }
......
...@@ -367,16 +367,6 @@ xfs_finish_flags( ...@@ -367,16 +367,6 @@ xfs_finish_flags(
return XFS_ERROR(EROFS); return XFS_ERROR(EROFS);
} }
/*
* disallow mount attempts with (IRIX) project quota enabled
*/
if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
(mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {
cmn_err(CE_WARN,
"XFS: cannot mount a filesystem with IRIX project quota enabled");
return XFS_ERROR(ENOSYS);
}
/* /*
* check for shared mount. * check for shared mount.
*/ */
......
...@@ -351,21 +351,28 @@ xfs_setattr( ...@@ -351,21 +351,28 @@ xfs_setattr(
* If the IDs do change before we take the ilock, we're covered * If the IDs do change before we take the ilock, we're covered
* because the i_*dquot fields will get updated anyway. * because the i_*dquot fields will get updated anyway.
*/ */
if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) { if (XFS_IS_QUOTA_ON(mp) &&
(mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
uint qflags = 0; uint qflags = 0;
if (mask & XFS_AT_UID) { if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
uid = vap->va_uid; uid = vap->va_uid;
qflags |= XFS_QMOPT_UQUOTA; qflags |= XFS_QMOPT_UQUOTA;
} else { } else {
uid = ip->i_d.di_uid; uid = ip->i_d.di_uid;
} }
if (mask & XFS_AT_GID) { if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
gid = vap->va_gid; gid = vap->va_gid;
qflags |= XFS_QMOPT_GQUOTA; qflags |= XFS_QMOPT_GQUOTA;
} else { } else {
gid = ip->i_d.di_gid; gid = ip->i_d.di_gid;
} }
if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
projid = vap->va_projid;
qflags |= XFS_QMOPT_PQUOTA;
} else {
projid = ip->i_d.di_projid;
}
/* /*
* We take a reference when we initialize udqp and gdqp, * We take a reference when we initialize udqp and gdqp,
* so it is important that we never blindly double trip on * so it is important that we never blindly double trip on
...@@ -373,7 +380,8 @@ xfs_setattr( ...@@ -373,7 +380,8 @@ xfs_setattr(
*/ */
ASSERT(udqp == NULL); ASSERT(udqp == NULL);
ASSERT(gdqp == NULL); ASSERT(gdqp == NULL);
code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp); code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
&udqp, &gdqp);
if (code) if (code)
return (code); return (code);
} }
...@@ -510,10 +518,11 @@ xfs_setattr( ...@@ -510,10 +518,11 @@ xfs_setattr(
goto error_return; goto error_return;
} }
/* /*
* Do a quota reservation only if uid or gid is actually * Do a quota reservation only if uid/projid/gid is actually
* going to change. * going to change.
*/ */
if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
(XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
(XFS_IS_GQUOTA_ON(mp) && igid != gid)) { (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
ASSERT(tp); ASSERT(tp);
code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
...@@ -774,6 +783,7 @@ xfs_setattr( ...@@ -774,6 +783,7 @@ xfs_setattr(
} }
if (igid != gid) { if (igid != gid) {
if (XFS_IS_GQUOTA_ON(mp)) { if (XFS_IS_GQUOTA_ON(mp)) {
ASSERT(!XFS_IS_PQUOTA_ON(mp));
ASSERT(mask & XFS_AT_GID); ASSERT(mask & XFS_AT_GID);
ASSERT(gdqp); ASSERT(gdqp);
olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
...@@ -782,6 +792,13 @@ xfs_setattr( ...@@ -782,6 +792,13 @@ xfs_setattr(
ip->i_d.di_gid = gid; ip->i_d.di_gid = gid;
} }
if (iprojid != projid) { if (iprojid != projid) {
if (XFS_IS_PQUOTA_ON(mp)) {
ASSERT(!XFS_IS_GQUOTA_ON(mp));
ASSERT(mask & XFS_AT_PROJID);
ASSERT(gdqp);
olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
&ip->i_gdquot, gdqp);
}
ip->i_d.di_projid = projid; ip->i_d.di_projid = projid;
/* /*
* We may have to rev the inode as well as * We may have to rev the inode as well as
...@@ -1907,7 +1924,7 @@ xfs_create( ...@@ -1907,7 +1924,7 @@ xfs_create(
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = XFS_QM_DQVOPALLOC(mp, dp, error = XFS_QM_DQVOPALLOC(mp, dp,
current_fsuid(credp), current_fsgid(credp), current_fsuid(credp), current_fsgid(credp), prid,
XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error) if (error)
goto std_return; goto std_return;
...@@ -2812,7 +2829,7 @@ xfs_mkdir( ...@@ -2812,7 +2829,7 @@ xfs_mkdir(
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = XFS_QM_DQVOPALLOC(mp, dp, error = XFS_QM_DQVOPALLOC(mp, dp,
current_fsuid(credp), current_fsgid(credp), current_fsuid(credp), current_fsgid(credp), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error) if (error)
goto std_return; goto std_return;
...@@ -3366,7 +3383,7 @@ xfs_symlink( ...@@ -3366,7 +3383,7 @@ xfs_symlink(
* Make sure that we have allocated dquot(s) on disk. * Make sure that we have allocated dquot(s) on disk.
*/ */
error = XFS_QM_DQVOPALLOC(mp, dp, error = XFS_QM_DQVOPALLOC(mp, dp,
current_fsuid(credp), current_fsgid(credp), current_fsuid(credp), current_fsgid(credp), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error) if (error)
goto std_return; goto std_return;
......
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