diff options
Diffstat (limited to 'fs/xfs/xfs_unlink_recover.c')
-rw-r--r-- | fs/xfs/xfs_unlink_recover.c | 47 |
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); } |