btrfs: add and use helper to assert an inode range is clean

We have four different scenarios where we don't expect to find ordered
extents after locking a file range:

1) During plain fallocate;
2) During hole punching;
3) During zero range;
4) During reflinks (both cloning and deduplication).

This is because in all these cases we follow the pattern:

1) Lock the inode's VFS lock in exclusive mode;

2) Lock the inode's i_mmap_lock in exclusive node, to serialize with
   mmap writes;

3) Flush delalloc in a file range and wait for all ordered extents
   to complete - both done through btrfs_wait_ordered_range();

4) Lock the file range in the inode's io_tree.

So add a helper that asserts that we don't have ordered extents for a
given range. Make the four scenarios listed above use this helper after
locking the respective file range.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Filipe Manana
2022-03-15 15:22:41 +00:00
committed by David Sterba
parent 55961c8abf
commit 63c34cb4c6
4 changed files with 51 additions and 2 deletions

View File

@@ -11261,6 +11261,41 @@ void btrfs_update_inode_bytes(struct btrfs_inode *inode,
spin_unlock(&inode->lock);
}
/**
* Verify that there are no ordered extents for a given file range.
*
* @inode: The target inode.
* @start: Start offset of the file range, should be sector size aligned.
* @end: End offset (inclusive) of the file range, its value +1 should be
* sector size aligned.
*
* This should typically be used for cases where we locked an inode's VFS lock in
* exclusive mode, we have also locked the inode's i_mmap_lock in exclusive mode,
* we have flushed all delalloc in the range, we have waited for all ordered
* extents in the range to complete and finally we have locked the file range in
* the inode's io_tree.
*/
void btrfs_assert_inode_range_clean(struct btrfs_inode *inode, u64 start, u64 end)
{
struct btrfs_root *root = inode->root;
struct btrfs_ordered_extent *ordered;
if (!IS_ENABLED(CONFIG_BTRFS_ASSERT))
return;
ordered = btrfs_lookup_first_ordered_range(inode, start, end + 1 - start);
if (ordered) {
btrfs_err(root->fs_info,
"found unexpected ordered extent in file range [%llu, %llu] for inode %llu root %llu (ordered range [%llu, %llu])",
start, end, btrfs_ino(inode), root->root_key.objectid,
ordered->file_offset,
ordered->file_offset + ordered->num_bytes - 1);
btrfs_put_ordered_extent(ordered);
}
ASSERT(ordered == NULL);
}
static const struct inode_operations btrfs_dir_inode_operations = {
.getattr = btrfs_getattr,
.lookup = btrfs_lookup,