diff options
-rw-r--r-- | fs/xfs/xfs_mount.c | 62 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.c | 72 | ||||
-rw-r--r-- | fs/xfs/xfs_qm_syscalls.c | 35 | ||||
-rw-r--r-- | fs/xfs/xfs_sb.h | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_super.c | 19 |
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 | ||
602 | void | 626 | void |
@@ -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 | ||
621 | static inline bool | 621 | static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp) |
622 | xfs_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 | ||
630 | static inline bool | ||
631 | xfs_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 | ||