]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: constrain dirty buffers while formatting a staged btree
authorDarrick J. Wong <djwong@kernel.org>
Mon, 15 Apr 2024 23:07:37 +0000 (16:07 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 17 Apr 2024 21:06:25 +0000 (14:06 -0700)
Source kernel commit: e069d549705e49841247acf9b3176744e27d5425

Constrain the number of dirty buffers that are locked by the btree
staging code at any given time by establishing a threshold at which we
put them all on the delwri queue and push them to disk.  This limits
memory consumption while writing out new btrees.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
libxfs/xfs_btree_staging.c
libxfs/xfs_btree_staging.h
repair/agbtree.c

index a6f0d7d3b2866505493d9d40106d21d9aaeb11bd..d4164e37bd38a0de1ca51bce79a9bd7418fdf807 100644 (file)
@@ -333,24 +333,41 @@ xfs_btree_commit_ifakeroot(
 /*
  * Put a btree block that we're loading onto the ordered list and release it.
  * The btree blocks will be written to disk when bulk loading is finished.
+ * If we reach the dirty buffer threshold, flush them to disk before
+ * continuing.
  */
-static void
+static int
 xfs_btree_bload_drop_buf(
-       struct list_head        *buffers_list,
-       struct xfs_buf          **bpp)
+       struct xfs_btree_bload          *bbl,
+       struct list_head                *buffers_list,
+       struct xfs_buf                  **bpp)
 {
-       if (*bpp == NULL)
-               return;
+       struct xfs_buf                  *bp = *bpp;
+       int                             error;
+
+       if (!bp)
+               return 0;
 
        /*
         * Mark this buffer XBF_DONE (i.e. uptodate) so that a subsequent
         * xfs_buf_read will not pointlessly reread the contents from the disk.
         */
-       (*bpp)->b_flags |= XBF_DONE;
+       bp->b_flags |= XBF_DONE;
 
-       xfs_buf_delwri_queue_here(*bpp, buffers_list);
-       xfs_buf_relse(*bpp);
+       xfs_buf_delwri_queue_here(bp, buffers_list);
+       xfs_buf_relse(bp);
        *bpp = NULL;
+       bbl->nr_dirty++;
+
+       if (!bbl->max_dirty || bbl->nr_dirty < bbl->max_dirty)
+               return 0;
+
+       error = xfs_buf_delwri_submit(buffers_list);
+       if (error)
+               return error;
+
+       bbl->nr_dirty = 0;
+       return 0;
 }
 
 /*
@@ -422,7 +439,10 @@ xfs_btree_bload_prep_block(
         */
        if (*blockp)
                xfs_btree_set_sibling(cur, *blockp, &new_ptr, XFS_BB_RIGHTSIB);
-       xfs_btree_bload_drop_buf(buffers_list, bpp);
+
+       ret = xfs_btree_bload_drop_buf(bbl, buffers_list, bpp);
+       if (ret)
+               return ret;
 
        /* Initialize the new btree block. */
        xfs_btree_init_block_cur(cur, new_bp, level, nr_this_block);
@@ -770,6 +790,7 @@ xfs_btree_bload(
        cur->bc_nlevels = bbl->btree_height;
        xfs_btree_set_ptr_null(cur, &child_ptr);
        xfs_btree_set_ptr_null(cur, &ptr);
+       bbl->nr_dirty = 0;
 
        xfs_btree_bload_level_geometry(cur, bbl, level, nr_this_level,
                        &avg_per_block, &blocks, &blocks_with_extra);
@@ -808,7 +829,10 @@ xfs_btree_bload(
                        xfs_btree_copy_ptrs(cur, &child_ptr, &ptr, 1);
        }
        total_blocks += blocks;
-       xfs_btree_bload_drop_buf(&buffers_list, &bp);
+
+       ret = xfs_btree_bload_drop_buf(bbl, &buffers_list, &bp);
+       if (ret)
+               goto out;
 
        /* Populate the internal btree nodes. */
        for (level = 1; level < cur->bc_nlevels; level++) {
@@ -850,7 +874,11 @@ xfs_btree_bload(
                                xfs_btree_copy_ptrs(cur, &first_ptr, &ptr, 1);
                }
                total_blocks += blocks;
-               xfs_btree_bload_drop_buf(&buffers_list, &bp);
+
+               ret = xfs_btree_bload_drop_buf(bbl, &buffers_list, &bp);
+               if (ret)
+                       goto out;
+
                xfs_btree_copy_ptrs(cur, &child_ptr, &first_ptr, 1);
        }
 
index bd5b3f004823a2e2cee7090d7ca38c42c0ca1df4..f0a5007284ef199885ea01b6cbe99ba660bb0136 100644 (file)
@@ -112,6 +112,16 @@ struct xfs_btree_bload {
         * height of the new btree.
         */
        unsigned int                    btree_height;
+
+       /*
+        * Flush the new btree block buffer list to disk after this many blocks
+        * have been formatted.  Zero prohibits writing any buffers until all
+        * blocks have been formatted.
+        */
+       uint16_t                        max_dirty;
+
+       /* Number of dirty buffers. */
+       uint16_t                        nr_dirty;
 };
 
 int xfs_btree_bload_compute_geometry(struct xfs_btree_cur *cur,
index 10a0c7e48c9a15d6020264d2b2052d4eab1af21c..981d8e340bf20cf8d54534aff2a8ba8b3d3d1492 100644 (file)
@@ -23,6 +23,7 @@ init_rebuild(
        memset(btr, 0, sizeof(struct bt_rebuild));
 
        bulkload_init_ag(&btr->newbt, sc, oinfo);
+       btr->bload.max_dirty = XFS_B_TO_FSBT(sc->mp, 256U << 10); /* 256K */
        bulkload_estimate_ag_slack(sc, &btr->bload, est_agfreeblocks);
 }