[PATCH 066/145] xfs_repair: merge data & attr fork reverse mappings

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Merge data and attribute fork reverse mappings.

Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx>
---
 repair/phase4.c |   10 ++++++++++
 repair/rmap.c   |   32 +++++++++++++++++++++++++++++---
 repair/rmap.h   |    2 ++
 3 files changed, 41 insertions(+), 3 deletions(-)


diff --git a/repair/phase4.c b/repair/phase4.c
index e234d92..3be3786 100644
--- a/repair/phase4.c
+++ b/repair/phase4.c
@@ -154,7 +154,17 @@ static void
 process_ags(
 	xfs_mount_t		*mp)
 {
+	xfs_agnumber_t		i;
+	int			error;
+
 	do_inode_prefetch(mp, ag_stride, process_ag_func, true, false);
+	for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+		error = finish_collecting_fork_rmaps(mp, i);
+		if (error)
+			do_error(
+_("unable to finish adding attr/data fork reverse-mapping data for AG %u.\n"),
+				i);
+	}
 }
 
 static void
diff --git a/repair/rmap.c b/repair/rmap.c
index 9c17ee8..e39df5a 100644
--- a/repair/rmap.c
+++ b/repair/rmap.c
@@ -41,6 +41,7 @@ struct xfs_ag_rmap {
 	struct xfs_slab	*ar_raw_rmaps;		/* unmerged rmaps */
 	int		ar_flcount;		/* agfl entries from leftover */
 						/* agbt allocations */
+	struct xfs_rmap_irec	ar_last_rmap;	/* last rmap seen */
 };
 
 static struct xfs_ag_rmap *ag_rmaps;
@@ -118,6 +119,7 @@ _("Insufficient memory while allocating reverse mapping slabs."));
 		if (error)
 			do_error(
 _("Insufficient memory while allocating raw metadata reverse mapping slabs."));
+		ag_rmaps[i].ar_last_rmap.rm_owner = XFS_RMAP_OWN_UNKNOWN;
 	}
 }
 
@@ -177,10 +179,11 @@ add_rmap(
 	int			whichfork,
 	struct xfs_bmbt_irec	*irec)
 {
-	struct xfs_slab		*rmaps;
 	struct xfs_rmap_irec	rmap;
 	xfs_agnumber_t		agno;
 	xfs_agblock_t		agbno;
+	struct xfs_rmap_irec	*last_rmap;
+	int			error = 0;
 
 	if (!needs_rmap_work(mp))
 		return 0;
@@ -193,7 +196,6 @@ add_rmap(
 	ASSERT(ino != NULLFSINO);
 	ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
 
-	rmaps = ag_rmaps[agno].ar_rmaps;
 	rmap.rm_owner = ino;
 	rmap.rm_offset = irec->br_startoff;
 	rmap.rm_flags = 0;
@@ -203,7 +205,31 @@ add_rmap(
 	rmap.rm_blockcount = irec->br_blockcount;
 	if (irec->br_state == XFS_EXT_UNWRITTEN)
 		rmap.rm_flags |= XFS_RMAP_UNWRITTEN;
-	return slab_add(rmaps, &rmap);
+	last_rmap = &ag_rmaps[agno].ar_last_rmap;
+	if (last_rmap->rm_owner == XFS_RMAP_OWN_UNKNOWN)
+		*last_rmap = rmap;
+	else if (mergeable_rmaps(last_rmap, &rmap))
+		last_rmap->rm_blockcount += rmap.rm_blockcount;
+	else {
+		error = slab_add(ag_rmaps[agno].ar_rmaps, last_rmap);
+		if (error)
+			return error;
+		*last_rmap = rmap;
+	}
+
+	return error;
+}
+
+/* Finish collecting inode data/attr fork rmaps. */
+int
+finish_collecting_fork_rmaps(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		agno)
+{
+	if (!needs_rmap_work(mp) ||
+	    ag_rmaps[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);
 }
 
 /* add a raw rmap; these will be merged later */
diff --git a/repair/rmap.h b/repair/rmap.h
index 4722266..69215e8 100644
--- a/repair/rmap.h
+++ b/repair/rmap.h
@@ -28,6 +28,8 @@ extern void init_rmaps(struct xfs_mount *);
 extern void free_rmaps(struct xfs_mount *);
 
 extern int add_rmap(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *);
+extern int finish_collecting_fork_rmaps(struct xfs_mount *mp,
+		xfs_agnumber_t agno);
 extern int add_ag_rmap(struct xfs_mount *, xfs_agnumber_t agno,
 		xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner);
 extern int add_bmbt_rmap(struct xfs_mount *, xfs_ino_t, int, xfs_fsblock_t);

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs



[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux