Commit c23232d4 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: report fs and rt health via geometry structure



Use our newly expanded geometry structure to report the overall fs and
realtime health status.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent 7cd5006b
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -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 */
+3 −0
Original line number Diff line number Diff line
@@ -34,6 +34,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 */
@@ -182,4 +183,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__ */
+56 −0
Original line number Diff line number Diff line
@@ -264,3 +264,59 @@ xfs_inode_measure_sickness(
	*checked = ip->i_checked;
	spin_unlock(&ip->i_flags_lock);
}

/* Mappings between internal sick masks and ioctl sick masks. */

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,
	const struct ioctl_sick_map	*m)
{
	if (checked & m->sick_mask)
		geo->checked |= m->ioctl_mask;
	if (sick & m->sick_mask)
		geo->sick |= m->ioctl_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);

	xfs_rt_measure_sickness(mp, &sick, &checked);
	for (m = rt_map; m->sick_mask; m++)
		xfgeo_health_tick(geo, sick, checked, m);
}
+4 −1
Original line number Diff line number Diff line
@@ -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>
@@ -797,8 +798,10 @@ xfs_ioc_fsgeometry(
		len = sizeof(struct xfs_fsop_geom_v1);
	else if (struct_version == 4)
		len = sizeof(struct xfs_fsop_geom_v4);
	else
	else {
		xfs_fsop_geom_health(mp, &fsgeo);
		len = sizeof(fsgeo);
	}

	if (copy_to_user(arg, &fsgeo, len))
		return -EFAULT;