• B
    xfs: fix broken multi-fsb buffer logging · a3916e52
    Brian Foster 提交于
    Multi-block buffers are logged based on buffer offset in
    xfs_trans_log_buf(). xfs_buf_item_log() ultimately walks each mapping in
    the buffer and marks the associated range to be logged in the
    xfs_buf_log_format bitmap for that mapping. This code is broken,
    however, in that it marks the actual buffer offsets of the associated
    range in each bitmap rather than shifting to the byte range for that
    particular mapping.
    
    For example, on a 4k fsb fs, buffer offset 4096 refers to the first byte
    of the second mapping in the buffer. This means byte 0 of the second log
    format bitmap should be tagged as dirty. Instead, the current code marks
    byte offset 4096 of the second log format bitmap, which is invalid and
    potentially out of range of the mapping.
    
    As a result of this, the log item format code invoked at transaction
    commit time is not be able to correctly identify what parts of the
    buffer to copy into log vectors. This can lead to NULL log vector
    pointer dereferences in CIL push context if the item format code was not
    able to locate any dirty ranges at all. This crash has been reproduced
    on a 4k FSB filesystem using 16k directory blocks where an unlink
    operation happened not to log anything in the first block of the
    mapping. The logged offsets were all over 4k, marked as such in the
    subsequent log format mappings, and thus left the transaction with an
    xfs_log_item that is marked DIRTY but without any logged regions.
    
    Further, even when the logged regions are marked correctly in the buffer
    log format bitmaps, the format code doesn't copy the correct ranges of
    the buffer into the log. This means that any logged region beyond the
    first block of a multi-block buffer is subject to corruption after a
    crash and log recovery sequence. This is due to a failure to convert the
    mapping bm_len field from basic blocks to bytes in the buffer offset
    tracking code in xfs_buf_item_format().
    
    Update xfs_buf_item_log() to convert buffer offsets to segment relative
    offsets when logging multi-block buffers. This ensures that the modified
    regions of a buffer are logged correctly and avoids the aforementioned
    crash. Also update xfs_buf_item_format() to correctly track the source
    offset into the buffer for the log vector formatting code. This ensures
    that the correct data is copied into the log.
    Signed-off-by: NBrian Foster <bfoster@redhat.com>
    Reviewed-by: NEric Sandeen <sandeen@redhat.com>
    Reviewed-by: NDave Chinner <dchinner@redhat.com>
    Signed-off-by: NDave Chinner <david@fromorbit.com>
    
    
    a3916e52
xfs_buf_item.c 33.7 KB