diff options
| author | Brian Foster <bfoster@redhat.com> | 2026-10-05 08:01:18 -0400 |
|---|---|---|
| committer | Carlos Maiolino <cem@kernel.org> | 2026-10-06 10:21:57 +0200 |
| commit | a644af916cf14daba9a4fd6413565c7bd34b5bdc (patch) | |
| tree | 32355e118ba990141eee5aabecc9398af373e46c /tools/perf/scripts/python | |
| parent | 831f4c28b5dca287422613fe1c1bf4ff1ad13cd1 (diff) | |
| download | linux-a644af916cf14daba9a4fd6413565c7bd34b5bdc.tar.gz linux-a644af916cf14daba9a4fd6413565c7bd34b5bdc.zip | |
xfs: incorporate increased AGFL min requirement for minleft allocs
Matt Fleming reports a filesystem shutdown due to inobt block
allocation failure during sparse chunk allocation. Inode creation
can involve multiple allocations in a transaction: the initial chunk
allocation and inode btree blocks via inobt record insertion. This
is expected to be safe by using the minleft parameter on the chunk
allocation to guarantee the selected AG has blocks available for
a followup inobt insertion.
The sequence that leads to this failure is that the alloc and inode
btrees are all full (require a full split on next insertion) and the
AG has just enough free space to satisfy a sparse chunk allocation
with minleft set (i.e. 7 blocks in this example). The chunk
allocation splits a free extent, triggers full allocbt splits, and
consumes 4 free blocks for the chunk and 4 AGFL blocks for the
btrees.
Next, the inobt record insertion triggers an inobt split. The AG has
enough free blocks, but the allocbt splits caused by the chunk
allocation have increased the min AGFL requirement for the AG due to
btree level increases. The AGFL requirement as calculated by
xfs_alloc_fix_freelist() is:
free + AGFL - res - minfree - minleft = avail
This evaluates to the following on initial chunk allocation:
2514 + 8 - 2505 - 8 - 2 = 7
... and then after the chunk allocation but before the inobt block
allocation:
2510 + 4 - 2505 - 12 - 0 = -3
This causes the inobt alloc to fail despite minleft being set in the
first allocation. The error path cancels the dirty transaction and
shuts down the fs. The problem here is that while minleft ensures
free blocks are available for the inobt insert, it is not sufficient
to cover the increase of the AGFL min free requirement.
To address this, first have xfs_alloc_freelist() return both min and
max freelist values. The min value is the current AGFL requirement
and remains used for actual AGFL sizing. The max value calculates
the worst case AGFL requirement after potential allocbt splits
during the current allocation. Incorporate the max value into space
availability checks for AG selection and the longest free extent
calculation. The latter is necessary because callers like the bmap
layer can size allocation requests based on the longest free extent.
Without this, aligned allocs can end up oversized, prematurely fail,
and fall back to non-aligned to make up the difference.
This ensures the selected AG has enough blocks for both the caller's
minleft value and the worst case AGFL increase. In the example
above, the initial calculation now evaluates to 3 blocks available
instead of 7 and the inode allocation fails gracefully with -ENOSPC.
Assisted-by: LLM
Reported-by: Matt Fleming <matt@readmodwrite.com>
Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Mark Tinguely <mark.tinguely@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Diffstat (limited to 'tools/perf/scripts/python')
0 files changed, 0 insertions, 0 deletions
