aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r--fs/xfs/xfs_mount.c59
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
47STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t); 47STATIC void xfs_mount_log_sb(xfs_mount_t *, __int64_t);
48STATIC int xfs_uuid_mount(xfs_mount_t *); 48STATIC int xfs_uuid_mount(xfs_mount_t *);
49STATIC void xfs_uuid_unmount(xfs_mount_t *mp); 49STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
50STATIC void xfs_unmountfs_wait(xfs_mount_t *); 50STATIC 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)
869STATIC void 871STATIC void
870xfs_set_inoalignment(xfs_mount_t *mp) 872xfs_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 */
1880STATIC void 1914STATIC void
1881xfs_mount_log_sbunit( 1915xfs_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,