• Filipe Manana's avatar
    btrfs: stop locking the source extent range during reflink · 5d6f0e98
    Filipe Manana authored
    Nowadays before starting a reflink operation we do this:
    
    1) Take the VFS lock of the inodes in exclusive mode (a rw semaphore);
    
    2) Take the  mmap lock of the inodes (struct btrfs_inode::i_mmap_lock);
    
    3) Flush all delalloc in the source and target ranges;
    
    4) Wait for all ordered extents in the source and target ranges to
       complete;
    
    5) Lock the source and destination ranges in the inodes' io trees.
    
    In step 5 we lock the source range because:
    
    1) We needed to serialize against mmap writes, but that is not needed
       anymore because nowadays we do that through the inode's i_mmap_lock
       (step 2). This happens since commit 8c99516a ("btrfs: exclude mmaps
       while doing remap");
    
    2) To serialize against a concurrent relocation and avoid generating
       a delayed ref for an extent that was just dropped by relocation, see
       commit d8b55242 ("Btrfs: fix race between reflink/dedupe and
       relocation").
    
    Locking the source range however blocks any concurrent reads for that
    range and makes test case generic/733 fail.
    
    So instead of locking the source range during reflinks, make relocation
    read lock the inode's i_mmap_lock, so that it serializes with a concurrent
    reflink while still able to run concurrently with mmap writes and allow
    concurrent reads too.
    Reviewed-by: default avatarBoris Burkov <boris@bur.io>
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    5d6f0e98
relocation.c 118 KB