aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChandra Seetharaman <sekharan@us.ibm.com>2013-07-11 01:00:40 -0400
committerBen Myers <bpm@sgi.com>2013-07-11 11:35:32 -0400
commit92f8ff73f18672b03ec8b92197cdddf2b5de7ea0 (patch)
treeb90205ed9a1e141d8ac5d096f4d8984e89774d2e /fs
parent42c49d7f249c2487f36d3314753d5d8ebcee8249 (diff)
xfs: Add pquota fields where gquota is used.
Add project quota changes to all the places where group quota field is used: * add separate project quota members into various structures * split project quota and group quotas so that instead of overriding the group quota members incore, the new project quota members are used instead * get rid of usage of the OQUOTA flag incore, in favor of separate group and project quota flags. * add a project dquot argument to various functions. Not using the pquotino field from superblock yet. Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_dquot.c15
-rw-r--r--fs/xfs/xfs_dquot.h7
-rw-r--r--fs/xfs/xfs_icache.c1
-rw-r--r--fs/xfs/xfs_inode.h1
-rw-r--r--fs/xfs/xfs_ioctl.c14
-rw-r--r--fs/xfs/xfs_iops.c4
-rw-r--r--fs/xfs/xfs_qm.c243
-rw-r--r--fs/xfs/xfs_qm.h20
-rw-r--r--fs/xfs/xfs_qm_bhv.c10
-rw-r--r--fs/xfs/xfs_qm_syscalls.c19
-rw-r--r--fs/xfs/xfs_quota.h32
-rw-r--r--fs/xfs/xfs_symlink.c10
-rw-r--r--fs/xfs/xfs_trans_dquot.c26
-rw-r--r--fs/xfs/xfs_vnodeops.c13
14 files changed, 291 insertions, 124 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index f01012de06d0..0adf27ecf3f1 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -936,6 +936,7 @@ xfs_qm_dqput_final(
936{ 936{
937 struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo; 937 struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo;
938 struct xfs_dquot *gdqp; 938 struct xfs_dquot *gdqp;
939 struct xfs_dquot *pdqp;
939 940
940 trace_xfs_dqput_free(dqp); 941 trace_xfs_dqput_free(dqp);
941 942
@@ -949,21 +950,29 @@ xfs_qm_dqput_final(
949 950
950 /* 951 /*
951 * If we just added a udquot to the freelist, then we want to release 952 * If we just added a udquot to the freelist, then we want to release
952 * the gdquot reference that it (probably) has. Otherwise it'll keep 953 * the gdquot/pdquot reference that it (probably) has. Otherwise it'll
953 * the gdquot from getting reclaimed. 954 * keep the gdquot/pdquot from getting reclaimed.
954 */ 955 */
955 gdqp = dqp->q_gdquot; 956 gdqp = dqp->q_gdquot;
956 if (gdqp) { 957 if (gdqp) {
957 xfs_dqlock(gdqp); 958 xfs_dqlock(gdqp);
958 dqp->q_gdquot = NULL; 959 dqp->q_gdquot = NULL;
959 } 960 }
961
962 pdqp = dqp->q_pdquot;
963 if (pdqp) {
964 xfs_dqlock(pdqp);
965 dqp->q_pdquot = NULL;
966 }
960 xfs_dqunlock(dqp); 967 xfs_dqunlock(dqp);
961 968
962 /* 969 /*
963 * If we had a group quota hint, release it now. 970 * If we had a group/project quota hint, release it now.
964 */ 971 */
965 if (gdqp) 972 if (gdqp)
966 xfs_qm_dqput(gdqp); 973 xfs_qm_dqput(gdqp);
974 if (pdqp)
975 xfs_qm_dqput(pdqp);
967} 976}
968 977
969/* 978/*
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index b596626249b8..55abbca2883d 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -53,6 +53,7 @@ typedef struct xfs_dquot {
53 xfs_fileoff_t q_fileoffset; /* offset in quotas file */ 53 xfs_fileoff_t q_fileoffset; /* offset in quotas file */
54 54
55 struct xfs_dquot*q_gdquot; /* group dquot, hint only */ 55 struct xfs_dquot*q_gdquot; /* group dquot, hint only */
56 struct xfs_dquot*q_pdquot; /* project dquot, hint only */
56 xfs_disk_dquot_t q_core; /* actual usage & quotas */ 57 xfs_disk_dquot_t q_core; /* actual usage & quotas */
57 xfs_dq_logitem_t q_logitem; /* dquot log item */ 58 xfs_dq_logitem_t q_logitem; /* dquot log item */
58 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ 59 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */
@@ -118,8 +119,9 @@ static inline int xfs_this_quota_on(struct xfs_mount *mp, int type)
118 case XFS_DQ_USER: 119 case XFS_DQ_USER:
119 return XFS_IS_UQUOTA_ON(mp); 120 return XFS_IS_UQUOTA_ON(mp);
120 case XFS_DQ_GROUP: 121 case XFS_DQ_GROUP:
122 return XFS_IS_GQUOTA_ON(mp);
121 case XFS_DQ_PROJ: 123 case XFS_DQ_PROJ:
122 return XFS_IS_OQUOTA_ON(mp); 124 return XFS_IS_PQUOTA_ON(mp);
123 default: 125 default:
124 return 0; 126 return 0;
125 } 127 }
@@ -131,8 +133,9 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
131 case XFS_DQ_USER: 133 case XFS_DQ_USER:
132 return ip->i_udquot; 134 return ip->i_udquot;
133 case XFS_DQ_GROUP: 135 case XFS_DQ_GROUP:
134 case XFS_DQ_PROJ:
135 return ip->i_gdquot; 136 return ip->i_gdquot;
137 case XFS_DQ_PROJ:
138 return ip->i_pdquot;
136 default: 139 default:
137 return NULL; 140 return NULL;
138 } 141 }
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 9560dc1f15a9..3f90e1ceb8d6 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -337,6 +337,7 @@ xfs_iget_cache_miss(
337 iflags |= XFS_IDONTCACHE; 337 iflags |= XFS_IDONTCACHE;
338 ip->i_udquot = NULL; 338 ip->i_udquot = NULL;
339 ip->i_gdquot = NULL; 339 ip->i_gdquot = NULL;
340 ip->i_pdquot = NULL;
340 xfs_iflags_set(ip, iflags); 341 xfs_iflags_set(ip, iflags);
341 342
342 /* insert the new inode */ 343 /* insert the new inode */
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 91129794aaec..b55fd347ab5b 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -250,6 +250,7 @@ typedef struct xfs_inode {
250 struct xfs_mount *i_mount; /* fs mount struct ptr */ 250 struct xfs_mount *i_mount; /* fs mount struct ptr */
251 struct xfs_dquot *i_udquot; /* user dquot */ 251 struct xfs_dquot *i_udquot; /* user dquot */
252 struct xfs_dquot *i_gdquot; /* group dquot */ 252 struct xfs_dquot *i_gdquot; /* group dquot */
253 struct xfs_dquot *i_pdquot; /* project dquot */
253 254
254 /* Inode location stuff */ 255 /* Inode location stuff */
255 xfs_ino_t i_ino; /* inode number (agno/agino)*/ 256 xfs_ino_t i_ino; /* inode number (agno/agino)*/
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index dc5b65983e5f..6e2bca5d44d6 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -928,7 +928,7 @@ xfs_ioctl_setattr(
928 struct xfs_trans *tp; 928 struct xfs_trans *tp;
929 unsigned int lock_flags = 0; 929 unsigned int lock_flags = 0;
930 struct xfs_dquot *udqp = NULL; 930 struct xfs_dquot *udqp = NULL;
931 struct xfs_dquot *gdqp = NULL; 931 struct xfs_dquot *pdqp = NULL;
932 struct xfs_dquot *olddquot = NULL; 932 struct xfs_dquot *olddquot = NULL;
933 int code; 933 int code;
934 934
@@ -957,7 +957,7 @@ xfs_ioctl_setattr(
957 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) { 957 if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
958 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid, 958 code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
959 ip->i_d.di_gid, fa->fsx_projid, 959 ip->i_d.di_gid, fa->fsx_projid,
960 XFS_QMOPT_PQUOTA, &udqp, &gdqp); 960 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
961 if (code) 961 if (code)
962 return code; 962 return code;
963 } 963 }
@@ -994,8 +994,8 @@ xfs_ioctl_setattr(
994 XFS_IS_PQUOTA_ON(mp) && 994 XFS_IS_PQUOTA_ON(mp) &&
995 xfs_get_projid(ip) != fa->fsx_projid) { 995 xfs_get_projid(ip) != fa->fsx_projid) {
996 ASSERT(tp); 996 ASSERT(tp);
997 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 997 code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
998 capable(CAP_FOWNER) ? 998 pdqp, capable(CAP_FOWNER) ?
999 XFS_QMOPT_FORCE_RES : 0); 999 XFS_QMOPT_FORCE_RES : 0);
1000 if (code) /* out of quota */ 1000 if (code) /* out of quota */
1001 goto error_return; 1001 goto error_return;
@@ -1113,7 +1113,7 @@ xfs_ioctl_setattr(
1113 if (xfs_get_projid(ip) != fa->fsx_projid) { 1113 if (xfs_get_projid(ip) != fa->fsx_projid) {
1114 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) { 1114 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
1115 olddquot = xfs_qm_vop_chown(tp, ip, 1115 olddquot = xfs_qm_vop_chown(tp, ip,
1116 &ip->i_gdquot, gdqp); 1116 &ip->i_pdquot, pdqp);
1117 } 1117 }
1118 xfs_set_projid(ip, fa->fsx_projid); 1118 xfs_set_projid(ip, fa->fsx_projid);
1119 1119
@@ -1160,13 +1160,13 @@ xfs_ioctl_setattr(
1160 */ 1160 */
1161 xfs_qm_dqrele(olddquot); 1161 xfs_qm_dqrele(olddquot);
1162 xfs_qm_dqrele(udqp); 1162 xfs_qm_dqrele(udqp);
1163 xfs_qm_dqrele(gdqp); 1163 xfs_qm_dqrele(pdqp);
1164 1164
1165 return code; 1165 return code;
1166 1166
1167 error_return: 1167 error_return:
1168 xfs_qm_dqrele(udqp); 1168 xfs_qm_dqrele(udqp);
1169 xfs_qm_dqrele(gdqp); 1169 xfs_qm_dqrele(pdqp);
1170 xfs_trans_cancel(tp, 0); 1170 xfs_trans_cancel(tp, 0);
1171 if (lock_flags) 1171 if (lock_flags)
1172 xfs_iunlock(ip, lock_flags); 1172 xfs_iunlock(ip, lock_flags);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 8865261e5417..96dda62d497b 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -539,7 +539,7 @@ xfs_setattr_nonsize(
539 ASSERT(udqp == NULL); 539 ASSERT(udqp == NULL);
540 ASSERT(gdqp == NULL); 540 ASSERT(gdqp == NULL);
541 error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip), 541 error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
542 qflags, &udqp, &gdqp); 542 qflags, &udqp, &gdqp, NULL);
543 if (error) 543 if (error)
544 return error; 544 return error;
545 } 545 }
@@ -575,7 +575,7 @@ xfs_setattr_nonsize(
575 (XFS_IS_GQUOTA_ON(mp) && igid != gid))) { 575 (XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
576 ASSERT(tp); 576 ASSERT(tp);
577 error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, 577 error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
578 capable(CAP_FOWNER) ? 578 NULL, capable(CAP_FOWNER) ?
579 XFS_QMOPT_FORCE_RES : 0); 579 XFS_QMOPT_FORCE_RES : 0);
580 if (error) /* out of quota */ 580 if (error) /* out of quota */
581 goto out_trans_cancel; 581 goto out_trans_cancel;
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 7a3e007b49f4..d320794d03ce 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -137,6 +137,7 @@ xfs_qm_dqpurge(
137 struct xfs_mount *mp = dqp->q_mount; 137 struct xfs_mount *mp = dqp->q_mount;
138 struct xfs_quotainfo *qi = mp->m_quotainfo; 138 struct xfs_quotainfo *qi = mp->m_quotainfo;
139 struct xfs_dquot *gdqp = NULL; 139 struct xfs_dquot *gdqp = NULL;
140 struct xfs_dquot *pdqp = NULL;
140 141
141 xfs_dqlock(dqp); 142 xfs_dqlock(dqp);
142 if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) { 143 if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -145,8 +146,7 @@ xfs_qm_dqpurge(
145 } 146 }
146 147
147 /* 148 /*
148 * If this quota has a group hint attached, prepare for releasing it 149 * If this quota has a hint attached, prepare for releasing it now.
149 * now.
150 */ 150 */
151 gdqp = dqp->q_gdquot; 151 gdqp = dqp->q_gdquot;
152 if (gdqp) { 152 if (gdqp) {
@@ -154,6 +154,12 @@ xfs_qm_dqpurge(
154 dqp->q_gdquot = NULL; 154 dqp->q_gdquot = NULL;
155 } 155 }
156 156
157 pdqp = dqp->q_pdquot;
158 if (pdqp) {
159 xfs_dqlock(pdqp);
160 dqp->q_pdquot = NULL;
161 }
162
157 dqp->dq_flags |= XFS_DQ_FREEING; 163 dqp->dq_flags |= XFS_DQ_FREEING;
158 164
159 xfs_dqflock(dqp); 165 xfs_dqflock(dqp);
@@ -208,6 +214,8 @@ xfs_qm_dqpurge(
208 214
209 if (gdqp) 215 if (gdqp)
210 xfs_qm_dqput(gdqp); 216 xfs_qm_dqput(gdqp);
217 if (pdqp)
218 xfs_qm_dqput(pdqp);
211 return 0; 219 return 0;
212} 220}
213 221
@@ -364,6 +372,10 @@ xfs_qm_unmount_quotas(
364 IRELE(mp->m_quotainfo->qi_gquotaip); 372 IRELE(mp->m_quotainfo->qi_gquotaip);
365 mp->m_quotainfo->qi_gquotaip = NULL; 373 mp->m_quotainfo->qi_gquotaip = NULL;
366 } 374 }
375 if (mp->m_quotainfo->qi_pquotaip) {
376 IRELE(mp->m_quotainfo->qi_pquotaip);
377 mp->m_quotainfo->qi_pquotaip = NULL;
378 }
367 } 379 }
368} 380}
369 381
@@ -410,7 +422,10 @@ xfs_qm_dqattach_one(
410 * be reclaimed as long as we have a ref from inode and we 422 * be reclaimed as long as we have a ref from inode and we
411 * hold the ilock. 423 * hold the ilock.
412 */ 424 */
413 dqp = udqhint->q_gdquot; 425 if (type == XFS_DQ_GROUP)
426 dqp = udqhint->q_gdquot;
427 else
428 dqp = udqhint->q_pdquot;
414 if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { 429 if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
415 ASSERT(*IO_idqpp == NULL); 430 ASSERT(*IO_idqpp == NULL);
416 431
@@ -453,28 +468,42 @@ xfs_qm_dqattach_one(
453 468
454 469
455/* 470/*
456 * Given a udquot and gdquot, attach a ptr to the group dquot in the 471 * Given a udquot and group/project type, attach the group/project
457 * udquot as a hint for future lookups. 472 * dquot pointer to the udquot as a hint for future lookups.
458 */ 473 */
459STATIC void 474STATIC void
460xfs_qm_dqattach_grouphint( 475xfs_qm_dqattach_hint(
461 xfs_dquot_t *udq, 476 struct xfs_inode *ip,
462 xfs_dquot_t *gdq) 477 int type)
463{ 478{
464 xfs_dquot_t *tmp; 479 struct xfs_dquot **dqhintp;
480 struct xfs_dquot *dqp;
481 struct xfs_dquot *udq = ip->i_udquot;
482
483 ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
465 484
466 xfs_dqlock(udq); 485 xfs_dqlock(udq);
467 486
468 tmp = udq->q_gdquot; 487 if (type == XFS_DQ_GROUP) {
469 if (tmp) { 488 dqp = ip->i_gdquot;
470 if (tmp == gdq) 489 dqhintp = &udq->q_gdquot;
490 } else {
491 dqp = ip->i_pdquot;
492 dqhintp = &udq->q_pdquot;
493 }
494
495 if (*dqhintp) {
496 struct xfs_dquot *tmp;
497
498 if (*dqhintp == dqp)
471 goto done; 499 goto done;
472 500
473 udq->q_gdquot = NULL; 501 tmp = *dqhintp;
502 *dqhintp = NULL;
474 xfs_qm_dqrele(tmp); 503 xfs_qm_dqrele(tmp);
475 } 504 }
476 505
477 udq->q_gdquot = xfs_qm_dqhold(gdq); 506 *dqhintp = xfs_qm_dqhold(dqp);
478done: 507done:
479 xfs_dqunlock(udq); 508 xfs_dqunlock(udq);
480} 509}
@@ -527,12 +556,8 @@ xfs_qm_dqattach_locked(
527 } 556 }
528 557
529 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 558 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
530 if (XFS_IS_OQUOTA_ON(mp)) { 559 if (XFS_IS_GQUOTA_ON(mp)) {
531 error = XFS_IS_GQUOTA_ON(mp) ? 560 error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
532 xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
533 flags & XFS_QMOPT_DQALLOC,
534 ip->i_udquot, &ip->i_gdquot) :
535 xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
536 flags & XFS_QMOPT_DQALLOC, 561 flags & XFS_QMOPT_DQALLOC,
537 ip->i_udquot, &ip->i_gdquot); 562 ip->i_udquot, &ip->i_gdquot);
538 /* 563 /*
@@ -544,14 +569,28 @@ xfs_qm_dqattach_locked(
544 nquotas++; 569 nquotas++;
545 } 570 }
546 571
572 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
573 if (XFS_IS_PQUOTA_ON(mp)) {
574 error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
575 flags & XFS_QMOPT_DQALLOC,
576 ip->i_udquot, &ip->i_pdquot);
577 /*
578 * Don't worry about the udquot that we may have
579 * attached above. It'll get detached, if not already.
580 */
581 if (error)
582 goto done;
583 nquotas++;
584 }
585
547 /* 586 /*
548 * Attach this group quota to the user quota as a hint. 587 * Attach this group/project quota to the user quota as a hint.
549 * This WON'T, in general, result in a thrash. 588 * This WON'T, in general, result in a thrash.
550 */ 589 */
551 if (nquotas == 2) { 590 if (nquotas > 1 && ip->i_udquot) {
552 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 591 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
553 ASSERT(ip->i_udquot); 592 ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp));
554 ASSERT(ip->i_gdquot); 593 ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp));
555 594
556 /* 595 /*
557 * We do not have i_udquot locked at this point, but this check 596 * We do not have i_udquot locked at this point, but this check
@@ -560,7 +599,10 @@ xfs_qm_dqattach_locked(
560 * succeed in general. 599 * succeed in general.
561 */ 600 */
562 if (ip->i_udquot->q_gdquot != ip->i_gdquot) 601 if (ip->i_udquot->q_gdquot != ip->i_gdquot)
563 xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); 602 xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
603
604 if (ip->i_udquot->q_pdquot != ip->i_pdquot)
605 xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
564 } 606 }
565 607
566 done: 608 done:
@@ -568,8 +610,10 @@ xfs_qm_dqattach_locked(
568 if (!error) { 610 if (!error) {
569 if (XFS_IS_UQUOTA_ON(mp)) 611 if (XFS_IS_UQUOTA_ON(mp))
570 ASSERT(ip->i_udquot); 612 ASSERT(ip->i_udquot);
571 if (XFS_IS_OQUOTA_ON(mp)) 613 if (XFS_IS_GQUOTA_ON(mp))
572 ASSERT(ip->i_gdquot); 614 ASSERT(ip->i_gdquot);
615 if (XFS_IS_PQUOTA_ON(mp))
616 ASSERT(ip->i_pdquot);
573 } 617 }
574 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); 618 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
575#endif 619#endif
@@ -602,7 +646,7 @@ void
602xfs_qm_dqdetach( 646xfs_qm_dqdetach(
603 xfs_inode_t *ip) 647 xfs_inode_t *ip)
604{ 648{
605 if (!(ip->i_udquot || ip->i_gdquot)) 649 if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot))
606 return; 650 return;
607 651
608 trace_xfs_dquot_dqdetach(ip); 652 trace_xfs_dquot_dqdetach(ip);
@@ -616,6 +660,10 @@ xfs_qm_dqdetach(
616 xfs_qm_dqrele(ip->i_gdquot); 660 xfs_qm_dqrele(ip->i_gdquot);
617 ip->i_gdquot = NULL; 661 ip->i_gdquot = NULL;
618 } 662 }
663 if (ip->i_pdquot) {
664 xfs_qm_dqrele(ip->i_pdquot);
665 ip->i_pdquot = NULL;
666 }
619} 667}
620 668
621int 669int
@@ -660,6 +708,7 @@ xfs_qm_init_quotainfo(
660 708
661 INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS); 709 INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS);
662 INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS); 710 INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);
711 INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS);
663 mutex_init(&qinf->qi_tree_lock); 712 mutex_init(&qinf->qi_tree_lock);
664 713
665 INIT_LIST_HEAD(&qinf->qi_lru_list); 714 INIT_LIST_HEAD(&qinf->qi_lru_list);
@@ -761,6 +810,10 @@ xfs_qm_destroy_quotainfo(
761 IRELE(qi->qi_gquotaip); 810 IRELE(qi->qi_gquotaip);
762 qi->qi_gquotaip = NULL; 811 qi->qi_gquotaip = NULL;
763 } 812 }
813 if (qi->qi_pquotaip) {
814 IRELE(qi->qi_pquotaip);
815 qi->qi_pquotaip = NULL;
816 }
764 mutex_destroy(&qi->qi_quotaofflock); 817 mutex_destroy(&qi->qi_quotaofflock);
765 kmem_free(qi); 818 kmem_free(qi);
766 mp->m_quotainfo = NULL; 819 mp->m_quotainfo = NULL;
@@ -1269,13 +1322,14 @@ xfs_qm_quotacheck(
1269 LIST_HEAD (buffer_list); 1322 LIST_HEAD (buffer_list);
1270 struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip; 1323 struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip;
1271 struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip; 1324 struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip;
1325 struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip;
1272 1326
1273 count = INT_MAX; 1327 count = INT_MAX;
1274 structsz = 1; 1328 structsz = 1;
1275 lastino = 0; 1329 lastino = 0;
1276 flags = 0; 1330 flags = 0;
1277 1331
1278 ASSERT(uip || gip); 1332 ASSERT(uip || gip || pip);
1279 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 1333 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
1280 1334
1281 xfs_notice(mp, "Quotacheck needed: Please wait."); 1335 xfs_notice(mp, "Quotacheck needed: Please wait.");
@@ -1294,13 +1348,19 @@ xfs_qm_quotacheck(
1294 } 1348 }
1295 1349
1296 if (gip) { 1350 if (gip) {
1297 error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ? 1351 error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA,
1298 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA,
1299 &buffer_list); 1352 &buffer_list);
1300 if (error) 1353 if (error)
1301 goto error_return; 1354 goto error_return;
1302 flags |= XFS_IS_GQUOTA_ON(mp) ? 1355 flags |= XFS_GQUOTA_CHKD;
1303 XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD; 1356 }
1357
1358 if (pip) {
1359 error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA,
1360 &buffer_list);
1361 if (error)
1362 goto error_return;
1363 flags |= XFS_PQUOTA_CHKD;
1304 } 1364 }
1305 1365
1306 do { 1366 do {
@@ -1397,6 +1457,7 @@ xfs_qm_init_quotainos(
1397{ 1457{
1398 struct xfs_inode *uip = NULL; 1458 struct xfs_inode *uip = NULL;
1399 struct xfs_inode *gip = NULL; 1459 struct xfs_inode *gip = NULL;
1460 struct xfs_inode *pip = NULL;
1400 int error; 1461 int error;
1401 __int64_t sbflags = 0; 1462 __int64_t sbflags = 0;
1402 uint flags = 0; 1463 uint flags = 0;
@@ -1415,7 +1476,7 @@ xfs_qm_init_quotainos(
1415 if (error) 1476 if (error)
1416 return XFS_ERROR(error); 1477 return XFS_ERROR(error);
1417 } 1478 }
1418 if (XFS_IS_OQUOTA_ON(mp) && 1479 if (XFS_IS_GQUOTA_ON(mp) &&
1419 mp->m_sb.sb_gquotino != NULLFSINO) { 1480 mp->m_sb.sb_gquotino != NULLFSINO) {
1420 ASSERT(mp->m_sb.sb_gquotino > 0); 1481 ASSERT(mp->m_sb.sb_gquotino > 0);
1421 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 1482 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos(
1423 if (error) 1484 if (error)
1424 goto error_rele; 1485 goto error_rele;
1425 } 1486 }
1487 /* XXX: Use gquotino for now */
1488 if (XFS_IS_PQUOTA_ON(mp) &&
1489 mp->m_sb.sb_gquotino != NULLFSINO) {
1490 ASSERT(mp->m_sb.sb_gquotino > 0);
1491 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
1492 0, 0, &pip);
1493 if (error)
1494 goto error_rele;
1495 }
1426 } else { 1496 } else {
1427 flags |= XFS_QMOPT_SBVERSION; 1497 flags |= XFS_QMOPT_SBVERSION;
1428 sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | 1498 sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
@@ -1430,7 +1500,7 @@ xfs_qm_init_quotainos(
1430 } 1500 }
1431 1501
1432 /* 1502 /*
1433 * Create the two inodes, if they don't exist already. The changes 1503 * Create the three inodes, if they don't exist already. The changes
1434 * made above will get added to a transaction and logged in one of 1504 * made above will get added to a transaction and logged in one of
1435 * the qino_alloc calls below. If the device is readonly, 1505 * the qino_alloc calls below. If the device is readonly,
1436 * temporarily switch to read-write to do this. 1506 * temporarily switch to read-write to do this.
@@ -1444,17 +1514,27 @@ xfs_qm_init_quotainos(
1444 1514
1445 flags &= ~XFS_QMOPT_SBVERSION; 1515 flags &= ~XFS_QMOPT_SBVERSION;
1446 } 1516 }
1447 if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) { 1517 if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
1448 flags |= (XFS_IS_GQUOTA_ON(mp) ?
1449 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
1450 error = xfs_qm_qino_alloc(mp, &gip, 1518 error = xfs_qm_qino_alloc(mp, &gip,
1451 sbflags | XFS_SB_GQUOTINO, flags); 1519 sbflags | XFS_SB_GQUOTINO,
1520 flags | XFS_QMOPT_GQUOTA);
1521 if (error)
1522 goto error_rele;
1523
1524 flags &= ~XFS_QMOPT_SBVERSION;
1525 }
1526 if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
1527 /* XXX: Use XFS_SB_GQUOTINO for now */
1528 error = xfs_qm_qino_alloc(mp, &pip,
1529 sbflags | XFS_SB_GQUOTINO,
1530 flags | XFS_QMOPT_PQUOTA);
1452 if (error) 1531 if (error)
1453 goto error_rele; 1532 goto error_rele;
1454 } 1533 }
1455 1534
1456 mp->m_quotainfo->qi_uquotaip = uip; 1535 mp->m_quotainfo->qi_uquotaip = uip;
1457 mp->m_quotainfo->qi_gquotaip = gip; 1536 mp->m_quotainfo->qi_gquotaip = gip;
1537 mp->m_quotainfo->qi_pquotaip = pip;
1458 1538
1459 return 0; 1539 return 0;
1460 1540
@@ -1463,6 +1543,8 @@ error_rele:
1463 IRELE(uip); 1543 IRELE(uip);
1464 if (gip) 1544 if (gip)
1465 IRELE(gip); 1545 IRELE(gip);
1546 if (pip)
1547 IRELE(pip);
1466 return XFS_ERROR(error); 1548 return XFS_ERROR(error);
1467} 1549}
1468 1550
@@ -1657,11 +1739,13 @@ xfs_qm_vop_dqalloc(
1657 prid_t prid, 1739 prid_t prid,
1658 uint flags, 1740 uint flags,
1659 struct xfs_dquot **O_udqpp, 1741 struct xfs_dquot **O_udqpp,
1660 struct xfs_dquot **O_gdqpp) 1742 struct xfs_dquot **O_gdqpp,
1743 struct xfs_dquot **O_pdqpp)
1661{ 1744{
1662 struct xfs_mount *mp = ip->i_mount; 1745 struct xfs_mount *mp = ip->i_mount;
1663 struct xfs_dquot *uq = NULL; 1746 struct xfs_dquot *uq = NULL;
1664 struct xfs_dquot *gq = NULL; 1747 struct xfs_dquot *gq = NULL;
1748 struct xfs_dquot *pq = NULL;
1665 int error; 1749 int error;
1666 uint lockflags; 1750 uint lockflags;
1667 1751
@@ -1741,24 +1825,25 @@ xfs_qm_vop_dqalloc(
1741 ASSERT(ip->i_gdquot); 1825 ASSERT(ip->i_gdquot);
1742 gq = xfs_qm_dqhold(ip->i_gdquot); 1826 gq = xfs_qm_dqhold(ip->i_gdquot);
1743 } 1827 }
1744 } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) { 1828 }
1829 if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
1745 if (xfs_get_projid(ip) != prid) { 1830 if (xfs_get_projid(ip) != prid) {
1746 xfs_iunlock(ip, lockflags); 1831 xfs_iunlock(ip, lockflags);
1747 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid, 1832 error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
1748 XFS_DQ_PROJ, 1833 XFS_DQ_PROJ,
1749 XFS_QMOPT_DQALLOC | 1834 XFS_QMOPT_DQALLOC |
1750 XFS_QMOPT_DOWARN, 1835 XFS_QMOPT_DOWARN,
1751 &gq); 1836 &pq);
1752 if (error) { 1837 if (error) {
1753 ASSERT(error != ENOENT); 1838 ASSERT(error != ENOENT);
1754 goto error_rele; 1839 goto error_rele;
1755 } 1840 }
1756 xfs_dqunlock(gq); 1841 xfs_dqunlock(pq);
1757 lockflags = XFS_ILOCK_SHARED; 1842 lockflags = XFS_ILOCK_SHARED;
1758 xfs_ilock(ip, lockflags); 1843 xfs_ilock(ip, lockflags);
1759 } else { 1844 } else {
1760 ASSERT(ip->i_gdquot); 1845 ASSERT(ip->i_pdquot);
1761 gq = xfs_qm_dqhold(ip->i_gdquot); 1846 pq = xfs_qm_dqhold(ip->i_pdquot);
1762 } 1847 }
1763 } 1848 }
1764 if (uq) 1849 if (uq)
@@ -1773,9 +1858,15 @@ xfs_qm_vop_dqalloc(
1773 *O_gdqpp = gq; 1858 *O_gdqpp = gq;
1774 else if (gq) 1859 else if (gq)
1775 xfs_qm_dqrele(gq); 1860 xfs_qm_dqrele(gq);
1861 if (O_pdqpp)
1862 *O_pdqpp = pq;
1863 else if (pq)
1864 xfs_qm_dqrele(pq);
1776 return 0; 1865 return 0;
1777 1866
1778error_rele: 1867error_rele:
1868 if (gq)
1869 xfs_qm_dqrele(gq);
1779 if (uq) 1870 if (uq)
1780 xfs_qm_dqrele(uq); 1871 xfs_qm_dqrele(uq);
1781 return error; 1872 return error;
@@ -1830,14 +1921,17 @@ xfs_qm_vop_chown_reserve(
1830 struct xfs_inode *ip, 1921 struct xfs_inode *ip,
1831 struct xfs_dquot *udqp, 1922 struct xfs_dquot *udqp,
1832 struct xfs_dquot *gdqp, 1923 struct xfs_dquot *gdqp,
1924 struct xfs_dquot *pdqp,
1833 uint flags) 1925 uint flags)
1834{ 1926{
1835 struct xfs_mount *mp = ip->i_mount; 1927 struct xfs_mount *mp = ip->i_mount;
1836 uint delblks, blkflags, prjflags = 0; 1928 uint delblks, blkflags, prjflags = 0;
1837 struct xfs_dquot *udq_unres = NULL; 1929 struct xfs_dquot *udq_unres = NULL;
1838 struct xfs_dquot *gdq_unres = NULL; 1930 struct xfs_dquot *gdq_unres = NULL;
1931 struct xfs_dquot *pdq_unres = NULL;
1839 struct xfs_dquot *udq_delblks = NULL; 1932 struct xfs_dquot *udq_delblks = NULL;
1840 struct xfs_dquot *gdq_delblks = NULL; 1933 struct xfs_dquot *gdq_delblks = NULL;
1934 struct xfs_dquot *pdq_delblks = NULL;
1841 int error; 1935 int error;
1842 1936
1843 1937
@@ -1861,24 +1955,28 @@ xfs_qm_vop_chown_reserve(
1861 udq_unres = ip->i_udquot; 1955 udq_unres = ip->i_udquot;
1862 } 1956 }
1863 } 1957 }
1864 if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) { 1958 if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
1865 if (XFS_IS_PQUOTA_ON(ip->i_mount) && 1959 ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) {
1866 xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id)) 1960 gdq_delblks = gdqp;
1867 prjflags = XFS_QMOPT_ENOSPC; 1961 if (delblks) {
1868 1962 ASSERT(ip->i_gdquot);
1869 if (prjflags || 1963 gdq_unres = ip->i_gdquot;
1870 (XFS_IS_GQUOTA_ON(ip->i_mount) && 1964 }
1871 ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) { 1965 }
1872 gdq_delblks = gdqp; 1966
1873 if (delblks) { 1967 if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
1874 ASSERT(ip->i_gdquot); 1968 xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) {
1875 gdq_unres = ip->i_gdquot; 1969 prjflags = XFS_QMOPT_ENOSPC;
1876 } 1970 pdq_delblks = pdqp;
1971 if (delblks) {
1972 ASSERT(ip->i_pdquot);
1973 pdq_unres = ip->i_pdquot;
1877 } 1974 }
1878 } 1975 }
1879 1976
1880 error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount, 1977 error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
1881 udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1, 1978 udq_delblks, gdq_delblks, pdq_delblks,
1979 ip->i_d.di_nblocks, 1,
1882 flags | blkflags | prjflags); 1980 flags | blkflags | prjflags);
1883 if (error) 1981 if (error)
1884 return error; 1982 return error;
@@ -1893,16 +1991,17 @@ xfs_qm_vop_chown_reserve(
1893 /* 1991 /*
1894 * Do the reservations first. Unreservation can't fail. 1992 * Do the reservations first. Unreservation can't fail.
1895 */ 1993 */
1896 ASSERT(udq_delblks || gdq_delblks); 1994 ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
1897 ASSERT(udq_unres || gdq_unres); 1995 ASSERT(udq_unres || gdq_unres || pdq_unres);
1898 error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 1996 error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
1899 udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0, 1997 udq_delblks, gdq_delblks, pdq_delblks,
1998 (xfs_qcnt_t)delblks, 0,
1900 flags | blkflags | prjflags); 1999 flags | blkflags | prjflags);
1901 if (error) 2000 if (error)
1902 return error; 2001 return error;
1903 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount, 2002 xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
1904 udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0, 2003 udq_unres, gdq_unres, pdq_unres,
1905 blkflags); 2004 -((xfs_qcnt_t)delblks), 0, blkflags);
1906 } 2005 }
1907 2006
1908 return (0); 2007 return (0);
@@ -1941,7 +2040,8 @@ xfs_qm_vop_create_dqattach(
1941 struct xfs_trans *tp, 2040 struct xfs_trans *tp,
1942 struct xfs_inode *ip, 2041 struct xfs_inode *ip,
1943 struct xfs_dquot *udqp, 2042 struct xfs_dquot *udqp,
1944 struct xfs_dquot *gdqp) 2043 struct xfs_dquot *gdqp,
2044 struct xfs_dquot *pdqp)
1945{ 2045{
1946 struct xfs_mount *mp = tp->t_mountp; 2046 struct xfs_mount *mp = tp->t_mountp;
1947 2047
@@ -1961,13 +2061,18 @@ xfs_qm_vop_create_dqattach(
1961 } 2061 }
1962 if (gdqp) { 2062 if (gdqp) {
1963 ASSERT(ip->i_gdquot == NULL); 2063 ASSERT(ip->i_gdquot == NULL);
1964 ASSERT(XFS_IS_OQUOTA_ON(mp)); 2064 ASSERT(XFS_IS_GQUOTA_ON(mp));
1965 ASSERT((XFS_IS_GQUOTA_ON(mp) ? 2065 ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
1966 ip->i_d.di_gid : xfs_get_projid(ip)) ==
1967 be32_to_cpu(gdqp->q_core.d_id));
1968
1969 ip->i_gdquot = xfs_qm_dqhold(gdqp); 2066 ip->i_gdquot = xfs_qm_dqhold(gdqp);
1970 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1); 2067 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
1971 } 2068 }
2069 if (pdqp) {
2070 ASSERT(ip->i_pdquot == NULL);
2071 ASSERT(XFS_IS_PQUOTA_ON(mp));
2072 ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
2073
2074 ip->i_pdquot = xfs_qm_dqhold(pdqp);
2075 xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1);
2076 }
1972} 2077}
1973 2078
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index bdb4f8b95207..579d6a02a5b6 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -44,9 +44,11 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
44typedef struct xfs_quotainfo { 44typedef struct xfs_quotainfo {
45 struct radix_tree_root qi_uquota_tree; 45 struct radix_tree_root qi_uquota_tree;
46 struct radix_tree_root qi_gquota_tree; 46 struct radix_tree_root qi_gquota_tree;
47 struct radix_tree_root qi_pquota_tree;
47 struct mutex qi_tree_lock; 48 struct mutex qi_tree_lock;
48 xfs_inode_t *qi_uquotaip; /* user quota inode */ 49 struct xfs_inode *qi_uquotaip; /* user quota inode */
49 xfs_inode_t *qi_gquotaip; /* group quota inode */ 50 struct xfs_inode *qi_gquotaip; /* group quota inode */
51 struct xfs_inode *qi_pquotaip; /* project quota inode */
50 struct list_head qi_lru_list; 52 struct list_head qi_lru_list;
51 struct mutex qi_lru_lock; 53 struct mutex qi_lru_lock;
52 int qi_lru_count; 54 int qi_lru_count;
@@ -78,8 +80,9 @@ xfs_dquot_tree(
78 case XFS_DQ_USER: 80 case XFS_DQ_USER:
79 return &qi->qi_uquota_tree; 81 return &qi->qi_uquota_tree;
80 case XFS_DQ_GROUP: 82 case XFS_DQ_GROUP:
81 case XFS_DQ_PROJ:
82 return &qi->qi_gquota_tree; 83 return &qi->qi_gquota_tree;
84 case XFS_DQ_PROJ:
85 return &qi->qi_pquota_tree;
83 default: 86 default:
84 ASSERT(0); 87 ASSERT(0);
85 } 88 }
@@ -93,8 +96,9 @@ xfs_dq_to_quota_inode(struct xfs_dquot *dqp)
93 case XFS_DQ_USER: 96 case XFS_DQ_USER:
94 return dqp->q_mount->m_quotainfo->qi_uquotaip; 97 return dqp->q_mount->m_quotainfo->qi_uquotaip;
95 case XFS_DQ_GROUP: 98 case XFS_DQ_GROUP:
96 case XFS_DQ_PROJ:
97 return dqp->q_mount->m_quotainfo->qi_gquotaip; 99 return dqp->q_mount->m_quotainfo->qi_gquotaip;
100 case XFS_DQ_PROJ:
101 return dqp->q_mount->m_quotainfo->qi_pquotaip;
98 default: 102 default:
99 ASSERT(0); 103 ASSERT(0);
100 } 104 }
@@ -107,18 +111,20 @@ extern void xfs_trans_mod_dquot(struct xfs_trans *,
107 struct xfs_dquot *, uint, long); 111 struct xfs_dquot *, uint, long);
108extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 112extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
109 struct xfs_mount *, struct xfs_dquot *, 113 struct xfs_mount *, struct xfs_dquot *,
110 struct xfs_dquot *, long, long, uint); 114 struct xfs_dquot *, struct xfs_dquot *,
115 long, long, uint);
111extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *); 116extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
112extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *); 117extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
113 118
114/* 119/*
115 * We keep the usr and grp dquots separately so that locking will be easier 120 * We keep the usr, grp, and prj dquots separately so that locking will be
116 * to do at commit time. All transactions that we know of at this point 121 * easier to do at commit time. All transactions that we know of at this point
117 * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value. 122 * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value.
118 */ 123 */
119enum { 124enum {
120 XFS_QM_TRANS_USR = 0, 125 XFS_QM_TRANS_USR = 0,
121 XFS_QM_TRANS_GRP, 126 XFS_QM_TRANS_GRP,
127 XFS_QM_TRANS_PRJ,
122 XFS_QM_TRANS_DQTYPES 128 XFS_QM_TRANS_DQTYPES
123}; 129};
124#define XFS_QM_TRANS_MAXDQS 2 130#define XFS_QM_TRANS_MAXDQS 2
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 2d02eac1c9a8..437a52d91f6d 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -112,16 +112,16 @@ xfs_qm_newmount(
112 112
113 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) || 113 if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
114 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) || 114 (!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
115 (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
116 (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) ||
117 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) || 115 (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
118 (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) && 116 (!gquotaondisk && XFS_IS_GQUOTA_ON(mp)) ||
117 (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
118 (!pquotaondisk && XFS_IS_PQUOTA_ON(mp))) &&
119 xfs_dev_is_read_only(mp, "changing quota state")) { 119 xfs_dev_is_read_only(mp, "changing quota state")) {
120 xfs_warn(mp, "please mount with%s%s%s%s.", 120 xfs_warn(mp, "please mount with%s%s%s%s.",
121 (!quotaondisk ? "out quota" : ""), 121 (!quotaondisk ? "out quota" : ""),
122 (uquotaondisk ? " usrquota" : ""), 122 (uquotaondisk ? " usrquota" : ""),
123 (pquotaondisk ? " prjquota" : ""), 123 (gquotaondisk ? " grpquota" : ""),
124 (gquotaondisk ? " grpquota" : "")); 124 (pquotaondisk ? " prjquota" : ""));
125 return XFS_ERROR(EPERM); 125 return XFS_ERROR(EPERM);
126 } 126 }
127 127
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index a08801ae24e2..b9363838b42b 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -119,7 +119,8 @@ xfs_qm_scall_quotaoff(
119 dqtype |= XFS_QMOPT_GQUOTA; 119 dqtype |= XFS_QMOPT_GQUOTA;
120 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD); 120 flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
121 inactivate_flags |= XFS_GQUOTA_ACTIVE; 121 inactivate_flags |= XFS_GQUOTA_ACTIVE;
122 } else if (flags & XFS_PQUOTA_ACCT) { 122 }
123 if (flags & XFS_PQUOTA_ACCT) {
123 dqtype |= XFS_QMOPT_PQUOTA; 124 dqtype |= XFS_QMOPT_PQUOTA;
124 flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD); 125 flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
125 inactivate_flags |= XFS_PQUOTA_ACTIVE; 126 inactivate_flags |= XFS_PQUOTA_ACTIVE;
@@ -214,10 +215,14 @@ xfs_qm_scall_quotaoff(
214 IRELE(q->qi_uquotaip); 215 IRELE(q->qi_uquotaip);
215 q->qi_uquotaip = NULL; 216 q->qi_uquotaip = NULL;
216 } 217 }
217 if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && q->qi_gquotaip) { 218 if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
218 IRELE(q->qi_gquotaip); 219 IRELE(q->qi_gquotaip);
219 q->qi_gquotaip = NULL; 220 q->qi_gquotaip = NULL;
220 } 221 }
222 if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
223 IRELE(q->qi_pquotaip);
224 q->qi_pquotaip = NULL;
225 }
221 226
222out_unlock: 227out_unlock:
223 mutex_unlock(&q->qi_quotaofflock); 228 mutex_unlock(&q->qi_quotaofflock);
@@ -859,9 +864,11 @@ xfs_dqrele_inode(
859{ 864{
860 /* skip quota inodes */ 865 /* skip quota inodes */
861 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip || 866 if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
862 ip == ip->i_mount->m_quotainfo->qi_gquotaip) { 867 ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
868 ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
863 ASSERT(ip->i_udquot == NULL); 869 ASSERT(ip->i_udquot == NULL);
864 ASSERT(ip->i_gdquot == NULL); 870 ASSERT(ip->i_gdquot == NULL);
871 ASSERT(ip->i_pdquot == NULL);
865 return 0; 872 return 0;
866 } 873 }
867 874
@@ -870,10 +877,14 @@ xfs_dqrele_inode(
870 xfs_qm_dqrele(ip->i_udquot); 877 xfs_qm_dqrele(ip->i_udquot);
871 ip->i_udquot = NULL; 878 ip->i_udquot = NULL;
872 } 879 }
873 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { 880 if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
874 xfs_qm_dqrele(ip->i_gdquot); 881 xfs_qm_dqrele(ip->i_gdquot);
875 ip->i_gdquot = NULL; 882 ip->i_gdquot = NULL;
876 } 883 }
884 if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
885 xfs_qm_dqrele(ip->i_pdquot);
886 ip->i_pdquot = NULL;
887 }
877 xfs_iunlock(ip, XFS_ILOCK_EXCL); 888 xfs_iunlock(ip, XFS_ILOCK_EXCL);
878 return 0; 889 return 0;
879} 890}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 40d508be9a00..09777c41d5b7 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -288,10 +288,10 @@ typedef struct xfs_qoff_logformat {
288 * we didn't have the inode locked, the appropriate dquot(s) will be 288 * we didn't have the inode locked, the appropriate dquot(s) will be
289 * attached atomically. 289 * attached atomically.
290 */ 290 */
291#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\ 291#define XFS_NOT_DQATTACHED(mp, ip) \
292 (ip)->i_udquot == NULL) || \ 292 ((XFS_IS_UQUOTA_ON(mp) && (ip)->i_udquot == NULL) || \
293 (XFS_IS_OQUOTA_ON(mp) && \ 293 (XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \
294 (ip)->i_gdquot == NULL)) 294 (XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL))
295 295
296#define XFS_QM_NEED_QUOTACHECK(mp) \ 296#define XFS_QM_NEED_QUOTACHECK(mp) \
297 ((XFS_IS_UQUOTA_ON(mp) && \ 297 ((XFS_IS_UQUOTA_ON(mp) && \
@@ -346,17 +346,18 @@ extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
346 struct xfs_inode *, long, long, uint); 346 struct xfs_inode *, long, long, uint);
347extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *, 347extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
348 struct xfs_mount *, struct xfs_dquot *, 348 struct xfs_mount *, struct xfs_dquot *,
349 struct xfs_dquot *, long, long, uint); 349 struct xfs_dquot *, struct xfs_dquot *, long, long, uint);
350 350
351extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint, 351extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint,
352 struct xfs_dquot **, struct xfs_dquot **); 352 struct xfs_dquot **, struct xfs_dquot **, struct xfs_dquot **);
353extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *, 353extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
354 struct xfs_dquot *, struct xfs_dquot *); 354 struct xfs_dquot *, struct xfs_dquot *, struct xfs_dquot *);
355extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **); 355extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **);
356extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *, 356extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
357 struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *); 357 struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
358extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *, 358extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *,
359 struct xfs_dquot *, struct xfs_dquot *, uint); 359 struct xfs_dquot *, struct xfs_dquot *,
360 struct xfs_dquot *, uint);
360extern int xfs_qm_dqattach(struct xfs_inode *, uint); 361extern int xfs_qm_dqattach(struct xfs_inode *, uint);
361extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint); 362extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint);
362extern void xfs_qm_dqdetach(struct xfs_inode *); 363extern void xfs_qm_dqdetach(struct xfs_inode *);
@@ -370,10 +371,12 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);
370#else 371#else
371static inline int 372static inline int
372xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid, 373xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid,
373 uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp) 374 uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp,
375 struct xfs_dquot **pdqp)
374{ 376{
375 *udqp = NULL; 377 *udqp = NULL;
376 *gdqp = NULL; 378 *gdqp = NULL;
379 *pdqp = NULL;
377 return 0; 380 return 0;
378} 381}
379#define xfs_trans_dup_dqinfo(tp, tp2) 382#define xfs_trans_dup_dqinfo(tp, tp2)
@@ -388,14 +391,15 @@ static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
388} 391}
389static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp, 392static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
390 struct xfs_mount *mp, struct xfs_dquot *udqp, 393 struct xfs_mount *mp, struct xfs_dquot *udqp,
391 struct xfs_dquot *gdqp, long nblks, long nions, uint flags) 394 struct xfs_dquot *gdqp, struct xfs_dquot *pdqp,
395 long nblks, long nions, uint flags)
392{ 396{
393 return 0; 397 return 0;
394} 398}
395#define xfs_qm_vop_create_dqattach(tp, ip, u, g) 399#define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
396#define xfs_qm_vop_rename_dqattach(it) (0) 400#define xfs_qm_vop_rename_dqattach(it) (0)
397#define xfs_qm_vop_chown(tp, ip, old, new) (NULL) 401#define xfs_qm_vop_chown(tp, ip, old, new) (NULL)
398#define xfs_qm_vop_chown_reserve(tp, ip, u, g, fl) (0) 402#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl) (0)
399#define xfs_qm_dqattach(ip, fl) (0) 403#define xfs_qm_dqattach(ip, fl) (0)
400#define xfs_qm_dqattach_locked(ip, fl) (0) 404#define xfs_qm_dqattach_locked(ip, fl) (0)
401#define xfs_qm_dqdetach(ip) 405#define xfs_qm_dqdetach(ip)
@@ -409,8 +413,8 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
409 413
410#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \ 414#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \
411 xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags) 415 xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags)
412#define xfs_trans_reserve_quota(tp, mp, ud, gd, nb, ni, f) \ 416#define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
413 xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \ 417 xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
414 f | XFS_QMOPT_RES_REGBLKS) 418 f | XFS_QMOPT_RES_REGBLKS)
415 419
416extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *, 420extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index e830fb56e27f..f4895b662fcb 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -360,6 +360,7 @@ xfs_symlink(
360 prid_t prid; 360 prid_t prid;
361 struct xfs_dquot *udqp = NULL; 361 struct xfs_dquot *udqp = NULL;
362 struct xfs_dquot *gdqp = NULL; 362 struct xfs_dquot *gdqp = NULL;
363 struct xfs_dquot *pdqp = NULL;
363 uint resblks; 364 uint resblks;
364 365
365 *ipp = NULL; 366 *ipp = NULL;
@@ -386,7 +387,7 @@ xfs_symlink(
386 * Make sure that we have allocated dquot(s) on disk. 387 * Make sure that we have allocated dquot(s) on disk.
387 */ 388 */
388 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, 389 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
389 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 390 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp);
390 if (error) 391 if (error)
391 goto std_return; 392 goto std_return;
392 393
@@ -427,7 +428,8 @@ xfs_symlink(
427 /* 428 /*
428 * Reserve disk quota : blocks and inode. 429 * Reserve disk quota : blocks and inode.
429 */ 430 */
430 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); 431 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
432 pdqp, resblks, 1, 0);
431 if (error) 433 if (error)
432 goto error_return; 434 goto error_return;
433 435
@@ -465,7 +467,7 @@ xfs_symlink(
465 /* 467 /*
466 * Also attach the dquot(s) to it, if applicable. 468 * Also attach the dquot(s) to it, if applicable.
467 */ 469 */
468 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); 470 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
469 471
470 if (resblks) 472 if (resblks)
471 resblks -= XFS_IALLOC_SPACE_RES(mp); 473 resblks -= XFS_IALLOC_SPACE_RES(mp);
@@ -563,6 +565,7 @@ xfs_symlink(
563 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); 565 error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
564 xfs_qm_dqrele(udqp); 566 xfs_qm_dqrele(udqp);
565 xfs_qm_dqrele(gdqp); 567 xfs_qm_dqrele(gdqp);
568 xfs_qm_dqrele(pdqp);
566 569
567 *ipp = ip; 570 *ipp = ip;
568 return 0; 571 return 0;
@@ -576,6 +579,7 @@ xfs_symlink(
576 xfs_trans_cancel(tp, cancel_flags); 579 xfs_trans_cancel(tp, cancel_flags);
577 xfs_qm_dqrele(udqp); 580 xfs_qm_dqrele(udqp);
578 xfs_qm_dqrele(gdqp); 581 xfs_qm_dqrele(gdqp);
582 xfs_qm_dqrele(pdqp);
579 583
580 if (unlock_dp_on_error) 584 if (unlock_dp_on_error)
581 xfs_iunlock(dp, XFS_ILOCK_EXCL); 585 xfs_iunlock(dp, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index db041a5e1f6d..61407a847b86 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -163,8 +163,10 @@ xfs_trans_mod_dquot_byino(
163 163
164 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) 164 if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
165 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta); 165 (void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
166 if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot) 166 if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)
167 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta); 167 (void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
168 if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot)
169 (void) xfs_trans_mod_dquot(tp, ip->i_pdquot, field, delta);
168} 170}
169 171
170STATIC struct xfs_dqtrx * 172STATIC struct xfs_dqtrx *
@@ -177,8 +179,12 @@ xfs_trans_get_dqtrx(
177 179
178 if (XFS_QM_ISUDQ(dqp)) 180 if (XFS_QM_ISUDQ(dqp))
179 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR]; 181 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
180 else 182 else if (XFS_QM_ISGDQ(dqp))
181 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP]; 183 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
184 else if (XFS_QM_ISPDQ(dqp))
185 qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ];
186 else
187 return NULL;
182 188
183 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) { 189 for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
184 if (qa[i].qt_dquot == NULL || 190 if (qa[i].qt_dquot == NULL ||
@@ -727,8 +733,8 @@ error_return:
727 733
728/* 734/*
729 * Given dquot(s), make disk block and/or inode reservations against them. 735 * Given dquot(s), make disk block and/or inode reservations against them.
730 * The fact that this does the reservation against both the usr and 736 * The fact that this does the reservation against user, group and
731 * grp/prj quotas is important, because this follows a both-or-nothing 737 * project quotas is important, because this follows a all-or-nothing
732 * approach. 738 * approach.
733 * 739 *
734 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. 740 * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
@@ -743,6 +749,7 @@ xfs_trans_reserve_quota_bydquots(
743 struct xfs_mount *mp, 749 struct xfs_mount *mp,
744 struct xfs_dquot *udqp, 750 struct xfs_dquot *udqp,
745 struct xfs_dquot *gdqp, 751 struct xfs_dquot *gdqp,
752 struct xfs_dquot *pdqp,
746 long nblks, 753 long nblks,
747 long ninos, 754 long ninos,
748 uint flags) 755 uint flags)
@@ -770,11 +777,21 @@ xfs_trans_reserve_quota_bydquots(
770 goto unwind_usr; 777 goto unwind_usr;
771 } 778 }
772 779
780 if (pdqp) {
781 error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
782 if (error)
783 goto unwind_grp;
784 }
785
773 /* 786 /*
774 * Didn't change anything critical, so, no need to log 787 * Didn't change anything critical, so, no need to log
775 */ 788 */
776 return 0; 789 return 0;
777 790
791unwind_grp:
792 flags |= XFS_QMOPT_FORCE_RES;
793 if (gdqp)
794 xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags);
778unwind_usr: 795unwind_usr:
779 flags |= XFS_QMOPT_FORCE_RES; 796 flags |= XFS_QMOPT_FORCE_RES;
780 if (udqp) 797 if (udqp)
@@ -816,6 +833,7 @@ xfs_trans_reserve_quota_nblks(
816 */ 833 */
817 return xfs_trans_reserve_quota_bydquots(tp, mp, 834 return xfs_trans_reserve_quota_bydquots(tp, mp,
818 ip->i_udquot, ip->i_gdquot, 835 ip->i_udquot, ip->i_gdquot,
836 ip->i_pdquot,
819 nblks, ninos, flags); 837 nblks, ninos, flags);
820} 838}
821 839
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 42c0ef288aeb..dc730ac272be 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -489,6 +489,7 @@ xfs_create(
489 prid_t prid; 489 prid_t prid;
490 struct xfs_dquot *udqp = NULL; 490 struct xfs_dquot *udqp = NULL;
491 struct xfs_dquot *gdqp = NULL; 491 struct xfs_dquot *gdqp = NULL;
492 struct xfs_dquot *pdqp = NULL;
492 uint resblks; 493 uint resblks;
493 uint log_res; 494 uint log_res;
494 uint log_count; 495 uint log_count;
@@ -507,7 +508,8 @@ xfs_create(
507 * Make sure that we have allocated dquot(s) on disk. 508 * Make sure that we have allocated dquot(s) on disk.
508 */ 509 */
509 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid, 510 error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
510 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); 511 XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
512 &udqp, &gdqp, &pdqp);
511 if (error) 513 if (error)
512 return error; 514 return error;
513 515
@@ -559,7 +561,8 @@ xfs_create(
559 /* 561 /*
560 * Reserve disk quota and the inode. 562 * Reserve disk quota and the inode.
561 */ 563 */
562 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0); 564 error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
565 pdqp, resblks, 1, 0);
563 if (error) 566 if (error)
564 goto out_trans_cancel; 567 goto out_trans_cancel;
565 568
@@ -623,7 +626,7 @@ xfs_create(
623 * These ids of the inode couldn't have changed since the new 626 * These ids of the inode couldn't have changed since the new
624 * inode has been locked ever since it was created. 627 * inode has been locked ever since it was created.
625 */ 628 */
626 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp); 629 xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
627 630
628 error = xfs_bmap_finish(&tp, &free_list, &committed); 631 error = xfs_bmap_finish(&tp, &free_list, &committed);
629 if (error) 632 if (error)
@@ -635,6 +638,7 @@ xfs_create(
635 638
636 xfs_qm_dqrele(udqp); 639 xfs_qm_dqrele(udqp);
637 xfs_qm_dqrele(gdqp); 640 xfs_qm_dqrele(gdqp);
641 xfs_qm_dqrele(pdqp);
638 642
639 *ipp = ip; 643 *ipp = ip;
640 return 0; 644 return 0;
@@ -656,6 +660,7 @@ xfs_create(
656 660
657 xfs_qm_dqrele(udqp); 661 xfs_qm_dqrele(udqp);
658 xfs_qm_dqrele(gdqp); 662 xfs_qm_dqrele(gdqp);
663 xfs_qm_dqrele(pdqp);
659 664
660 if (unlock_dp_on_error) 665 if (unlock_dp_on_error)
661 xfs_iunlock(dp, XFS_ILOCK_EXCL); 666 xfs_iunlock(dp, XFS_ILOCK_EXCL);
@@ -1568,7 +1573,7 @@ xfs_free_file_space(
1568 } 1573 }
1569 xfs_ilock(ip, XFS_ILOCK_EXCL); 1574 xfs_ilock(ip, XFS_ILOCK_EXCL);
1570 error = xfs_trans_reserve_quota(tp, mp, 1575 error = xfs_trans_reserve_quota(tp, mp,
1571 ip->i_udquot, ip->i_gdquot, 1576 ip->i_udquot, ip->i_gdquot, ip->i_pdquot,
1572 resblks, 0, XFS_QMOPT_RES_REGBLKS); 1577 resblks, 0, XFS_QMOPT_RES_REGBLKS);
1573 if (error) 1578 if (error)
1574 goto error1; 1579 goto error1;