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

xfs: repair refcount btrees

parent dbfbf3bd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -186,6 +186,7 @@ xfs-y += $(addprefix scrub/, \
				   ialloc_repair.o \
				   newbt.o \
				   reap.o \
				   refcount_repair.o \
				   repair.o \
				   )
endif
+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ struct xfs_perag {
	 * verifiers while rebuilding the AG btrees.
	 */
	uint8_t		pagf_repair_levels[XFS_BTNUM_AGF];
	uint8_t		pagf_repair_refcount_level;
#endif

	spinlock_t	pag_state_lock;
+26 −0
Original line number Diff line number Diff line
@@ -5212,3 +5212,29 @@ xfs_btree_destroy_cur_caches(void)
	xfs_rmapbt_destroy_cur_cache();
	xfs_refcountbt_destroy_cur_cache();
}

/* Move the btree cursor before the first record. */
int
xfs_btree_goto_left_edge(
	struct xfs_btree_cur	*cur)
{
	int			stat = 0;
	int			error;

	memset(&cur->bc_rec, 0, sizeof(cur->bc_rec));
	error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat);
	if (error)
		return error;
	if (!stat)
		return 0;

	error = xfs_btree_decrement(cur, 0, &stat);
	if (error)
		return error;
	if (stat != 0) {
		ASSERT(0);
		return -EFSCORRUPTED;
	}

	return 0;
}
+2 −0
Original line number Diff line number Diff line
@@ -738,4 +738,6 @@ xfs_btree_alloc_cursor(
int __init xfs_btree_init_cur_caches(void);
void xfs_btree_destroy_cur_caches(void);

int xfs_btree_goto_left_edge(struct xfs_btree_cur *cur);

#endif	/* __XFS_BTREE_H__ */
+3 −5
Original line number Diff line number Diff line
@@ -123,11 +123,9 @@ xfs_refcount_btrec_to_irec(
/* Simple checks for refcount records. */
xfs_failaddr_t
xfs_refcount_check_irec(
	struct xfs_btree_cur		*cur,
	struct xfs_perag		*pag,
	const struct xfs_refcount_irec	*irec)
{
	struct xfs_perag		*pag = cur->bc_ag.pag;

	if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
		return __this_address;

@@ -179,7 +177,7 @@ xfs_refcount_get_rec(
		return error;

	xfs_refcount_btrec_to_irec(rec, irec);
	fa = xfs_refcount_check_irec(cur, irec);
	fa = xfs_refcount_check_irec(cur->bc_ag.pag, irec);
	if (fa)
		return xfs_refcount_complain_bad_rec(cur, fa, irec);

@@ -1899,7 +1897,7 @@ xfs_refcount_recover_extent(
	INIT_LIST_HEAD(&rr->rr_list);
	xfs_refcount_btrec_to_irec(rec, &rr->rr_rrec);

	if (xfs_refcount_check_irec(cur, &rr->rr_rrec) != NULL ||
	if (xfs_refcount_check_irec(cur->bc_ag.pag, &rr->rr_rrec) != NULL ||
	    XFS_IS_CORRUPT(cur->bc_mp,
			   rr->rr_rrec.rc_domain != XFS_REFC_DOMAIN_COW)) {
		kfree(rr);
Loading