Commit ffa8fc60 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba

btrfs: remove ordered extent check and wait during fallocate

For fallocate() we have this loop that checks if we have ordered extents
after locking the file range, and if so unlock the range, wait for ordered
extents, and retry until we don't find more ordered extents.

This logic was needed in the past because:

1) Direct IO writes within the i_size boundary did not take the inode's
   VFS lock. This was because that lock used to be a mutex, then some
   years ago it was switched to a rw semaphore (commit 9902af79
   ("parallel lookups: actual switch to rwsem")), and then btrfs was
   changed to take the VFS inode's lock in shared mode for writes that
   don't cross the i_size boundary (commit e9adabb9 ("btrfs: use
   shared lock for direct writes within EOF"));

2) We could race with memory mapped writes, because memory mapped writes
   don't acquire the inode's VFS lock. We don't have that race anymore,
   as we have a rw semaphore to synchronize memory mapped writes with
   fallocate (and reflinking too). That change happened with commit
   8d9b4a16 ("btrfs: exclude mmap from happening during all
   fallocate operations").

So stop looking for ordered extents after locking the file range when
doing a plain fallocate.
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 1c6cbbbe
...@@ -3474,8 +3474,12 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -3474,8 +3474,12 @@ static long btrfs_fallocate(struct file *file, int mode,
} }
/* /*
* wait for ordered IO before we have any locks. We'll loop again * We have locked the inode at the VFS level (in exclusive mode) and we
* below with the locks held. * have locked the i_mmap_lock lock (in exclusive mode). Now before
* locking the file range, flush all dealloc in the range and wait for
* all ordered extents in the range to complete. After this we can lock
* the file range and, due to the previous locking we did, we know there
* can't be more delalloc or ordered extents in the range.
*/ */
ret = btrfs_wait_ordered_range(inode, alloc_start, ret = btrfs_wait_ordered_range(inode, alloc_start,
alloc_end - alloc_start); alloc_end - alloc_start);
...@@ -3489,38 +3493,8 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -3489,38 +3493,8 @@ static long btrfs_fallocate(struct file *file, int mode,
} }
locked_end = alloc_end - 1; locked_end = alloc_end - 1;
while (1) { lock_extent_bits(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
struct btrfs_ordered_extent *ordered;
/* the extent lock is ordered inside the running
* transaction
*/
lock_extent_bits(&BTRFS_I(inode)->io_tree, alloc_start,
locked_end, &cached_state);
ordered = btrfs_lookup_first_ordered_extent(BTRFS_I(inode),
locked_end);
if (ordered &&
ordered->file_offset + ordered->num_bytes > alloc_start &&
ordered->file_offset < alloc_end) {
btrfs_put_ordered_extent(ordered);
unlock_extent_cached(&BTRFS_I(inode)->io_tree,
alloc_start, locked_end,
&cached_state); &cached_state);
/*
* we can't wait on the range with the transaction
* running or with the extent lock held
*/
ret = btrfs_wait_ordered_range(inode, alloc_start,
alloc_end - alloc_start);
if (ret)
goto out;
} else {
if (ordered)
btrfs_put_ordered_extent(ordered);
break;
}
}
/* First, check if we exceed the qgroup limit */ /* First, check if we exceed the qgroup limit */
INIT_LIST_HEAD(&reserve_list); INIT_LIST_HEAD(&reserve_list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment