summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2020-02-19 17:01:50 -0800
committerDarrick J. Wong <darrick.wong@oracle.com>2020-06-01 21:16:32 -0700
commit6aa633a57dd3cb245ecf1f275f8b00e82bbd8406 (patch)
treedbd39794b142605f68209077a65a0e4f3f1e92f9
parentf13e935a9e9f8c838ff5c997abf4083c8f999089 (diff)
xfs: separate the marking of sick and checked metadata
Split the setting of the sick and checked masks into separate functions as part of preparing to add the ability for regular runtime fs code (i.e. not scrub) to mark metadata structures sick when corruptions are found. Improve the documentation of libxfs' requirements for helper behavior. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--fs/xfs/libxfs/xfs_health.h16
-rw-r--r--fs/xfs/scrub/health.c20
-rw-r--r--fs/xfs/xfs_health.c49
-rw-r--r--fs/xfs/xfs_mount.c5
4 files changed, 80 insertions, 10 deletions
diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h
index 272005ac8c88..96919a257870 100644
--- a/fs/xfs/libxfs/xfs_health.h
+++ b/fs/xfs/libxfs/xfs_health.h
@@ -97,24 +97,38 @@ struct xfs_fsop_geom;
XFS_SICK_INO_SYMLINK | \
XFS_SICK_INO_PARENT)
-/* These functions must be provided by the xfs implementation. */
+/*
+ * These functions must be provided by the xfs implementation. Function
+ * behavior with respect to the first argument should be as follows:
+ *
+ * xfs_*_mark_sick: set the sick flags and do not set checked flags.
+ * xfs_*_mark_checked: set the checked flags.
+ * xfs_*_mark_healthy: clear the sick flags and set the checked flags.
+ *
+ * xfs_*_measure_sickness: return the sick and check status in the provided
+ * out parameters.
+ */
void xfs_fs_mark_sick(struct xfs_mount *mp, unsigned int mask);
+void xfs_fs_mark_checked(struct xfs_mount *mp, unsigned int mask);
void xfs_fs_mark_healthy(struct xfs_mount *mp, unsigned int mask);
void xfs_fs_measure_sickness(struct xfs_mount *mp, unsigned int *sick,
unsigned int *checked);
void xfs_rt_mark_sick(struct xfs_mount *mp, unsigned int mask);
+void xfs_rt_mark_checked(struct xfs_mount *mp, unsigned int mask);
void xfs_rt_mark_healthy(struct xfs_mount *mp, unsigned int mask);
void xfs_rt_measure_sickness(struct xfs_mount *mp, unsigned int *sick,
unsigned int *checked);
void xfs_ag_mark_sick(struct xfs_perag *pag, unsigned int mask);
+void xfs_ag_mark_checked(struct xfs_perag *pag, unsigned int mask);
void xfs_ag_mark_healthy(struct xfs_perag *pag, unsigned int mask);
void xfs_ag_measure_sickness(struct xfs_perag *pag, unsigned int *sick,
unsigned int *checked);
void xfs_inode_mark_sick(struct xfs_inode *ip, unsigned int mask);
+void xfs_inode_mark_checked(struct xfs_inode *ip, unsigned int mask);
void xfs_inode_mark_healthy(struct xfs_inode *ip, unsigned int mask);
void xfs_inode_measure_sickness(struct xfs_inode *ip, unsigned int *sick,
unsigned int *checked);
diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c
index 8cff49b3ef60..4d1bea2fc36d 100644
--- a/fs/xfs/scrub/health.c
+++ b/fs/xfs/scrub/health.c
@@ -137,30 +137,34 @@ xchk_update_health(
switch (type_to_health_flag[sc->sm->sm_type].group) {
case XHG_AG:
pag = xfs_perag_get(sc->mp, sc->sm->sm_agno);
- if (bad)
+ if (bad) {
xfs_ag_mark_sick(pag, sc->sick_mask);
- else
+ xfs_ag_mark_checked(pag, sc->sick_mask);
+ } else
xfs_ag_mark_healthy(pag, sc->sick_mask);
xfs_perag_put(pag);
break;
case XHG_INO:
if (!sc->ip)
return;
- if (bad)
+ if (bad) {
xfs_inode_mark_sick(sc->ip, sc->sick_mask);
- else
+ xfs_inode_mark_checked(sc->ip, sc->sick_mask);
+ } else
xfs_inode_mark_healthy(sc->ip, sc->sick_mask);
break;
case XHG_FS:
- if (bad)
+ if (bad) {
xfs_fs_mark_sick(sc->mp, sc->sick_mask);
- else
+ xfs_fs_mark_checked(sc->mp, sc->sick_mask);
+ } else
xfs_fs_mark_healthy(sc->mp, sc->sick_mask);
break;
case XHG_RT:
- if (bad)
+ if (bad) {
xfs_rt_mark_sick(sc->mp, sc->sick_mask);
- else
+ xfs_rt_mark_checked(sc->mp, sc->sick_mask);
+ } else
xfs_rt_mark_healthy(sc->mp, sc->sick_mask);
break;
default:
diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c
index 8e0cb05a7142..860dc70c99e7 100644
--- a/fs/xfs/xfs_health.c
+++ b/fs/xfs/xfs_health.c
@@ -100,6 +100,18 @@ xfs_fs_mark_sick(
spin_lock(&mp->m_sb_lock);
mp->m_fs_sick |= mask;
+ spin_unlock(&mp->m_sb_lock);
+}
+
+/* Mark per-fs metadata as having been checked. */
+void
+xfs_fs_mark_checked(
+ struct xfs_mount *mp,
+ unsigned int mask)
+{
+ ASSERT(!(mask & ~XFS_SICK_FS_PRIMARY));
+
+ spin_lock(&mp->m_sb_lock);
mp->m_fs_checked |= mask;
spin_unlock(&mp->m_sb_lock);
}
@@ -143,6 +155,19 @@ xfs_rt_mark_sick(
spin_lock(&mp->m_sb_lock);
mp->m_rt_sick |= mask;
+ spin_unlock(&mp->m_sb_lock);
+}
+
+/* Mark realtime metadata as having been checked. */
+void
+xfs_rt_mark_checked(
+ struct xfs_mount *mp,
+ unsigned int mask)
+{
+ ASSERT(!(mask & ~XFS_SICK_RT_PRIMARY));
+ trace_xfs_rt_mark_sick(mp, mask);
+
+ spin_lock(&mp->m_sb_lock);
mp->m_rt_checked |= mask;
spin_unlock(&mp->m_sb_lock);
}
@@ -186,6 +211,18 @@ xfs_ag_mark_sick(
spin_lock(&pag->pag_state_lock);
pag->pag_sick |= mask;
+ spin_unlock(&pag->pag_state_lock);
+}
+
+/* Mark per-ag metadata as having been checked. */
+void
+xfs_ag_mark_checked(
+ struct xfs_perag *pag,
+ unsigned int mask)
+{
+ ASSERT(!(mask & ~XFS_SICK_AG_PRIMARY));
+
+ spin_lock(&pag->pag_state_lock);
pag->pag_checked |= mask;
spin_unlock(&pag->pag_state_lock);
}
@@ -229,6 +266,18 @@ xfs_inode_mark_sick(
spin_lock(&ip->i_flags_lock);
ip->i_sick |= mask;
+ spin_unlock(&ip->i_flags_lock);
+}
+
+/* Mark inode metadata as having been checked. */
+void
+xfs_inode_mark_checked(
+ struct xfs_inode *ip,
+ unsigned int mask)
+{
+ ASSERT(!(mask & ~XFS_SICK_INO_PRIMARY));
+
+ spin_lock(&ip->i_flags_lock);
ip->i_checked |= mask;
spin_unlock(&ip->i_flags_lock);
}
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index a9d359f8fad2..c94ee3bf5417 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -608,8 +608,10 @@ xfs_check_summary_counts(
if (XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
(mp->m_sb.sb_fdblocks > mp->m_sb.sb_dblocks ||
!xfs_verify_icount(mp, mp->m_sb.sb_icount) ||
- mp->m_sb.sb_ifree > mp->m_sb.sb_icount))
+ mp->m_sb.sb_ifree > mp->m_sb.sb_icount)) {
xfs_fs_mark_sick(mp, XFS_SICK_FS_COUNTERS);
+ xfs_fs_mark_checked(mp, XFS_SICK_FS_COUNTERS);
+ }
/*
* We can safely re-initialise incore superblock counters from the
@@ -1386,6 +1388,7 @@ xfs_force_summary_recalc(
return;
xfs_fs_mark_sick(mp, XFS_SICK_FS_COUNTERS);
+ xfs_fs_mark_checked(mp, XFS_SICK_FS_COUNTERS);
}
/*