brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 7deeb94 Raw
174 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2020-2024 Oracle.  All Rights Reserved.4 * Author: Darrick J. Wong <djwong@kernel.org>5 */6#include "xfs.h"7#include "xfs_fs.h"8#include "xfs_shared.h"9#include "xfs_format.h"10#include "xfs_trans_resv.h"11#include "xfs_mount.h"12#include "xfs_btree.h"13#include "xfs_log_format.h"14#include "xfs_trans.h"15#include "xfs_rtalloc.h"16#include "xfs_inode.h"17#include "xfs_bit.h"18#include "xfs_bmap.h"19#include "xfs_bmap_btree.h"20#include "xfs_exchmaps.h"21#include "xfs_rtbitmap.h"22#include "scrub/scrub.h"23#include "scrub/common.h"24#include "scrub/trace.h"25#include "scrub/repair.h"26#include "scrub/tempfile.h"27#include "scrub/tempexch.h"28#include "scrub/reap.h"29#include "scrub/xfile.h"30#include "scrub/rtsummary.h"31 32/* Set us up to repair the rtsummary file. */33int34xrep_setup_rtsummary(35	struct xfs_scrub	*sc,36	struct xchk_rtsummary	*rts)37{38	struct xfs_mount	*mp = sc->mp;39	unsigned long long	blocks;40	int			error;41 42	error = xrep_tempfile_create(sc, S_IFREG);43	if (error)44		return error;45 46	/*47	 * If we're doing a repair, we reserve enough blocks to write out a48	 * completely new summary file, plus twice as many blocks as we would49	 * need if we can only allocate one block per data fork mapping.  This50	 * should cover the preallocation of the temporary file and exchanging51	 * the extent mappings.52	 *53	 * We cannot use xfs_exchmaps_estimate because we have not yet54	 * constructed the replacement rtsummary and therefore do not know how55	 * many extents it will use.  By the time we do, we will have a dirty56	 * transaction (which we cannot drop because we cannot drop the57	 * rtsummary ILOCK) and cannot ask for more reservation.58	 */59	blocks = mp->m_rsumblocks;60	blocks += xfs_bmbt_calc_size(mp, blocks) * 2;61	if (blocks > UINT_MAX)62		return -EOPNOTSUPP;63 64	rts->resblks += blocks;65	return 0;66}67 68static int69xrep_rtsummary_prep_buf(70	struct xfs_scrub	*sc,71	struct xfs_buf		*bp,72	void			*data)73{74	struct xchk_rtsummary	*rts = data;75	struct xfs_mount	*mp = sc->mp;76	union xfs_suminfo_raw	*ondisk;77	int			error;78 79	rts->args.mp = sc->mp;80	rts->args.tp = sc->tp;81	rts->args.sumbp = bp;82	ondisk = xfs_rsumblock_infoptr(&rts->args, 0);83	rts->args.sumbp = NULL;84 85	bp->b_ops = &xfs_rtbuf_ops;86 87	error = xfsum_copyout(sc, rts->prep_wordoff, ondisk, mp->m_blockwsize);88	if (error)89		return error;90 91	rts->prep_wordoff += mp->m_blockwsize;92	xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTSUMMARY_BUF);93	return 0;94}95 96/* Repair the realtime summary. */97int98xrep_rtsummary(99	struct xfs_scrub	*sc)100{101	struct xchk_rtsummary	*rts = sc->buf;102	struct xfs_mount	*mp = sc->mp;103	int			error;104 105	/* We require the rmapbt to rebuild anything. */106	if (!xfs_has_rmapbt(mp))107		return -EOPNOTSUPP;108	/* We require atomic file exchange range to rebuild anything. */109	if (!xfs_has_exchange_range(mp))110		return -EOPNOTSUPP;111 112	/* Walk away if we disagree on the size of the rt bitmap. */113	if (rts->rbmblocks != mp->m_sb.sb_rbmblocks)114		return 0;115 116	/* Make sure any problems with the fork are fixed. */117	error = xrep_metadata_inode_forks(sc);118	if (error)119		return error;120 121	/*122	 * Try to take ILOCK_EXCL of the temporary file.  We had better be the123	 * only ones holding onto this inode, but we can't block while holding124	 * the rtsummary file's ILOCK_EXCL.125	 */126	while (!xrep_tempfile_ilock_nowait(sc)) {127		if (xchk_should_terminate(sc, &error))128			return error;129		delay(1);130	}131 132	/* Make sure we have space allocated for the entire summary file. */133	xfs_trans_ijoin(sc->tp, sc->ip, 0);134	xfs_trans_ijoin(sc->tp, sc->tempip, 0);135	error = xrep_tempfile_prealloc(sc, 0, rts->rsumblocks);136	if (error)137		return error;138 139	/* Last chance to abort before we start committing fixes. */140	if (xchk_should_terminate(sc, &error))141		return error;142 143	/* Copy the rtsummary file that we generated. */144	error = xrep_tempfile_copyin(sc, 0, rts->rsumblocks,145			xrep_rtsummary_prep_buf, rts);146	if (error)147		return error;148	error = xrep_tempfile_set_isize(sc, XFS_FSB_TO_B(mp, rts->rsumblocks));149	if (error)150		return error;151 152	/*153	 * Now exchange the contents.  Nothing in repair uses the temporary154	 * buffer, so we can reuse it for the tempfile exchrange information.155	 */156	error = xrep_tempexch_trans_reserve(sc, XFS_DATA_FORK, &rts->tempexch);157	if (error)158		return error;159 160	error = xrep_tempexch_contents(sc, &rts->tempexch);161	if (error)162		return error;163 164	/* Reset incore state and blow out the summary cache. */165	if (mp->m_rsum_cache)166		memset(mp->m_rsum_cache, 0xFF, mp->m_sb.sb_rbmblocks);167 168	mp->m_rsumlevels = rts->rsumlevels;169	mp->m_rsumblocks = rts->rsumblocks;170 171	/* Free the old rtsummary blocks if they're not in use. */172	return xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);173}174