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)) { |
