• Filipe Manana's avatar
    Btrfs: fix ENOSPC errors, leading to transaction aborts, when cloning extents · 690a5dbf
    Filipe Manana authored
    When cloning extents (or deduplicating) we create a transaction with a
    space reservation that considers we will drop or update a single file
    extent item of the destination inode (that we modify a single leaf). That
    is fine for the vast majority of scenarios, however it might happen that
    we need to drop many file extent items, and adjust at most two file extent
    items, in the destination root, which can span multiple leafs. This will
    lead to either the call to btrfs_drop_extents() to fail with ENOSPC or
    the subsequent calls to btrfs_insert_empty_item() or btrfs_update_inode()
    (called through clone_finish_inode_update()) to fail with ENOSPC. Such
    failure results in a transaction abort, leaving the filesystem in a
    read-only mode.
    
    In order to fix this we need to follow the same approach as the hole
    punching code, where we create a local reservation with 1 unit and keep
    ending and starting transactions, after balancing the btree inode,
    when __btrfs_drop_extents() returns ENOSPC. So fix this by making the
    extent cloning call calls the recently added btrfs_punch_hole_range()
    helper, which is what does the mentioned work for hole punching, and
    make sure whenever we drop extent items in a transaction, we also add a
    replacing file extent item, to avoid corruption (a hole) if after ending
    a transaction and before starting a new one, the old transaction gets
    committed and a power failure happens before we finish cloning.
    
    A test case for fstests follows soon.
    Reported-by: default avatarDavid Goodwin <david@codepoets.co.uk>
    Link: https://lore.kernel.org/linux-btrfs/a4a4cf31-9cf4-e52c-1f86-c62d336c9cd1@codepoets.co.uk/Reported-by: default avatarSam Tygier <sam@tygier.co.uk>
    Link: https://lore.kernel.org/linux-btrfs/82aace9f-a1e3-1f0b-055f-3ea75f7a41a0@tygier.co.uk/
    Fixes: b6f3409b ("Btrfs: reserve sufficient space for ioctl clone")
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    690a5dbf
file.c 92.1 KB