• Filipe Manana's avatar
    btrfs: fix missed extent on fsync after dropping extent maps · cef7820d
    Filipe Manana authored
    When dropping extent maps for a range, through btrfs_drop_extent_cache(),
    if we find an extent map that starts before our target range and/or ends
    before the target range, and we are not able to allocate extent maps for
    splitting that extent map, then we don't fail and simply remove the entire
    extent map from the inode's extent map tree.
    
    This is generally fine, because in case anyone needs to access the extent
    map, it can just load it again later from the respective file extent
    item(s) in the subvolume btree. However, if that extent map is new and is
    in the list of modified extents, then a fast fsync will miss the parts of
    the extent that were outside our range (that needed to be split),
    therefore not logging them. Fix that by marking the inode for a full
    fsync. This issue was introduced after removing BUG_ON()s triggered when
    the split extent map allocations failed, done by commit 7014cdb4
    ("Btrfs: btrfs_drop_extent_cache should never fail"), back in 2012, and
    the fast fsync path already existed but was very recent.
    
    Also, in the case where we could allocate extent maps for the split
    operations but then fail to add a split extent map to the tree, mark the
    inode for a full fsync as well. This is not supposed to ever fail, and we
    assert that, but in case assertions are disabled (CONFIG_BTRFS_ASSERT is
    not set), it's the correct thing to do to make sure a fast fsync will not
    miss a new extent.
    
    CC: stable@vger.kernel.org # 5.15+
    Reviewed-by: default avatarAnand Jain <anand.jain@oracle.com>
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    cef7820d
file.c 119 KB