Skip to content

Commit 50a524e

Browse files
Christoph Hellwigcmaiolino
authored andcommitted
xfs: refactor backing memory allocations for buffers
Lift handling of shmem and slab backed buffers into xfs_buf_alloc_pages and rename the result to xfs_buf_alloc_backing_mem. This shares more code and ensures uncached buffers can also use slab, which slightly reduces the memory usage of growfs on 512 byte sector size file systems, but more importantly means the allocation invariants are the same for cached and uncached buffers. Document these new invariants with a big fat comment mostly stolen from a patch by Dave Chinner. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Carlos Maiolino <cem@kernel.org>
1 parent 48a325a commit 50a524e

1 file changed

Lines changed: 36 additions & 19 deletions

File tree

fs/xfs/xfs_buf.c

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -271,19 +271,49 @@ xfs_buf_alloc_kmem(
271271
return 0;
272272
}
273273

274+
/*
275+
* Allocate backing memory for a buffer.
276+
*
277+
* For tmpfs-backed buffers used by in-memory btrees this directly maps the
278+
* tmpfs page cache folios.
279+
*
280+
* For real file system buffers there are two different kinds backing memory:
281+
*
282+
* The first type backs the buffer by a kmalloc allocation. This is done for
283+
* less than PAGE_SIZE allocations to avoid wasting memory.
284+
*
285+
* The second type of buffer is the multi-page buffer. These are always made
286+
* up of single pages so that they can be fed to vmap_ram() to return a
287+
* contiguous memory region we can access the data through, or mark it as
288+
* XBF_UNMAPPED and access the data directly through individual page_address()
289+
* calls.
290+
*/
274291
static int
275-
xfs_buf_alloc_pages(
292+
xfs_buf_alloc_backing_mem(
276293
struct xfs_buf *bp,
277294
xfs_buf_flags_t flags)
278295
{
296+
size_t size = BBTOB(bp->b_length);
279297
gfp_t gfp_mask = GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOWARN;
280298
long filled = 0;
281299

300+
if (xfs_buftarg_is_mem(bp->b_target))
301+
return xmbuf_map_page(bp);
302+
303+
/*
304+
* For buffers that fit entirely within a single page, first attempt to
305+
* allocate the memory from the heap to minimise memory usage. If we
306+
* can't get heap memory for these small buffers, we fall back to using
307+
* the page allocator.
308+
*/
309+
if (size < PAGE_SIZE && xfs_buf_alloc_kmem(new_bp, flags) == 0)
310+
return 0;
311+
282312
if (flags & XBF_READ_AHEAD)
283313
gfp_mask |= __GFP_NORETRY;
284314

285315
/* Make sure that we have a page list */
286-
bp->b_page_count = DIV_ROUND_UP(BBTOB(bp->b_length), PAGE_SIZE);
316+
bp->b_page_count = DIV_ROUND_UP(size, PAGE_SIZE);
287317
if (bp->b_page_count <= XB_PAGES) {
288318
bp->b_pages = bp->b_page_array;
289319
} else {
@@ -564,18 +594,7 @@ xfs_buf_find_insert(
564594
if (error)
565595
goto out_drop_pag;
566596

567-
if (xfs_buftarg_is_mem(new_bp->b_target)) {
568-
error = xmbuf_map_page(new_bp);
569-
} else if (BBTOB(new_bp->b_length) >= PAGE_SIZE ||
570-
xfs_buf_alloc_kmem(new_bp, flags) < 0) {
571-
/*
572-
* For buffers that fit entirely within a single page, first
573-
* attempt to allocate the memory from the heap to minimise
574-
* memory usage. If we can't get heap memory for these small
575-
* buffers, we fall back to using the page allocator.
576-
*/
577-
error = xfs_buf_alloc_pages(new_bp, flags);
578-
}
597+
error = xfs_buf_alloc_backing_mem(new_bp, flags);
579598
if (error)
580599
goto out_free_buf;
581600

@@ -939,14 +958,12 @@ xfs_buf_get_uncached(
939958
if (error)
940959
return error;
941960

942-
if (xfs_buftarg_is_mem(bp->b_target))
943-
error = xmbuf_map_page(bp);
944-
else
945-
error = xfs_buf_alloc_pages(bp, flags);
961+
error = xfs_buf_alloc_backing_mem(bp, flags);
946962
if (error)
947963
goto fail_free_buf;
948964

949-
error = _xfs_buf_map_pages(bp, 0);
965+
if (!bp->b_addr)
966+
error = _xfs_buf_map_pages(bp, 0);
950967
if (unlikely(error)) {
951968
xfs_warn(target->bt_mount,
952969
"%s: failed to map pages", __func__);

0 commit comments

Comments
 (0)