+ return error;
+ }
+ }
+ return 0;
+}
+
+/*
+ * xfs_mountfs
+ *
+ * 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,
+ int mfsi_flags)
+{
+ xfs_sb_t *sbp = &(mp->m_sb);
+ xfs_inode_t *rip;
+ bhv_vnode_t *rvp = NULL;
+ __uint64_t resblks;
+ __int64_t update_flags = 0LL;
+ uint quotamount, quotaflags;
+ int agno;
+ int uuid_mounted = 0;
+ int error = 0;
+
+ if (mp->m_sb_bp == NULL) {
+ error = xfs_readsb(mp, mfsi_flags);
+ if (error)
+ return error;
+ }
+ 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;
+ 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_ATTR2;
+
+ }
+
+ /*
+ * Check if sb_agblocks is aligned at stripe boundary
+ * If sb_agblocks is NOT aligned turn off m_dalign since
+ * allocator alignment is within an ag, therefore ag has
+ * to be aligned at stripe boundary.
+ */
+ error = xfs_update_alignment(mp, mfsi_flags, &update_flags);
+ if (error)
+ goto error1;
+
+ xfs_alloc_compute_maxlevels(mp);
+ xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
+ xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
+ xfs_ialloc_compute_maxlevels(mp);
+
+ xfs_set_maxicount(mp);
+
+ mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
+
+ /*
+ * XFS uses the uuid from the superblock as the unique
+ * identifier for fsid. We can not use the uuid from the volume
+ * since a single partition filesystem is identical to a single
+ * partition volume/filesystem.
+ */
+ if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
+ (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
+ if (xfs_uuid_mount(mp)) {
+ error = XFS_ERROR(EINVAL);