• Brian Foster's avatar
    xfs: fix recovery failure when log record header wraps log end · 35093926
    Brian Foster authored
    commit 284f1c2c upstream.
    
    The high-level log recovery algorithm consists of two loops that
    walk the physical log and process log records from the tail to the
    head. The first loop handles the case where the tail is beyond the
    head and processes records up to the end of the physical log. The
    subsequent loop processes records from the beginning of the physical
    log to the head.
    
    Because log records can wrap around the end of the physical log, the
    first loop mentioned above must handle this case appropriately.
    Records are processed from in-core buffers, which means that this
    algorithm must split the reads of such records into two partial
    I/Os: 1.) from the beginning of the record to the end of the log and
    2.) from the beginning of the log to the end of the record. This is
    further complicated by the fact that the log record header and log
    record data are read into independent buffers.
    
    The current handling of each buffer correctly splits the reads when
    either the header or data starts before the end of the log and wraps
    around the end. The data read does not correctly handle the case
    where the prior header read wrapped or ends on the physical log end
    boundary. blk_no is incremented to or beyond the log end after the
    header read to point to the record data, but the split data read
    logic triggers, attempts to read from an invalid log block and
    ultimately causes log recovery to fail. This can be reproduced
    fairly reliably via xfstests tests generic/047 and generic/388 with
    large iclog sizes (256k) and small (10M) logs.
    
    If the record header read has pushed beyond the end of the physical
    log, the subsequent data read is actually contiguous. Update the
    data read logic to detect the case where blk_no has wrapped, mod it
    against the log size to read from the correct address and issue one
    contiguous read for the log data buffer. The log record is processed
    as normal from the buffer(s), the loop exits after the current
    iteration and the subsequent loop picks up with the first new record
    after the start of the log.
    Signed-off-by: default avatarBrian Foster <bfoster@redhat.com>
    Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    35093926
xfs_log_recover.c 161 KB