]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfs: make xfs_bmapi_convert_delalloc() to allocate the target offset
authorZhang Yi <yi.zhang@huawei.com>
Wed, 30 Apr 2025 21:26:57 +0000 (14:26 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 May 2025 07:41:38 +0000 (09:41 +0200)
[ Upstream commit 2e08371a83f1c06fd85eea8cd37c87a224cc4cc4 ]

Since xfs_bmapi_convert_delalloc() only attempts to allocate the entire
delalloc extent and require multiple invocations to allocate the target
offset. So xfs_convert_blocks() add a loop to do this job and we call it
in the write back path, but xfs_convert_blocks() isn't a common helper.
Let's do it in xfs_bmapi_convert_delalloc() and drop
xfs_convert_blocks(), preparing for the post EOF delalloc blocks
converting in the buffered write begin path.

Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Chandan Babu R <chandanbabu@kernel.org>
Signed-off-by: Leah Rumancik <leah.rumancik@gmail.com>
Acked-by: "Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/xfs_aops.c

index 92d321dd8944c04ccfaa31d4eecaba43d83d631c..a3c4d4a442af8fe5a5fc905f7d3b723e2d168499 100644 (file)
@@ -4522,8 +4522,8 @@ error0:
  * invocations to allocate the target offset if a large enough physical extent
  * is not available.
  */
-int
-xfs_bmapi_convert_delalloc(
+static int
+xfs_bmapi_convert_one_delalloc(
        struct xfs_inode        *ip,
        int                     whichfork,
        xfs_off_t               offset,
@@ -4651,6 +4651,36 @@ out_trans_cancel:
        return error;
 }
 
+/*
+ * Pass in a dellalloc extent and convert it to real extents, return the real
+ * extent that maps offset_fsb in iomap.
+ */
+int
+xfs_bmapi_convert_delalloc(
+       struct xfs_inode        *ip,
+       int                     whichfork,
+       loff_t                  offset,
+       struct iomap            *iomap,
+       unsigned int            *seq)
+{
+       int                     error;
+
+       /*
+        * Attempt to allocate whatever delalloc extent currently backs offset
+        * and put the result into iomap.  Allocate in a loop because it may
+        * take several attempts to allocate real blocks for a contiguous
+        * delalloc extent if free space is sufficiently fragmented.
+        */
+       do {
+               error = xfs_bmapi_convert_one_delalloc(ip, whichfork, offset,
+                                       iomap, seq);
+               if (error)
+                       return error;
+       } while (iomap->offset + iomap->length <= offset);
+
+       return 0;
+}
+
 int
 xfs_bmapi_remap(
        struct xfs_trans        *tp,
index 21c241e96d48309df4136d25f250a0067a250793..50a7f2745514b2fad0b08e7a960e78a786ca7ffe 100644 (file)
@@ -225,45 +225,6 @@ xfs_imap_valid(
        return true;
 }
 
-/*
- * Pass in a dellalloc extent and convert it to real extents, return the real
- * extent that maps offset_fsb in wpc->iomap.
- *
- * The current page is held locked so nothing could have removed the block
- * backing offset_fsb, although it could have moved from the COW to the data
- * fork by another thread.
- */
-static int
-xfs_convert_blocks(
-       struct iomap_writepage_ctx *wpc,
-       struct xfs_inode        *ip,
-       int                     whichfork,
-       loff_t                  offset)
-{
-       int                     error;
-       unsigned                *seq;
-
-       if (whichfork == XFS_COW_FORK)
-               seq = &XFS_WPC(wpc)->cow_seq;
-       else
-               seq = &XFS_WPC(wpc)->data_seq;
-
-       /*
-        * Attempt to allocate whatever delalloc extent currently backs offset
-        * and put the result into wpc->iomap.  Allocate in a loop because it
-        * may take several attempts to allocate real blocks for a contiguous
-        * delalloc extent if free space is sufficiently fragmented.
-        */
-       do {
-               error = xfs_bmapi_convert_delalloc(ip, whichfork, offset,
-                               &wpc->iomap, seq);
-               if (error)
-                       return error;
-       } while (wpc->iomap.offset + wpc->iomap.length <= offset);
-
-       return 0;
-}
-
 static int
 xfs_map_blocks(
        struct iomap_writepage_ctx *wpc,
@@ -281,6 +242,7 @@ xfs_map_blocks(
        struct xfs_iext_cursor  icur;
        int                     retries = 0;
        int                     error = 0;
+       unsigned int            *seq;
 
        if (xfs_is_shutdown(mp))
                return -EIO;
@@ -376,7 +338,19 @@ retry:
        trace_xfs_map_blocks_found(ip, offset, count, whichfork, &imap);
        return 0;
 allocate_blocks:
-       error = xfs_convert_blocks(wpc, ip, whichfork, offset);
+       /*
+        * Convert a dellalloc extent to a real one. The current page is held
+        * locked so nothing could have removed the block backing offset_fsb,
+        * although it could have moved from the COW to the data fork by another
+        * thread.
+        */
+       if (whichfork == XFS_COW_FORK)
+               seq = &XFS_WPC(wpc)->cow_seq;
+       else
+               seq = &XFS_WPC(wpc)->data_seq;
+
+       error = xfs_bmapi_convert_delalloc(ip, whichfork, offset,
+                               &wpc->iomap, seq);
        if (error) {
                /*
                 * If we failed to find the extent in the COW fork we might have