]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
repair: factor out threading setup code
authorDave Chinner <dchinner@redhat.com>
Mon, 3 Mar 2014 01:18:25 +0000 (12:18 +1100)
committerDave Chinner <david@fromorbit.com>
Mon, 3 Mar 2014 01:18:25 +0000 (12:18 +1100)
The same code is repeated in different places to set up
multithreaded prefetching. This can all be factored into a single
implementation.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
repair/dinode.h
repair/phase3.c
repair/phase4.c
repair/phase6.c
repair/prefetch.c
repair/prefetch.h

index 7521521172716d0c57fef91b1964bdcc1b3d2d60..5ee51ca49d0aa10825ceb750fd8cdd3d5d3938a9 100644 (file)
@@ -18,9 +18,8 @@
 #ifndef _XR_DINODE_H
 #define _XR_DINODE_H
 
-#include "prefetch.h"
-
 struct blkmap;
+struct prefetch_args;
 
 int
 verify_agbno(xfs_mount_t       *mp,
@@ -103,12 +102,12 @@ int
 process_uncertain_aginodes(xfs_mount_t         *mp,
                                xfs_agnumber_t  agno);
 void
-process_aginodes(xfs_mount_t   *mp,
-               prefetch_args_t *pf_args,
-               xfs_agnumber_t  agno,
-               int             check_dirs,
-               int             check_dups,
-               int             extra_attr_check);
+process_aginodes(xfs_mount_t           *mp,
+               struct prefetch_args    *pf_args,
+               xfs_agnumber_t          agno,
+               int                     check_dirs,
+               int                     check_dups,
+               int                     extra_attr_check);
 
 void
 check_uncertain_aginodes(xfs_mount_t   *mp,
index 3e439384768233e8f0efb9c35084489a9300ace1..213d368447ae368c86812fe2de94fc8a9a46c903 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <libxfs.h>
+#include "threads.h"
+#include "prefetch.h"
 #include "avl.h"
 #include "globals.h"
 #include "agheader.h"
@@ -24,9 +26,7 @@
 #include "protos.h"
 #include "err_protos.h"
 #include "dinode.h"
-#include "threads.h"
 #include "progress.h"
-#include "prefetch.h"
 
 static void
 process_agi_unlinked(
@@ -82,41 +82,7 @@ static void
 process_ags(
        xfs_mount_t             *mp)
 {
-       int                     i, j;
-       xfs_agnumber_t          agno;
-       work_queue_t            *queues;
-       prefetch_args_t         *pf_args[2];
-
-       queues = malloc(thread_count * sizeof(work_queue_t));
-
-       if (ag_stride) {
-               /*
-                * create one worker thread for each segment of the volume
-                */
-               for (i = 0, agno = 0; i < thread_count; i++) {
-                       create_work_queue(&queues[i], mp, 1);
-                       pf_args[0] = NULL;
-                       for (j = 0; j < ag_stride && agno < mp->m_sb.sb_agcount;
-                                       j++, agno++) {
-                               pf_args[0] = start_inode_prefetch(agno, 0, pf_args[0]);
-                               queue_work(&queues[i], process_ag_func, agno, pf_args[0]);
-                       }
-               }
-               /*
-                * wait for workers to complete
-                */
-               for (i = 0; i < thread_count; i++)
-                       destroy_work_queue(&queues[i]);
-       } else {
-               queues[0].mp = mp;
-               pf_args[0] = start_inode_prefetch(0, 0, NULL);
-               for (i = 0; i < mp->m_sb.sb_agcount; i++) {
-                       pf_args[(~i) & 1] = start_inode_prefetch(i + 1, 0,
-                                       pf_args[i & 1]);
-                       process_ag_func(&queues[0], i, pf_args[i & 1]);
-               }
-       }
-       free(queues);
+       do_inode_prefetch(mp, ag_stride, process_ag_func, false, false);
 }
 
 void
index a822aaab3bd96ed0df95449146c2cb4b0bebcc92..189eeb93ad66fd9b1ff5e0e9d1baa5e8a7cbac41 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <libxfs.h>
+#include "threads.h"
+#include "prefetch.h"
 #include "avl.h"
 #include "globals.h"
 #include "agheader.h"
@@ -27,9 +29,7 @@
 #include "bmap.h"
 #include "versions.h"
 #include "dir2.h"
-#include "threads.h"
 #include "progress.h"
-#include "prefetch.h"
 
 
 /*
@@ -150,49 +150,7 @@ static void
 process_ags(
        xfs_mount_t             *mp)
 {
-       int                     i, j;
-       xfs_agnumber_t          agno;
-       work_queue_t            *queues;
-       prefetch_args_t         *pf_args[2];
-
-       queues = malloc(thread_count * sizeof(work_queue_t));
-
-       if (!libxfs_bcache_overflowed()) {
-               queues[0].mp = mp;
-               create_work_queue(&queues[0], mp, libxfs_nproc());
-               for (i = 0; i < mp->m_sb.sb_agcount; i++)
-                       queue_work(&queues[0], process_ag_func, i, NULL);
-               destroy_work_queue(&queues[0]);
-       } else {
-               if (ag_stride) {
-                       /*
-                        * create one worker thread for each segment of the volume
-                        */
-                       for (i = 0, agno = 0; i < thread_count; i++) {
-                               create_work_queue(&queues[i], mp, 1);
-                               pf_args[0] = NULL;
-                               for (j = 0; j < ag_stride && agno < mp->m_sb.sb_agcount;
-                                               j++, agno++) {
-                                       pf_args[0] = start_inode_prefetch(agno, 0, pf_args[0]);
-                                       queue_work(&queues[i], process_ag_func, agno, pf_args[0]);
-                               }
-                       }
-                       /*
-                        * wait for workers to complete
-                        */
-                       for (i = 0; i < thread_count; i++)
-                               destroy_work_queue(&queues[i]);
-               } else {
-                       queues[0].mp = mp;
-                       pf_args[0] = start_inode_prefetch(0, 0, NULL);
-                       for (i = 0; i < mp->m_sb.sb_agcount; i++) {
-                               pf_args[(~i) & 1] = start_inode_prefetch(i + 1,
-                                               0, pf_args[i & 1]);
-                               process_ag_func(&queues[0], i, pf_args[i & 1]);
-                       }
-               }
-       }
-       free(queues);
+       do_inode_prefetch(mp, ag_stride, process_ag_func, true, false);
 }
 
 
index 63359d1c010ac0b8ac3fe71a5a36d2254913a16c..446f3ee45e5a36d50db87cf88ec048e86bf4587a 100644 (file)
@@ -17,6 +17,8 @@
  */
 
 #include <libxfs.h>
+#include "threads.h"
+#include "prefetch.h"
 #include "avl.h"
 #include "globals.h"
 #include "agheader.h"
@@ -25,9 +27,7 @@
 #include "protos.h"
 #include "err_protos.h"
 #include "dinode.h"
-#include "prefetch.h"
 #include "progress.h"
-#include "threads.h"
 #include "versions.h"
 
 static struct cred             zerocr;
@@ -3039,23 +3039,9 @@ update_missing_dotdot_entries(
 
 static void
 traverse_ags(
-       xfs_mount_t             *mp)
+       struct xfs_mount        *mp)
 {
-       int                     i;
-       work_queue_t            queue;
-       prefetch_args_t         *pf_args[2];
-
-       /*
-        * we always do prefetch for phase 6 as it will fill in the gaps
-        * not read during phase 3 prefetch.
-        */
-       queue.mp = mp;
-       pf_args[0] = start_inode_prefetch(0, 1, NULL);
-       for (i = 0; i < glob_agcount; i++) {
-               pf_args[(~i) & 1] = start_inode_prefetch(i + 1, 1,
-                               pf_args[i & 1]);
-               traverse_function(&queue, i, pf_args[i & 1]);
-       }
+       do_inode_prefetch(mp, 0, traverse_function, false, true);
 }
 
 void
index 946e822b5ee77094821ae5bb26cb5652d89f31e0..aee6342d51d22da13d0137875a24e82029909e5b 100644 (file)
@@ -866,6 +866,77 @@ start_inode_prefetch(
        return args;
 }
 
+/*
+ * Do inode prefetch in the most optimal way for the context under which repair
+ * has been run.
+ */
+void
+do_inode_prefetch(
+       struct xfs_mount        *mp,
+       int                     stride,
+       void                    (*func)(struct work_queue *,
+                                       xfs_agnumber_t, void *),
+       bool                    check_cache,
+       bool                    dirs_only)
+{
+       int                     i, j;
+       xfs_agnumber_t          agno;
+       struct work_queue       queue;
+       struct work_queue       *queues;
+       struct prefetch_args    *pf_args[2];
+
+       /*
+        * If the previous phases of repair have not overflowed the buffer
+        * cache, then we don't need to re-read any of the metadata in the
+        * filesystem - it's all in the cache. In that case, run a thread per
+        * CPU to maximise parallelism of the queue to be processed.
+        */
+       if (check_cache && !libxfs_bcache_overflowed()) {
+               queue.mp = mp;
+               create_work_queue(&queue, mp, libxfs_nproc());
+               for (i = 0; i < mp->m_sb.sb_agcount; i++)
+                       queue_work(&queue, func, i, NULL);
+               destroy_work_queue(&queue);
+               return;
+       }
+
+       /*
+        * single threaded behaviour - single prefetch thread, processed
+        * directly after each AG is queued.
+        */
+       if (!stride) {
+               queue.mp = mp;
+               pf_args[0] = start_inode_prefetch(0, dirs_only, NULL);
+               for (i = 0; i < mp->m_sb.sb_agcount; i++) {
+                       pf_args[(~i) & 1] = start_inode_prefetch(i + 1,
+                                       dirs_only, pf_args[i & 1]);
+                       func(&queue, i, pf_args[i & 1]);
+               }
+               return;
+       }
+
+       /*
+        * create one worker thread for each segment of the volume
+        */
+       queues = malloc(thread_count * sizeof(work_queue_t));
+       for (i = 0, agno = 0; i < thread_count; i++) {
+               create_work_queue(&queues[i], mp, 1);
+               pf_args[0] = NULL;
+               for (j = 0; j < stride && agno < mp->m_sb.sb_agcount;
+                               j++, agno++) {
+                       pf_args[0] = start_inode_prefetch(agno, dirs_only,
+                                                         pf_args[0]);
+                       queue_work(&queues[i], func, agno, pf_args[0]);
+               }
+       }
+       /*
+        * wait for workers to complete
+        */
+       for (i = 0; i < thread_count; i++)
+               destroy_work_queue(&queues[i]);
+       free(queues);
+}
+
 void
 wait_for_inode_prefetch(
        prefetch_args_t         *args)
index 44a406c0198bcb893717d11666537501b5df7071..b837752607d417b8b87150c671e7edc42e303c9b 100644 (file)
@@ -4,6 +4,7 @@
 #include <semaphore.h>
 #include "incore.h"
 
+struct work_queue;
 
 extern int     do_prefetch;
 
@@ -40,6 +41,15 @@ start_inode_prefetch(
        int                     dirs_only,
        prefetch_args_t         *prev_args);
 
+void
+do_inode_prefetch(
+       struct xfs_mount        *mp,
+       int                     stride,
+       void                    (*func)(struct work_queue *,
+                                       xfs_agnumber_t, void *),
+       bool                    check_cache,
+       bool                    dirs_only);
+
 void
 wait_for_inode_prefetch(
        prefetch_args_t         *args);