aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2005-06-21 01:38:48 -0400
committerNathan Scott <nathans@sgi.com>2005-06-21 01:38:48 -0400
commitc8ad20ffeb592d66ea869c57f8c525a9d727c67b (patch)
tree3306edfe984170bc881a1d7fbeab29b4b59f0305 /fs
parent8401e9631c26dca9ebbc6997ac445fd49b06c79e (diff)
[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: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c6
-rw-r--r--fs/xfs/quota/xfs_dquot.c34
-rw-r--r--fs/xfs/quota/xfs_dquot.h29
-rw-r--r--fs/xfs/quota/xfs_qm.c142
-rw-r--r--fs/xfs/quota/xfs_qm.h4
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c41
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c151
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h6
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c6
-rw-r--r--fs/xfs/xfs_buf_item.h2
-rw-r--r--fs/xfs/xfs_log_recover.c11
-rw-r--r--fs/xfs/xfs_mount.h6
-rw-r--r--fs/xfs/xfs_quota.h61
-rw-r--r--fs/xfs/xfs_trans_buf.c1
-rw-r--r--fs/xfs/xfs_utils.c2
-rw-r--r--fs/xfs/xfs_vfsops.c10
-rw-r--r--fs/xfs/xfs_vnodeops.c33
18 files changed, 348 insertions, 203 deletions
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 71bb41019a12..44eb313f22b9 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -230,8 +230,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
230 * field (see the QCMD macro in quota.h). These macros help keep the 230 * field (see the QCMD macro in quota.h). These macros help keep the
231 * code portable - they are not visible from the syscall interface. 231 * code portable - they are not visible from the syscall interface.
232 */ 232 */
233#define Q_XSETGQLIM XQM_CMD(0x8) /* set groups disk limits */ 233#define Q_XSETGQLIM XQM_CMD(8) /* set groups disk limits */
234#define Q_XGETGQUOTA XQM_CMD(0x9) /* get groups disk limits */ 234#define Q_XGETGQUOTA XQM_CMD(9) /* get groups disk limits */
235#define Q_XSETPQLIM XQM_CMD(10) /* set projects disk limits */
236#define Q_XGETPQUOTA XQM_CMD(11) /* get projects disk limits */
235 237
236/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */ 238/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
237/* we may well need to fine-tune this if it ever becomes an issue. */ 239/* we may well need to fine-tune this if it ever becomes an issue. */
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 455e2b2fb964..d5f0340ddcd9 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -701,7 +701,8 @@ linvfs_getxquota(
701 struct vfs *vfsp = LINVFS_GET_VFS(sb); 701 struct vfs *vfsp = LINVFS_GET_VFS(sb);
702 int error, getmode; 702 int error, getmode;
703 703
704 getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA; 704 getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
705 ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
705 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); 706 VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
706 return -error; 707 return -error;
707} 708}
@@ -716,7 +717,8 @@ linvfs_setxquota(
716 struct vfs *vfsp = LINVFS_GET_VFS(sb); 717 struct vfs *vfsp = LINVFS_GET_VFS(sb);
717 int error, setmode; 718 int error, setmode;
718 719
719 setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM; 720 setmode = (type == USRQUOTA) ? Q_XSETQLIM :
721 ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
720 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); 722 VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
721 return -error; 723 return -error;
722} 724}
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 9ce471430a0e..68089f56d5cd 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -399,9 +399,9 @@ xfs_qm_init_dquot_blk(
399 for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++) 399 for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
400 xfs_qm_dqinit_core(curid, type, d); 400 xfs_qm_dqinit_core(curid, type, d);
401 xfs_trans_dquot_buf(tp, bp, 401 xfs_trans_dquot_buf(tp, bp,
402 type & XFS_DQ_USER ? 402 (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF :
403 XFS_BLI_UDQUOT_BUF : 403 ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF :
404 XFS_BLI_GDQUOT_BUF); 404 XFS_BLI_GDQUOT_BUF)));
405 xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1); 405 xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
406} 406}
407 407
@@ -482,8 +482,7 @@ xfs_qm_dqalloc(
482 * the entire thing. 482 * the entire thing.
483 */ 483 */
484 xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT), 484 xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
485 dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP), 485 dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
486 bp);
487 486
488 if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) { 487 if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
489 goto error1; 488 goto error1;
@@ -613,8 +612,7 @@ xfs_qm_dqtobp(
613 /* 612 /*
614 * A simple sanity check in case we got a corrupted dquot... 613 * A simple sanity check in case we got a corrupted dquot...
615 */ 614 */
616 if (xfs_qm_dqcheck(ddq, id, 615 if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
617 dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
618 flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN), 616 flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
619 "dqtobp")) { 617 "dqtobp")) {
620 if (!(flags & XFS_QMOPT_DQREPAIR)) { 618 if (!(flags & XFS_QMOPT_DQREPAIR)) {
@@ -891,8 +889,8 @@ int
891xfs_qm_dqget( 889xfs_qm_dqget(
892 xfs_mount_t *mp, 890 xfs_mount_t *mp,
893 xfs_inode_t *ip, /* locked inode (optional) */ 891 xfs_inode_t *ip, /* locked inode (optional) */
894 xfs_dqid_t id, /* gid or uid, depending on type */ 892 xfs_dqid_t id, /* uid/projid/gid depending on type */
895 uint type, /* UDQUOT or GDQUOT */ 893 uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
896 uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */ 894 uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
897 xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */ 895 xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
898{ 896{
@@ -903,7 +901,9 @@ xfs_qm_dqget(
903 901
904 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 902 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
905 if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) || 903 if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
904 (! XFS_IS_PQUOTA_ON(mp) && type == XFS_DQ_PROJ) ||
906 (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) { 905 (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
906printk("XQM: ESRCH1\n");
907 return (ESRCH); 907 return (ESRCH);
908 } 908 }
909 h = XFS_DQ_HASH(mp, id, type); 909 h = XFS_DQ_HASH(mp, id, type);
@@ -921,7 +921,9 @@ xfs_qm_dqget(
921 again: 921 again:
922 922
923#ifdef DEBUG 923#ifdef DEBUG
924 ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP); 924 ASSERT(type == XFS_DQ_USER ||
925 type == XFS_DQ_PROJ ||
926 type == XFS_DQ_GROUP);
925 if (ip) { 927 if (ip) {
926 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 928 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
927 if (type == XFS_DQ_USER) 929 if (type == XFS_DQ_USER)
@@ -979,6 +981,7 @@ xfs_qm_dqget(
979 &dqp))) { 981 &dqp))) {
980 if (ip) 982 if (ip)
981 xfs_ilock(ip, XFS_ILOCK_EXCL); 983 xfs_ilock(ip, XFS_ILOCK_EXCL);
984if (error == ESRCH) printk("XQM: ESRCH2\n");
982 return (error); 985 return (error);
983 } 986 }
984 987
@@ -1004,6 +1007,7 @@ xfs_qm_dqget(
1004 if (! XFS_IS_DQTYPE_ON(mp, type)) { 1007 if (! XFS_IS_DQTYPE_ON(mp, type)) {
1005 /* inode stays locked on return */ 1008 /* inode stays locked on return */
1006 xfs_qm_dqdestroy(dqp); 1009 xfs_qm_dqdestroy(dqp);
1010printk("XQM: ESRCH3\n");
1007 return XFS_ERROR(ESRCH); 1011 return XFS_ERROR(ESRCH);
1008 } 1012 }
1009 /* 1013 /*
@@ -1244,8 +1248,8 @@ xfs_qm_dqflush(
1244 return (error); 1248 return (error);
1245 } 1249 }
1246 1250
1247 if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN, 1251 if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT),
1248 "dqflush (incore copy)")) { 1252 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
1249 xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE); 1253 xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
1250 return XFS_ERROR(EIO); 1254 return XFS_ERROR(EIO);
1251 } 1255 }
@@ -1397,7 +1401,8 @@ xfs_dqlock2(
1397{ 1401{
1398 if (d1 && d2) { 1402 if (d1 && d2) {
1399 ASSERT(d1 != d2); 1403 ASSERT(d1 != d2);
1400 if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) { 1404 if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) >
1405 INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
1401 xfs_dqlock(d2); 1406 xfs_dqlock(d2);
1402 xfs_dqlock(d1); 1407 xfs_dqlock(d1);
1403 } else { 1408 } else {
@@ -1520,8 +1525,7 @@ xfs_qm_dqprint(xfs_dquot_t *dqp)
1520 cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------"); 1525 cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
1521 cmn_err(CE_DEBUG, "---- dquotID = %d", 1526 cmn_err(CE_DEBUG, "---- dquotID = %d",
1522 (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT)); 1527 (int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
1523 cmn_err(CE_DEBUG, "---- type = %s", 1528 cmn_err(CE_DEBUG, "---- type = %s", DQFLAGTO_TYPESTR(dqp));
1524 XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
1525 cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount); 1529 cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount);
1526 cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno); 1530 cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno);
1527 cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset); 1531 cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset);
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 35aeeafe4799..39175103c8e0 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -114,25 +114,18 @@ typedef struct xfs_dquot {
114#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) 114#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++)
115 115
116/* 116/*
117 * Quota Accounting flags 117 * Quota Accounting/Enforcement flags
118 */ 118 */
119#define XFS_ALL_QUOTA_ACCT (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT) 119#define XFS_ALL_QUOTA_ACCT \
120#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD) 120 (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
121#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD) 121#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
122#define XFS_ALL_QUOTA_ACTV (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE) 122#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
123#define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
124 XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD)
125 123
126#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT) 124#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
127#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
128#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
129
130/*
131 * Quota Limit Enforcement flags
132 */
133#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD) 125#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
134#define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD) 126#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
135#define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD) 127#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
128#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
136 129
137#ifdef DEBUG 130#ifdef DEBUG
138static inline int 131static inline int
@@ -167,6 +160,8 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
167#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) 160#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp))
168#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) 161#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY)
169#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) 162#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
163#define XFS_QM_ISPDQ(dqp) ((dqp)->dq_flags & XFS_DQ_PROJ)
164#define XFS_QM_ISGDQ(dqp) ((dqp)->dq_flags & XFS_DQ_GROUP)
170#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo) 165#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo)
171#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \ 166#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \
172 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ 167 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
@@ -174,7 +169,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
174 169
175#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \ 170#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
176 (XFS_IS_UQUOTA_ON((d)->q_mount)) : \ 171 (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
177 (XFS_IS_GQUOTA_ON((d)->q_mount)))) 172 (XFS_IS_OQUOTA_ON((d)->q_mount))))
178 173
179#ifdef XFS_DQUOT_TRACE 174#ifdef XFS_DQUOT_TRACE
180/* 175/*
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 41bbc49d535e..3ea75972767c 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -310,9 +310,9 @@ xfs_qm_mount_quotainit(
310 uint flags) 310 uint flags)
311{ 311{
312 /* 312 /*
313 * User or group quotas has to be on. 313 * User, projects or group quotas has to be on.
314 */ 314 */
315 ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)); 315 ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
316 316
317 /* 317 /*
318 * Initialize the flags in the mount structure. From this point 318 * Initialize the flags in the mount structure. From this point
@@ -330,7 +330,11 @@ xfs_qm_mount_quotainit(
330 if (flags & XFSMNT_GQUOTA) { 330 if (flags & XFSMNT_GQUOTA) {
331 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE); 331 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
332 if (flags & XFSMNT_GQUOTAENF) 332 if (flags & XFSMNT_GQUOTAENF)
333 mp->m_qflags |= XFS_GQUOTA_ENFD; 333 mp->m_qflags |= XFS_OQUOTA_ENFD;
334 } else if (flags & XFSMNT_PQUOTA) {
335 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
336 if (flags & XFSMNT_PQUOTAENF)
337 mp->m_qflags |= XFS_OQUOTA_ENFD;
334 } 338 }
335} 339}
336 340
@@ -363,11 +367,11 @@ xfs_qm_mount_quotas(
363 367
364 /* 368 /*
365 * If a file system had quotas running earlier, but decided to 369 * If a file system had quotas running earlier, but decided to
366 * mount without -o quota/uquota/gquota options, revoke the 370 * mount without -o uquota/pquota/gquota options, revoke the
367 * quotachecked license, and bail out. 371 * quotachecked license, and bail out.
368 */ 372 */
369 if (! XFS_IS_QUOTA_ON(mp) && 373 if (! XFS_IS_QUOTA_ON(mp) &&
370 (mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) { 374 (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
371 mp->m_qflags = 0; 375 mp->m_qflags = 0;
372 goto write_changes; 376 goto write_changes;
373 } 377 }
@@ -619,7 +623,7 @@ xfs_qm_detach_gdquots(
619STATIC int 623STATIC int
620xfs_qm_dqpurge_int( 624xfs_qm_dqpurge_int(
621 xfs_mount_t *mp, 625 xfs_mount_t *mp,
622 uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */ 626 uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
623{ 627{
624 xfs_dquot_t *dqp; 628 xfs_dquot_t *dqp;
625 uint dqtype; 629 uint dqtype;
@@ -631,6 +635,7 @@ xfs_qm_dqpurge_int(
631 return (0); 635 return (0);
632 636
633 dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0; 637 dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
638 dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
634 dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0; 639 dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
635 640
636 xfs_qm_mplist_lock(mp); 641 xfs_qm_mplist_lock(mp);
@@ -740,11 +745,11 @@ xfs_qm_dqattach_one(
740 745
741 /* 746 /*
742 * udqhint is the i_udquot field in inode, and is non-NULL only 747 * udqhint is the i_udquot field in inode, and is non-NULL only
743 * when the type arg is XFS_DQ_GROUP. Its purpose is to save a 748 * when the type arg is group/project. Its purpose is to save a
744 * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside 749 * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
745 * the user dquot. 750 * the user dquot.
746 */ 751 */
747 ASSERT(!udqhint || type == XFS_DQ_GROUP); 752 ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
748 if (udqhint && !dolock) 753 if (udqhint && !dolock)
749 xfs_dqlock(udqhint); 754 xfs_dqlock(udqhint);
750 755
@@ -903,8 +908,8 @@ xfs_qm_dqattach_grouphint(
903 908
904 909
905/* 910/*
906 * Given a locked inode, attach dquot(s) to it, taking UQUOTAON / GQUOTAON 911 * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
907 * in to account. 912 * into account.
908 * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. 913 * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
909 * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty 914 * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
910 * much made this code a complete mess, but it has been pretty useful. 915 * much made this code a complete mess, but it has been pretty useful.
@@ -943,8 +948,13 @@ xfs_qm_dqattach(
943 nquotas++; 948 nquotas++;
944 } 949 }
945 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip)); 950 ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
946 if (XFS_IS_GQUOTA_ON(mp)) { 951 if (XFS_IS_OQUOTA_ON(mp)) {
947 error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, 952 error = XFS_IS_GQUOTA_ON(mp) ?
953 xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
954 flags & XFS_QMOPT_DQALLOC,
955 flags & XFS_QMOPT_DQLOCK,
956 ip->i_udquot, &ip->i_gdquot) :
957 xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
948 flags & XFS_QMOPT_DQALLOC, 958 flags & XFS_QMOPT_DQALLOC,
949 flags & XFS_QMOPT_DQLOCK, 959 flags & XFS_QMOPT_DQLOCK,
950 ip->i_udquot, &ip->i_gdquot); 960 ip->i_udquot, &ip->i_gdquot);
@@ -995,7 +1005,7 @@ xfs_qm_dqattach(
995 } 1005 }
996 if (XFS_IS_UQUOTA_ON(mp)) 1006 if (XFS_IS_UQUOTA_ON(mp))
997 ASSERT(ip->i_udquot); 1007 ASSERT(ip->i_udquot);
998 if (XFS_IS_GQUOTA_ON(mp)) 1008 if (XFS_IS_OQUOTA_ON(mp))
999 ASSERT(ip->i_gdquot); 1009 ASSERT(ip->i_gdquot);
1000 } 1010 }
1001#endif 1011#endif
@@ -1024,13 +1034,13 @@ xfs_qm_dqdetach(
1024 1034
1025 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino); 1035 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
1026 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino); 1036 ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
1027 if (ip->i_udquot)
1028 xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
1029 if (ip->i_udquot) { 1037 if (ip->i_udquot) {
1038 xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
1030 xfs_qm_dqrele(ip->i_udquot); 1039 xfs_qm_dqrele(ip->i_udquot);
1031 ip->i_udquot = NULL; 1040 ip->i_udquot = NULL;
1032 } 1041 }
1033 if (ip->i_gdquot) { 1042 if (ip->i_gdquot) {
1043 xfs_dqtrace_entry_ino(ip->i_gdquot, "DQDETTACH", ip);
1034 xfs_qm_dqrele(ip->i_gdquot); 1044 xfs_qm_dqrele(ip->i_gdquot);
1035 ip->i_gdquot = NULL; 1045 ip->i_gdquot = NULL;
1036 } 1046 }
@@ -1208,8 +1218,9 @@ xfs_qm_init_quotainfo(
1208 * and group quotas, at least not at this point. 1218 * and group quotas, at least not at this point.
1209 */ 1219 */
1210 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0, 1220 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
1211 (XFS_IS_UQUOTA_RUNNING(mp)) ? 1221 XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER :
1212 XFS_DQ_USER : XFS_DQ_GROUP, 1222 (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
1223 XFS_DQ_PROJ),
1213 XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN, 1224 XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
1214 &dqp); 1225 &dqp);
1215 if (! error) { 1226 if (! error) {
@@ -1372,13 +1383,20 @@ xfs_qm_dqget_noattach(
1372 ASSERT(udqp); 1383 ASSERT(udqp);
1373 } 1384 }
1374 1385
1375 if (XFS_IS_GQUOTA_ON(mp)) { 1386 if (XFS_IS_OQUOTA_ON(mp)) {
1376 ASSERT(ip->i_gdquot == NULL); 1387 ASSERT(ip->i_gdquot == NULL);
1377 if (udqp) 1388 if (udqp)
1378 xfs_dqunlock(udqp); 1389 xfs_dqunlock(udqp);
1379 if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_gid, XFS_DQ_GROUP, 1390 error = XFS_IS_GQUOTA_ON(mp) ?
1380 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN, 1391 xfs_qm_dqget(mp, ip,
1381 &gdqp))) { 1392 ip->i_d.di_gid, XFS_DQ_GROUP,
1393 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
1394 &gdqp) :
1395 xfs_qm_dqget(mp, ip,
1396 ip->i_d.di_projid, XFS_DQ_PROJ,
1397 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
1398 &gdqp);
1399 if (error) {
1382 if (udqp) 1400 if (udqp)
1383 xfs_qm_dqrele(udqp); 1401 xfs_qm_dqrele(udqp);
1384 ASSERT(error != ESRCH); 1402 ASSERT(error != ESRCH);
@@ -1547,11 +1565,14 @@ xfs_qm_dqiter_bufs(
1547 int error; 1565 int error;
1548 int notcommitted; 1566 int notcommitted;
1549 int incr; 1567 int incr;
1568 int type;
1550 1569
1551 ASSERT(blkcnt > 0); 1570 ASSERT(blkcnt > 0);
1552 notcommitted = 0; 1571 notcommitted = 0;
1553 incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ? 1572 incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
1554 XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt; 1573 XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
1574 type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
1575 (flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
1555 error = 0; 1576 error = 0;
1556 1577
1557 /* 1578 /*
@@ -1570,9 +1591,7 @@ xfs_qm_dqiter_bufs(
1570 if (error) 1591 if (error)
1571 break; 1592 break;
1572 1593
1573 (void) xfs_qm_reset_dqcounts(mp, bp, firstid, 1594 (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
1574 flags & XFS_QMOPT_UQUOTA ?
1575 XFS_DQ_USER : XFS_DQ_GROUP);
1576 xfs_bdwrite(mp, bp); 1595 xfs_bdwrite(mp, bp);
1577 /* 1596 /*
1578 * goto the next block. 1597 * goto the next block.
@@ -1584,7 +1603,7 @@ xfs_qm_dqiter_bufs(
1584} 1603}
1585 1604
1586/* 1605/*
1587 * Iterate over all allocated USR/GRP dquots in the system, calling a 1606 * Iterate over all allocated USR/GRP/PRJ dquots in the system, calling a
1588 * caller supplied function for every chunk of dquots that we find. 1607 * caller supplied function for every chunk of dquots that we find.
1589 */ 1608 */
1590STATIC int 1609STATIC int
@@ -1855,7 +1874,7 @@ xfs_qm_dqusage_adjust(
1855 xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks); 1874 xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
1856 xfs_qm_dqput(udqp); 1875 xfs_qm_dqput(udqp);
1857 } 1876 }
1858 if (XFS_IS_GQUOTA_ON(mp)) { 1877 if (XFS_IS_OQUOTA_ON(mp)) {
1859 ASSERT(gdqp); 1878 ASSERT(gdqp);
1860 xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks); 1879 xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
1861 xfs_qm_dqput(gdqp); 1880 xfs_qm_dqput(gdqp);
@@ -1904,7 +1923,7 @@ xfs_qm_quotacheck(
1904 cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname); 1923 cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
1905 1924
1906 /* 1925 /*
1907 * First we go thru all the dquots on disk, USR and GRP, and reset 1926 * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
1908 * their counters to zero. We need a clean slate. 1927 * their counters to zero. We need a clean slate.
1909 * We don't log our changes till later. 1928 * We don't log our changes till later.
1910 */ 1929 */
@@ -1915,9 +1934,10 @@ xfs_qm_quotacheck(
1915 } 1934 }
1916 1935
1917 if ((gip = XFS_QI_GQIP(mp))) { 1936 if ((gip = XFS_QI_GQIP(mp))) {
1918 if ((error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA))) 1937 if ((error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
1938 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA)))
1919 goto error_return; 1939 goto error_return;
1920 flags |= XFS_GQUOTA_CHKD; 1940 flags |= XFS_OQUOTA_CHKD;
1921 } 1941 }
1922 1942
1923 do { 1943 do {
@@ -1944,7 +1964,7 @@ xfs_qm_quotacheck(
1944 if (error) { 1964 if (error) {
1945 xfs_qm_dqpurge_all(mp, 1965 xfs_qm_dqpurge_all(mp,
1946 XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA| 1966 XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
1947 XFS_QMOPT_QUOTAOFF); 1967 XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
1948 goto error_return; 1968 goto error_return;
1949 } 1969 }
1950 /* 1970 /*
@@ -1967,7 +1987,7 @@ xfs_qm_quotacheck(
1967 * quotachecked status, since we won't be doing accounting for 1987 * quotachecked status, since we won't be doing accounting for
1968 * that type anymore. 1988 * that type anymore.
1969 */ 1989 */
1970 mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD); 1990 mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
1971 mp->m_qflags |= flags; 1991 mp->m_qflags |= flags;
1972 1992
1973 XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++"); 1993 XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++");
@@ -2019,7 +2039,7 @@ xfs_qm_init_quotainos(
2019 0, 0, &uip, 0))) 2039 0, 0, &uip, 0)))
2020 return XFS_ERROR(error); 2040 return XFS_ERROR(error);
2021 } 2041 }
2022 if (XFS_IS_GQUOTA_ON(mp) && 2042 if (XFS_IS_OQUOTA_ON(mp) &&
2023 mp->m_sb.sb_gquotino != NULLFSINO) { 2043 mp->m_sb.sb_gquotino != NULLFSINO) {
2024 ASSERT(mp->m_sb.sb_gquotino > 0); 2044 ASSERT(mp->m_sb.sb_gquotino > 0);
2025 if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 2045 if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -2049,10 +2069,12 @@ xfs_qm_init_quotainos(
2049 2069
2050 flags &= ~XFS_QMOPT_SBVERSION; 2070 flags &= ~XFS_QMOPT_SBVERSION;
2051 } 2071 }
2052 if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) { 2072 if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
2053 if ((error = xfs_qm_qino_alloc(mp, &gip, 2073 flags |= (XFS_IS_GQUOTA_ON(mp) ?
2054 sbflags | XFS_SB_GQUOTINO, 2074 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
2055 flags | XFS_QMOPT_GQUOTA))) { 2075 error = xfs_qm_qino_alloc(mp, &gip,
2076 sbflags | XFS_SB_GQUOTINO, flags);
2077 if (error) {
2056 if (uip) 2078 if (uip)
2057 VN_RELE(XFS_ITOV(uip)); 2079 VN_RELE(XFS_ITOV(uip));
2058 2080
@@ -2458,6 +2480,7 @@ xfs_qm_vop_dqalloc(
2458 xfs_inode_t *ip, 2480 xfs_inode_t *ip,
2459 uid_t uid, 2481 uid_t uid,
2460 gid_t gid, 2482 gid_t gid,
2483 prid_t prid,
2461 uint flags, 2484 uint flags,
2462 xfs_dquot_t **O_udqpp, 2485 xfs_dquot_t **O_udqpp,
2463 xfs_dquot_t **O_gdqpp) 2486 xfs_dquot_t **O_gdqpp)
@@ -2489,8 +2512,7 @@ xfs_qm_vop_dqalloc(
2489 } 2512 }
2490 2513
2491 uq = gq = NULL; 2514 uq = gq = NULL;
2492 if ((flags & XFS_QMOPT_UQUOTA) && 2515 if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
2493 XFS_IS_UQUOTA_ON(mp)) {
2494 if (ip->i_d.di_uid != uid) { 2516 if (ip->i_d.di_uid != uid) {
2495 /* 2517 /*
2496 * What we need is the dquot that has this uid, and 2518 * What we need is the dquot that has this uid, and
@@ -2528,8 +2550,7 @@ xfs_qm_vop_dqalloc(
2528 xfs_dqunlock(uq); 2550 xfs_dqunlock(uq);
2529 } 2551 }
2530 } 2552 }
2531 if ((flags & XFS_QMOPT_GQUOTA) && 2553 if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
2532 XFS_IS_GQUOTA_ON(mp)) {
2533 if (ip->i_d.di_gid != gid) { 2554 if (ip->i_d.di_gid != gid) {
2534 xfs_iunlock(ip, lockflags); 2555 xfs_iunlock(ip, lockflags);
2535 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid, 2556 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
@@ -2552,6 +2573,29 @@ xfs_qm_vop_dqalloc(
2552 XFS_DQHOLD(gq); 2573 XFS_DQHOLD(gq);
2553 xfs_dqunlock(gq); 2574 xfs_dqunlock(gq);
2554 } 2575 }
2576 } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
2577 if (ip->i_d.di_projid != prid) {
2578 xfs_iunlock(ip, lockflags);
2579 if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
2580 XFS_DQ_PROJ,
2581 XFS_QMOPT_DQALLOC |
2582 XFS_QMOPT_DOWARN,
2583 &gq))) {
2584 if (uq)
2585 xfs_qm_dqrele(uq);
2586 ASSERT(error != ENOENT);
2587 return (error);
2588 }
2589 xfs_dqunlock(gq);
2590 lockflags = XFS_ILOCK_SHARED;
2591 xfs_ilock(ip, lockflags);
2592 } else {
2593 ASSERT(ip->i_gdquot);
2594 gq = ip->i_gdquot;
2595 xfs_dqlock(gq);
2596 XFS_DQHOLD(gq);
2597 xfs_dqunlock(gq);
2598 }
2555 } 2599 }
2556 if (uq) 2600 if (uq)
2557 xfs_dqtrace_entry_ino(uq, "DQALLOC", ip); 2601 xfs_dqtrace_entry_ino(uq, "DQALLOC", ip);
@@ -2617,7 +2661,7 @@ xfs_qm_vop_chown(
2617} 2661}
2618 2662
2619/* 2663/*
2620 * Quota reservations for setattr(AT_UID|AT_GID). 2664 * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
2621 */ 2665 */
2622int 2666int
2623xfs_qm_vop_chown_reserve( 2667xfs_qm_vop_chown_reserve(
@@ -2652,12 +2696,16 @@ xfs_qm_vop_chown_reserve(
2652 unresudq = ip->i_udquot; 2696 unresudq = ip->i_udquot;
2653 } 2697 }
2654 } 2698 }
2655 if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp && 2699 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
2656 ip->i_d.di_gid != INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) { 2700 if ((XFS_IS_GQUOTA_ON(ip->i_mount) && ip->i_d.di_gid !=
2657 delblksgdq = gdqp; 2701 INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) ||
2658 if (delblks) { 2702 (XFS_IS_PQUOTA_ON(ip->i_mount) && ip->i_d.di_projid !=
2659 ASSERT(ip->i_gdquot); 2703 INT_GET(gdqp->q_core.d_id, ARCH_CONVERT))) {
2660 unresgdq = ip->i_gdquot; 2704 delblksgdq = gdqp;
2705 if (delblks) {
2706 ASSERT(ip->i_gdquot);
2707 unresgdq = ip->i_gdquot;
2708 }
2661 } 2709 }
2662 } 2710 }
2663 2711
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index ae626eca5aca..781968779540 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as 5 * 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 202
203/* vop stuff */ 203/* vop stuff */
204extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, 204extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
205 uid_t, gid_t, uint, 205 uid_t, gid_t, prid_t, uint,
206 xfs_dquot_t **, xfs_dquot_t **); 206 xfs_dquot_t **, xfs_dquot_t **);
207extern void xfs_qm_vop_dqattach_and_dqmod_newinode( 207extern void xfs_qm_vop_dqattach_and_dqmod_newinode(
208 xfs_trans_t *, xfs_inode_t *, 208 xfs_trans_t *, xfs_inode_t *,
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index 09b1171dfb83..dc3c37a1e158 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -71,10 +71,13 @@
71#define MNTOPT_NOQUOTA "noquota" /* no quotas */ 71#define MNTOPT_NOQUOTA "noquota" /* no quotas */
72#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */ 72#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
73#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */ 73#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
74#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
74#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */ 75#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
75#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */ 76#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
77#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
76#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */ 78#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
77#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */ 79#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
80#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
78#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */ 81#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
79 82
80STATIC int 83STATIC int
@@ -109,6 +112,14 @@ xfs_qm_parseargs(
109 args->flags |= XFSMNT_UQUOTA; 112 args->flags |= XFSMNT_UQUOTA;
110 args->flags &= ~XFSMNT_UQUOTAENF; 113 args->flags &= ~XFSMNT_UQUOTAENF;
111 referenced = 1; 114 referenced = 1;
115 } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
116 !strcmp(this_char, MNTOPT_PRJQUOTA)) {
117 args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
118 referenced = 1;
119 } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
120 args->flags |= XFSMNT_PQUOTA;
121 args->flags &= ~XFSMNT_PQUOTAENF;
122 referenced = 1;
112 } else if (!strcmp(this_char, MNTOPT_GQUOTA) || 123 } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
113 !strcmp(this_char, MNTOPT_GRPQUOTA)) { 124 !strcmp(this_char, MNTOPT_GRPQUOTA)) {
114 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF; 125 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
@@ -127,6 +138,12 @@ xfs_qm_parseargs(
127 *this_char++ = ','; 138 *this_char++ = ',';
128 } 139 }
129 140
141 if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
142 cmn_err(CE_WARN,
143 "XFS: cannot mount with both project and group quota");
144 return XFS_ERROR(EINVAL);
145 }
146
130 PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); 147 PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
131 if (!error && !referenced) 148 if (!error && !referenced)
132 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); 149 bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
@@ -148,13 +165,19 @@ xfs_qm_showargs(
148 seq_puts(m, "," MNTOPT_UQUOTANOENF); 165 seq_puts(m, "," MNTOPT_UQUOTANOENF);
149 } 166 }
150 167
168 if (mp->m_qflags & XFS_PQUOTA_ACCT) {
169 (mp->m_qflags & XFS_OQUOTA_ENFD) ?
170 seq_puts(m, "," MNTOPT_PRJQUOTA) :
171 seq_puts(m, "," MNTOPT_PQUOTANOENF);
172 }
173
151 if (mp->m_qflags & XFS_GQUOTA_ACCT) { 174 if (mp->m_qflags & XFS_GQUOTA_ACCT) {
152 (mp->m_qflags & XFS_GQUOTA_ENFD) ? 175 (mp->m_qflags & XFS_OQUOTA_ENFD) ?
153 seq_puts(m, "," MNTOPT_GRPQUOTA) : 176 seq_puts(m, "," MNTOPT_GRPQUOTA) :
154 seq_puts(m, "," MNTOPT_GQUOTANOENF); 177 seq_puts(m, "," MNTOPT_GQUOTANOENF);
155 } 178 }
156 179
157 if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) 180 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
158 seq_puts(m, "," MNTOPT_NOQUOTA); 181 seq_puts(m, "," MNTOPT_NOQUOTA);
159 182
160 PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); 183 PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
@@ -171,7 +194,7 @@ xfs_qm_mount(
171 struct xfs_mount *mp = XFS_VFSTOM(vfsp); 194 struct xfs_mount *mp = XFS_VFSTOM(vfsp);
172 int error; 195 int error;
173 196
174 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA)) 197 if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
175 xfs_qm_mount_quotainit(mp, args->flags); 198 xfs_qm_mount_quotainit(mp, args->flags);
176 PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); 199 PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
177 return error; 200 return error;
@@ -255,16 +278,17 @@ xfs_qm_newmount(
255 uint *quotaflags) 278 uint *quotaflags)
256{ 279{
257 uint quotaondisk; 280 uint quotaondisk;
258 uint uquotaondisk = 0, gquotaondisk = 0; 281 uint uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
259 282
260 *quotaflags = 0; 283 *quotaflags = 0;
261 *needquotamount = B_FALSE; 284 *needquotamount = B_FALSE;
262 285
263 quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && 286 quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
264 mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); 287 (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
265 288
266 if (quotaondisk) { 289 if (quotaondisk) {
267 uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT; 290 uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
291 pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
268 gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT; 292 gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
269 } 293 }
270 294
@@ -277,13 +301,16 @@ xfs_qm_newmount(
277 301
278 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || 302 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
279 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || 303 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
304 (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
305 (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) ||
280 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || 306 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
281 (!gquotaondisk && XFS_IS_GQUOTA_ON(mp))) && 307 (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) &&
282 xfs_dev_is_read_only(mp, "changing quota state")) { 308 xfs_dev_is_read_only(mp, "changing quota state")) {
283 cmn_err(CE_WARN, 309 cmn_err(CE_WARN,
284 "XFS: please mount with%s%s%s.", 310 "XFS: please mount with%s%s%s%s.",
285 (!quotaondisk ? "out quota" : ""), 311 (!quotaondisk ? "out quota" : ""),
286 (uquotaondisk ? " usrquota" : ""), 312 (uquotaondisk ? " usrquota" : ""),
313 (pquotaondisk ? " prjquota" : ""),
287 (gquotaondisk ? " grpquota" : "")); 314 (gquotaondisk ? " grpquota" : ""));
288 return XFS_ERROR(EPERM); 315 return XFS_ERROR(EPERM);
289 } 316 }
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 229f5b5a2d25..365a054f02d6 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -118,40 +118,41 @@ xfs_qm_quotactl(
118 * The following commands are valid even when quotaoff. 118 * The following commands are valid even when quotaoff.
119 */ 119 */
120 switch (cmd) { 120 switch (cmd) {
121 case Q_XQUOTARM:
121 /* 122 /*
122 * truncate quota files. quota must be off. 123 * Truncate quota files. quota must be off.
123 */ 124 */
124 case Q_XQUOTARM:
125 if (XFS_IS_QUOTA_ON(mp) || addr == NULL) 125 if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
126 return XFS_ERROR(EINVAL); 126 return XFS_ERROR(EINVAL);
127 if (vfsp->vfs_flag & VFS_RDONLY) 127 if (vfsp->vfs_flag & VFS_RDONLY)
128 return XFS_ERROR(EROFS); 128 return XFS_ERROR(EROFS);
129 return (xfs_qm_scall_trunc_qfiles(mp, 129 return (xfs_qm_scall_trunc_qfiles(mp,
130 xfs_qm_import_qtype_flags(*(uint *)addr))); 130 xfs_qm_import_qtype_flags(*(uint *)addr)));
131
132 case Q_XGETQSTAT:
131 /* 133 /*
132 * Get quota status information. 134 * Get quota status information.
133 */ 135 */
134 case Q_XGETQSTAT:
135 return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); 136 return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
136 137
138 case Q_XQUOTAON:
137 /* 139 /*
138 * QUOTAON for root f/s and quota enforcement on others.. 140 * QUOTAON - enabling quota enforcement.
139 * Quota accounting for non-root f/s's must be turned on 141 * Quota accounting must be turned on at mount time.
140 * at mount time.
141 */ 142 */
142 case Q_XQUOTAON:
143 if (addr == NULL) 143 if (addr == NULL)
144 return XFS_ERROR(EINVAL); 144 return XFS_ERROR(EINVAL);
145 if (vfsp->vfs_flag & VFS_RDONLY) 145 if (vfsp->vfs_flag & VFS_RDONLY)
146 return XFS_ERROR(EROFS); 146 return XFS_ERROR(EROFS);
147 return (xfs_qm_scall_quotaon(mp, 147 return (xfs_qm_scall_quotaon(mp,
148 xfs_qm_import_flags(*(uint *)addr))); 148 xfs_qm_import_flags(*(uint *)addr)));
149 case Q_XQUOTAOFF: 149
150 case Q_XQUOTAOFF:
150 if (vfsp->vfs_flag & VFS_RDONLY) 151 if (vfsp->vfs_flag & VFS_RDONLY)
151 return XFS_ERROR(EROFS); 152 return XFS_ERROR(EROFS);
152 break; 153 break;
153 154
154 default: 155 default:
155 break; 156 break;
156 } 157 }
157 158
@@ -159,7 +160,7 @@ xfs_qm_quotactl(
159 return XFS_ERROR(ESRCH); 160 return XFS_ERROR(ESRCH);
160 161
161 switch (cmd) { 162 switch (cmd) {
162 case Q_XQUOTAOFF: 163 case Q_XQUOTAOFF:
163 if (vfsp->vfs_flag & VFS_RDONLY) 164 if (vfsp->vfs_flag & VFS_RDONLY)
164 return XFS_ERROR(EROFS); 165 return XFS_ERROR(EROFS);
165 error = xfs_qm_scall_quotaoff(mp, 166 error = xfs_qm_scall_quotaoff(mp,
@@ -167,42 +168,39 @@ xfs_qm_quotactl(
167 B_FALSE); 168 B_FALSE);
168 break; 169 break;
169 170
170 /* 171 case Q_XGETQUOTA:
171 * Defaults to XFS_GETUQUOTA.
172 */
173 case Q_XGETQUOTA:
174 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, 172 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
175 (fs_disk_quota_t *)addr); 173 (fs_disk_quota_t *)addr);
176 break; 174 break;
177 /* 175 case Q_XGETGQUOTA:
178 * Set limits, both hard and soft. Defaults to Q_SETUQLIM. 176 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
179 */ 177 (fs_disk_quota_t *)addr);
180 case Q_XSETQLIM: 178 break;
179 case Q_XGETPQUOTA:
180 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
181 (fs_disk_quota_t *)addr);
182 break;
183
184 case Q_XSETQLIM:
181 if (vfsp->vfs_flag & VFS_RDONLY) 185 if (vfsp->vfs_flag & VFS_RDONLY)
182 return XFS_ERROR(EROFS); 186 return XFS_ERROR(EROFS);
183 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, 187 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
184 (fs_disk_quota_t *)addr); 188 (fs_disk_quota_t *)addr);
185 break; 189 break;
186 190 case Q_XSETGQLIM:
187 case Q_XSETGQLIM:
188 if (vfsp->vfs_flag & VFS_RDONLY) 191 if (vfsp->vfs_flag & VFS_RDONLY)
189 return XFS_ERROR(EROFS); 192 return XFS_ERROR(EROFS);
190 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, 193 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
191 (fs_disk_quota_t *)addr); 194 (fs_disk_quota_t *)addr);
192 break; 195 break;
193 196 case Q_XSETPQLIM:
194 197 if (vfsp->vfs_flag & VFS_RDONLY)
195 case Q_XGETGQUOTA: 198 return XFS_ERROR(EROFS);
196 error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, 199 error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
197 (fs_disk_quota_t *)addr); 200 (fs_disk_quota_t *)addr);
198 break; 201 break;
199 202
200 /* 203 default:
201 * Quotas are entirely undefined after quotaoff in XFS quotas.
202 * For instance, there's no way to set limits when quotaoff.
203 */
204
205 default:
206 error = XFS_ERROR(EINVAL); 204 error = XFS_ERROR(EINVAL);
207 break; 205 break;
208 } 206 }
@@ -286,8 +284,12 @@ xfs_qm_scall_quotaoff(
286 } 284 }
287 if (flags & XFS_GQUOTA_ACCT) { 285 if (flags & XFS_GQUOTA_ACCT) {
288 dqtype |= XFS_QMOPT_GQUOTA; 286 dqtype |= XFS_QMOPT_GQUOTA;
289 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); 287 flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
290 inactivate_flags |= XFS_GQUOTA_ACTIVE; 288 inactivate_flags |= XFS_GQUOTA_ACTIVE;
289 } else if (flags & XFS_PQUOTA_ACCT) {
290 dqtype |= XFS_QMOPT_PQUOTA;
291 flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
292 inactivate_flags |= XFS_PQUOTA_ACTIVE;
291 } 293 }
292 294
293 /* 295 /*
@@ -364,7 +366,8 @@ xfs_qm_scall_quotaoff(
364 /* 366 /*
365 * If quotas is completely disabled, close shop. 367 * If quotas is completely disabled, close shop.
366 */ 368 */
367 if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) { 369 if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
370 ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
368 mutex_unlock(&(XFS_QI_QOFFLOCK(mp))); 371 mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
369 xfs_qm_destroy_quotainfo(mp); 372 xfs_qm_destroy_quotainfo(mp);
370 return (0); 373 return (0);
@@ -378,7 +381,7 @@ xfs_qm_scall_quotaoff(
378 XFS_PURGE_INODE(XFS_QI_UQIP(mp)); 381 XFS_PURGE_INODE(XFS_QI_UQIP(mp));
379 XFS_QI_UQIP(mp) = NULL; 382 XFS_QI_UQIP(mp) = NULL;
380 } 383 }
381 if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) { 384 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
382 XFS_PURGE_INODE(XFS_QI_GQIP(mp)); 385 XFS_PURGE_INODE(XFS_QI_GQIP(mp));
383 XFS_QI_GQIP(mp) = NULL; 386 XFS_QI_GQIP(mp) = NULL;
384 } 387 }
@@ -411,7 +414,8 @@ xfs_qm_scall_trunc_qfiles(
411 } 414 }
412 } 415 }
413 416
414 if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) { 417 if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
418 mp->m_sb.sb_gquotino != NULLFSINO) {
415 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0); 419 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
416 if (! error) { 420 if (! error) {
417 (void) xfs_truncate_file(mp, qip); 421 (void) xfs_truncate_file(mp, qip);
@@ -434,7 +438,7 @@ xfs_qm_scall_quotaon(
434 uint flags) 438 uint flags)
435{ 439{
436 int error; 440 int error;
437 unsigned long s; 441 unsigned long s;
438 uint qf; 442 uint qf;
439 uint accflags; 443 uint accflags;
440 __int64_t sbflags; 444 __int64_t sbflags;
@@ -468,9 +472,13 @@ xfs_qm_scall_quotaon(
468 (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 && 472 (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
469 (flags & XFS_UQUOTA_ENFD)) 473 (flags & XFS_UQUOTA_ENFD))
470 || 474 ||
475 ((flags & XFS_PQUOTA_ACCT) == 0 &&
476 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
477 (flags & XFS_OQUOTA_ENFD))
478 ||
471 ((flags & XFS_GQUOTA_ACCT) == 0 && 479 ((flags & XFS_GQUOTA_ACCT) == 0 &&
472 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 && 480 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
473 (flags & XFS_GQUOTA_ENFD))) { 481 (flags & XFS_OQUOTA_ENFD))) {
474 qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n", 482 qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
475 flags, mp->m_sb.sb_qflags); 483 flags, mp->m_sb.sb_qflags);
476 return XFS_ERROR(EINVAL); 484 return XFS_ERROR(EINVAL);
@@ -504,6 +512,10 @@ xfs_qm_scall_quotaon(
504 */ 512 */
505 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) != 513 if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
506 (mp->m_qflags & XFS_UQUOTA_ACCT)) || 514 (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
515 ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
516 (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
517 ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
518 (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
507 (flags & XFS_ALL_QUOTA_ENFD) == 0) 519 (flags & XFS_ALL_QUOTA_ENFD) == 0)
508 return (0); 520 return (0);
509 521
@@ -521,7 +533,6 @@ xfs_qm_scall_quotaon(
521} 533}
522 534
523 535
524
525/* 536/*
526 * Return quota status information, such as uquota-off, enforcements, etc. 537 * Return quota status information, such as uquota-off, enforcements, etc.
527 */ 538 */
@@ -776,9 +787,9 @@ xfs_qm_log_quotaoff_end(
776 xfs_qoff_logitem_t *startqoff, 787 xfs_qoff_logitem_t *startqoff,
777 uint flags) 788 uint flags)
778{ 789{
779 xfs_trans_t *tp; 790 xfs_trans_t *tp;
780 int error; 791 int error;
781 xfs_qoff_logitem_t *qoffi; 792 xfs_qoff_logitem_t *qoffi;
782 793
783 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END); 794 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
784 795
@@ -928,18 +939,26 @@ xfs_qm_export_dquot(
928 939
929STATIC uint 940STATIC uint
930xfs_qm_import_qtype_flags( 941xfs_qm_import_qtype_flags(
931 uint uflags) 942 uint uflags)
932{ 943{
944 uint oflags = 0;
945
933 /* 946 /*
934 * Can't be both at the same time. 947 * Can't be more than one, or none.
935 */ 948 */
936 if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 949 if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
937 (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) || 950 (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
938 ((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0)) 951 ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
952 (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
953 ((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
954 (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
955 ((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
939 return (0); 956 return (0);
940 957
941 return (uflags & XFS_USER_QUOTA) ? 958 oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
942 XFS_DQ_USER : XFS_DQ_GROUP; 959 oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
960 oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
961 return oflags;
943} 962}
944 963
945STATIC uint 964STATIC uint
@@ -947,14 +966,19 @@ xfs_qm_export_qtype_flags(
947 uint flags) 966 uint flags)
948{ 967{
949 /* 968 /*
950 * Can't be both at the same time. 969 * Can't be more than one, or none.
951 */ 970 */
952 ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 971 ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) !=
953 (XFS_GROUP_QUOTA | XFS_USER_QUOTA)); 972 (XFS_PROJ_QUOTA | XFS_USER_QUOTA));
954 ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0); 973 ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) !=
974 (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA));
975 ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) !=
976 (XFS_USER_QUOTA | XFS_GROUP_QUOTA));
977 ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0);
955 978
956 return (flags & XFS_DQ_USER) ? 979 return (flags & XFS_DQ_USER) ?
957 XFS_USER_QUOTA : XFS_GROUP_QUOTA; 980 XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
981 XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
958} 982}
959 983
960STATIC uint 984STATIC uint
@@ -965,12 +989,14 @@ xfs_qm_import_flags(
965 989
966 if (uflags & XFS_QUOTA_UDQ_ACCT) 990 if (uflags & XFS_QUOTA_UDQ_ACCT)
967 flags |= XFS_UQUOTA_ACCT; 991 flags |= XFS_UQUOTA_ACCT;
992 if (uflags & XFS_QUOTA_PDQ_ACCT)
993 flags |= XFS_PQUOTA_ACCT;
968 if (uflags & XFS_QUOTA_GDQ_ACCT) 994 if (uflags & XFS_QUOTA_GDQ_ACCT)
969 flags |= XFS_GQUOTA_ACCT; 995 flags |= XFS_GQUOTA_ACCT;
970 if (uflags & XFS_QUOTA_UDQ_ENFD) 996 if (uflags & XFS_QUOTA_UDQ_ENFD)
971 flags |= XFS_UQUOTA_ENFD; 997 flags |= XFS_UQUOTA_ENFD;
972 if (uflags & XFS_QUOTA_GDQ_ENFD) 998 if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
973 flags |= XFS_GQUOTA_ENFD; 999 flags |= XFS_OQUOTA_ENFD;
974 return (flags); 1000 return (flags);
975} 1001}
976 1002
@@ -984,12 +1010,16 @@ xfs_qm_export_flags(
984 uflags = 0; 1010 uflags = 0;
985 if (flags & XFS_UQUOTA_ACCT) 1011 if (flags & XFS_UQUOTA_ACCT)
986 uflags |= XFS_QUOTA_UDQ_ACCT; 1012 uflags |= XFS_QUOTA_UDQ_ACCT;
1013 if (flags & XFS_PQUOTA_ACCT)
1014 uflags |= XFS_QUOTA_PDQ_ACCT;
987 if (flags & XFS_GQUOTA_ACCT) 1015 if (flags & XFS_GQUOTA_ACCT)
988 uflags |= XFS_QUOTA_GDQ_ACCT; 1016 uflags |= XFS_QUOTA_GDQ_ACCT;
989 if (flags & XFS_UQUOTA_ENFD) 1017 if (flags & XFS_UQUOTA_ENFD)
990 uflags |= XFS_QUOTA_UDQ_ENFD; 1018 uflags |= XFS_QUOTA_UDQ_ENFD;
991 if (flags & XFS_GQUOTA_ENFD) 1019 if (flags & (XFS_OQUOTA_ENFD)) {
992 uflags |= XFS_QUOTA_GDQ_ENFD; 1020 uflags |= (flags & XFS_GQUOTA_ACCT) ?
1021 XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;
1022 }
993 return (uflags); 1023 return (uflags);
994} 1024}
995 1025
@@ -1070,7 +1100,7 @@ again:
1070 xfs_qm_dqrele(ip->i_udquot); 1100 xfs_qm_dqrele(ip->i_udquot);
1071 ip->i_udquot = NULL; 1101 ip->i_udquot = NULL;
1072 } 1102 }
1073 if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) { 1103 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
1074 xfs_qm_dqrele(ip->i_gdquot); 1104 xfs_qm_dqrele(ip->i_gdquot);
1075 ip->i_gdquot = NULL; 1105 ip->i_gdquot = NULL;
1076 } 1106 }
@@ -1160,7 +1190,6 @@ xfs_qm_dqtest_print(
1160{ 1190{
1161 cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------"); 1191 cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
1162 cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id); 1192 cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
1163 cmn_err(CE_DEBUG, "---- type = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
1164 cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount); 1193 cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount);
1165 cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)", 1194 cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)",
1166 d->d_bcount, (int)d->d_bcount); 1195 d->d_bcount, (int)d->d_bcount);
@@ -1231,7 +1260,7 @@ xfs_dqtest_cmp2(
1231#ifdef QUOTADEBUG 1260#ifdef QUOTADEBUG
1232 if (!err) { 1261 if (!err) {
1233 cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked", 1262 cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
1234 d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount); 1263 d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
1235 } 1264 }
1236#endif 1265#endif
1237 return (err); 1266 return (err);
@@ -1287,6 +1316,7 @@ STATIC void
1287xfs_qm_internalqcheck_get_dquots( 1316xfs_qm_internalqcheck_get_dquots(
1288 xfs_mount_t *mp, 1317 xfs_mount_t *mp,
1289 xfs_dqid_t uid, 1318 xfs_dqid_t uid,
1319 xfs_dqid_t projid,
1290 xfs_dqid_t gid, 1320 xfs_dqid_t gid,
1291 xfs_dqtest_t **ud, 1321 xfs_dqtest_t **ud,
1292 xfs_dqtest_t **gd) 1322 xfs_dqtest_t **gd)
@@ -1295,6 +1325,8 @@ xfs_qm_internalqcheck_get_dquots(
1295 xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud); 1325 xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
1296 if (XFS_IS_GQUOTA_ON(mp)) 1326 if (XFS_IS_GQUOTA_ON(mp))
1297 xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd); 1327 xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
1328 else if (XFS_IS_PQUOTA_ON(mp))
1329 xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
1298} 1330}
1299 1331
1300 1332
@@ -1362,13 +1394,14 @@ xfs_qm_internalqcheck_adjust(
1362 } 1394 }
1363 xfs_qm_internalqcheck_get_dquots(mp, 1395 xfs_qm_internalqcheck_get_dquots(mp,
1364 (xfs_dqid_t) ip->i_d.di_uid, 1396 (xfs_dqid_t) ip->i_d.di_uid,
1397 (xfs_dqid_t) ip->i_d.di_projid,
1365 (xfs_dqid_t) ip->i_d.di_gid, 1398 (xfs_dqid_t) ip->i_d.di_gid,
1366 &ud, &gd); 1399 &ud, &gd);
1367 if (XFS_IS_UQUOTA_ON(mp)) { 1400 if (XFS_IS_UQUOTA_ON(mp)) {
1368 ASSERT(ud); 1401 ASSERT(ud);
1369 xfs_qm_internalqcheck_dqadjust(ip, ud); 1402 xfs_qm_internalqcheck_dqadjust(ip, ud);
1370 } 1403 }
1371 if (XFS_IS_GQUOTA_ON(mp)) { 1404 if (XFS_IS_OQUOTA_ON(mp)) {
1372 ASSERT(gd); 1405 ASSERT(gd);
1373 xfs_qm_internalqcheck_dqadjust(ip, gd); 1406 xfs_qm_internalqcheck_dqadjust(ip, gd);
1374 } 1407 }
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 675f03f443d2..472afd3570c6 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -102,7 +102,8 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
102 (xfs_Gqm->qm_grp_dqhtable + \ 102 (xfs_Gqm->qm_grp_dqhtable + \
103 XFS_DQ_HASHVAL(mp, id))) 103 XFS_DQ_HASHVAL(mp, id)))
104#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \ 104#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \
105 XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp)) 105 XFS_IS_UQUOTA_ON(mp) : \
106 XFS_IS_OQUOTA_ON(mp))
106#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \ 107#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
107 !dqp->q_core.d_blk_hardlimit && \ 108 !dqp->q_core.d_blk_hardlimit && \
108 !dqp->q_core.d_blk_softlimit && \ 109 !dqp->q_core.d_blk_softlimit && \
@@ -180,7 +181,8 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
180 IRELE(ip); 181 IRELE(ip);
181 182
182#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \ 183#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
183 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : "???")) 184 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
185 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
184#define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY") 186#define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
185 187
186#endif /* __XFS_QUOTA_PRIV_H__ */ 188#endif /* __XFS_QUOTA_PRIV_H__ */
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 3644ca00cc82..565efb73c233 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -207,12 +207,10 @@ xfs_trans_mod_dquot_byino(
207 if (tp->t_dqinfo == NULL) 207 if (tp->t_dqinfo == NULL)
208 xfs_trans_alloc_dqinfo(tp); 208 xfs_trans_alloc_dqinfo(tp);
209 209
210 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) { 210 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
211 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); 211 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
212 } 212 if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
213 if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
214 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); 213 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
215 }
216} 214}
217 215
218STATIC xfs_dqtrx_t * 216STATIC xfs_dqtrx_t *
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 5f1b0c9308f6..01aed5f2d579 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -80,7 +80,7 @@ typedef struct xfs_buf_log_format_t {
80 * user or group dquots and may require special recovery handling. 80 * user or group dquots and may require special recovery handling.
81 */ 81 */
82#define XFS_BLI_UDQUOT_BUF 0x4 82#define XFS_BLI_UDQUOT_BUF 0x4
83/* #define XFS_BLI_PDQUOT_BUF 0x8 */ 83#define XFS_BLI_PDQUOT_BUF 0x8
84#define XFS_BLI_GDQUOT_BUF 0x10 84#define XFS_BLI_GDQUOT_BUF 0x10
85 85
86#define XFS_BLI_CHUNK 128 86#define XFS_BLI_CHUNK 128
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 593e597c86b2..91d764a5a9b2 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1964,7 +1964,8 @@ xlog_recover_do_reg_buffer(
1964 * probably a good thing to do for other buf types also. 1964 * probably a good thing to do for other buf types also.
1965 */ 1965 */
1966 error = 0; 1966 error = 0;
1967 if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) { 1967 if (buf_f->blf_flags &
1968 (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
1968 error = xfs_qm_dqcheck((xfs_disk_dquot_t *) 1969 error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
1969 item->ri_buf[i].i_addr, 1970 item->ri_buf[i].i_addr,
1970 -1, 0, XFS_QMOPT_DOWARN, 1971 -1, 0, XFS_QMOPT_DOWARN,
@@ -2030,6 +2031,7 @@ xfs_qm_dqcheck(
2030 } 2031 }
2031 2032
2032 if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER && 2033 if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER &&
2034 INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_PROJ &&
2033 INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) { 2035 INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) {
2034 if (flags & XFS_QMOPT_DOWARN) 2036 if (flags & XFS_QMOPT_DOWARN)
2035 cmn_err(CE_ALERT, 2037 cmn_err(CE_ALERT,
@@ -2135,6 +2137,8 @@ xlog_recover_do_dquot_buffer(
2135 type = 0; 2137 type = 0;
2136 if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF) 2138 if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
2137 type |= XFS_DQ_USER; 2139 type |= XFS_DQ_USER;
2140 if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
2141 type |= XFS_DQ_PROJ;
2138 if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF) 2142 if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
2139 type |= XFS_DQ_GROUP; 2143 type |= XFS_DQ_GROUP;
2140 /* 2144 /*
@@ -2247,7 +2251,8 @@ xlog_recover_do_buffer_trans(
2247 error = 0; 2251 error = 0;
2248 if (flags & XFS_BLI_INODE_BUF) { 2252 if (flags & XFS_BLI_INODE_BUF) {
2249 error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f); 2253 error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
2250 } else if (flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) { 2254 } else if (flags &
2255 (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
2251 xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f); 2256 xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
2252 } else { 2257 } else {
2253 xlog_recover_do_reg_buffer(mp, item, bp, buf_f); 2258 xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
@@ -2619,7 +2624,7 @@ xlog_recover_do_dquot_trans(
2619 * This type of quotas was turned off, so ignore this record. 2624 * This type of quotas was turned off, so ignore this record.
2620 */ 2625 */
2621 type = INT_GET(recddq->d_flags, ARCH_CONVERT) & 2626 type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
2622 (XFS_DQ_USER | XFS_DQ_GROUP); 2627 (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
2623 ASSERT(type); 2628 ASSERT(type);
2624 if (log->l_quotaoffs_flag & type) 2629 if (log->l_quotaoffs_flag & type)
2625 return (0); 2630 return (0);
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index cd5170ec73a3..5affba38a577 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -141,7 +141,7 @@ typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint);
141typedef void (*xfs_dqdetach_t)(struct xfs_inode *); 141typedef void (*xfs_dqdetach_t)(struct xfs_inode *);
142typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint); 142typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
143typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *, 143typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *,
144 struct xfs_inode *, uid_t, gid_t, uint, 144 struct xfs_inode *, uid_t, gid_t, prid_t, uint,
145 struct xfs_dquot **, struct xfs_dquot **); 145 struct xfs_dquot **, struct xfs_dquot **);
146typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *, 146typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
147 struct xfs_dquot *, struct xfs_dquot *); 147 struct xfs_dquot *, struct xfs_dquot *);
@@ -185,8 +185,8 @@ typedef struct xfs_qmops {
185 (*(mp)->m_qm_ops.xfs_dqdetach)(ip) 185 (*(mp)->m_qm_ops.xfs_dqdetach)(ip)
186#define XFS_QM_DQPURGEALL(mp, fl) \ 186#define XFS_QM_DQPURGEALL(mp, fl) \
187 (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl) 187 (*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
188#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \ 188#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
189 (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2) 189 (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
190#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \ 190#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
191 (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2) 191 (*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
192#define XFS_QM_DQVOPRENAME(mp, ip) \ 192#define XFS_QM_DQVOPRENAME(mp, ip) \
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 703ec4efcb41..341cb4604c66 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -96,7 +96,7 @@ typedef struct xfs_dqblk {
96 * flags for q_flags field in the dquot. 96 * flags for q_flags field in the dquot.
97 */ 97 */
98#define XFS_DQ_USER 0x0001 /* a user quota */ 98#define XFS_DQ_USER 0x0001 /* a user quota */
99/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */ 99#define XFS_DQ_PROJ 0x0002 /* project quota */
100#define XFS_DQ_GROUP 0x0004 /* a group quota */ 100#define XFS_DQ_GROUP 0x0004 /* a group quota */
101#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */ 101#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */
102#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */ 102#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */
@@ -104,6 +104,8 @@ typedef struct xfs_dqblk {
104#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */ 104#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */
105#define XFS_DQ_MARKER 0x0080 /* sentinel */ 105#define XFS_DQ_MARKER 0x0080 /* sentinel */
106 106
107#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
108
107/* 109/*
108 * In the worst case, when both user and group quotas are on, 110 * In the worst case, when both user and group quotas are on,
109 * we can have a max of three dquots changing in a single transaction. 111 * we can have a max of three dquots changing in a single transaction.
@@ -124,7 +126,7 @@ typedef struct xfs_dqblk {
124typedef struct xfs_dq_logformat { 126typedef struct xfs_dq_logformat {
125 __uint16_t qlf_type; /* dquot log item type */ 127 __uint16_t qlf_type; /* dquot log item type */
126 __uint16_t qlf_size; /* size of this item */ 128 __uint16_t qlf_size; /* size of this item */
127 xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */ 129 xfs_dqid_t qlf_id; /* usr/grp/proj id : 32 bits */
128 __int64_t qlf_blkno; /* blkno of dquot buffer */ 130 __int64_t qlf_blkno; /* blkno of dquot buffer */
129 __int32_t qlf_len; /* len of dquot buffer */ 131 __int32_t qlf_len; /* len of dquot buffer */
130 __uint32_t qlf_boffset; /* off of dquot in buffer */ 132 __uint32_t qlf_boffset; /* off of dquot in buffer */
@@ -152,9 +154,9 @@ typedef struct xfs_qoff_logformat {
152#define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */ 154#define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */
153#define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */ 155#define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */
154#define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */ 156#define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */
155#define XFS_PQUOTA_ACCT 0x0008 /* (IRIX) project quota accounting ON */ 157#define XFS_PQUOTA_ACCT 0x0008 /* project quota accounting ON */
156#define XFS_GQUOTA_ENFD 0x0010 /* group quota limits enforced */ 158#define XFS_OQUOTA_ENFD 0x0010 /* other (grp/prj) quota limits enforced */
157#define XFS_GQUOTA_CHKD 0x0020 /* quotacheck run on grp quotas */ 159#define XFS_OQUOTA_CHKD 0x0020 /* quotacheck run on other (grp/prj) quotas */
158#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */ 160#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
159 161
160/* 162/*
@@ -162,17 +164,22 @@ typedef struct xfs_qoff_logformat {
162 * are in the process of getting turned off. These flags are in m_qflags but 164 * are in the process of getting turned off. These flags are in m_qflags but
163 * never in sb_qflags. 165 * never in sb_qflags.
164 */ 166 */
165#define XFS_UQUOTA_ACTIVE 0x0080 /* uquotas are being turned off */ 167#define XFS_UQUOTA_ACTIVE 0x0100 /* uquotas are being turned off */
166#define XFS_GQUOTA_ACTIVE 0x0100 /* gquotas are being turned off */ 168#define XFS_PQUOTA_ACTIVE 0x0200 /* pquotas are being turned off */
169#define XFS_GQUOTA_ACTIVE 0x0400 /* gquotas are being turned off */
167 170
168/* 171/*
169 * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees 172 * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
170 * quota will be not be switched off as long as that inode lock is held. 173 * quota will be not be switched off as long as that inode lock is held.
171 */ 174 */
172#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \ 175#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
173 XFS_GQUOTA_ACTIVE)) 176 XFS_GQUOTA_ACTIVE | \
177 XFS_PQUOTA_ACTIVE))
178#define XFS_IS_OQUOTA_ON(mp) ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
179 XFS_PQUOTA_ACTIVE))
174#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE) 180#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
175#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE) 181#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
182#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
176 183
177/* 184/*
178 * Flags to tell various functions what to do. Not all of these are meaningful 185 * Flags to tell various functions what to do. Not all of these are meaningful
@@ -182,7 +189,7 @@ typedef struct xfs_qoff_logformat {
182#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */ 189#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */
183#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ 190#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */
184#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ 191#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */
185#define XFS_QMOPT_GQUOTA 0x0000008 /* group dquot requested */ 192#define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */
186#define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */ 193#define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */
187#define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */ 194#define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */
188#define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */ 195#define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */
@@ -192,6 +199,7 @@ typedef struct xfs_qoff_logformat {
192#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */ 199#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */
193#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */ 200#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */
194#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */ 201#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */
202#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */
195 203
196/* 204/*
197 * flags to xfs_trans_mod_dquot to indicate which field needs to be 205 * flags to xfs_trans_mod_dquot to indicate which field needs to be
@@ -231,7 +239,8 @@ typedef struct xfs_qoff_logformat {
231#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT 239#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
232 240
233 241
234#define XFS_QMOPT_QUOTALL (XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA) 242#define XFS_QMOPT_QUOTALL \
243 (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
235#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS) 244#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
236 245
237#ifdef __KERNEL__ 246#ifdef __KERNEL__
@@ -246,21 +255,33 @@ typedef struct xfs_qoff_logformat {
246 */ 255 */
247#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ 256#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
248 (ip)->i_udquot == NULL) || \ 257 (ip)->i_udquot == NULL) || \
249 (XFS_IS_GQUOTA_ON(mp) && \ 258 (XFS_IS_OQUOTA_ON(mp) && \
250 (ip)->i_gdquot == NULL)) 259 (ip)->i_gdquot == NULL))
251 260
252#define XFS_QM_NEED_QUOTACHECK(mp) ((XFS_IS_UQUOTA_ON(mp) && \ 261#define XFS_QM_NEED_QUOTACHECK(mp) \
253 (mp->m_sb.sb_qflags & \ 262 ((XFS_IS_UQUOTA_ON(mp) && \
254 XFS_UQUOTA_CHKD) == 0) || \ 263 (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
255 (XFS_IS_GQUOTA_ON(mp) && \ 264 (XFS_IS_GQUOTA_ON(mp) && \
256 (mp->m_sb.sb_qflags & \ 265 ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
257 XFS_GQUOTA_CHKD) == 0)) 266 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
267 (XFS_IS_PQUOTA_ON(mp) && \
268 ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
269 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
270
271#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
272 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
273 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
274
275#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
276 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
277 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
258 278
259#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\ 279#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
260 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\ 280 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
261 XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD) 281 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
282 XFS_GQUOTA_ACCT)
262#define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \ 283#define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
263 XFS_GQUOTA_ACTIVE) 284 XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
264 285
265 286
266/* 287/*
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index a9682b9510c1..144da7a85466 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -976,6 +976,7 @@ xfs_trans_dquot_buf(
976 ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp); 976 ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
977 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL); 977 ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
978 ASSERT(type == XFS_BLI_UDQUOT_BUF || 978 ASSERT(type == XFS_BLI_UDQUOT_BUF ||
979 type == XFS_BLI_PDQUOT_BUF ||
979 type == XFS_BLI_GDQUOT_BUF); 980 type == XFS_BLI_GDQUOT_BUF);
980 981
981 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *); 982 bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index d1f8146a06ea..11351f08d438 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -428,7 +428,7 @@ xfs_truncate_file(
428 if (ip->i_ino != mp->m_sb.sb_uquotino) 428 if (ip->i_ino != mp->m_sb.sb_uquotino)
429 ASSERT(ip->i_udquot); 429 ASSERT(ip->i_udquot);
430 } 430 }
431 if (XFS_IS_GQUOTA_ON(mp)) { 431 if (XFS_IS_OQUOTA_ON(mp)) {
432 if (ip->i_ino != mp->m_sb.sb_gquotino) 432 if (ip->i_ino != mp->m_sb.sb_gquotino)
433 ASSERT(ip->i_gdquot); 433 ASSERT(ip->i_gdquot);
434 } 434 }
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index fb1ae6cfb1f3..103500498342 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -368,16 +368,6 @@ xfs_finish_flags(
368 } 368 }
369 369
370 /* 370 /*
371 * disallow mount attempts with (IRIX) project quota enabled
372 */
373 if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
374 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {
375 cmn_err(CE_WARN,
376 "XFS: cannot mount a filesystem with IRIX project quota enabled");
377 return XFS_ERROR(ENOSYS);
378 }
379
380 /*
381 * check for shared mount. 371 * check for shared mount.
382 */ 372 */
383 if (ap->flags & XFSMNT_SHARED) { 373 if (ap->flags & XFSMNT_SHARED) {
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 5703783991fa..695978b27497 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -351,21 +351,28 @@ xfs_setattr(
351 * If the IDs do change before we take the ilock, we're covered 351 * If the IDs do change before we take the ilock, we're covered
352 * because the i_*dquot fields will get updated anyway. 352 * because the i_*dquot fields will get updated anyway.
353 */ 353 */
354 if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) { 354 if (XFS_IS_QUOTA_ON(mp) &&
355 (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
355 uint qflags = 0; 356 uint qflags = 0;
356 357
357 if (mask & XFS_AT_UID) { 358 if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
358 uid = vap->va_uid; 359 uid = vap->va_uid;
359 qflags |= XFS_QMOPT_UQUOTA; 360 qflags |= XFS_QMOPT_UQUOTA;
360 } else { 361 } else {
361 uid = ip->i_d.di_uid; 362 uid = ip->i_d.di_uid;
362 } 363 }
363 if (mask & XFS_AT_GID) { 364 if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
364 gid = vap->va_gid; 365 gid = vap->va_gid;
365 qflags |= XFS_QMOPT_GQUOTA; 366 qflags |= XFS_QMOPT_GQUOTA;
366 } else { 367 } else {
367 gid = ip->i_d.di_gid; 368 gid = ip->i_d.di_gid;
368 } 369 }
370 if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
371 projid = vap->va_projid;
372 qflags |= XFS_QMOPT_PQUOTA;
373 } else {
374 projid = ip->i_d.di_projid;
375 }
369 /* 376 /*
370 * We take a reference when we initialize udqp and gdqp, 377 * We take a reference when we initialize udqp and gdqp,
371 * so it is important that we never blindly double trip on 378 * so it is important that we never blindly double trip on
@@ -373,7 +380,8 @@ xfs_setattr(
373 */ 380 */
374 ASSERT(udqp == NULL); 381 ASSERT(udqp == NULL);
375 ASSERT(gdqp == NULL); 382 ASSERT(gdqp == NULL);
376 code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp); 383 code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
384 &udqp, &gdqp);
377 if (code) 385 if (code)
378 return (code); 386 return (code);
379 } 387 }
@@ -510,10 +518,11 @@ xfs_setattr(
510 goto error_return; 518 goto error_return;
511 } 519 }
512 /* 520 /*
513 * Do a quota reservation only if uid or gid is actually 521 * Do a quota reservation only if uid/projid/gid is actually
514 * going to change. 522 * going to change.
515 */ 523 */
516 if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) || 524 if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
525 (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
517 (XFS_IS_GQUOTA_ON(mp) && igid != gid)) { 526 (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
518 ASSERT(tp); 527 ASSERT(tp);
519 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp, 528 code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
@@ -774,6 +783,7 @@ xfs_setattr(
774 } 783 }
775 if (igid != gid) { 784 if (igid != gid) {
776 if (XFS_IS_GQUOTA_ON(mp)) { 785 if (XFS_IS_GQUOTA_ON(mp)) {
786 ASSERT(!XFS_IS_PQUOTA_ON(mp));
777 ASSERT(mask & XFS_AT_GID); 787 ASSERT(mask & XFS_AT_GID);
778 ASSERT(gdqp); 788 ASSERT(gdqp);
779 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip, 789 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
@@ -782,6 +792,13 @@ xfs_setattr(
782 ip->i_d.di_gid = gid; 792 ip->i_d.di_gid = gid;
783 } 793 }
784 if (iprojid != projid) { 794 if (iprojid != projid) {
795 if (XFS_IS_PQUOTA_ON(mp)) {
796 ASSERT(!XFS_IS_GQUOTA_ON(mp));
797 ASSERT(mask & XFS_AT_PROJID);
798 ASSERT(gdqp);
799 olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
800 &ip->i_gdquot, gdqp);
801 }
785 ip->i_d.di_projid = projid; 802 ip->i_d.di_projid = projid;
786 /* 803 /*
787 * We may have to rev the inode as well as 804 * We may have to rev the inode as well as
@@ -1907,7 +1924,7 @@ xfs_create(
1907 * Make sure that we have allocated dquot(s) on disk. 1924 * Make sure that we have allocated dquot(s) on disk.
1908 */ 1925 */
1909 error = XFS_QM_DQVOPALLOC(mp, dp, 1926 error = XFS_QM_DQVOPALLOC(mp, dp,
1910 current_fsuid(credp), current_fsgid(credp), 1927 current_fsuid(credp), current_fsgid(credp), prid,
1911 XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); 1928 XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
1912 if (error) 1929 if (error)
1913 goto std_return; 1930 goto std_return;
@@ -2812,7 +2829,7 @@ xfs_mkdir(
2812 * Make sure that we have allocated dquot(s) on disk. 2829 * Make sure that we have allocated dquot(s) on disk.
2813 */ 2830 */
2814 error = XFS_QM_DQVOPALLOC(mp, dp, 2831 error = XFS_QM_DQVOPALLOC(mp, dp,
2815 current_fsuid(credp), current_fsgid(credp), 2832 current_fsuid(credp), current_fsgid(credp), prid,
2816 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 2833 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
2817 if (error) 2834 if (error)
2818 goto std_return; 2835 goto std_return;
@@ -3366,7 +3383,7 @@ xfs_symlink(
3366 * Make sure that we have allocated dquot(s) on disk. 3383 * Make sure that we have allocated dquot(s) on disk.
3367 */ 3384 */
3368 error = XFS_QM_DQVOPALLOC(mp, dp, 3385 error = XFS_QM_DQVOPALLOC(mp, dp,
3369 current_fsuid(credp), current_fsgid(credp), 3386 current_fsuid(credp), current_fsgid(credp), prid,
3370 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 3387 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
3371 if (error) 3388 if (error)
3372 goto std_return; 3389 goto std_return;