]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
repair: parallelise uncertin inode processing in phase 3
authorDave Chinner <dchinner@redhat.com>
Tue, 9 Feb 2016 00:12:45 +0000 (11:12 +1100)
committerDave Chinner <david@fromorbit.com>
Tue, 9 Feb 2016 00:12:45 +0000 (11:12 +1100)
This can take a long time when there are millions of uncertain inodes in badly
broken filesystems. THe processing is per-ag, the data structures are all
per-ag, and the load is mostly CPU time spent checking CRCs on each
uncertaini inode. Parallelising reduced the runtime of this phase on a badly
broken filesytem from ~30 minutes to under 5 miniutes.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
repair/phase3.c
repair/protos.h
repair/xfs_repair.c

index 76c9440367fd47f59c3c5cb1e56dacac9a38dbbc..0890a27d22dc91d3d961d162a5454313c4e7fd5c 100644 (file)
@@ -28,6 +28,7 @@
 #include "dinode.h"
 #include "progress.h"
 #include "bmap.h"
+#include "threads.h"
 
 static void
 process_agi_unlinked(
@@ -87,10 +88,33 @@ process_ags(
        do_inode_prefetch(mp, ag_stride, process_ag_func, false, false);
 }
 
+static void
+do_uncertain_aginodes(
+       work_queue_t    *wq,
+       xfs_agnumber_t  agno,
+       void            *arg)
+{
+       int             *count = arg;
+
+       *count = process_uncertain_aginodes(wq->mp, agno);
+
+#ifdef XR_INODE_TRACE
+       fprintf(stderr,
+               "\t\t phase 3 - ag %d process_uncertain_inodes returns %d\n",
+               *count, j);
+#endif
+
+       PROG_RPT_INC(prog_rpt_done[agno], 1);
+}
+
 void
-phase3(xfs_mount_t *mp)
+phase3(
+       struct xfs_mount *mp,
+       int             scan_threads)
 {
-       int                     i, j;
+       int                     i, j;
+       int                     *counts;
+       work_queue_t            wq;
 
        do_log(_("Phase 3 - for each AG...\n"));
        if (!no_modify)
@@ -129,20 +153,35 @@ phase3(xfs_mount_t *mp)
         */
        do_log(_("        - process newly discovered inodes...\n"));
        set_progress_msg(PROG_FMT_NEW_INODES, (__uint64_t) glob_agcount);
+
+       counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount);
+       if (!counts) {
+               do_abort(_("no memory for uncertain inode counts\n"));
+               return;
+       }
+
        do  {
                /*
                 * have to loop until no ag has any uncertain
                 * inodes
                 */
                j = 0;
-               for (i = 0; i < mp->m_sb.sb_agcount; i++)  {
-                       j += process_uncertain_aginodes(mp, i);
-#ifdef XR_INODE_TRACE
-                       fprintf(stderr,
-                               "\t\t phase 3 - process_uncertain_inodes returns %d\n", j);
-#endif
-                       PROG_RPT_INC(prog_rpt_done[i], 1);
-               }
+               memset(counts, 0, mp->m_sb.sb_agcount * sizeof(*counts));
+
+               create_work_queue(&wq, mp, scan_threads);
+
+               for (i = 0; i < mp->m_sb.sb_agcount; i++)
+                       queue_work(&wq, do_uncertain_aginodes, i, &counts[i]);
+
+               destroy_work_queue(&wq);
+
+               /* tally up the counts */
+               for (i = 0; i < mp->m_sb.sb_agcount; i++)
+                       j += counts[i];
+
        } while (j != 0);
+
+       free(counts);
+
        print_final_rpt();
 }
index b113aca5db62d6114e8d2f08396169c33dae43cc..0290420b9b7363b20d006a4e450327bcaeb1de0c 100644 (file)
@@ -46,7 +46,7 @@ void  thread_init(void);
 
 void   phase1(struct xfs_mount *);
 void   phase2(struct xfs_mount *, int);
-void   phase3(struct xfs_mount *);
+void   phase3(struct xfs_mount *, int);
 void   phase4(struct xfs_mount *);
 void   phase5(struct xfs_mount *);
 void   phase6(struct xfs_mount *);
index fcdb212f279cc4d0426f532948e2844606fac4b8..5d5f3aa855045370edb1d9706db1553bc441baf9 100644 (file)
@@ -871,7 +871,7 @@ main(int argc, char **argv)
        if (do_prefetch)
                init_prefetch(mp);
 
-       phase3(mp);
+       phase3(mp, phase2_threads);
        timestamp(PHASE_END, 3, NULL);
 
        phase4(mp);