• Dave Chinner's avatar
    xfs: fix livelock in delayed allocation at ENOSPC · 9419092f
    Dave Chinner authored
    On a filesystem with a non-zero stripe unit and a large sequential
    write, delayed allocation will set a minimum allocation length of
    the stripe unit. If allocation fails because there are no extents
    long enough for an aligned minlen allocation, it is supposed to
    fall back to unaligned allocation which allows single block extents
    to be allocated.
    
    When the allocator code was rewritting in the 6.3 cycle, this
    fallback was broken - the old code used args->fsbno as the both the
    allocation target and the allocation result, the new code passes the
    target as a separate parameter. The conversion didn't handle the
    aligned->unaligned fallback path correctly - it reset args->fsbno to
    the target fsbno on failure which broke allocation failure detection
    in the high level code and so it never fell back to unaligned
    allocations.
    
    This resulted in a loop in writeback trying to allocate an aligned
    block, getting a false positive success, trying to insert the result
    in the BMBT. This did nothing because the extent already was in the
    BMBT (merge results in an unchanged extent) and so it returned the
    prior extent to the conversion code as the current iomap.
    
    Because the iomap returned didn't cover the offset we tried to map,
    xfs_convert_blocks() then retries the allocation, which fails in the
    same way and now we have a livelock.
    Reported-and-tested-by: default avatarBrian Foster <bfoster@redhat.com>
    Fixes: 85843327 ("xfs: factor xfs_bmap_btalloc()")
    Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
    Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
    9419092f
xfs_bmap.c 166 KB