• Brian Foster's avatar
    xfs: remove bli from AIL before release on transaction abort · 3d4b4a3e
    Brian Foster authored
    When a buffer is modified, logged and committed, it ultimately ends
    up sitting on the AIL with a dirty bli waiting for metadata
    writeback. If another transaction locks and invalidates the buffer
    (freeing an inode chunk, for example) in the meantime, the bli is
    flagged as stale, the dirty state is cleared and the bli remains in
    the AIL.
    
    If a shutdown occurs before the transaction that has invalidated the
    buffer is committed, the transaction is ultimately aborted. The log
    items are flagged as such and ->iop_unlock() handles the aborted
    items. Because the bli is clean (due to the invalidation),
    ->iop_unlock() unconditionally releases it. The log item may still
    reside in the AIL, however, which means the I/O completion handler
    may still run and attempt to access it. This results in assert
    failure due to the release of the bli while still present in the AIL
    and a subsequent NULL dereference and panic in the buffer I/O
    completion handling. This can be reproduced by running generic/388
    in repetition.
    
    To avoid this problem, update xfs_buf_item_unlock() to first check
    whether the bli is aborted and if so, remove it from the AIL before
    it is released. This ensures that the bli is no longer accessed
    during the shutdown sequence after it has been freed.
    Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Reviewed-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
    Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
    3d4b4a3e
xfs_buf_item.c 34 KB