[PATCH 24/29] xfs_repair: extend ag_rmap[] for realtime mapping collection

"Darrick J. Wong" <[email protected]>
Newsgroups gmane.comp.file-systems.xfs.general
Message-ID <[email protected]>
Extend the ag_rmap[] infrastructure to have an extra group to store
realtime extent reverse mappings.  Since we're pretending that the
realtime device is AG "-1", we can just play some pointer arithmetic
to make this work out.  In the next patch we'll actually use this
data for something.  Extend the ag_locks[] array in a similar manner.

Signed-off-by: Darrick J. Wong <[email protected]>
---
 repair/dinode.c |    2 +
 repair/incore.c |    9 ++++-
 repair/phase4.c |   10 +++--
 repair/rmap.c   |  105 ++++++++++++++++++++++++++++++++++++-------------------
 repair/rmap.h   |   10 +++++
 5 files changed, 91 insertions(+), 45 deletions(-)


diff --git a/repair/dinode.c b/repair/dinode.c
index 6718cd2..f768cdf 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -801,7 +801,7 @@ _("illegal state %d in block map %" PRIu64 "\n"),
 			}
 		}
 		if (collect_rmaps) { /* && !check_dups */
-			error = rmap_add_rec(mp, ino, whichfork, &irec);
+			error = rmap_add_rec(mp, ino, whichfork, &irec, false);
 			if (error)
 				do_error(
 _("couldn't add reverse mapping\n")
diff --git a/repair/incore.c b/repair/incore.c
index cb57316..fbb05ad 100644
--- a/repair/incore.c
+++ b/repair/incore.c
@@ -294,14 +294,17 @@ init_bmaps(xfs_mount_t *mp)
 	if (!ag_bmap)
 		do_error(_("couldn't allocate block map btree roots\n"));
 
-	ag_locks = calloc(mp->m_sb.sb_agcount, sizeof(struct aglock));
+	ag_locks = calloc(mp->m_sb.sb_agcount + 1, sizeof(struct aglock));
 	if (!ag_locks)
 		do_error(_("couldn't allocate block map locks\n"));
 
+	/* One ag_lock per AG, and one more for the realtime device. */
 	for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
 		btree_init(&ag_bmap[i]);
 		pthread_mutex_init(&ag_locks[i].lock, NULL);
 	}
+	pthread_mutex_init(&ag_locks[mp->m_sb.sb_agcount].lock, NULL);
+	ag_locks++;
 
 	init_rt_bmap(mp);
 	reset_bmaps(mp);
@@ -312,6 +315,10 @@ free_bmaps(xfs_mount_t *mp)
 {
 	xfs_agnumber_t i;
 
+	ag_locks--;
+	free(ag_locks);
+	ag_locks = NULL;
+
 	for (i = 0; i < mp->m_sb.sb_agcount; i++)
 		btree_destroy(ag_bmap[i]);
 	free(ag_bmap);
diff --git a/repair/phase4.c b/repair/phase4.c
index 395d373..512f774 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -158,7 +158,7 @@ process_ags(
 	int			error;
 
 	do_inode_prefetch(mp, ag_stride, process_ag_func, true, false);
-	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+	for_each_rmap_group(mp, i) {
 		error = rmap_finish_collecting_fork_recs(mp, i);
 		if (error)
 			do_error(
@@ -248,7 +248,7 @@ process_rmap_data(
 		return;
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_rmap_group(mp, i)
 		queue_work(&wq, check_rmap_btrees, i, NULL);
 	destroy_work_queue(&wq);
 
@@ -256,17 +256,17 @@ process_rmap_data(
 		return;
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_ag(mp, i)
 		queue_work(&wq, compute_ag_refcounts, i, NULL);
 	destroy_work_queue(&wq);
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_ag(mp, i)
 		queue_work(&wq, process_inode_reflink_flags, i, NULL);
 	destroy_work_queue(&wq);
 
 	create_work_queue(&wq, mp, libxfs_nproc());
-	for (i = 0; i < mp->m_sb.sb_agcount; i++)
+	for_each_ag(mp, i)
 		queue_work(&wq, check_refcount_btrees, i, NULL);
 	destroy_work_queue(&wq);
 }
diff --git a/repair/rmap.c b/repair/rmap.c
index 3b3a195..37da251 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -45,6 +45,7 @@ struct xfs_ag_rmap {
 	struct xfs_slab	*ar_refcount_items;	/* refcount items, p4-5 */
 };
 
+/* One ag_rmap per AG, and one more for the realtime device. */
 static struct xfs_ag_rmap *ag_rmaps;
 static bool rmapbt_suspect;
 static bool refcbt_suspect;
@@ -83,6 +84,17 @@ rmap_compare(
 }
 
 /*
+ * Return the ag_rmap for a given AG.
+ * Note that NULLAGNUMBER (-1) is the realtime device.
+ */
+static struct xfs_ag_rmap*
+rmap_for_ag(
+	xfs_agnumber_t		agno)
+{
+	return &ag_rmaps[(signed)agno];
+}
+
+/*
  * Returns true if we must reconstruct either the reference count or reverse
  * mapping trees.
  */
@@ -107,11 +119,12 @@ rmaps_init(
 	if (!rmap_needs_work(mp))
 		return;
 
-	ag_rmaps = calloc(mp->m_sb.sb_agcount, sizeof(struct xfs_ag_rmap));
+	/* One ag_rmap per AG, and one more for the realtime device. */
+	ag_rmaps = calloc(mp->m_sb.sb_agcount + 1, sizeof(struct xfs_ag_rmap));
 	if (!ag_rmaps)
 		do_error(_("couldn't allocate per-AG reverse map roots\n"));
 
-	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+	for (i = 0; i < mp->m_sb.sb_agcount + 1; i++) {
 		error = init_slab(&ag_rmaps[i].ar_rmaps,
 				sizeof(struct xfs_rmap_irec));
 		if (error)
@@ -129,6 +142,7 @@ _("Insufficient memory while allocating raw metadata reverse mapping slabs."));
 			do_error(
 _("Insufficient memory while allocating refcount item slabs."));
 	}
+	ag_rmaps++;
 }
 
 /*
@@ -143,7 +157,8 @@ rmaps_free(
 	if (!rmap_needs_work(mp))
 		return;
 
-	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+	ag_rmaps--;
+	for (i = 0; i < mp->m_sb.sb_agcount + 1; i++) {
 		free_slab(&ag_rmaps[i].ar_rmaps);
 		free_slab(&ag_rmaps[i].ar_raw_rmaps);
 		free_slab(&ag_rmaps[i].ar_refcount_items);
@@ -186,22 +201,31 @@ rmap_add_rec(
 	struct xfs_mount	*mp,
 	xfs_ino_t		ino,
 	int			whichfork,
-	struct xfs_bmbt_irec	*irec)
+	struct xfs_bmbt_irec	*irec,
+	bool			realtime)
 {
+	struct xfs_ag_rmap	*ag_rmap;
 	struct xfs_rmap_irec	rmap;
 	xfs_agnumber_t		agno;
-	xfs_agblock_t		agbno;
+	xfs_fsblock_t		agbno;
 	struct xfs_rmap_irec	*last_rmap;
 	int			error = 0;
 
 	if (!rmap_needs_work(mp))
 		return 0;
 
-	agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
-	agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
-	ASSERT(agno != NULLAGNUMBER);
-	ASSERT(agno < mp->m_sb.sb_agcount);
-	ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks);
+	if (realtime) {
+		agno = NULLAGNUMBER;
+		agbno = irec->br_startblock;
+		ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_rblocks);
+	} else {
+		agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
+		agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
+		ASSERT(agno != NULLAGNUMBER);
+		ASSERT(agno < mp->m_sb.sb_agcount);
+		ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks);
+	}
+	ag_rmap = rmap_for_ag(agno);
 	ASSERT(ino != NULLFSINO);
 	ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
 
@@ -214,13 +238,13 @@ rmap_add_rec(
 	rmap.rm_blockcount = irec->br_blockcount;
 	if (irec->br_state == XFS_EXT_UNWRITTEN)
 		rmap.rm_flags |= XFS_RMAP_UNWRITTEN;
-	last_rmap = &ag_rmaps[agno].ar_last_rmap;
+	last_rmap = &ag_rmap->ar_last_rmap;
 	if (last_rmap->rm_owner == XFS_RMAP_OWN_UNKNOWN)
 		*last_rmap = rmap;
 	else if (rmaps_are_mergeable(last_rmap, &rmap))
 		last_rmap->rm_blockcount += rmap.rm_blockcount;
 	else {
-		error = slab_add(ag_rmaps[agno].ar_rmaps, last_rmap);
+		error = slab_add(ag_rmap->ar_rmaps, last_rmap);
 		if (error)
 			return error;
 		*last_rmap = rmap;
@@ -236,9 +260,10 @@ rmap_finish_collecting_fork_recs(
 	xfs_agnumber_t		agno)
 {
 	if (!rmap_needs_work(mp) ||
-	    ag_rmaps[agno].ar_last_rmap.rm_owner == XFS_RMAP_OWN_UNKNOWN)
+	    rmap_for_ag(agno)->ar_last_rmap.rm_owner == XFS_RMAP_OWN_UNKNOWN)
 		return 0;
-	return slab_add(ag_rmaps[agno].ar_rmaps, &ag_rmaps[agno].ar_last_rmap);
+	return slab_add(rmap_for_ag(agno)->ar_rmaps,
+			&rmap_for_ag(agno)->ar_last_rmap);
 }
 
 /* add a raw rmap; these will be merged later */
@@ -264,7 +289,7 @@ __rmap_add_raw_rec(
 		rmap.rm_flags |= XFS_RMAP_BMBT_BLOCK;
 	rmap.rm_startblock = agbno;
 	rmap.rm_blockcount = len;
-	return slab_add(ag_rmaps[agno].ar_raw_rmaps, &rmap);
+	return slab_add(rmap_for_ag(agno)->ar_raw_rmaps, &rmap);
 }
 
 /*
@@ -322,16 +347,18 @@ rmap_fold_raw_recs(
 	struct xfs_mount	*mp,
 	xfs_agnumber_t		agno)
 {
+	struct xfs_ag_rmap	*ag_rmap;
 	struct xfs_slab_cursor	*cur = NULL;
 	struct xfs_rmap_irec	*prev, *rec;
 	size_t			old_sz;
 	int			error = 0;
 
-	old_sz = slab_count(ag_rmaps[agno].ar_rmaps);
-	if (slab_count(ag_rmaps[agno].ar_raw_rmaps) == 0)
+	ag_rmap = rmap_for_ag(agno);
+	old_sz = slab_count(ag_rmap->ar_rmaps);
+	if (slab_count(ag_rmap->ar_raw_rmaps) == 0)
 		goto no_raw;
-	qsort_slab(ag_rmaps[agno].ar_raw_rmaps, rmap_compare);
-	error = init_slab_cursor(ag_rmaps[agno].ar_raw_rmaps, rmap_compare,
+	qsort_slab(ag_rmap->ar_raw_rmaps, rmap_compare);
+	error = init_slab_cursor(ag_rmap->ar_raw_rmaps, rmap_compare,
 			&cur);
 	if (error)
 		goto err;
@@ -344,26 +371,26 @@ rmap_fold_raw_recs(
 			rec = pop_slab_cursor(cur);
 			continue;
 		}
-		error = slab_add(ag_rmaps[agno].ar_rmaps, prev);
+		error = slab_add(ag_rmap->ar_rmaps, prev);
 		if (error)
 			goto err;
 		prev = rec;
 		rec = pop_slab_cursor(cur);
 	}
 	if (prev) {
-		error = slab_add(ag_rmaps[agno].ar_rmaps, prev);
+		error = slab_add(ag_rmap->ar_rmaps, prev);
 		if (error)
 			goto err;
 	}
-	free_slab(&ag_rmaps[agno].ar_raw_rmaps);
-	error = init_slab(&ag_rmaps[agno].ar_raw_rmaps,
+	free_slab(&ag_rmap->ar_raw_rmaps);
+	error = init_slab(&ag_rmap->ar_raw_rmaps,
 			sizeof(struct xfs_rmap_irec));
 	if (error)
 		do_error(
 _("Insufficient memory while allocating raw metadata reverse mapping slabs."));
 no_raw:
 	if (old_sz)
-		qsort_slab(ag_rmaps[agno].ar_rmaps, rmap_compare);
+		qsort_slab(ag_rmap->ar_rmaps, rmap_compare);
 err:
 	free_slab_cursor(&cur);
 	return error;
@@ -419,6 +446,9 @@ rmap_add_fixed_ag_rec(
 	if (!rmap_needs_work(mp))
 		return 0;
 
+	if (agno == NULLAGNUMBER)
+		return 0;
+
 	/* sb/agi/agf/agfl headers */
 	error = rmap_add_ag_rec(mp, agno, 0, XFS_BNO_BLOCK(mp),
 			XFS_RMAP_OWN_FS);
@@ -493,6 +523,7 @@ rmap_store_ag_btree_rec(
 	struct xfs_trans	*tp;
 	struct xfs_trans_res tres = {0};
 	__be32			*agfl_bno, *b;
+	struct xfs_ag_rmap	*ag_rmap;
 	int			error = 0;
 	struct xfs_owner_info	oinfo;
 
@@ -500,9 +531,9 @@ rmap_store_ag_btree_rec(
 		return 0;
 
 	/* Release the ar_rmaps; they were put into the rmapbt during p5. */
-	free_slab(&ag_rmaps[agno].ar_rmaps);
-	error = init_slab(&ag_rmaps[agno].ar_rmaps,
-				  sizeof(struct xfs_rmap_irec));
+	ag_rmap = rmap_for_ag(agno);
+	free_slab(&ag_rmap->ar_rmaps);
+	error = init_slab(&ag_rmap->ar_rmaps, sizeof(struct xfs_rmap_irec));
 	if (error)
 		goto err;
 
@@ -515,7 +546,7 @@ rmap_store_ag_btree_rec(
 		goto err;
 
 	agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp);
-	agfl_bno += ag_rmaps[agno].ar_flcount;
+	agfl_bno += ag_rmap->ar_flcount;
 	b = agfl_bno;
 	while (*b != NULLAGBLOCK && b - agfl_bno <= XFS_AGFL_SIZE(mp)) {
 		error = rmap_add_ag_rec(mp, agno, be32_to_cpu(*b), 1,
@@ -533,7 +564,7 @@ rmap_store_ag_btree_rec(
 		goto err;
 
 	/* Create cursors to refcount structures */
-	error = init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare,
+	error = init_slab_cursor(ag_rmap->ar_rmaps, rmap_compare,
 			&rm_cur);
 	if (error)
 		goto err;
@@ -714,7 +745,7 @@ refcount_emit(
 	int			error;
 	struct xfs_slab		*rlslab;
 
-	rlslab = ag_rmaps[agno].ar_refcount_items;
+	rlslab = rmap_for_ag(agno)->ar_refcount_items;
 	ASSERT(nr_rmaps > 0);
 
 	dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n",
@@ -736,7 +767,7 @@ _("Insufficient memory while recreating refcount tree."));
 #define RMAP_END(r)	((r)->rm_startblock + (r)->rm_blockcount)
 int
 compute_refcounts(
-	struct xfs_mount		*mp,
+	struct xfs_mount	*mp,
 	xfs_agnumber_t		agno)
 {
 	struct xfs_bag		*stack_top = NULL;
@@ -754,7 +785,7 @@ compute_refcounts(
 	if (!xfs_sb_version_hasreflink(&mp->m_sb))
 		return 0;
 
-	rmaps = ag_rmaps[agno].ar_rmaps;
+	rmaps = rmap_for_ag(agno)->ar_rmaps;
 
 	error = init_slab_cursor(rmaps, rmap_compare, &rmaps_cur);
 	if (error)
@@ -864,7 +895,7 @@ rmap_record_count(
 	struct xfs_mount		*mp,
 	xfs_agnumber_t		agno)
 {
-	return slab_count(ag_rmaps[agno].ar_rmaps);
+	return slab_count(rmap_for_ag(agno)->ar_rmaps);
 }
 
 /*
@@ -875,7 +906,7 @@ rmap_init_cursor(
 	xfs_agnumber_t		agno,
 	struct xfs_slab_cursor	**cur)
 {
-	return init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare, cur);
+	return init_slab_cursor(rmap_for_ag(agno)->ar_rmaps, rmap_compare, cur);
 }
 
 /*
@@ -1269,7 +1300,7 @@ refcount_record_count(
 	struct xfs_mount		*mp,
 	xfs_agnumber_t		agno)
 {
-	return slab_count(ag_rmaps[agno].ar_refcount_items);
+	return slab_count(rmap_for_ag(agno)->ar_refcount_items);
 }
 
 /*
@@ -1280,7 +1311,7 @@ init_refcount_cursor(
 	xfs_agnumber_t		agno,
 	struct xfs_slab_cursor	**cur)
 {
-	return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur);
+	return init_slab_cursor(rmap_for_ag(agno)->ar_refcount_items, NULL, cur);
 }
 
 /*
@@ -1461,5 +1492,5 @@ rmap_store_agflcount(
 	if (!rmap_needs_work(mp))
 		return;
 
-	ag_rmaps[agno].ar_flcount = count;
+	rmap_for_ag(agno)->ar_flcount = count;
 }
diff --git a/repair/rmap.h b/repair/rmap.h
index 752ece8..7069b6b 100644
--- a/repair/rmap.h
+++ b/repair/rmap.h
@@ -27,7 +27,8 @@ extern bool rmap_needs_work(struct xfs_mount *);
 extern void rmaps_init(struct xfs_mount *);
 extern void rmaps_free(struct xfs_mount *);
 
-extern int rmap_add_rec(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *);
+extern int rmap_add_rec(struct xfs_mount *, xfs_ino_t, int,
+		struct xfs_bmbt_irec *, bool realtime);
 extern int rmap_finish_collecting_fork_recs(struct xfs_mount *mp,
 		xfs_agnumber_t agno);
 extern int rmap_add_ag_rec(struct xfs_mount *, xfs_agnumber_t agno,
@@ -62,4 +63,11 @@ extern int fix_inode_reflink_flags(struct xfs_mount *, xfs_agnumber_t);
 extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool);
 extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int);
 
+#define for_each_ag(mp, agno) \
+	for ((agno) = 0; (agno) < (mp)->m_sb.sb_agcount; (agno)++)
+
+#define for_each_rmap_group(mp, agno) \
+	for ((agno) = NULLAGNUMBER; (agno) == NULLAGNUMBER || \
+	(agno) < (mp)->m_sb.sb_agcount; (agno)++)
+
 #endif /* RMAP_H_ */

_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.