[PATCH 06/38] xfs: factor xfs_blockgc_start_flush() from xfs_blockgc_flush_all()
Dave Chinner <[email protected]>
| Newsgroups | org.kernel.vger.linux-xfs |
|---|---|
| Message-ID | <[email protected]> |
Factor xfs_blockgc_start_flush() out of xfs_blockgc_flush_all() to provide an async variant that kicks the per-AG background blockgc workers without waiting for them to complete. xfs_blockgc_flush_all() uses synchronous flush_delayed_work() calls to wait for the blockgc workers and inodegc to finish. This cannot be used from contexts that hold the ILOCK because the blockgc workers need to take the ILOCK to scan inodes for reclaimable speculative preallocations, and the inode we hold the ILOCK on pins journal space that the workers need to run transactions. Signed-off-by: Dave Chinner <[email protected]> --- fs/xfs/xfs_icache.c | 27 +++++++++++++++++++-------- fs/xfs/xfs_icache.h | 1 + 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 9d8dd30bd927..bad09cb090cc 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -1596,23 +1596,34 @@ xfs_blockgc_free_space( } /* - * Reclaim all the free space that we can by scheduling the background blockgc - * and inodegc workers immediately and waiting for them all to clear. + * Kick all the blockgc workers immediately so they start freeing speculative + * preallocations. This does not wait for the workers to complete, so callers + * that need to wait for space to become available should call + * xfs_blockgc_flush_all() instead. */ -int -xfs_blockgc_flush_all( +void +xfs_blockgc_start_flush( struct xfs_mount *mp) { struct xfs_perag *pag = NULL; trace_xfs_blockgc_flush_all(mp, __return_address); - /* - * For each blockgc worker, move its queue time up to now. If it wasn't - * queued, it will not be requeued. Then flush whatever is left. - */ while ((pag = xfs_perag_grab_next_tag(mp, pag, XFS_ICI_BLOCKGC_TAG))) mod_delayed_work(mp->m_blockgc_wq, &pag->pag_blockgc_work, 0); +} + +/* + * Reclaim all the free space that we can by scheduling the background blockgc + * and inodegc workers immediately and waiting for them all to clear. + */ +int +xfs_blockgc_flush_all( + struct xfs_mount *mp) +{ + struct xfs_perag *pag = NULL; + + xfs_blockgc_start_flush(mp); while ((pag = xfs_perag_grab_next_tag(mp, pag, XFS_ICI_BLOCKGC_TAG))) flush_delayed_work(&pag->pag_blockgc_work); diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 905944dafbe5..e68d13125f7b 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -62,6 +62,7 @@ int xfs_blockgc_free_dquots(struct xfs_mount *mp, struct xfs_dquot *udqp, unsigned int iwalk_flags); int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int iwalk_flags); int xfs_blockgc_free_space(struct xfs_mount *mp, struct xfs_icwalk *icm); +void xfs_blockgc_start_flush(struct xfs_mount *mp); int xfs_blockgc_flush_all(struct xfs_mount *mp); void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip); -- 2.55.0