• Filipe Manana's avatar
    Btrfs: fix race when checking if we can skip fsync'ing an inode · affc0ff9
    Filipe Manana authored
    If we're about to do a fast fsync for an inode and btrfs_inode_in_log()
    returns false, it's possible that we had an ordered extent in progress
    (btrfs_finish_ordered_io() not run yet) when we noticed that the inode's
    last_trans field was not greater than the id of the last committed
    transaction, but shortly after, before we checked if there were any
    ongoing ordered extents, the ordered extent had just completed and
    removed itself from the inode's ordered tree, in which case we end up not
    logging the inode, losing some data if a power failure or crash happens
    after the fsync handler returns and before the transaction is committed.
    
    Fix this by checking first if there are any ongoing ordered extents
    before comparing the inode's last_trans with the id of the last committed
    transaction - when it completes, an ordered extent always updates the
    inode's last_trans before it removes itself from the inode's ordered
    tree (at btrfs_finish_ordered_io()).
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarChris Mason <clm@fb.com>
    affc0ff9
file.c 80.2 KB