// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (c) 2020-2024 Oracle.  All Rights Reserved.
 * Author: Darrick J. Wong <djwong@kernel.org>
 */
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_trans_resv.h"
#include "xfs_mount.h"
#include "xfs_btree.h"
#include "xfs_log_format.h"
#include "xfs_trans.h"
#include "xfs_rtalloc.h"
#include "xfs_inode.h"
#include "xfs_bit.h"
#include "xfs_bmap.h"
#include "xfs_bmap_btree.h"
#include "xfs_exchmaps.h"
#include "xfs_rtbitmap.h"
#include "scrub/scrub.h"
#include "scrub/common.h"
#include "scrub/trace.h"
#include "scrub/repair.h"
#include "scrub/tempfile.h"
#include "scrub/tempexch.h"
#include "scrub/reap.h"
#include "scrub/xfile.h"
#include "scrub/rtsummary.h"

/* Set us up to repair the rtsummary file. */
int
xrep_setup_rtsummary(
	struct xfs_scrub	*sc,
	struct xchk_rtsummary	*rts)
{
	struct xfs_mount	*mp = sc->mp;
	unsigned long long	blocks;
	int			error;

	error = xrep_tempfile_create(sc, S_IFREG);
	if (error)
		return error;

	/*
	 * If we're doing a repair, we reserve enough blocks to write out a
	 * completely new summary file, plus twice as many blocks as we would
	 * need if we can only allocate one block per data fork mapping.  This
	 * should cover the preallocation of the temporary file and exchanging
	 * the extent mappings.
	 *
	 * We cannot use xfs_exchmaps_estimate because we have not yet
	 * constructed the replacement rtsummary and therefore do not know how
	 * many extents it will use.  By the time we do, we will have a dirty
	 * transaction (which we cannot drop because we cannot drop the
	 * rtsummary ILOCK) and cannot ask for more reservation.
	 */
	blocks = XFS_B_TO_FSB(mp, mp->m_rsumsize);
	blocks += xfs_bmbt_calc_size(mp, blocks) * 2;
	if (blocks > UINT_MAX)
		return -EOPNOTSUPP;

	rts->resblks += blocks;
	return 0;
}

static int
xrep_rtsummary_prep_buf(
	struct xfs_scrub	*sc,
	struct xfs_buf		*bp,
	void			*data)
{
	struct xchk_rtsummary	*rts = data;
	struct xfs_mount	*mp = sc->mp;
	union xfs_suminfo_raw	*ondisk;
	int			error;

	rts->args.mp = sc->mp;
	rts->args.tp = sc->tp;
	rts->args.sumbp = bp;
	ondisk = xfs_rsumblock_infoptr(&rts->args, 0);
	rts->args.sumbp = NULL;

	bp->b_ops = &xfs_rtbuf_ops;

	error = xfsum_copyout(sc, rts->prep_wordoff, ondisk, mp->m_blockwsize);
	if (error)
		return error;

	rts->prep_wordoff += mp->m_blockwsize;
	xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTSUMMARY_BUF);
	return 0;
}

/* Repair the realtime summary. */
int
xrep_rtsummary(
	struct xfs_scrub	*sc)
{
	struct xchk_rtsummary	*rts = sc->buf;
	struct xfs_mount	*mp = sc->mp;
	xfs_filblks_t		rsumblocks;
	int			error;

	/* We require the rmapbt to rebuild anything. */
	if (!xfs_has_rmapbt(mp))
		return -EOPNOTSUPP;
	/* We require atomic file exchange range to rebuild anything. */
	if (!xfs_has_exchange_range(mp))
		return -EOPNOTSUPP;

	/* Walk away if we disagree on the size of the rt bitmap. */
	if (rts->rbmblocks != mp->m_sb.sb_rbmblocks)
		return 0;

	/* Make sure any problems with the fork are fixed. */
	error = xrep_metadata_inode_forks(sc);
	if (error)
		return error;

	/*
	 * Try to take ILOCK_EXCL of the temporary file.  We had better be the
	 * only ones holding onto this inode, but we can't block while holding
	 * the rtsummary file's ILOCK_EXCL.
	 */
	while (!xrep_tempfile_ilock_nowait(sc)) {
		if (xchk_should_terminate(sc, &error))
			return error;
		delay(1);
	}

	/* Make sure we have space allocated for the entire summary file. */
	rsumblocks = XFS_B_TO_FSB(mp, rts->rsumsize);
	xfs_trans_ijoin(sc->tp, sc->ip, 0);
	xfs_trans_ijoin(sc->tp, sc->tempip, 0);
	error = xrep_tempfile_prealloc(sc, 0, rsumblocks);
	if (error)
		return error;

	/* Last chance to abort before we start committing fixes. */
	if (xchk_should_terminate(sc, &error))
		return error;

	/* Copy the rtsummary file that we generated. */
	error = xrep_tempfile_copyin(sc, 0, rsumblocks,
			xrep_rtsummary_prep_buf, rts);
	if (error)
		return error;
	error = xrep_tempfile_set_isize(sc, rts->rsumsize);
	if (error)
		return error;

	/*
	 * Now exchange the contents.  Nothing in repair uses the temporary
	 * buffer, so we can reuse it for the tempfile exchrange information.
	 */
	error = xrep_tempexch_trans_reserve(sc, XFS_DATA_FORK, &rts->tempexch);
	if (error)
		return error;

	error = xrep_tempexch_contents(sc, &rts->tempexch);
	if (error)
		return error;

	/* Reset incore state and blow out the summary cache. */
	if (mp->m_rsum_cache)
		memset(mp->m_rsum_cache, 0xFF, mp->m_sb.sb_rbmblocks);

	mp->m_rsumlevels = rts->rsumlevels;
	mp->m_rsumsize = rts->rsumsize;

	/* Free the old rtsummary blocks if they're not in use. */
	return xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);
}
