diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 92 |
1 files changed, 66 insertions, 26 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index e8e310c05097..2b0ba3581656 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -336,6 +336,14 @@ 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 | |||
339 | /* | 347 | /* |
340 | * Version 5 superblock feature mask validation. Reject combinations the | 348 | * Version 5 superblock feature mask validation. Reject combinations the |
341 | * kernel cannot support up front before checking anything else. For | 349 | * kernel cannot support up front before checking anything else. For |
@@ -561,6 +569,18 @@ out_unwind: | |||
561 | return error; | 569 | return error; |
562 | } | 570 | } |
563 | 571 | ||
572 | static void | ||
573 | xfs_sb_quota_from_disk(struct xfs_sb *sbp) | ||
574 | { | ||
575 | if (sbp->sb_qflags & XFS_OQUOTA_ENFD) | ||
576 | sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? | ||
577 | XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD; | ||
578 | if (sbp->sb_qflags & XFS_OQUOTA_CHKD) | ||
579 | sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ? | ||
580 | XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; | ||
581 | sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); | ||
582 | } | ||
583 | |||
564 | void | 584 | void |
565 | xfs_sb_from_disk( | 585 | xfs_sb_from_disk( |
566 | struct xfs_sb *to, | 586 | struct xfs_sb *to, |
@@ -622,6 +642,35 @@ xfs_sb_from_disk( | |||
622 | to->sb_lsn = be64_to_cpu(from->sb_lsn); | 642 | to->sb_lsn = be64_to_cpu(from->sb_lsn); |
623 | } | 643 | } |
624 | 644 | ||
645 | static inline void | ||
646 | xfs_sb_quota_to_disk( | ||
647 | xfs_dsb_t *to, | ||
648 | xfs_sb_t *from, | ||
649 | __int64_t *fields) | ||
650 | { | ||
651 | __uint16_t qflags = from->sb_qflags; | ||
652 | |||
653 | if (*fields & XFS_SB_QFLAGS) { | ||
654 | /* | ||
655 | * The in-core version of sb_qflags do not have | ||
656 | * XFS_OQUOTA_* flags, whereas the on-disk version | ||
657 | * does. So, convert incore XFS_{PG}QUOTA_* flags | ||
658 | * to on-disk XFS_OQUOTA_* flags. | ||
659 | */ | ||
660 | qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD | | ||
661 | XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD); | ||
662 | |||
663 | if (from->sb_qflags & | ||
664 | (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD)) | ||
665 | qflags |= XFS_OQUOTA_ENFD; | ||
666 | if (from->sb_qflags & | ||
667 | (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) | ||
668 | qflags |= XFS_OQUOTA_CHKD; | ||
669 | to->sb_qflags = cpu_to_be16(qflags); | ||
670 | *fields &= ~XFS_SB_QFLAGS; | ||
671 | } | ||
672 | } | ||
673 | |||
625 | /* | 674 | /* |
626 | * Copy in core superblock to ondisk one. | 675 | * Copy in core superblock to ondisk one. |
627 | * | 676 | * |
@@ -643,6 +692,7 @@ xfs_sb_to_disk( | |||
643 | if (!fields) | 692 | if (!fields) |
644 | return; | 693 | return; |
645 | 694 | ||
695 | xfs_sb_quota_to_disk(to, from, &fields); | ||
646 | while (fields) { | 696 | while (fields) { |
647 | f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); | 697 | f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields); |
648 | first = xfs_sb_info[f].offset; | 698 | first = xfs_sb_info[f].offset; |
@@ -835,6 +885,7 @@ reread: | |||
835 | */ | 885 | */ |
836 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); | 886 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); |
837 | 887 | ||
888 | xfs_sb_quota_from_disk(&mp->m_sb); | ||
838 | /* | 889 | /* |
839 | * We must be able to do sector-sized and sector-aligned IO. | 890 | * We must be able to do sector-sized and sector-aligned IO. |
840 | */ | 891 | */ |
@@ -987,42 +1038,27 @@ xfs_update_alignment(xfs_mount_t *mp) | |||
987 | */ | 1038 | */ |
988 | if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || | 1039 | if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || |
989 | (BBTOB(mp->m_swidth) & mp->m_blockmask)) { | 1040 | (BBTOB(mp->m_swidth) & mp->m_blockmask)) { |
990 | if (mp->m_flags & XFS_MOUNT_RETERR) { | 1041 | xfs_warn(mp, |
991 | xfs_warn(mp, "alignment check failed: " | 1042 | "alignment check failed: sunit/swidth vs. blocksize(%d)", |
992 | "(sunit/swidth vs. blocksize)"); | 1043 | sbp->sb_blocksize); |
993 | return XFS_ERROR(EINVAL); | 1044 | return XFS_ERROR(EINVAL); |
994 | } | ||
995 | mp->m_dalign = mp->m_swidth = 0; | ||
996 | } else { | 1045 | } else { |
997 | /* | 1046 | /* |
998 | * Convert the stripe unit and width to FSBs. | 1047 | * Convert the stripe unit and width to FSBs. |
999 | */ | 1048 | */ |
1000 | mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign); | 1049 | mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign); |
1001 | if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) { | 1050 | if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) { |
1002 | if (mp->m_flags & XFS_MOUNT_RETERR) { | ||
1003 | xfs_warn(mp, "alignment check failed: " | ||
1004 | "(sunit/swidth vs. ag size)"); | ||
1005 | return XFS_ERROR(EINVAL); | ||
1006 | } | ||
1007 | xfs_warn(mp, | 1051 | xfs_warn(mp, |
1008 | "stripe alignment turned off: sunit(%d)/swidth(%d) " | 1052 | "alignment check failed: sunit/swidth vs. agsize(%d)", |
1009 | "incompatible with agsize(%d)", | 1053 | sbp->sb_agblocks); |
1010 | mp->m_dalign, mp->m_swidth, | 1054 | return XFS_ERROR(EINVAL); |
1011 | sbp->sb_agblocks); | ||
1012 | |||
1013 | mp->m_dalign = 0; | ||
1014 | mp->m_swidth = 0; | ||
1015 | } else if (mp->m_dalign) { | 1055 | } else if (mp->m_dalign) { |
1016 | mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); | 1056 | mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); |
1017 | } else { | 1057 | } else { |
1018 | if (mp->m_flags & XFS_MOUNT_RETERR) { | 1058 | xfs_warn(mp, |
1019 | xfs_warn(mp, "alignment check failed: " | 1059 | "alignment check failed: sunit(%d) less than bsize(%d)", |
1020 | "sunit(%d) less than bsize(%d)", | 1060 | mp->m_dalign, sbp->sb_blocksize); |
1021 | mp->m_dalign, | 1061 | return XFS_ERROR(EINVAL); |
1022 | mp->m_blockmask +1); | ||
1023 | return XFS_ERROR(EINVAL); | ||
1024 | } | ||
1025 | mp->m_swidth = 0; | ||
1026 | } | 1062 | } |
1027 | } | 1063 | } |
1028 | 1064 | ||
@@ -1039,6 +1075,10 @@ xfs_update_alignment(xfs_mount_t *mp) | |||
1039 | sbp->sb_width = mp->m_swidth; | 1075 | sbp->sb_width = mp->m_swidth; |
1040 | mp->m_update_flags |= XFS_SB_WIDTH; | 1076 | mp->m_update_flags |= XFS_SB_WIDTH; |
1041 | } | 1077 | } |
1078 | } else { | ||
1079 | xfs_warn(mp, | ||
1080 | "cannot change alignment: superblock does not support data alignment"); | ||
1081 | return XFS_ERROR(EINVAL); | ||
1042 | } | 1082 | } |
1043 | } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && | 1083 | } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && |
1044 | xfs_sb_version_hasdalign(&mp->m_sb)) { | 1084 | xfs_sb_version_hasdalign(&mp->m_sb)) { |