#ifndef _XR_DINODE_H
#define _XR_DINODE_H
-#include "prefetch.h"
-
struct blkmap;
+struct prefetch_args;
int
verify_agbno(xfs_mount_t *mp,
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,
*/
#include <libxfs.h>
+#include "threads.h"
+#include "prefetch.h"
#include "avl.h"
#include "globals.h"
#include "agheader.h"
#include "protos.h"
#include "err_protos.h"
#include "dinode.h"
-#include "threads.h"
#include "progress.h"
-#include "prefetch.h"
static void
process_agi_unlinked(
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
*/
#include <libxfs.h>
+#include "threads.h"
+#include "prefetch.h"
#include "avl.h"
#include "globals.h"
#include "agheader.h"
#include "bmap.h"
#include "versions.h"
#include "dir2.h"
-#include "threads.h"
#include "progress.h"
-#include "prefetch.h"
/*
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);
}
*/
#include <libxfs.h>
+#include "threads.h"
+#include "prefetch.h"
#include "avl.h"
#include "globals.h"
#include "agheader.h"
#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;
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
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)
#include <semaphore.h>
#include "incore.h"
+struct work_queue;
extern int do_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);