Jiri Slaby 2c66b1
From: Dave Chinner <dchinner@redhat.com>
Jiri Slaby 2c66b1
Date: Thu, 27 Apr 2023 09:02:11 +1000
Jiri Slaby 2c66b1
Subject: xfs: fix livelock in delayed allocation at ENOSPC
Jiri Slaby 2c66b1
Git-commit: 9419092fb2630c30e4ffeb9ef61007ef0c61827a
Jiri Slaby 2c66b1
Patch-mainline: 6.4-rc1
Jiri Slaby 2c66b1
References: brc#2208553 xfs-issue
Jiri Slaby 2c66b1
Jiri Slaby 2c66b1
On a filesystem with a non-zero stripe unit and a large sequential
Jiri Slaby 2c66b1
write, delayed allocation will set a minimum allocation length of
Jiri Slaby 2c66b1
the stripe unit. If allocation fails because there are no extents
Jiri Slaby 2c66b1
long enough for an aligned minlen allocation, it is supposed to
Jiri Slaby 2c66b1
fall back to unaligned allocation which allows single block extents
Jiri Slaby 2c66b1
to be allocated.
Jiri Slaby 2c66b1
Jiri Slaby 2c66b1
When the allocator code was rewritting in the 6.3 cycle, this
Jiri Slaby 2c66b1
fallback was broken - the old code used args->fsbno as the both the
Jiri Slaby 2c66b1
allocation target and the allocation result, the new code passes the
Jiri Slaby 2c66b1
target as a separate parameter. The conversion didn't handle the
Jiri Slaby 2c66b1
aligned->unaligned fallback path correctly - it reset args->fsbno to
Jiri Slaby 2c66b1
the target fsbno on failure which broke allocation failure detection
Jiri Slaby 2c66b1
in the high level code and so it never fell back to unaligned
Jiri Slaby 2c66b1
allocations.
Jiri Slaby 2c66b1
Jiri Slaby 2c66b1
This resulted in a loop in writeback trying to allocate an aligned
Jiri Slaby 2c66b1
block, getting a false positive success, trying to insert the result
Jiri Slaby 2c66b1
in the BMBT. This did nothing because the extent already was in the
Jiri Slaby 2c66b1
BMBT (merge results in an unchanged extent) and so it returned the
Jiri Slaby 2c66b1
prior extent to the conversion code as the current iomap.
Jiri Slaby 2c66b1
Jiri Slaby 2c66b1
Because the iomap returned didn't cover the offset we tried to map,
Jiri Slaby 2c66b1
xfs_convert_blocks() then retries the allocation, which fails in the
Jiri Slaby 2c66b1
same way and now we have a livelock.
Jiri Slaby 2c66b1
Jiri Slaby 2c66b1
Reported-and-tested-by: Brian Foster <bfoster@redhat.com>
Jiri Slaby 2c66b1
Fixes: 85843327094f ("xfs: factor xfs_bmap_btalloc()")
Jiri Slaby 2c66b1
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Jiri Slaby 2c66b1
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Jiri Slaby 2c66b1
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 2c66b1
---
Jiri Slaby 2c66b1
 fs/xfs/libxfs/xfs_bmap.c |    1 -
Jiri Slaby 2c66b1
 1 file changed, 1 deletion(-)
Jiri Slaby 2c66b1
Jiri Slaby 2c66b1
--- a/fs/xfs/libxfs/xfs_bmap.c
Jiri Slaby 2c66b1
+++ b/fs/xfs/libxfs/xfs_bmap.c
Jiri Slaby 2c66b1
@@ -3505,7 +3505,6 @@ xfs_bmap_btalloc_at_eof(
Jiri Slaby 2c66b1
 	 * original non-aligned state so the caller can proceed on allocation
Jiri Slaby 2c66b1
 	 * failure as if this function was never called.
Jiri Slaby 2c66b1
 	 */
Jiri Slaby 2c66b1
-	args->fsbno = ap->blkno;
Jiri Slaby 2c66b1
 	args->alignment = 1;
Jiri Slaby 2c66b1
 	return 0;
Jiri Slaby 2c66b1
 }