From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> Use our newly expanded geometry structure to report the overall fs and realtime health status. Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_fs.h | 11 ++++++++ fs/xfs/libxfs/xfs_health.h | 3 ++ fs/xfs/xfs_health.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_ioctl.c | 2 ++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index ee33d628a240..6b8956dbf49d 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -199,9 +199,18 @@ struct xfs_fsop_geom { __u32 rtsectsize; /* realtime sector size, bytes */ __u32 dirblocksize; /* directory block size, bytes */ __u32 logsunit; /* log stripe unit, bytes */ - __u64 reserved[18]; /* reserved space */ + uint32_t sick; /* o: unhealthy fs & rt metadata */ + uint32_t checked; /* o: checked fs & rt metadata */ + __u64 reserved[17]; /* reserved space */ }; +#define XFS_FSOP_GEOM_SICK_COUNTERS (1 << 0) /* summary counters */ +#define XFS_FSOP_GEOM_SICK_UQUOTA (1 << 1) /* user quota */ +#define XFS_FSOP_GEOM_SICK_GQUOTA (1 << 2) /* group quota */ +#define XFS_FSOP_GEOM_SICK_PQUOTA (1 << 3) /* project quota */ +#define XFS_FSOP_GEOM_SICK_RT_BITMAP (1 << 4) /* realtime bitmap */ +#define XFS_FSOP_GEOM_SICK_RT_SUMMARY (1 << 5) /* realtime summary */ + /* Output for XFS_FS_COUNTS */ typedef struct xfs_fsop_counts { __u64 freedata; /* free data section blocks */ diff --git a/fs/xfs/libxfs/xfs_health.h b/fs/xfs/libxfs/xfs_health.h index a434b47f2aa0..c72142ec7cbb 100644 --- a/fs/xfs/libxfs/xfs_health.h +++ b/fs/xfs/libxfs/xfs_health.h @@ -26,6 +26,7 @@ struct xfs_mount; struct xfs_perag; struct xfs_inode; +struct xfs_fsop_geom; /* Observable health issues for metadata spanning the entire filesystem. */ #define XFS_SICK_FS_COUNTERS (1 << 0) /* summary counters */ @@ -174,4 +175,6 @@ xfs_inode_is_healthy(struct xfs_inode *ip) return !xfs_inode_has_sickness(ip, -1U); } +void xfs_fsop_geom_health(struct xfs_mount *mp, struct xfs_fsop_geom *geo); + #endif /* __XFS_HEALTH_H__ */ diff --git a/fs/xfs/xfs_health.c b/fs/xfs/xfs_health.c index 21728228e08b..eb8dbc3a952a 100644 --- a/fs/xfs/xfs_health.c +++ b/fs/xfs/xfs_health.c @@ -264,3 +264,60 @@ xfs_inode_measure_sickness( *checked = ip->i_checked; spin_unlock(&ip->i_flags_lock); } + +struct ioctl_sick_map { + unsigned int sick_mask; + unsigned int ioctl_mask; +}; + +static const struct ioctl_sick_map fs_map[] = { + { XFS_SICK_FS_COUNTERS, XFS_FSOP_GEOM_SICK_COUNTERS}, + { XFS_SICK_FS_UQUOTA, XFS_FSOP_GEOM_SICK_UQUOTA }, + { XFS_SICK_FS_GQUOTA, XFS_FSOP_GEOM_SICK_GQUOTA }, + { XFS_SICK_FS_PQUOTA, XFS_FSOP_GEOM_SICK_PQUOTA }, + { 0, 0 }, +}; + +static const struct ioctl_sick_map rt_map[] = { + { XFS_SICK_RT_BITMAP, XFS_FSOP_GEOM_SICK_RT_BITMAP }, + { XFS_SICK_RT_SUMMARY, XFS_FSOP_GEOM_SICK_RT_SUMMARY }, + { 0, 0 }, +}; + +static inline void +xfgeo_health_tick( + struct xfs_fsop_geom *geo, + unsigned int sick, + unsigned int checked, + unsigned int sick_mask, + unsigned int fsop_mask) +{ + if (checked & sick_mask) + geo->checked |= fsop_mask; + if (sick & sick_mask) + geo->sick |= fsop_mask; +} + +/* Fill out fs geometry health info. */ +void +xfs_fsop_geom_health( + struct xfs_mount *mp, + struct xfs_fsop_geom *geo) +{ + const struct ioctl_sick_map *m; + unsigned int sick; + unsigned int checked; + + geo->sick = 0; + geo->checked = 0; + + xfs_fs_measure_sickness(mp, &sick, &checked); + for (m = fs_map; m->sick_mask; m++) + xfgeo_health_tick(geo, sick, checked, m->sick_mask, + m->ioctl_mask); + + xfs_rt_measure_sickness(mp, &sick, &checked); + for (m = rt_map; m->sick_mask; m++) + xfgeo_health_tick(geo, sick, checked, m->sick_mask, + m->ioctl_mask); +} diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 0aaf4f88524d..3e3ee197bd0f 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -34,6 +34,7 @@ #include "scrub/xfs_scrub.h" #include "xfs_sb.h" #include "xfs_ag.h" +#include "xfs_health.h" #include <linux/capability.h> #include <linux/cred.h> @@ -792,6 +793,7 @@ xfs_ioc_fsgeometry( error = xfs_fs_geometry(&mp->m_sb, &fsgeo, struct_version); if (error) return error; + xfs_fsop_geom_health(mp, &fsgeo); if (struct_version <= 3) len = sizeof(struct xfs_fsop_geom_v1);