btrfs: lock the inode first before flushing range when punching hole
authorFilipe Manana <fdmanana@suse.com>
Tue, 15 Mar 2022 15:22:39 +0000 (15:22 +0000)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:03:09 +0000 (17:03 +0200)
When doing hole punching we are flushing delalloc and waiting for ordered
extents to complete before locking the inode (VFS lock and the btrfs
specific i_mmap_lock). This is fine because even if a write happens after
we call btrfs_wait_ordered_range() and before we lock the inode (call
btrfs_inode_lock()), we will notice the write at
btrfs_punch_hole_lock_range() and flush delalloc and wait for its ordered
extent.

We can however make this simpler by locking first the inode an then call
btrfs_wait_ordered_range(), which will allow us to remove the ordered
extent lookup logic from btrfs_punch_hole_lock_range() in the next patch.
It also makes the behaviour the same as plain fallocate, hole punching
and reflinks.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/file.c

index 0a9b334..f8eaa18 100644 (file)
@@ -2976,11 +2976,12 @@ static int btrfs_punch_hole(struct file *file, loff_t offset, loff_t len)
        bool truncated_block = false;
        bool updated_inode = false;
 
+       btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP);
+
        ret = btrfs_wait_ordered_range(inode, offset, len);
        if (ret)
-               return ret;
+               goto out_only_mutex;
 
-       btrfs_inode_lock(inode, BTRFS_ILOCK_MMAP);
        ino_size = round_up(inode->i_size, fs_info->sectorsize);
        ret = find_first_non_hole(BTRFS_I(inode), &offset, &len);
        if (ret < 0)