From: Dave Chinner <dchinner@xxxxxxxxxx> 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@xxxxxxxxxx> --- repair/dinode.h | 15 ++++++------ repair/phase3.c | 40 +++---------------------------- repair/phase4.c | 48 +++---------------------------------- repair/phase6.c | 22 ++++------------- repair/prefetch.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/prefetch.h | 10 ++++++++ 6 files changed, 98 insertions(+), 108 deletions(-) diff --git a/repair/dinode.h b/repair/dinode.h index 7521521..5ee51ca 100644 --- a/repair/dinode.h +++ b/repair/dinode.h @@ -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, diff --git a/repair/phase3.c b/repair/phase3.c index 3e43938..213d368 100644 --- a/repair/phase3.c +++ b/repair/phase3.c @@ -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 diff --git a/repair/phase4.c b/repair/phase4.c index a822aaa..189eeb9 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -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); } diff --git a/repair/phase6.c b/repair/phase6.c index cdbf4db..08f78d2 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -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; @@ -3031,23 +3031,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, true, true); } void diff --git a/repair/prefetch.c b/repair/prefetch.c index 984beda..e573e35 100644 --- a/repair/prefetch.c +++ b/repair/prefetch.c @@ -865,6 +865,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) diff --git a/repair/prefetch.h b/repair/prefetch.h index 44a406c..b837752 100644 --- a/repair/prefetch.h +++ b/repair/prefetch.h @@ -4,6 +4,7 @@ #include <semaphore.h> #include "incore.h" +struct work_queue; extern int do_prefetch; @@ -41,6 +42,15 @@ start_inode_prefetch( 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); -- 1.8.4.rc3 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs