xfs: streamline xfs_filestream_pick_ag

Directly return the error from xfs_bmap_longest_free_extent instead
of breaking from the loop and handling it there, and use a done
label to directly jump to the exist when we found a suitable perag
structure to reduce the indentation level and pag/max_pag check
complexity in the tail of the function.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
Christoph Hellwig 2024-10-23 15:37:23 +02:00 committed by Carlos Maiolino
parent dc60992ce7
commit 81a1e1c32e

View File

@ -67,22 +67,28 @@ xfs_filestream_pick_ag(
xfs_extlen_t minfree, maxfree = 0;
xfs_agnumber_t agno;
bool first_pass = true;
int err;
/* 2% of an AG's blocks must be free for it to be chosen. */
minfree = mp->m_sb.sb_agblocks / 50;
restart:
for_each_perag_wrap(mp, start_agno, agno, pag) {
int err;
trace_xfs_filestream_scan(pag, pino);
*longest = 0;
err = xfs_bmap_longest_free_extent(pag, NULL, longest);
if (err) {
if (err != -EAGAIN)
break;
/* Couldn't lock the AGF, skip this AG. */
err = 0;
continue;
if (err == -EAGAIN) {
/* Couldn't lock the AGF, skip this AG. */
err = 0;
continue;
}
xfs_perag_rele(pag);
if (max_pag)
xfs_perag_rele(max_pag);
return err;
}
/* Keep track of the AG with the most free blocks. */
@ -107,7 +113,9 @@ restart:
!(flags & XFS_PICK_USERDATA) ||
(flags & XFS_PICK_LOWSPACE))) {
/* Break out, retaining the reference on the AG. */
break;
if (max_pag)
xfs_perag_rele(max_pag);
goto done;
}
}
@ -115,56 +123,44 @@ restart:
atomic_dec(&pag->pagf_fstrms);
}
if (err) {
xfs_perag_rele(pag);
if (max_pag)
xfs_perag_rele(max_pag);
return err;
/*
* Allow a second pass to give xfs_bmap_longest_free_extent() another
* attempt at locking AGFs that it might have skipped over before we
* fail.
*/
if (first_pass) {
first_pass = false;
goto restart;
}
if (!pag) {
/*
* Allow a second pass to give xfs_bmap_longest_free_extent()
* another attempt at locking AGFs that it might have skipped
* over before we fail.
*/
if (first_pass) {
first_pass = false;
goto restart;
}
/*
* We must be low on data space, so run a final lowspace
* optimised selection pass if we haven't already.
*/
if (!(flags & XFS_PICK_LOWSPACE)) {
flags |= XFS_PICK_LOWSPACE;
goto restart;
}
/*
* No unassociated AGs are available, so select the AG with the
* most free space, regardless of whether it's already in use by
* another filestream. It none suit, just use whatever AG we can
* grab.
*/
if (!max_pag) {
for_each_perag_wrap(args->mp, 0, start_agno, pag) {
max_pag = pag;
break;
}
/* Bail if there are no AGs at all to select from. */
if (!max_pag)
return -ENOSPC;
}
pag = max_pag;
atomic_inc(&pag->pagf_fstrms);
} else if (max_pag) {
xfs_perag_rele(max_pag);
/*
* We must be low on data space, so run a final lowspace optimised
* selection pass if we haven't already.
*/
if (!(flags & XFS_PICK_LOWSPACE)) {
flags |= XFS_PICK_LOWSPACE;
goto restart;
}
/*
* No unassociated AGs are available, so select the AG with the most
* free space, regardless of whether it's already in use by another
* filestream. It none suit, just use whatever AG we can grab.
*/
if (!max_pag) {
for_each_perag_wrap(args->mp, 0, start_agno, pag) {
max_pag = pag;
break;
}
/* Bail if there are no AGs at all to select from. */
if (!max_pag)
return -ENOSPC;
}
pag = max_pag;
atomic_inc(&pag->pagf_fstrms);
done:
trace_xfs_filestream_pick(pag, pino);
args->pag = pag;
return 0;