diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
| -rw-r--r-- | fs/xfs/xfs_mount.c | 59 |
1 files changed, 47 insertions, 12 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 6409b3762995..8ed164eb9544 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
| @@ -44,7 +44,7 @@ | |||
| 44 | #include "xfs_quota.h" | 44 | #include "xfs_quota.h" |
| 45 | #include "xfs_fsops.h" | 45 | #include "xfs_fsops.h" |
| 46 | 46 | ||
| 47 | STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t); | 47 | STATIC void xfs_mount_log_sb(xfs_mount_t *, __int64_t); |
| 48 | STATIC int xfs_uuid_mount(xfs_mount_t *); | 48 | STATIC int xfs_uuid_mount(xfs_mount_t *); |
| 49 | STATIC void xfs_uuid_unmount(xfs_mount_t *mp); | 49 | STATIC void xfs_uuid_unmount(xfs_mount_t *mp); |
| 50 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); | 50 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); |
| @@ -119,6 +119,7 @@ static const struct { | |||
| 119 | { offsetof(xfs_sb_t, sb_logsectsize),0 }, | 119 | { offsetof(xfs_sb_t, sb_logsectsize),0 }, |
| 120 | { offsetof(xfs_sb_t, sb_logsunit), 0 }, | 120 | { offsetof(xfs_sb_t, sb_logsunit), 0 }, |
| 121 | { offsetof(xfs_sb_t, sb_features2), 0 }, | 121 | { offsetof(xfs_sb_t, sb_features2), 0 }, |
| 122 | { offsetof(xfs_sb_t, sb_bad_features2), 0 }, | ||
| 122 | { sizeof(xfs_sb_t), 0 } | 123 | { sizeof(xfs_sb_t), 0 } |
| 123 | }; | 124 | }; |
| 124 | 125 | ||
| @@ -225,7 +226,7 @@ xfs_mount_validate_sb( | |||
| 225 | return XFS_ERROR(EWRONGFS); | 226 | return XFS_ERROR(EWRONGFS); |
| 226 | } | 227 | } |
| 227 | 228 | ||
| 228 | if (!XFS_SB_GOOD_VERSION(sbp)) { | 229 | if (!xfs_sb_good_version(sbp)) { |
| 229 | xfs_fs_mount_cmn_err(flags, "bad version"); | 230 | xfs_fs_mount_cmn_err(flags, "bad version"); |
| 230 | return XFS_ERROR(EWRONGFS); | 231 | return XFS_ERROR(EWRONGFS); |
| 231 | } | 232 | } |
| @@ -300,7 +301,7 @@ xfs_mount_validate_sb( | |||
| 300 | /* | 301 | /* |
| 301 | * Version 1 directory format has never worked on Linux. | 302 | * Version 1 directory format has never worked on Linux. |
| 302 | */ | 303 | */ |
| 303 | if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) { | 304 | if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { |
| 304 | xfs_fs_mount_cmn_err(flags, | 305 | xfs_fs_mount_cmn_err(flags, |
| 305 | "file system using version 1 directory format"); | 306 | "file system using version 1 directory format"); |
| 306 | return XFS_ERROR(ENOSYS); | 307 | return XFS_ERROR(ENOSYS); |
| @@ -449,6 +450,7 @@ xfs_sb_from_disk( | |||
| 449 | to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); | 450 | to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize); |
| 450 | to->sb_logsunit = be32_to_cpu(from->sb_logsunit); | 451 | to->sb_logsunit = be32_to_cpu(from->sb_logsunit); |
| 451 | to->sb_features2 = be32_to_cpu(from->sb_features2); | 452 | to->sb_features2 = be32_to_cpu(from->sb_features2); |
| 453 | to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2); | ||
| 452 | } | 454 | } |
| 453 | 455 | ||
| 454 | /* | 456 | /* |
| @@ -781,7 +783,7 @@ xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags) | |||
| 781 | * Update superblock with new values | 783 | * Update superblock with new values |
| 782 | * and log changes | 784 | * and log changes |
| 783 | */ | 785 | */ |
| 784 | if (XFS_SB_VERSION_HASDALIGN(sbp)) { | 786 | if (xfs_sb_version_hasdalign(sbp)) { |
| 785 | if (sbp->sb_unit != mp->m_dalign) { | 787 | if (sbp->sb_unit != mp->m_dalign) { |
| 786 | sbp->sb_unit = mp->m_dalign; | 788 | sbp->sb_unit = mp->m_dalign; |
| 787 | *update_flags |= XFS_SB_UNIT; | 789 | *update_flags |= XFS_SB_UNIT; |
| @@ -792,7 +794,7 @@ xfs_update_alignment(xfs_mount_t *mp, int mfsi_flags, __uint64_t *update_flags) | |||
| 792 | } | 794 | } |
| 793 | } | 795 | } |
| 794 | } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && | 796 | } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN && |
| 795 | XFS_SB_VERSION_HASDALIGN(&mp->m_sb)) { | 797 | xfs_sb_version_hasdalign(&mp->m_sb)) { |
| 796 | mp->m_dalign = sbp->sb_unit; | 798 | mp->m_dalign = sbp->sb_unit; |
| 797 | mp->m_swidth = sbp->sb_width; | 799 | mp->m_swidth = sbp->sb_width; |
| 798 | } | 800 | } |
| @@ -869,7 +871,7 @@ xfs_set_rw_sizes(xfs_mount_t *mp) | |||
| 869 | STATIC void | 871 | STATIC void |
| 870 | xfs_set_inoalignment(xfs_mount_t *mp) | 872 | xfs_set_inoalignment(xfs_mount_t *mp) |
| 871 | { | 873 | { |
| 872 | if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) && | 874 | if (xfs_sb_version_hasalign(&mp->m_sb) && |
| 873 | mp->m_sb.sb_inoalignmt >= | 875 | mp->m_sb.sb_inoalignmt >= |
| 874 | XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) | 876 | XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size)) |
| 875 | mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; | 877 | mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1; |
| @@ -970,6 +972,38 @@ xfs_mountfs( | |||
| 970 | xfs_mount_common(mp, sbp); | 972 | xfs_mount_common(mp, sbp); |
| 971 | 973 | ||
| 972 | /* | 974 | /* |
| 975 | * Check for a mismatched features2 values. Older kernels | ||
| 976 | * read & wrote into the wrong sb offset for sb_features2 | ||
| 977 | * on some platforms due to xfs_sb_t not being 64bit size aligned | ||
| 978 | * when sb_features2 was added, which made older superblock | ||
| 979 | * reading/writing routines swap it as a 64-bit value. | ||
| 980 | * | ||
| 981 | * For backwards compatibility, we make both slots equal. | ||
| 982 | * | ||
| 983 | * If we detect a mismatched field, we OR the set bits into the | ||
| 984 | * existing features2 field in case it has already been modified; we | ||
| 985 | * don't want to lose any features. We then update the bad location | ||
| 986 | * with the ORed value so that older kernels will see any features2 | ||
| 987 | * flags, and mark the two fields as needing updates once the | ||
| 988 | * transaction subsystem is online. | ||
| 989 | */ | ||
| 990 | if (xfs_sb_has_mismatched_features2(sbp)) { | ||
| 991 | cmn_err(CE_WARN, | ||
| 992 | "XFS: correcting sb_features alignment problem"); | ||
| 993 | sbp->sb_features2 |= sbp->sb_bad_features2; | ||
| 994 | sbp->sb_bad_features2 = sbp->sb_features2; | ||
| 995 | update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; | ||
| 996 | |||
| 997 | /* | ||
| 998 | * Re-check for ATTR2 in case it was found in bad_features2 | ||
| 999 | * slot. | ||
| 1000 | */ | ||
| 1001 | if (xfs_sb_version_hasattr2(&mp->m_sb)) | ||
| 1002 | mp->m_flags |= XFS_MOUNT_ATTR2; | ||
| 1003 | |||
| 1004 | } | ||
| 1005 | |||
| 1006 | /* | ||
| 973 | * Check if sb_agblocks is aligned at stripe boundary | 1007 | * Check if sb_agblocks is aligned at stripe boundary |
| 974 | * If sb_agblocks is NOT aligned turn off m_dalign since | 1008 | * If sb_agblocks is NOT aligned turn off m_dalign since |
| 975 | * allocator alignment is within an ag, therefore ag has | 1009 | * allocator alignment is within an ag, therefore ag has |
| @@ -1159,11 +1193,10 @@ xfs_mountfs( | |||
| 1159 | } | 1193 | } |
| 1160 | 1194 | ||
| 1161 | /* | 1195 | /* |
| 1162 | * If fs is not mounted readonly, then update the superblock | 1196 | * If fs is not mounted readonly, then update the superblock changes. |
| 1163 | * unit and width changes. | ||
| 1164 | */ | 1197 | */ |
| 1165 | if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) | 1198 | if (update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) |
| 1166 | xfs_mount_log_sbunit(mp, update_flags); | 1199 | xfs_mount_log_sb(mp, update_flags); |
| 1167 | 1200 | ||
| 1168 | /* | 1201 | /* |
| 1169 | * Initialise the XFS quota management subsystem for this mount | 1202 | * Initialise the XFS quota management subsystem for this mount |
| @@ -1875,16 +1908,18 @@ xfs_uuid_unmount( | |||
| 1875 | 1908 | ||
| 1876 | /* | 1909 | /* |
| 1877 | * Used to log changes to the superblock unit and width fields which could | 1910 | * Used to log changes to the superblock unit and width fields which could |
| 1878 | * be altered by the mount options. Only the first superblock is updated. | 1911 | * be altered by the mount options, as well as any potential sb_features2 |
| 1912 | * fixup. Only the first superblock is updated. | ||
| 1879 | */ | 1913 | */ |
| 1880 | STATIC void | 1914 | STATIC void |
| 1881 | xfs_mount_log_sbunit( | 1915 | xfs_mount_log_sb( |
| 1882 | xfs_mount_t *mp, | 1916 | xfs_mount_t *mp, |
| 1883 | __int64_t fields) | 1917 | __int64_t fields) |
| 1884 | { | 1918 | { |
| 1885 | xfs_trans_t *tp; | 1919 | xfs_trans_t *tp; |
| 1886 | 1920 | ||
| 1887 | ASSERT(fields & (XFS_SB_UNIT|XFS_SB_WIDTH|XFS_SB_UUID)); | 1921 | ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID | |
| 1922 | XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2)); | ||
| 1888 | 1923 | ||
| 1889 | tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); | 1924 | tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); |
| 1890 | if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, | 1925 | if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0, |
