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

xfs: repair inodes that have realtime extents



Plumb into the inode core repair code the ability to search for extents
on realtime devices.

Signed-off-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent f1a6d9b4
Loading
Loading
Loading
Loading
+57 −1
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@
#include "xfs_log_priv.h"
#include "xfs_health.h"
#include "xfs_symlink_remote.h"
#include "xfs_rtgroup.h"
#include "xfs_rtrmap_btree.h"
#include "scrub/xfs_scrub.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
@@ -773,17 +775,71 @@ xrep_dinode_count_ag_rmaps(
	return error;
}

/* Count extents and blocks for an inode given an rt rmap. */
STATIC int
xrep_dinode_walk_rtrmap(
	struct xfs_btree_cur		*cur,
	const struct xfs_rmap_irec	*rec,
	void				*priv)
{
	struct xrep_inode		*ri = priv;
	int				error = 0;

	if (xchk_should_terminate(ri->sc, &error))
		return error;

	/* We only care about this inode. */
	if (rec->rm_owner != ri->sc->sm->sm_ino)
		return 0;

	if (rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))
		return -EFSCORRUPTED;

	ri->rt_blocks += rec->rm_blockcount;
	ri->rt_extents++;
	return 0;
}

/* Count extents and blocks for an inode from all realtime rmap data. */
STATIC int
xrep_dinode_count_rtgroup_rmaps(
	struct xrep_inode	*ri,
	struct xfs_rtgroup	*rtg)
{
	struct xfs_scrub	*sc = ri->sc;
	int			error;

	error = xrep_rtgroup_init(sc, rtg, &sc->sr, XFS_RTGLOCK_RMAP);
	if (error)
		return error;

	error = xfs_rmap_query_all(sc->sr.rmap_cur, xrep_dinode_walk_rtrmap,
			ri);
	xchk_rtgroup_btcur_free(&sc->sr);
	xchk_rtgroup_free(sc, &sc->sr);
	return error;
}

/* Count extents and blocks for a given inode from all rmap data. */
STATIC int
xrep_dinode_count_rmaps(
	struct xrep_inode	*ri)
{
	struct xfs_perag	*pag = NULL;
	struct xfs_rtgroup	*rtg = NULL;
	int			error;

	if (!xfs_has_rmapbt(ri->sc->mp) || xfs_has_realtime(ri->sc->mp))
	if (!xfs_has_rmapbt(ri->sc->mp))
		return -EOPNOTSUPP;

	while ((rtg = xfs_rtgroup_next(ri->sc->mp, rtg))) {
		error = xrep_dinode_count_rtgroup_rmaps(ri, rtg);
		if (error) {
			xfs_rtgroup_rele(rtg);
			return error;
		}
	}

	while ((pag = xfs_perag_next(ri->sc->mp, pag))) {
		error = xrep_dinode_count_ag_rmaps(ri, pag);
		if (error) {