summaryrefslogtreecommitdiff
path: root/fs/xfs/libxfs/xfs_alloc.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2023-02-13 09:14:54 +1100
committerDave Chinner <dchinner@redhat.com>2023-02-13 09:14:54 +1100
commit5f36b2ce79f254dd00cdc88374271df7ce843d56 (patch)
treeaf462c68a7e91f992134c5b861f8215c28c0659e /fs/xfs/libxfs/xfs_alloc.c
parentdb4710fd12248e5d4c3842520cd13f034136576b (diff)
xfs: introduce xfs_alloc_vextent_exact_bno()
Two of the callers to xfs_alloc_vextent_this_ag() actually want exact block number allocation, not anywhere-in-ag allocation. Split this out from _this_ag() as a first class citizen so no external extent allocation code needs to care about args->type anymore. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs/xfs/libxfs/xfs_alloc.c')
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c63
1 files changed, 54 insertions, 9 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 85e3b65286ac..5093fa856f35 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -3272,28 +3272,34 @@ xfs_alloc_vextent_set_fsbno(
*/
int
xfs_alloc_vextent_this_ag(
- struct xfs_alloc_arg *args)
+ struct xfs_alloc_arg *args,
+ xfs_agnumber_t agno)
{
struct xfs_mount *mp = args->mp;
xfs_agnumber_t minimum_agno = 0;
+ xfs_rfsblock_t target = XFS_AGB_TO_FSB(mp, agno, 0);
int error;
if (args->tp->t_highest_agno != NULLAGNUMBER)
minimum_agno = args->tp->t_highest_agno;
- error = xfs_alloc_vextent_check_args(args, args->fsbno);
+ if (minimum_agno > agno) {
+ trace_xfs_alloc_vextent_skip_deadlock(args);
+ args->fsbno = NULLFSBLOCK;
+ return 0;
+ }
+
+ error = xfs_alloc_vextent_check_args(args, target);
if (error) {
if (error == -ENOSPC)
return 0;
return error;
}
- args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
- if (minimum_agno > args->agno) {
- trace_xfs_alloc_vextent_skip_deadlock(args);
- args->fsbno = NULLFSBLOCK;
- return 0;
- }
+ args->agno = agno;
+ args->agbno = 0;
+ args->fsbno = target;
+ args->type = XFS_ALLOCTYPE_THIS_AG;
error = xfs_alloc_ag_vextent(args);
xfs_alloc_vextent_set_fsbno(args, minimum_agno);
@@ -3472,13 +3478,52 @@ xfs_alloc_vextent_first_ag(
start_agno = max(minimum_agno, XFS_FSB_TO_AGNO(mp, target));
args->type = XFS_ALLOCTYPE_THIS_AG;
args->fsbno = target;
- error = xfs_alloc_vextent_iterate_ags(args, minimum_agno,
+ error = xfs_alloc_vextent_iterate_ags(args, minimum_agno,
start_agno, 0);
xfs_alloc_vextent_set_fsbno(args, minimum_agno);
return error;
}
/*
+ * Allocate within a single AG only.
+ */
+int
+xfs_alloc_vextent_exact_bno(
+ struct xfs_alloc_arg *args,
+ xfs_fsblock_t target)
+{
+ struct xfs_mount *mp = args->mp;
+ xfs_agnumber_t minimum_agno = 0;
+ int error;
+
+ if (args->tp->t_highest_agno != NULLAGNUMBER)
+ minimum_agno = args->tp->t_highest_agno;
+
+ error = xfs_alloc_vextent_check_args(args, target);
+ if (error) {
+ if (error == -ENOSPC)
+ return 0;
+ return error;
+ }
+
+ args->agno = XFS_FSB_TO_AGNO(mp, target);
+ if (minimum_agno > args->agno) {
+ trace_xfs_alloc_vextent_skip_deadlock(args);
+ return 0;
+ }
+
+ args->agbno = XFS_FSB_TO_AGBNO(mp, target);
+ args->fsbno = target;
+ args->type = XFS_ALLOCTYPE_THIS_BNO;
+ error = xfs_alloc_ag_vextent(args);
+ if (error)
+ return error;
+
+ xfs_alloc_vextent_set_fsbno(args, minimum_agno);
+ return 0;
+}
+
+/*
* Allocate an extent as close to the target as possible. If there are not
* viable candidates in the AG, then fail the allocation.
*/