Commit 42c01100 authored by Naohiro Aota's avatar Naohiro Aota Committed by David Sterba
Browse files

btrfs: zoned: introduce dedicated data write path for zoned filesystems



If more than one IO is issued for one file extent, these IO can be
written to separate regions on a device. Since we cannot map one file
extent to such a separate area on a zoned filesystem, we need to follow
the "one IO == one ordered extent" rule.

The normal buffered, uncompressed and not pre-allocated write path (used
by cow_file_range()) sometimes does not follow this rule. It can write a
part of an ordered extent when specified a region to write e.g., when
its called from fdatasync().

Introduce a dedicated (uncompressed buffered) data write path for zoned
filesystems, that will COW the region and write it at once.

Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 544d24f9
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -1394,6 +1394,29 @@ static int cow_file_range_async(struct btrfs_inode *inode,
	return 0;
}

static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
				       struct page *locked_page, u64 start,
				       u64 end, int *page_started,
				       unsigned long *nr_written)
{
	int ret;

	ret = cow_file_range(inode, locked_page, start, end, page_started,
			     nr_written, 0);
	if (ret)
		return ret;

	if (*page_started)
		return 0;

	__set_page_dirty_nobuffers(locked_page);
	account_page_redirty(locked_page);
	extent_write_locked_range(&inode->vfs_inode, start, end, WB_SYNC_ALL);
	*page_started = 1;

	return 0;
}

static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
					u64 bytenr, u64 num_bytes)
{
@@ -1871,15 +1894,22 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page
{
	int ret;
	int force_cow = need_force_cow(inode, start, end);
	const bool zoned = btrfs_is_zoned(inode->root->fs_info);

	if (inode->flags & BTRFS_INODE_NODATACOW && !force_cow) {
		ASSERT(!zoned);
		ret = run_delalloc_nocow(inode, locked_page, start, end,
					 page_started, 1, nr_written);
	} else if (inode->flags & BTRFS_INODE_PREALLOC && !force_cow) {
		ASSERT(!zoned);
		ret = run_delalloc_nocow(inode, locked_page, start, end,
					 page_started, 0, nr_written);
	} else if (!inode_can_compress(inode) ||
		   !inode_need_compress(inode, start, end)) {
		if (zoned)
			ret = run_delalloc_zoned(inode, locked_page, start, end,
						 page_started, nr_written);
		else
			ret = cow_file_range(inode, locked_page, start, end,
					     page_started, nr_written, 1);
	} else {