]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: merge data & attr fork reverse mappings
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 19 Aug 2016 00:52:06 +0000 (10:52 +1000)
committerDave Chinner <david@fromorbit.com>
Fri, 19 Aug 2016 00:52:06 +0000 (10:52 +1000)
Merge data and attribute fork reverse mappings.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
repair/phase4.c
repair/rmap.c
repair/rmap.h

index e234d9283e55909dca8f069b03c330e26be6fe38..3be3786b96fb1345e4a7c016d529b8e144e1136a 100644 (file)
@@ -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
index 128e07741fb4829d2c914b919d26daa75bc9b963..f22f4f0662275b70e4fee90ed8828daddfd8e500 100644 (file)
@@ -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 */
index 4722266d7e9aa51f8120cb4fb16959bc159342ea..69215e889e9f8d6cc759b7f6c8d4aad446d8aed3 100644 (file)
@@ -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);