+ if (mp->m_sb.sb_qflags == 0)
+ return 0;
+ spin_lock(&mp->m_sb_lock);
+ mp->m_sb.sb_qflags = 0;
+ spin_unlock(&mp->m_sb_lock);
+
+ /*
+ * If the fs is readonly, let the incore superblock run
+ * with quotas off but don't flush the update out to disk
+ */
+ if (mp->m_flags & XFS_MOUNT_RDONLY)
+ return 0;
+
+#ifdef QUOTADEBUG
+ xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes");
+#endif
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
+ error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
+ XFS_DEFAULT_LOG_COUNT);
+ if (error) {
+ xfs_trans_cancel(tp, 0);
+ xfs_fs_cmn_err(CE_ALERT, mp,
+ "xfs_mount_reset_sbqflags: Superblock update failed!");
+ return error;
+ }
+
+ xfs_mod_sb(tp, XFS_SB_QFLAGS);
+ return xfs_trans_commit(tp, 0);
+}
+
+/*
+ * This function does the following on an initial mount of a file system:
+ * - reads the superblock from disk and init the mount struct
+ * - if we're a 32-bit kernel, do a size check on the superblock
+ * so we don't mount terabyte filesystems
+ * - init mount struct realtime fields
+ * - allocate inode hash table for fs
+ * - init directory manager
+ * - perform recovery and init the log manager
+ */
+int
+xfs_mountfs(
+ xfs_mount_t *mp)
+{
+ xfs_sb_t *sbp = &(mp->m_sb);
+ xfs_inode_t *rip;
+ __uint64_t resblks;
+ uint quotamount = 0;
+ uint quotaflags = 0;
+ int error = 0;
+
+ xfs_mount_common(mp, sbp);
+
+ /*
+ * Check for a mismatched features2 values. Older kernels
+ * read & wrote into the wrong sb offset for sb_features2
+ * on some platforms due to xfs_sb_t not being 64bit size aligned
+ * when sb_features2 was added, which made older superblock
+ * reading/writing routines swap it as a 64-bit value.
+ *
+ * For backwards compatibility, we make both slots equal.
+ *
+ * If we detect a mismatched field, we OR the set bits into the
+ * existing features2 field in case it has already been modified; we
+ * don't want to lose any features. We then update the bad location
+ * with the ORed value so that older kernels will see any features2
+ * flags, and mark the two fields as needing updates once the
+ * transaction subsystem is online.
+ */
+ if (xfs_sb_has_mismatched_features2(sbp)) {
+ cmn_err(CE_WARN,
+ "XFS: correcting sb_features alignment problem");
+ sbp->sb_features2 |= sbp->sb_bad_features2;
+ sbp->sb_bad_features2 = sbp->sb_features2;
+ mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
+
+ /*
+ * Re-check for ATTR2 in case it was found in bad_features2
+ * slot.
+ */
+ if (xfs_sb_version_hasattr2(&mp->m_sb) &&
+ !(mp->m_flags & XFS_MOUNT_NOATTR2))
+ mp->m_flags |= XFS_MOUNT_ATTR2;
+ }
+
+ if (xfs_sb_version_hasattr2(&mp->m_sb) &&
+ (mp->m_flags & XFS_MOUNT_NOATTR2)) {
+ xfs_sb_version_removeattr2(&mp->m_sb);
+ mp->m_update_flags |= XFS_SB_FEATURES2;
+
+ /* update sb_versionnum for the clearing of the morebits */
+ if (!sbp->sb_features2)
+ mp->m_update_flags |= XFS_SB_VERSIONNUM;