diff options
author | Dave Chinner <dchinner@redhat.com> | 2023-02-13 09:14:55 +1100 |
---|---|---|
committer | Dave Chinner <dchinner@redhat.com> | 2023-02-13 09:14:55 +1100 |
commit | f38b46bbfa76a854c4c2a27b1617d66fefbb3f80 (patch) | |
tree | 0d0ca98f0ca7c970c772fa30032d8c839d6dffe9 /fs/xfs/xfs_filestream.c | |
parent | 3e43877a9dac13771ac722462c87bea0bdc50759 (diff) | |
download | lwn-f38b46bbfa76a854c4c2a27b1617d66fefbb3f80.tar.gz lwn-f38b46bbfa76a854c4c2a27b1617d66fefbb3f80.zip |
xfs: factor out MRU hit case in xfs_filestream_select_ag
Because it now stands out like a sore thumb. Factoring out this case
starts the process of simplifying xfs_filestream_select_ag() again.
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/xfs_filestream.c')
-rw-r--r-- | fs/xfs/xfs_filestream.c | 133 |
1 files changed, 83 insertions, 50 deletions
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 95e28aae35ab..147296a1079e 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -260,9 +260,84 @@ out: } /* + * Lookup the mru cache for an existing association. If one exists and we can + * use it, return with the agno and blen indicating that the allocation will + * proceed with that association. + * + * If we have no association, or we cannot use the current one and have to + * destroy it, return with blen = 0 and agno pointing at the next agno to try. + */ +int +xfs_filestream_select_ag_mru( + struct xfs_bmalloca *ap, + struct xfs_alloc_arg *args, + struct xfs_inode *pip, + xfs_agnumber_t *agno, + xfs_extlen_t *blen) +{ + struct xfs_mount *mp = ap->ip->i_mount; + struct xfs_perag *pag; + struct xfs_mru_cache_elem *mru; + int error; + + mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino); + if (!mru) + goto out_default_agno; + + *agno = container_of(mru, struct xfs_fstrm_item, mru)->ag; + xfs_mru_cache_done(mp->m_filestream); + + trace_xfs_filestream_lookup(mp, ap->ip->i_ino, *agno); + + ap->blkno = XFS_AGB_TO_FSB(args->mp, *agno, 0); + xfs_bmap_adjacent(ap); + + pag = xfs_perag_grab(mp, *agno); + if (!pag) + goto out_default_agno; + + error = xfs_bmap_longest_free_extent(pag, args->tp, blen); + xfs_perag_rele(pag); + if (error) { + if (error != -EAGAIN) + return error; + *blen = 0; + } + + /* + * We are done if there's still enough contiguous free space to succeed. + */ + if (*blen >= args->maxlen) + return 0; + + /* Changing parent AG association now, so remove the existing one. */ + mru = xfs_mru_cache_remove(mp->m_filestream, pip->i_ino); + if (mru) { + struct xfs_fstrm_item *item = + container_of(mru, struct xfs_fstrm_item, mru); + *agno = (item->ag + 1) % mp->m_sb.sb_agcount; + xfs_fstrm_free_func(mp, mru); + return 0; + } + +out_default_agno: + if (xfs_is_inode32(mp)) { + xfs_agnumber_t rotorstep = xfs_rotorstep; + *agno = (mp->m_agfrotor / rotorstep) % + mp->m_sb.sb_agcount; + mp->m_agfrotor = (mp->m_agfrotor + 1) % + (mp->m_sb.sb_agcount * rotorstep); + return 0; + } + *agno = XFS_INO_TO_AGNO(mp, pip->i_ino); + return 0; + +} + +/* * Search for an allocation group with a single extent large enough for - * the request. If one isn't found, then the largest available free extent is - * returned as the best length possible. + * the request. If one isn't found, then adjust the minimum allocation + * size to the largest space found. */ int xfs_filestream_select_ag( @@ -271,12 +346,10 @@ xfs_filestream_select_ag( xfs_extlen_t *blen) { struct xfs_mount *mp = ap->ip->i_mount; - struct xfs_perag *pag; struct xfs_inode *pip = NULL; - xfs_agnumber_t agno = NULLAGNUMBER; - struct xfs_mru_cache_elem *mru; + xfs_agnumber_t agno; int flags = 0; - int error = 0; + int error; args->total = ap->total; *blen = 0; @@ -287,48 +360,10 @@ xfs_filestream_select_ag( goto out_select; } - mru = xfs_mru_cache_lookup(mp->m_filestream, pip->i_ino); - if (mru) { - agno = container_of(mru, struct xfs_fstrm_item, mru)->ag; - xfs_mru_cache_done(mp->m_filestream); - mru = NULL; - - trace_xfs_filestream_lookup(mp, ap->ip->i_ino, agno); - xfs_irele(pip); - - ap->blkno = XFS_AGB_TO_FSB(args->mp, agno, 0); - xfs_bmap_adjacent(ap); - - pag = xfs_perag_grab(mp, agno); - if (pag) { - error = xfs_bmap_longest_free_extent(pag, args->tp, blen); - xfs_perag_rele(pag); - if (error) { - if (error != -EAGAIN) - goto out_error; - *blen = 0; - } - } - if (*blen >= args->maxlen) - goto out_select; - } else if (xfs_is_inode32(mp)) { - xfs_agnumber_t rotorstep = xfs_rotorstep; - agno = (mp->m_agfrotor / rotorstep) % - mp->m_sb.sb_agcount; - mp->m_agfrotor = (mp->m_agfrotor + 1) % - (mp->m_sb.sb_agcount * rotorstep); - } else { - agno = XFS_INO_TO_AGNO(mp, pip->i_ino); - } + error = xfs_filestream_select_ag_mru(ap, args, pip, &agno, blen); + if (error || *blen >= args->maxlen) + goto out_rele; - /* Changing parent AG association now, so remove the existing one. */ - mru = xfs_mru_cache_remove(mp->m_filestream, pip->i_ino); - if (mru) { - struct xfs_fstrm_item *item = - container_of(mru, struct xfs_fstrm_item, mru); - agno = (item->ag + 1) % mp->m_sb.sb_agcount; - xfs_fstrm_free_func(mp, mru); - } ap->blkno = XFS_AGB_TO_FSB(args->mp, agno, 0); xfs_bmap_adjacent(ap); @@ -347,8 +382,6 @@ xfs_filestream_select_ag( *blen = ap->length; error = xfs_filestream_pick_ag(pip, &agno, flags, blen); - if (error) - goto out_error; if (agno == NULLAGNUMBER) { agno = 0; *blen = 0; @@ -356,7 +389,7 @@ xfs_filestream_select_ag( out_select: ap->blkno = XFS_AGB_TO_FSB(mp, agno, 0); -out_error: +out_rele: xfs_irele(pip); return error; |