• Jan Kara's avatar
    jbd2/ocfs2: Fix block checksumming when a buffer is used in several transactions · 13ceef09
    Jan Kara authored
    OCFS2 uses t_commit trigger to compute and store checksum of the just
    committed blocks. When a buffer has b_frozen_data, checksum is computed
    for it instead of b_data but this can result in an old checksum being
    written to the filesystem in the following scenario:
    
    1) transaction1 is opened
    2) handle1 is opened
    3) journal_access(handle1, bh)
        - This sets jh->b_transaction to transaction1
    4) modify(bh)
    5) journal_dirty(handle1, bh)
    6) handle1 is closed
    7) start committing transaction1, opening transaction2
    8) handle2 is opened
    9) journal_access(handle2, bh)
        - This copies off b_frozen_data to make it safe for transaction1 to commit.
          jh->b_next_transaction is set to transaction2.
    10) jbd2_journal_write_metadata() checksums b_frozen_data
    11) the journal correctly writes b_frozen_data to the disk journal
    12) handle2 is closed
        - There was no dirty call for the bh on handle2, so it is never queued for
          any more journal operation
    13) Checkpointing finally happens, and it just spools the bh via normal buffer
    writeback.  This will write b_data, which was never triggered on and thus
    contains a wrong (old) checksum.
    
    This patch fixes the problem by calling the trigger at the moment data is
    frozen for journal commit - i.e., either when b_frozen_data is created by
    do_get_write_access or just before we write a buffer to the log if
    b_frozen_data does not exist. We also rename the trigger to t_frozen as
    that better describes when it is called.
    Signed-off-by: default avatarJan Kara <jack@suse.cz>
    Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
    Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
    13ceef09
transaction.c 64 KB