• Filipe Manana's avatar
    btrfs: reset last_reflink_trans after fsyncing inode · 23e3337f
    Filipe Manana authored
    When an inode has a last_reflink_trans matching the current transaction,
    we have to take special care when logging its checksums in order to
    avoid getting checksum items with overlapping ranges in a log tree,
    which could result in missing checksums after log replay (more on that
    in the changelogs of commit 40e046ac ("Btrfs: fix missing data
    checksums after replaying a log tree") and commit e289f03e ("btrfs:
    fix corrupt log due to concurrent fsync of inodes with shared extents")).
    We also need to make sure a full fsync will copy all old file extent
    items it finds in modified leaves, because they might have been copied
    from some other inode.
    
    However once we fsync an inode, we don't need to keep paying the price of
    that extra special care in future fsyncs done in the same transaction,
    unless the inode is used for another reflink operation or the full sync
    flag is set on it (truncate, failure to allocate extent maps for holes,
    and other exceptional and infrequent cases).
    
    So after we fsync an inode reset its last_unlink_trans to zero. In case
    another reflink happens, we continue to update the last_reflink_trans of
    the inode, just as before. Also set last_reflink_trans to the generation
    of the last transaction that modified the inode whenever we need to set
    the full sync flag on the inode, just like when we need to load an inode
    from disk after eviction.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    23e3337f
tree-log.c 195 KB