Commit fd43925c authored by Chandan Babu R's avatar Chandan Babu R
Browse files

Merge tag 'repair-rmap-btree-6.9_2024-02-23' of...

Merge tag 'repair-rmap-btree-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux

 into xfs-6.9-mergeC

xfs: online repair of rmap btrees

We have now constructed the four tools that we need to scan the
filesystem looking for reverse mappings: an inode scanner, hooks to
receive live updates from other writer threads, the ability to construct
btrees in memory, and a btree bulk loader.

This series glues those three together, enabling us to scan the
filesystem for mappings and keep it up to date while other writers run,
and then commit the new btree to disk atomically.

To reduce the size of each patch, the functionality is left disabled
until the end of the series and broken up into three patches: one to
create the mechanics of scanning the filesystem, a second to transition
to in-memory btrees, and a third to set up the live hooks.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>

* tag 'repair-rmap-btree-6.9_2024-02-23' of https://git.kernel.org/pub/scm/linux/kernel/git/djwong/xfs-linux:
  xfs: hook live rmap operations during a repair operation
  xfs: create a shadow rmap btree during rmap repair
  xfs: repair the rmapbt
  xfs: create agblock bitmap helper to count the number of set regions
  xfs: create a helper to decide if a file mapping targets the rt volume
parents 8394a97c 7e1b84b2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -201,6 +201,7 @@ xfs-y += $(addprefix scrub/, \
				   reap.o \
				   refcount_repair.o \
				   repair.o \
				   rmap_repair.o \
				   )

xfs-$(CONFIG_XFS_RT)		+= $(addprefix scrub/, \
+1 −0
Original line number Diff line number Diff line
@@ -417,6 +417,7 @@ xfs_initialize_perag(
		init_waitqueue_head(&pag->pag_active_wq);
		pag->pagb_count = 0;
		pag->pagb_tree = RB_ROOT;
		xfs_hooks_init(&pag->pag_rmap_update_hooks);
#endif /* __KERNEL__ */

		error = xfs_buf_cache_init(&pag->pag_bcache);
+4 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ struct xfs_perag {
	uint8_t		pagf_repair_bno_level;
	uint8_t		pagf_repair_cnt_level;
	uint8_t		pagf_repair_refcount_level;
	uint8_t		pagf_repair_rmap_level;
#endif

	spinlock_t	pag_state_lock;
@@ -119,6 +120,9 @@ struct xfs_perag {
	 * inconsistencies.
	 */
	struct xfs_defer_drain	pag_intents_drain;

	/* Hook to feed rmapbt updates to an active online repair. */
	struct xfs_hooks	pag_rmap_update_hooks;
#endif /* __KERNEL__ */
};

+46 −3
Original line number Diff line number Diff line
@@ -4913,7 +4913,7 @@ xfs_bmap_del_extent_delay(

	XFS_STATS_INC(mp, xs_del_exlist);

	isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
	isrt = xfs_ifork_is_realtime(ip, whichfork);
	del_endoff = del->br_startoff + del->br_blockcount;
	got_endoff = got->br_startoff + got->br_blockcount;
	da_old = startblockval(got->br_startblock);
@@ -5149,7 +5149,7 @@ xfs_bmap_del_extent_real(
		return -ENOSPC;

	*logflagsp = XFS_ILOG_CORE;
	if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
	if (xfs_ifork_is_realtime(ip, whichfork)) {
		if (!(bflags & XFS_BMAPI_REMAP)) {
			error = xfs_rtfree_blocks(tp, del->br_startblock,
					del->br_blockcount);
@@ -5396,7 +5396,7 @@ __xfs_bunmapi(
		return 0;
	}
	XFS_STATS_INC(mp, xs_blk_unmap);
	isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip);
	isrt = xfs_ifork_is_realtime(ip, whichfork);
	end = start + len;

	if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) {
@@ -6379,3 +6379,46 @@ xfs_bunmapi_range(
out:
	return error;
}

struct xfs_bmap_query_range {
	xfs_bmap_query_range_fn	fn;
	void			*priv;
};

/* Format btree record and pass to our callback. */
STATIC int
xfs_bmap_query_range_helper(
	struct xfs_btree_cur		*cur,
	const union xfs_btree_rec	*rec,
	void				*priv)
{
	struct xfs_bmap_query_range	*query = priv;
	struct xfs_bmbt_irec		irec;
	xfs_failaddr_t			fa;

	xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
	fa = xfs_bmap_validate_extent(cur->bc_ino.ip, cur->bc_ino.whichfork,
			&irec);
	if (fa) {
		xfs_btree_mark_sick(cur);
		return xfs_bmap_complain_bad_rec(cur->bc_ino.ip,
				cur->bc_ino.whichfork, fa, &irec);
	}

	return query->fn(cur, &irec, query->priv);
}

/* Find all bmaps. */
int
xfs_bmap_query_all(
	struct xfs_btree_cur		*cur,
	xfs_bmap_query_range_fn		fn,
	void				*priv)
{
	struct xfs_bmap_query_range	query = {
		.priv			= priv,
		.fn			= fn,
	};

	return xfs_btree_query_all(cur, xfs_bmap_query_range_helper, &query);
}
+8 −0
Original line number Diff line number Diff line
@@ -280,4 +280,12 @@ extern struct kmem_cache *xfs_bmap_intent_cache;
int __init xfs_bmap_intent_init_cache(void);
void xfs_bmap_intent_destroy_cache(void);

typedef int (*xfs_bmap_query_range_fn)(
	struct xfs_btree_cur	*cur,
	struct xfs_bmbt_irec	*rec,
	void			*priv);

int xfs_bmap_query_all(struct xfs_btree_cur *cur, xfs_bmap_query_range_fn fn,
		void *priv);

#endif	/* __XFS_BMAP_H__ */
Loading