diff options
author | Darrick J. Wong <djwong@kernel.org> | 2021-03-18 16:37:13 -0700 |
---|---|---|
committer | Darrick J. Wong <djwong@kernel.org> | 2021-03-25 17:08:55 -0700 |
commit | 2f0ea3b2feee76a1928996f05aba85e7689b6ace (patch) | |
tree | f1028977d201ba70a304e5aadec9e683f5efbf94 | |
parent | c55285a74e5daf0b95dda6f3881e54076521d477 (diff) |
xfs: parallelise the work we do to make the fs writablefaster-mount_2021-03-25
Parallelise all the work that we do at mount time to prepare the
filesystem to accept write requests.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
-rw-r--r-- | fs/xfs/xfs_fsops.c | 79 | ||||
-rw-r--r-- | fs/xfs/xfs_reflink.c | 24 | ||||
-rw-r--r-- | fs/xfs/xfs_reflink.h | 1 |
3 files changed, 73 insertions, 31 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 83c8258e468e..b4087b0117c6 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -22,7 +22,8 @@ #include "xfs_inode.h" #include "xfs_icache.h" #include "xfs_rtalloc.h" -#include "xfs_reflink.h" +#include "xfs_refcount.h" +#include "xfs_pwork.h" /* * growfs operations @@ -556,21 +557,87 @@ xfs_fs_reserve_ag_blocks( return error; } +struct xfs_make_writable { + struct xfs_pwork pwork; + xfs_agnumber_t agno; +}; + +static int +xfs_fs_make_ag_writable( + struct xfs_mount *mp, + struct xfs_pwork *pwork) +{ + struct xfs_make_writable *mw; + struct xfs_perag *pag; + int error; + + mw = container_of(pwork, struct xfs_make_writable, pwork); + + if (xfs_pwork_want_abort(pwork)) + goto out; + + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + error = xfs_refcount_recover_cow_leftovers(mp, mw->agno); + if (error) { + xfs_warn(mp, + "Error %d recovering AG %u leftover CoW staging.", error, mw->agno); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); + goto out; + } + } + + if (mw->agno == NULLAGNUMBER) { + error = xfs_rt_resv_init(mp, NULL); + } else { + pag = xfs_perag_get(mp, mw->agno); + error = xfs_ag_resv_init(pag, NULL); + xfs_perag_put(pag); + } + + if (error == -ENOSPC) + error = 0; + if (error) { + xfs_warn(mp, + "Error %d reserving AG %u metadata reserve pool.", error, mw->agno); + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); + } + +out: + kmem_free(mw); + return error; +} + /* Do all the work required to make the filesystem writable. */ int xfs_fs_make_writable( struct xfs_mount *mp) { + struct xfs_pwork_ctl pctl; + struct xfs_make_writable *mw; + xfs_agnumber_t agno; int error; - error = xfs_reflink_recover_cow(mp); + error = xfs_pwork_init(mp, &pctl, xfs_fs_make_ag_writable, + "xfs-mount-rw"); if (error) return error; - error = xfs_fs_reserve_ag_blocks(mp); - if (error == -ENOSPC) - return 0; - return error; + if (xfs_sb_version_hasrealtime(&mp->m_sb)) { + mw = kmem_zalloc(sizeof(struct xfs_make_writable), 0); + mw->agno = NULLAGNUMBER; + xfs_pwork_queue(&pctl, &mw->pwork); + } + + for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + if (xfs_pwork_ctl_want_abort(&pctl)) + break; + + mw = kmem_zalloc(sizeof(struct xfs_make_writable), 0); + mw->agno = agno; + xfs_pwork_queue(&pctl, &mw->pwork); + } + + return xfs_pwork_destroy(&pctl); } /* diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index a30bab84783f..8108499c0c1b 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -831,30 +831,6 @@ xfs_reflink_end_cow( } /* - * Free leftover CoW reservations that didn't get cleaned out. - */ -int -xfs_reflink_recover_cow( - struct xfs_mount *mp) -{ - xfs_agnumber_t agno; - int error = 0; - - if (!xfs_sb_version_hasreflink(&mp->m_sb)) - return 0; - - for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { - error = xfs_refcount_recover_cow_leftovers(mp, agno); - if (error) - return error; - } - - if (xfs_sb_version_hasrealtime(&mp->m_sb)) - return xfs_refcount_recover_cow_leftovers(mp, NULLAGNUMBER); - return 0; -} - -/* * Reflinking (Block) Ranges of Two Files Together * * First, ensure that the reflink flag is set on both inodes. The flag is an diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 666d7e2413b0..c8f0c17392e1 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -24,7 +24,6 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t count, bool cancel_real); extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t count); -extern int xfs_reflink_recover_cow(struct xfs_mount *mp); extern loff_t xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t len, unsigned int remap_flags); |