]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: rework the rtalloc fallback handling
authorChristoph Hellwig <hch@lst.de>
Fri, 30 Aug 2024 22:37:10 +0000 (15:37 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Sun, 1 Sep 2024 15:58:19 +0000 (08:58 -0700)
xfs_rtallocate currently has two fallbacks, when an allocation fails:

 1) drop the requested extent size alignment, if any, and retry
 2) ignore the locality hint

Oddly enough it does those in order, as trying a different location
is more in line with what the user asked for, and does it in a very
unstructured way.

Lift the fallback to try to allocate without the locality hint into
xfs_rtallocate to both perform them in a more sensible order and to
clean up the code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/xfs_rtalloc.c

index 12cf7cb3c02c1875f067e4492d02105b7476d36f..a6b9ba572cdc872c70af900c65c230690558ed49 100644 (file)
@@ -1271,6 +1271,8 @@ xfs_rtallocate(
        xfs_rtxlen_t            maxlen,
        xfs_rtxlen_t            prod,
        bool                    wasdel,
+       bool                    initial_user_data,
+       bool                    *rtlocked,
        xfs_rtblock_t           *bno,
        xfs_extlen_t            *blen)
 {
@@ -1280,12 +1282,38 @@ xfs_rtallocate(
        };
        xfs_rtxnum_t            rtx;
        xfs_rtxlen_t            len = 0;
-       int                     error;
+       int                     error = 0;
+
+       /*
+        * Lock out modifications to both the RT bitmap and summary inodes.
+        */
+       if (!*rtlocked) {
+               xfs_rtbitmap_lock(args.mp);
+               xfs_rtbitmap_trans_join(tp);
+               *rtlocked = true;
+       }
+
+       /*
+        * For an allocation to an empty file at offset 0, pick an extent that
+        * will space things out in the rt area.
+        */
+       if (!start && initial_user_data)
+               start = xfs_rtpick_extent(args.mp, tp, maxlen);
 
        if (start) {
                error = xfs_rtallocate_extent_near(&args, start, minlen, maxlen,
                                &len, prod, &rtx);
-       } else {
+               /*
+                * If we can't allocate near a specific rt extent, try again
+                * without locality criteria.
+                */
+               if (error == -ENOSPC) {
+                       xfs_rtbuf_cache_relse(&args);
+                       error = 0;
+               }
+       }
+
+       if (!error) {
                error = xfs_rtallocate_extent_size(&args, minlen, maxlen, &len,
                                prod, &rtx);
        }
@@ -1314,7 +1342,7 @@ xfs_bmap_rtalloc(
 {
        struct xfs_mount        *mp = ap->ip->i_mount;
        xfs_fileoff_t           orig_offset = ap->offset;
-       xfs_rtxnum_t            start;     /* allocation hint rtextent no */
+       xfs_rtxnum_t            start = 0;   /* allocation hint rtextent no */
        xfs_rtxlen_t            prod = 0;  /* product factor for allocators */
        xfs_extlen_t            mod = 0;   /* product factor for allocators */
        xfs_rtxlen_t            ralen = 0; /* realtime allocation length */
@@ -1323,7 +1351,6 @@ xfs_bmap_rtalloc(
        xfs_extlen_t            minlen = mp->m_sb.sb_rextsize;
        xfs_rtxlen_t            raminlen;
        bool                    rtlocked = false;
-       bool                    ignore_locality = false;
        int                     error;
 
        align = xfs_get_extsz_hint(ap->ip);
@@ -1361,28 +1388,8 @@ retry:
        ASSERT(raminlen > 0);
        ASSERT(raminlen <= ralen);
 
-       /*
-        * Lock out modifications to both the RT bitmap and summary inodes
-        */
-       if (!rtlocked) {
-               xfs_rtbitmap_lock(mp);
-               xfs_rtbitmap_trans_join(ap->tp);
-               rtlocked = true;
-       }
-
-       if (ignore_locality) {
-               start = 0;
-       } else if (xfs_bmap_adjacent(ap)) {
+       if (xfs_bmap_adjacent(ap))
                start = xfs_rtb_to_rtx(mp, ap->blkno);
-       } else if (ap->datatype & XFS_ALLOC_INITIAL_USER_DATA) {
-               /*
-                * If it's an allocation to an empty file at offset 0, pick an
-                * extent that will space things out in the rt area.
-                */
-               start = xfs_rtpick_extent(mp, ap->tp, ralen);
-       } else {
-               start = 0;
-       }
 
        /*
         * Only bother calculating a real prod factor if offset & length are
@@ -1398,7 +1405,8 @@ retry:
        }
 
        error = xfs_rtallocate(ap->tp, start, raminlen, ralen, prod, ap->wasdel,
-                              &ap->blkno, &ap->length);
+                       ap->datatype & XFS_ALLOC_INITIAL_USER_DATA, &rtlocked,
+                       &ap->blkno, &ap->length);
        if (error == -ENOSPC) {
                if (align > mp->m_sb.sb_rextsize) {
                        /*
@@ -1414,15 +1422,6 @@ retry:
                        goto retry;
                }
 
-               if (!ignore_locality && start != 0) {
-                       /*
-                        * If we can't allocate near a specific rt extent, try
-                        * again without locality criteria.
-                        */
-                       ignore_locality = true;
-                       goto retry;
-               }
-
                ap->blkno = NULLFSBLOCK;
                ap->length = 0;
                return 0;