|
@@ -606,6 +606,56 @@ xfs_default_resblks(xfs_mount_t *mp)
|
|
|
return resblks;
|
|
|
}
|
|
|
|
|
|
+/* Ensure the summary counts are correct. */
|
|
|
+STATIC int
|
|
|
+xfs_check_summary_counts(
|
|
|
+ struct xfs_mount *mp)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * The AG0 superblock verifier rejects in-progress filesystems,
|
|
|
+ * so we should never see the flag set this far into mounting.
|
|
|
+ */
|
|
|
+ if (mp->m_sb.sb_inprogress) {
|
|
|
+ xfs_err(mp, "sb_inprogress set after log recovery??");
|
|
|
+ WARN_ON(1);
|
|
|
+ return -EFSCORRUPTED;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Now the log is mounted, we know if it was an unclean shutdown or
|
|
|
+ * not. If it was, with the first phase of recovery has completed, we
|
|
|
+ * have consistent AG blocks on disk. We have not recovered EFIs yet,
|
|
|
+ * but they are recovered transactionally in the second recovery phase
|
|
|
+ * later.
|
|
|
+ *
|
|
|
+ * If the log was clean when we mounted, we can check the summary
|
|
|
+ * counters. If any of them are obviously incorrect, we can recompute
|
|
|
+ * them from the AGF headers in the next step.
|
|
|
+ */
|
|
|
+ if (XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
|
|
|
+ (mp->m_sb.sb_fdblocks > mp->m_sb.sb_dblocks ||
|
|
|
+ mp->m_sb.sb_ifree > mp->m_sb.sb_icount))
|
|
|
+ mp->m_flags |= XFS_MOUNT_BAD_SUMMARY;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We can safely re-initialise incore superblock counters from the
|
|
|
+ * per-ag data. These may not be correct if the filesystem was not
|
|
|
+ * cleanly unmounted, so we waited for recovery to finish before doing
|
|
|
+ * this.
|
|
|
+ *
|
|
|
+ * If the filesystem was cleanly unmounted or the previous check did
|
|
|
+ * not flag anything weird, then we can trust the values in the
|
|
|
+ * superblock to be correct and we don't need to do anything here.
|
|
|
+ * Otherwise, recalculate the summary counters.
|
|
|
+ */
|
|
|
+ if ((!xfs_sb_version_haslazysbcount(&mp->m_sb) ||
|
|
|
+ XFS_LAST_UNMOUNT_WAS_CLEAN(mp)) &&
|
|
|
+ !(mp->m_flags & XFS_MOUNT_BAD_SUMMARY))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ return xfs_initialize_perag_data(mp, mp->m_sb.sb_agcount);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This function does the following on an initial mount of a file system:
|
|
|
* - reads the superblock from disk and init the mount struct
|
|
@@ -831,32 +881,10 @@ xfs_mountfs(
|
|
|
goto out_fail_wait;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * Now the log is mounted, we know if it was an unclean shutdown or
|
|
|
- * not. If it was, with the first phase of recovery has completed, we
|
|
|
- * have consistent AG blocks on disk. We have not recovered EFIs yet,
|
|
|
- * but they are recovered transactionally in the second recovery phase
|
|
|
- * later.
|
|
|
- *
|
|
|
- * Hence we can safely re-initialise incore superblock counters from
|
|
|
- * the per-ag data. These may not be correct if the filesystem was not
|
|
|
- * cleanly unmounted, so we need to wait for recovery to finish before
|
|
|
- * doing this.
|
|
|
- *
|
|
|
- * If the filesystem was cleanly unmounted, then we can trust the
|
|
|
- * values in the superblock to be correct and we don't need to do
|
|
|
- * anything here.
|
|
|
- *
|
|
|
- * If we are currently making the filesystem, the initialisation will
|
|
|
- * fail as the perag data is in an undefined state.
|
|
|
- */
|
|
|
- if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
|
|
|
- !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
|
|
|
- !mp->m_sb.sb_inprogress) {
|
|
|
- error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
|
|
|
- if (error)
|
|
|
- goto out_log_dealloc;
|
|
|
- }
|
|
|
+ /* Make sure the summary counts are ok. */
|
|
|
+ error = xfs_check_summary_counts(mp);
|
|
|
+ if (error)
|
|
|
+ goto out_log_dealloc;
|
|
|
|
|
|
/*
|
|
|
* Get and sanity-check the root inode.
|