aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_mount.c62
-rw-r--r--fs/xfs/xfs_qm.c72
-rw-r--r--fs/xfs/xfs_qm_syscalls.c35
-rw-r--r--fs/xfs/xfs_sb.h13
-rw-r--r--fs/xfs/xfs_super.c19
5 files changed, 158 insertions, 43 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 7263e1bb59f7..a0fa8021330d 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -336,14 +336,6 @@ xfs_mount_validate_sb(
336 return XFS_ERROR(EWRONGFS); 336 return XFS_ERROR(EWRONGFS);
337 } 337 }
338 338
339 if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
340 (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
341 XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
342 xfs_notice(mp,
343"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
344 return XFS_ERROR(EFSCORRUPTED);
345 }
346
347 /* 339 /*
348 * Version 5 superblock feature mask validation. Reject combinations the 340 * Version 5 superblock feature mask validation. Reject combinations the
349 * kernel cannot support up front before checking anything else. For 341 * kernel cannot support up front before checking anything else. For
@@ -387,6 +379,19 @@ xfs_mount_validate_sb(
387 } 379 }
388 } 380 }
389 381
382 if (xfs_sb_version_has_pquotino(sbp)) {
383 if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
384 xfs_notice(mp,
385 "Version 5 of Super block has XFS_OQUOTA bits.\n");
386 return XFS_ERROR(EFSCORRUPTED);
387 }
388 } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
389 XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
390 xfs_notice(mp,
391"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n");
392 return XFS_ERROR(EFSCORRUPTED);
393 }
394
390 if (unlikely( 395 if (unlikely(
391 sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { 396 sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
392 xfs_warn(mp, 397 xfs_warn(mp,
@@ -590,6 +595,13 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
590 if (sbp->sb_pquotino == 0) 595 if (sbp->sb_pquotino == 0)
591 sbp->sb_pquotino = NULLFSINO; 596 sbp->sb_pquotino = NULLFSINO;
592 597
598 /*
599 * We need to do these manipilations only if we are working
600 * with an older version of on-disk superblock.
601 */
602 if (xfs_sb_version_has_pquotino(sbp))
603 return;
604
593 if (sbp->sb_qflags & XFS_OQUOTA_ENFD) 605 if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
594 sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? 606 sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
595 XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD; 607 XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
@@ -597,6 +609,18 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp)
597 sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? 609 sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
598 XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; 610 XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
599 sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); 611 sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
612
613 if (sbp->sb_qflags & XFS_PQUOTA_ACCT) {
614 /*
615 * In older version of superblock, on-disk superblock only
616 * has sb_gquotino, and in-core superblock has both sb_gquotino
617 * and sb_pquotino. But, only one of them is supported at any
618 * point of time. So, if PQUOTA is set in disk superblock,
619 * copy over sb_gquotino to sb_pquotino.
620 */
621 sbp->sb_pquotino = sbp->sb_gquotino;
622 sbp->sb_gquotino = NULLFSINO;
623 }
600} 624}
601 625
602void 626void
@@ -668,6 +692,13 @@ xfs_sb_quota_to_disk(
668{ 692{
669 __uint16_t qflags = from->sb_qflags; 693 __uint16_t qflags = from->sb_qflags;
670 694
695 /*
696 * We need to do these manipilations only if we are working
697 * with an older version of on-disk superblock.
698 */
699 if (xfs_sb_version_has_pquotino(from))
700 return;
701
671 if (*fields & XFS_SB_QFLAGS) { 702 if (*fields & XFS_SB_QFLAGS) {
672 /* 703 /*
673 * The in-core version of sb_qflags do not have 704 * The in-core version of sb_qflags do not have
@@ -687,6 +718,21 @@ xfs_sb_quota_to_disk(
687 to->sb_qflags = cpu_to_be16(qflags); 718 to->sb_qflags = cpu_to_be16(qflags);
688 *fields &= ~XFS_SB_QFLAGS; 719 *fields &= ~XFS_SB_QFLAGS;
689 } 720 }
721
722 /*
723 * GQUOTINO and PQUOTINO cannot be used together in versions
724 * of superblock that do not have pquotino. from->sb_flags
725 * tells us which quota is active and should be copied to
726 * disk.
727 */
728 if ((*fields & XFS_SB_GQUOTINO) &&
729 (from->sb_qflags & XFS_GQUOTA_ACCT))
730 to->sb_gquotino = cpu_to_be64(from->sb_gquotino);
731 else if ((*fields & XFS_SB_PQUOTINO) &&
732 (from->sb_qflags & XFS_PQUOTA_ACCT))
733 to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
734
735 *fields &= ~(XFS_SB_PQUOTINO | XFS_SB_GQUOTINO);
690} 736}
691 737
692/* 738/*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index d320794d03ce..1e2361d0294e 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -834,6 +834,36 @@ xfs_qm_qino_alloc(
834 int error; 834 int error;
835 int committed; 835 int committed;
836 836
837 *ip = NULL;
838 /*
839 * With superblock that doesn't have separate pquotino, we
840 * share an inode between gquota and pquota. If the on-disk
841 * superblock has GQUOTA and the filesystem is now mounted
842 * with PQUOTA, just use sb_gquotino for sb_pquotino and
843 * vice-versa.
844 */
845 if (!xfs_sb_version_has_pquotino(&mp->m_sb) &&
846 (flags & (XFS_QMOPT_PQUOTA|XFS_QMOPT_GQUOTA))) {
847 xfs_ino_t ino = NULLFSINO;
848
849 if ((flags & XFS_QMOPT_PQUOTA) &&
850 (mp->m_sb.sb_gquotino != NULLFSINO)) {
851 ino = mp->m_sb.sb_gquotino;
852 ASSERT(mp->m_sb.sb_pquotino == NULLFSINO);
853 } else if ((flags & XFS_QMOPT_GQUOTA) &&
854 (mp->m_sb.sb_pquotino != NULLFSINO)) {
855 ino = mp->m_sb.sb_pquotino;
856 ASSERT(mp->m_sb.sb_gquotino == NULLFSINO);
857 }
858 if (ino != NULLFSINO) {
859 error = xfs_iget(mp, NULL, ino, 0, 0, ip);
860 if (error)
861 return error;
862 mp->m_sb.sb_gquotino = NULLFSINO;
863 mp->m_sb.sb_pquotino = NULLFSINO;
864 }
865 }
866
837 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE); 867 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
838 if ((error = xfs_trans_reserve(tp, 868 if ((error = xfs_trans_reserve(tp,
839 XFS_QM_QINOCREATE_SPACE_RES(mp), 869 XFS_QM_QINOCREATE_SPACE_RES(mp),
@@ -844,11 +874,14 @@ xfs_qm_qino_alloc(
844 return error; 874 return error;
845 } 875 }
846 876
847 error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip, &committed); 877 if (!*ip) {
848 if (error) { 878 error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0, 0, 1, ip,
849 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | 879 &committed);
850 XFS_TRANS_ABORT); 880 if (error) {
851 return error; 881 xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
882 XFS_TRANS_ABORT);
883 return error;
884 }
852 } 885 }
853 886
854 /* 887 /*
@@ -860,21 +893,25 @@ xfs_qm_qino_alloc(
860 if (flags & XFS_QMOPT_SBVERSION) { 893 if (flags & XFS_QMOPT_SBVERSION) {
861 ASSERT(!xfs_sb_version_hasquota(&mp->m_sb)); 894 ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
862 ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | 895 ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
863 XFS_SB_GQUOTINO | XFS_SB_QFLAGS)) == 896 XFS_SB_GQUOTINO | XFS_SB_PQUOTINO | XFS_SB_QFLAGS)) ==
864 (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | 897 (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
865 XFS_SB_GQUOTINO | XFS_SB_QFLAGS)); 898 XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |
899 XFS_SB_QFLAGS));
866 900
867 xfs_sb_version_addquota(&mp->m_sb); 901 xfs_sb_version_addquota(&mp->m_sb);
868 mp->m_sb.sb_uquotino = NULLFSINO; 902 mp->m_sb.sb_uquotino = NULLFSINO;
869 mp->m_sb.sb_gquotino = NULLFSINO; 903 mp->m_sb.sb_gquotino = NULLFSINO;
904 mp->m_sb.sb_pquotino = NULLFSINO;
870 905
871 /* qflags will get updated _after_ quotacheck */ 906 /* qflags will get updated fully _after_ quotacheck */
872 mp->m_sb.sb_qflags = 0; 907 mp->m_sb.sb_qflags = mp->m_qflags & XFS_ALL_QUOTA_ACCT;
873 } 908 }
874 if (flags & XFS_QMOPT_UQUOTA) 909 if (flags & XFS_QMOPT_UQUOTA)
875 mp->m_sb.sb_uquotino = (*ip)->i_ino; 910 mp->m_sb.sb_uquotino = (*ip)->i_ino;
876 else 911 else if (flags & XFS_QMOPT_GQUOTA)
877 mp->m_sb.sb_gquotino = (*ip)->i_ino; 912 mp->m_sb.sb_gquotino = (*ip)->i_ino;
913 else
914 mp->m_sb.sb_pquotino = (*ip)->i_ino;
878 spin_unlock(&mp->m_sb_lock); 915 spin_unlock(&mp->m_sb_lock);
879 xfs_mod_sb(tp, sbfields); 916 xfs_mod_sb(tp, sbfields);
880 917
@@ -1484,11 +1521,10 @@ xfs_qm_init_quotainos(
1484 if (error) 1521 if (error)
1485 goto error_rele; 1522 goto error_rele;
1486 } 1523 }
1487 /* XXX: Use gquotino for now */
1488 if (XFS_IS_PQUOTA_ON(mp) && 1524 if (XFS_IS_PQUOTA_ON(mp) &&
1489 mp->m_sb.sb_gquotino != NULLFSINO) { 1525 mp->m_sb.sb_pquotino != NULLFSINO) {
1490 ASSERT(mp->m_sb.sb_gquotino > 0); 1526 ASSERT(mp->m_sb.sb_pquotino > 0);
1491 error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 1527 error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
1492 0, 0, &pip); 1528 0, 0, &pip);
1493 if (error) 1529 if (error)
1494 goto error_rele; 1530 goto error_rele;
@@ -1496,7 +1532,8 @@ xfs_qm_init_quotainos(
1496 } else { 1532 } else {
1497 flags |= XFS_QMOPT_SBVERSION; 1533 flags |= XFS_QMOPT_SBVERSION;
1498 sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | 1534 sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
1499 XFS_SB_GQUOTINO | XFS_SB_QFLAGS); 1535 XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |
1536 XFS_SB_QFLAGS);
1500 } 1537 }
1501 1538
1502 /* 1539 /*
@@ -1524,9 +1561,8 @@ xfs_qm_init_quotainos(
1524 flags &= ~XFS_QMOPT_SBVERSION; 1561 flags &= ~XFS_QMOPT_SBVERSION;
1525 } 1562 }
1526 if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) { 1563 if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
1527 /* XXX: Use XFS_SB_GQUOTINO for now */
1528 error = xfs_qm_qino_alloc(mp, &pip, 1564 error = xfs_qm_qino_alloc(mp, &pip,
1529 sbflags | XFS_SB_GQUOTINO, 1565 sbflags | XFS_SB_PQUOTINO,
1530 flags | XFS_QMOPT_PQUOTA); 1566 flags | XFS_QMOPT_PQUOTA);
1531 if (error) 1567 if (error)
1532 goto error_rele; 1568 goto error_rele;
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index e4f8b2d6f38b..8d9e4c78e1ab 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -296,8 +296,10 @@ xfs_qm_scall_trunc_qfiles(
296 296
297 if (flags & XFS_DQ_USER) 297 if (flags & XFS_DQ_USER)
298 error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino); 298 error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
299 if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) 299 if (flags & XFS_DQ_GROUP)
300 error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino); 300 error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
301 if (flags & XFS_DQ_PROJ)
302 error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
301 303
302 return error ? error : error2; 304 return error ? error : error2;
303} 305}
@@ -413,8 +415,10 @@ xfs_qm_scall_getqstat(
413 struct xfs_quotainfo *q = mp->m_quotainfo; 415 struct xfs_quotainfo *q = mp->m_quotainfo;
414 struct xfs_inode *uip = NULL; 416 struct xfs_inode *uip = NULL;
415 struct xfs_inode *gip = NULL; 417 struct xfs_inode *gip = NULL;
418 struct xfs_inode *pip = NULL;
416 bool tempuqip = false; 419 bool tempuqip = false;
417 bool tempgqip = false; 420 bool tempgqip = false;
421 bool temppqip = false;
418 422
419 memset(out, 0, sizeof(fs_quota_stat_t)); 423 memset(out, 0, sizeof(fs_quota_stat_t));
420 424
@@ -424,16 +428,14 @@ xfs_qm_scall_getqstat(
424 out->qs_gquota.qfs_ino = NULLFSINO; 428 out->qs_gquota.qfs_ino = NULLFSINO;
425 return (0); 429 return (0);
426 } 430 }
431
427 out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags & 432 out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
428 (XFS_ALL_QUOTA_ACCT| 433 (XFS_ALL_QUOTA_ACCT|
429 XFS_ALL_QUOTA_ENFD)); 434 XFS_ALL_QUOTA_ENFD));
430 out->qs_pad = 0;
431 out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
432 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
433
434 if (q) { 435 if (q) {
435 uip = q->qi_uquotaip; 436 uip = q->qi_uquotaip;
436 gip = q->qi_gquotaip; 437 gip = q->qi_gquotaip;
438 pip = q->qi_pquotaip;
437 } 439 }
438 if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) { 440 if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
439 if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 441 if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
@@ -445,18 +447,41 @@ xfs_qm_scall_getqstat(
445 0, 0, &gip) == 0) 447 0, 0, &gip) == 0)
446 tempgqip = true; 448 tempgqip = true;
447 } 449 }
450 /*
451 * Q_XGETQSTAT doesn't have room for both group and project quotas.
452 * So, allow the project quota values to be copied out only if
453 * there is no group quota information available.
454 */
455 if (!gip) {
456 if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
457 if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
458 0, 0, &pip) == 0)
459 temppqip = true;
460 }
461 } else
462 pip = NULL;
448 if (uip) { 463 if (uip) {
464 out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
449 out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks; 465 out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
450 out->qs_uquota.qfs_nextents = uip->i_d.di_nextents; 466 out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
451 if (tempuqip) 467 if (tempuqip)
452 IRELE(uip); 468 IRELE(uip);
453 } 469 }
470
454 if (gip) { 471 if (gip) {
472 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
455 out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks; 473 out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
456 out->qs_gquota.qfs_nextents = gip->i_d.di_nextents; 474 out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
457 if (tempgqip) 475 if (tempgqip)
458 IRELE(gip); 476 IRELE(gip);
459 } 477 }
478 if (pip) {
479 out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
480 out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
481 out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
482 if (temppqip)
483 IRELE(pip);
484 }
460 if (q) { 485 if (q) {
461 out->qs_incoredqs = q->qi_dquots; 486 out->qs_incoredqs = q->qi_dquots;
462 out->qs_btimelimit = q->qi_btimelimit; 487 out->qs_btimelimit = q->qi_btimelimit;
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 78f9e70b80c7..a6ff9d6e72f6 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -618,16 +618,23 @@ xfs_sb_has_incompat_log_feature(
618 return (sbp->sb_features_log_incompat & feature) != 0; 618 return (sbp->sb_features_log_incompat & feature) != 0;
619} 619}
620 620
621static inline bool 621static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp)
622xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
623{ 622{
624 return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino); 623 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
625} 624}
626 625
627/* 626/*
628 * end of superblock version macros 627 * end of superblock version macros
629 */ 628 */
630 629
630static inline bool
631xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
632{
633 return (ino == sbp->sb_uquotino ||
634 ino == sbp->sb_gquotino ||
635 ino == sbp->sb_pquotino);
636}
637
631#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */ 638#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in filesystem/ag */
632#define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR) 639#define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR)
633#define XFS_BUF_TO_SBP(bp) ((xfs_dsb_t *)((bp)->b_addr)) 640#define XFS_BUF_TO_SBP(bp) ((xfs_dsb_t *)((bp)->b_addr))
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 1d68ffcdeaa7..525524e43f22 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -421,12 +421,6 @@ xfs_parseargs(
421 } 421 }
422#endif 422#endif
423 423
424 if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
425 (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) {
426 xfs_warn(mp, "cannot mount with both project and group quota");
427 return EINVAL;
428 }
429
430 if ((dsunit && !dswidth) || (!dsunit && dswidth)) { 424 if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
431 xfs_warn(mp, "sunit and swidth must be specified together"); 425 xfs_warn(mp, "sunit and swidth must be specified together");
432 return EINVAL; 426 return EINVAL;
@@ -556,14 +550,13 @@ xfs_showargs(
556 else if (mp->m_qflags & XFS_UQUOTA_ACCT) 550 else if (mp->m_qflags & XFS_UQUOTA_ACCT)
557 seq_puts(m, "," MNTOPT_UQUOTANOENF); 551 seq_puts(m, "," MNTOPT_UQUOTANOENF);
558 552
559 /* Either project or group quotas can be active, not both */
560
561 if (mp->m_qflags & XFS_PQUOTA_ACCT) { 553 if (mp->m_qflags & XFS_PQUOTA_ACCT) {
562 if (mp->m_qflags & XFS_PQUOTA_ENFD) 554 if (mp->m_qflags & XFS_PQUOTA_ENFD)
563 seq_puts(m, "," MNTOPT_PRJQUOTA); 555 seq_puts(m, "," MNTOPT_PRJQUOTA);
564 else 556 else
565 seq_puts(m, "," MNTOPT_PQUOTANOENF); 557 seq_puts(m, "," MNTOPT_PQUOTANOENF);
566 } else if (mp->m_qflags & XFS_GQUOTA_ACCT) { 558 }
559 if (mp->m_qflags & XFS_GQUOTA_ACCT) {
567 if (mp->m_qflags & XFS_GQUOTA_ENFD) 560 if (mp->m_qflags & XFS_GQUOTA_ENFD)
568 seq_puts(m, "," MNTOPT_GRPQUOTA); 561 seq_puts(m, "," MNTOPT_GRPQUOTA);
569 else 562 else
@@ -1396,6 +1389,14 @@ xfs_finish_flags(
1396 return XFS_ERROR(EROFS); 1389 return XFS_ERROR(EROFS);
1397 } 1390 }
1398 1391
1392 if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
1393 (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
1394 !xfs_sb_version_has_pquotino(&mp->m_sb)) {
1395 xfs_warn(mp,
1396 "Super block does not support project and group quota together");
1397 return XFS_ERROR(EINVAL);
1398 }
1399
1399 return 0; 1400 return 0;
1400} 1401}
1401 1402