summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_unlink_recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_unlink_recover.c')
-rw-r--r--fs/xfs/xfs_unlink_recover.c47
1 files changed, 41 insertions, 6 deletions
diff --git a/fs/xfs/xfs_unlink_recover.c b/fs/xfs/xfs_unlink_recover.c
index 4ce39ae6a424..7635a9e9f03f 100644
--- a/fs/xfs/xfs_unlink_recover.c
+++ b/fs/xfs/xfs_unlink_recover.c
@@ -21,6 +21,7 @@
#include "xfs_trans_priv.h"
#include "xfs_ialloc.h"
#include "xfs_icache.h"
+#include "xfs_pwork.h"
/*
* This routine performs a transaction to null out a bad inode pointer
@@ -194,20 +195,54 @@ xlog_recover_process_ag_iunlinked(
return 0;
}
+struct xlog_recover_unlinked {
+ struct xfs_pwork pwork;
+ xfs_agnumber_t agno;
+};
+
+static int
+xlog_recover_process_unlinked_ag(
+ struct xfs_mount *mp,
+ struct xfs_pwork *pwork)
+{
+ struct xlog_recover_unlinked *ru;
+ int error = 0;
+
+ ru = container_of(pwork, struct xlog_recover_unlinked, pwork);
+ if (xfs_pwork_want_abort(pwork))
+ goto out;
+
+ error = xlog_recover_process_ag_iunlinked(mp, ru->agno);
+out:
+ kmem_free(ru);
+ return error;
+}
+
int
xlog_recover_process_unlinked(
struct xlog *log)
{
struct xfs_mount *mp = log->l_mp;
+ struct xfs_pwork_ctl pctl;
+ struct xlog_recover_unlinked *ru;
+ unsigned int nr_threads;
xfs_agnumber_t agno;
- int error = 0;
- int err2;
+ int error;
+
+ nr_threads = xfs_pwork_guess_datadev_parallelism(mp);
+ error = xfs_pwork_init(mp, &pctl, xlog_recover_process_unlinked_ag,
+ "xlog_recover", nr_threads);
+ if (error)
+ return error;
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
- err2 = xlog_recover_process_ag_iunlinked(mp, agno);
- if (!error && err2)
- error = err2;
+ if (xfs_pwork_ctl_want_abort(&pctl))
+ break;
+
+ ru = kmem_zalloc(sizeof(struct xlog_recover_unlinked), 0);
+ ru->agno = agno;
+ xfs_pwork_queue(&pctl, &ru->pwork);
}
- return error;
+ return xfs_pwork_destroy(&pctl);
}