xfs: use xfs_alloc_vextent_first_ag() where appropriate
authorDave Chinner <dchinner@redhat.com>
Sun, 12 Feb 2023 22:14:53 +0000 (09:14 +1100)
committerDave Chinner <dchinner@redhat.com>
Sun, 12 Feb 2023 22:14:53 +0000 (09:14 +1100)
Change obvious callers of single AG allocation to use
xfs_alloc_vextent_first_ag(). This gets rid of
XFS_ALLOCTYPE_FIRST_AG as the type used within
xfs_alloc_vextent_first_ag() during iteration is _THIS_AG. Hence we
can remove the setting of args->type from all the callers of
_first_ag() and remove the alloctype.

While doing this, pass the allocation target fsb as a parameter
rather than encoding it in args->fsbno. This starts the process
of making args->fsbno an output only variable rather than
input/output.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_alloc.h
fs/xfs/libxfs/xfs_bmap.c

index 7e4452c..bd77e64 100644 (file)
@@ -3183,7 +3183,8 @@ xfs_alloc_read_agf(
  */
 static int
 xfs_alloc_vextent_check_args(
-       struct xfs_alloc_arg    *args)
+       struct xfs_alloc_arg    *args,
+       xfs_fsblock_t           target)
 {
        struct xfs_mount        *mp = args->mp;
        xfs_agblock_t           agsize;
@@ -3201,13 +3202,13 @@ xfs_alloc_vextent_check_args(
                args->maxlen = agsize;
        if (args->alignment == 0)
                args->alignment = 1;
-       ASSERT(XFS_FSB_TO_AGNO(mp, args->fsbno) < mp->m_sb.sb_agcount);
-       ASSERT(XFS_FSB_TO_AGBNO(mp, args->fsbno) < agsize);
+       ASSERT(XFS_FSB_TO_AGNO(mp, target) < mp->m_sb.sb_agcount);
+       ASSERT(XFS_FSB_TO_AGBNO(mp, target) < agsize);
        ASSERT(args->minlen <= args->maxlen);
        ASSERT(args->minlen <= agsize);
        ASSERT(args->mod < args->prod);
-       if (XFS_FSB_TO_AGNO(mp, args->fsbno) >= mp->m_sb.sb_agcount ||
-           XFS_FSB_TO_AGBNO(mp, args->fsbno) >= agsize ||
+       if (XFS_FSB_TO_AGNO(mp, target) >= mp->m_sb.sb_agcount ||
+           XFS_FSB_TO_AGBNO(mp, target) >= agsize ||
            args->minlen > args->maxlen || args->minlen > agsize ||
            args->mod >= args->prod) {
                args->fsbno = NULLFSBLOCK;
@@ -3281,7 +3282,7 @@ xfs_alloc_vextent_this_ag(
        if (args->tp->t_highest_agno != NULLAGNUMBER)
                minimum_agno = args->tp->t_highest_agno;
 
-       error = xfs_alloc_vextent_check_args(args);
+       error = xfs_alloc_vextent_check_args(args, args->fsbno);
        if (error) {
                if (error == -ENOSPC)
                        return 0;
@@ -3406,7 +3407,7 @@ xfs_alloc_vextent_start_ag(
        bool                    bump_rotor = false;
        int                     error;
 
-       error = xfs_alloc_vextent_check_args(args);
+       error = xfs_alloc_vextent_check_args(args, args->fsbno);
        if (error) {
                if (error == -ENOSPC)
                        return 0;
@@ -3444,25 +3445,29 @@ xfs_alloc_vextent_start_ag(
  * filesystem attempting blocking allocation. This does not wrap or try a second
  * pass, so will not recurse into AGs lower than indicated by fsbno.
  */
-static int
+int
 xfs_alloc_vextent_first_ag(
        struct xfs_alloc_arg    *args,
-       xfs_agnumber_t          minimum_agno)
-{
+       xfs_fsblock_t           target)
+ {
        struct xfs_mount        *mp = args->mp;
+       xfs_agnumber_t          minimum_agno = 0;
        xfs_agnumber_t          start_agno;
        int                     error;
 
-       error = xfs_alloc_vextent_check_args(args);
+       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;
        }
 
-       start_agno = max(minimum_agno, XFS_FSB_TO_AGNO(mp, args->fsbno));
-
+       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,
                        start_agno, 0);
        xfs_alloc_vextent_set_fsbno(args, minimum_agno);
@@ -3495,8 +3500,6 @@ xfs_alloc_vextent(
                break;
        case XFS_ALLOCTYPE_START_BNO:
                return xfs_alloc_vextent_start_ag(args, minimum_agno);
-       case XFS_ALLOCTYPE_FIRST_AG:
-               return xfs_alloc_vextent_first_ag(args, minimum_agno);
        default:
                error = -EFSCORRUPTED;
                ASSERT(0);
index 0a9ad6c..9be46f4 100644 (file)
@@ -19,7 +19,6 @@ unsigned int xfs_agfl_size(struct xfs_mount *mp);
 /*
  * Freespace allocation types.  Argument to xfs_alloc_[v]extent.
  */
-#define XFS_ALLOCTYPE_FIRST_AG 0x02    /* ... start at ag 0 */
 #define XFS_ALLOCTYPE_THIS_AG  0x08    /* anywhere in this a.g. */
 #define XFS_ALLOCTYPE_START_BNO        0x10    /* near this block else anywhere */
 #define XFS_ALLOCTYPE_NEAR_BNO 0x20    /* in this a.g. and near this block */
@@ -29,7 +28,6 @@ unsigned int xfs_agfl_size(struct xfs_mount *mp);
 typedef unsigned int xfs_alloctype_t;
 
 #define XFS_ALLOC_TYPES \
-       { XFS_ALLOCTYPE_FIRST_AG,       "FIRST_AG" }, \
        { XFS_ALLOCTYPE_THIS_AG,        "THIS_AG" }, \
        { XFS_ALLOCTYPE_START_BNO,      "START_BNO" }, \
        { XFS_ALLOCTYPE_NEAR_BNO,       "NEAR_BNO" }, \
@@ -131,6 +129,14 @@ xfs_alloc_vextent(
 int xfs_alloc_vextent_this_ag(struct xfs_alloc_arg *args);
 
 /*
+ * Iterate from the AG indicated from args->fsbno through to the end of the
+ * filesystem attempting blocking allocation. This is for use in last
+ * resort allocation attempts when everything else has failed.
+ */
+int xfs_alloc_vextent_first_ag(struct xfs_alloc_arg *args,
+               xfs_fsblock_t target);
+
+/*
  * Free an extent.
  */
 int                            /* error */
index a28d57b..efca40f 100644 (file)
@@ -3248,13 +3248,6 @@ xfs_bmap_btalloc_filestreams(
        int                     notinit = 0;
        int                     error;
 
-       if (ap->tp->t_flags & XFS_TRANS_LOWMODE) {
-               args->type = XFS_ALLOCTYPE_FIRST_AG;
-               args->total = ap->minlen;
-               args->minlen = ap->minlen;
-               return 0;
-       }
-
        args->type = XFS_ALLOCTYPE_NEAR_BNO;
        args->total = ap->total;
 
@@ -3462,9 +3455,7 @@ xfs_bmap_exact_minlen_extent_alloc(
         */
        ap->blkno = XFS_AGB_TO_FSB(mp, 0, 0);
 
-       args.fsbno = ap->blkno;
        args.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE;
-       args.type = XFS_ALLOCTYPE_FIRST_AG;
        args.minlen = args.maxlen = ap->minlen;
        args.total = ap->total;
 
@@ -3476,7 +3467,7 @@ xfs_bmap_exact_minlen_extent_alloc(
        args.resv = XFS_AG_RESV_NONE;
        args.datatype = ap->datatype;
 
-       error = xfs_alloc_vextent(&args);
+       error = xfs_alloc_vextent_first_ag(&args, ap->blkno);
        if (error)
                return error;
 
@@ -3623,10 +3614,21 @@ xfs_bmap_btalloc_best_length(
         * size to the largest space found.
         */
        if ((ap->datatype & XFS_ALLOC_USERDATA) &&
-           xfs_inode_is_filestream(ap->ip))
+           xfs_inode_is_filestream(ap->ip)) {
+               /*
+                * If there is very little free space before we start a
+                * filestreams allocation, we're almost guaranteed to fail to
+                * find an AG with enough contiguous free space to succeed, so
+                * just go straight to the low space algorithm.
+                */
+               if (ap->tp->t_flags & XFS_TRANS_LOWMODE) {
+                       args->minlen = ap->minlen;
+                       goto critically_low_space;
+               }
                error = xfs_bmap_btalloc_filestreams(ap, args, &blen);
-       else
+       } else {
                error = xfs_bmap_btalloc_select_lengths(ap, args, &blen);
+       }
        if (error)
                return error;
 
@@ -3673,10 +3675,9 @@ xfs_bmap_btalloc_best_length(
         * so they don't waste time on allocation modes that are unlikely to
         * succeed.
         */
-       args->fsbno = 0;
-       args->type = XFS_ALLOCTYPE_FIRST_AG;
+critically_low_space:
        args->total = ap->minlen;
-       error = xfs_alloc_vextent(args);
+       error = xfs_alloc_vextent_first_ag(args, 0);
        if (error)
                return error;
        ap->tp->t_flags |= XFS_TRANS_LOWMODE;