mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
xfs: fix incorrect use of gfp flags in xfs_buf_alloc_backing_mem
xfs_buf_alloc_backing_mem currently has two issues with how the GFP_
flags are set:
- when aiming for a large folio allocation, the gfp mask is adjusted
to try less hard, but these flags then persist for the vmalloc
allocation, which is bogus.
- the __GFP_NOFAIL for small allocations is also applied when readahead
force __GFP_NORETRY which doesn't make any sense.
Fix this by only applying __GFP_NOFAIL when __GFP_NORETRY is not set,
and by reordering the code so that the large folio gfp adjustments
are performed locally just for that allocation.
Fixes: 94c78cfa3b ("xfs: convert buffer cache to use high order folios")
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
parent
27d7d15184
commit
0144bcf619
|
|
@ -223,22 +223,6 @@ xfs_buf_alloc_backing_mem(
|
|||
if (flags & XBF_READ_AHEAD)
|
||||
gfp_mask |= __GFP_NORETRY;
|
||||
|
||||
/*
|
||||
* For buffers smaller than PAGE_SIZE use a kmalloc allocation if that
|
||||
* is properly aligned. The slab allocator now guarantees an aligned
|
||||
* allocation for all power of two sizes, which matches most of the
|
||||
* smaller than PAGE_SIZE buffers used by XFS.
|
||||
*/
|
||||
if (size < PAGE_SIZE && is_power_of_2(size))
|
||||
return xfs_buf_alloc_kmem(bp, size, gfp_mask | __GFP_NOFAIL);
|
||||
|
||||
/*
|
||||
* Don't bother with the retry loop for single PAGE allocations: vmalloc
|
||||
* won't do any better.
|
||||
*/
|
||||
if (size <= PAGE_SIZE)
|
||||
gfp_mask |= __GFP_NOFAIL;
|
||||
|
||||
/*
|
||||
* Optimistically attempt a single high order folio allocation for
|
||||
* larger than PAGE_SIZE buffers.
|
||||
|
|
@ -251,18 +235,31 @@ xfs_buf_alloc_backing_mem(
|
|||
* path for them instead of wasting memory here.
|
||||
*/
|
||||
if (size > PAGE_SIZE) {
|
||||
if (!is_power_of_2(size))
|
||||
return xfs_buf_alloc_vmalloc(bp, size, gfp_mask, flags);
|
||||
gfp_mask &= ~__GFP_DIRECT_RECLAIM;
|
||||
gfp_mask |= __GFP_NORETRY;
|
||||
}
|
||||
if (xfs_buf_alloc_folio(bp, size, gfp_mask) < 0) {
|
||||
if (size <= PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
trace_xfs_buf_backing_fallback(bp, _RET_IP_);
|
||||
if (is_power_of_2(size)) {
|
||||
gfp_t folio_gfp = gfp_mask;
|
||||
|
||||
folio_gfp &= ~__GFP_DIRECT_RECLAIM;
|
||||
folio_gfp |= __GFP_NORETRY;
|
||||
if (xfs_buf_alloc_folio(bp, size, folio_gfp) == 0)
|
||||
return 0;
|
||||
trace_xfs_buf_backing_fallback(bp, _RET_IP_);
|
||||
}
|
||||
return xfs_buf_alloc_vmalloc(bp, size, gfp_mask, flags);
|
||||
}
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The slab allocator now guarantees aligned allocations for all power
|
||||
* of two sizes. This covers most smaller XFS buffers, so just use
|
||||
* kmalloc in this case.
|
||||
*
|
||||
* Don't bother with the vmalloc fallback for allocations of page size
|
||||
* or less: vmalloc won't do any better.
|
||||
*/
|
||||
if (!(gfp_mask & __GFP_NORETRY))
|
||||
gfp_mask |= __GFP_NOFAIL;
|
||||
if (size < PAGE_SIZE && is_power_of_2(size))
|
||||
return xfs_buf_alloc_kmem(bp, size, gfp_mask);
|
||||
return xfs_buf_alloc_folio(bp, size, gfp_mask);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user