Commit 041c39da authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: enable large data folios for data reloc inode



For data reloc inodes, they are a special type of inodes that are not
exposed to user space, and are only utilized during data block groups
relocation.

They do not go under regular read-write operations, but have their file
extents manually created to have the same layout of a block group, then
its content is read from the original block group, and written back to
the new location which is in a new block group.

Previously all the handling was done in page units, and commit
c2832898 ("btrfs: make relocate_one_page() handle subpage case")
changed the handling to subpage blocks.

On the other hand, data reloc inodes are a perfect match for large data
folios, as each relocation cluster represents one or more data extents
that are contiguous in their logical addresses.

This patch enables large folios for data reloc inodes by:

- Remove the special handling of data reloc inodes when setting folio
  order

- Change relocate_one_folio() to return the file offset of the next
  folio
  Originally it's designed to handle fixed page sized blocks, but with
  large folios, we can handle a large folio, thus we have to return the
  end of the current folio.

- Remove the warning on folio_order()

- Use folio_size() to replace fixed PAGE_SIZE usage

- Use file_offset as iterator inside relocate_file_extent_cluster

Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent cec780a1
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -530,10 +530,6 @@ static inline void btrfs_set_inode_mapping_order(struct btrfs_inode *inode)
	/* Metadata inode should not reach here. */
	ASSERT(is_data_inode(inode));

	/* For data reloc inode, it still requires page sized folio. */
	if (unlikely(btrfs_is_data_reloc_root(inode->root)))
		return;

	/* We only allow BITS_PER_LONGS blocks for each bitmap. */
#ifdef CONFIG_BTRFS_EXPERIMENTAL
	mapping_set_folio_order_range(inode->vfs_inode.i_mapping, 0,
+13 −11
Original line number Diff line number Diff line
@@ -2772,13 +2772,15 @@ static u64 get_cluster_boundary_end(const struct file_extent_cluster *cluster,

static int relocate_one_folio(struct reloc_control *rc,
			      struct file_ra_state *ra,
			      int *cluster_nr, pgoff_t index)
			      int *cluster_nr, u64 *file_offset_ret)
{
	const struct file_extent_cluster *cluster = &rc->cluster;
	struct inode *inode = rc->data_inode;
	struct btrfs_fs_info *fs_info = inode_to_fs_info(inode);
	const u64 orig_file_offset = *file_offset_ret;
	u64 offset = BTRFS_I(inode)->reloc_block_group_start;
	const pgoff_t last_index = (cluster->end - offset) >> PAGE_SHIFT;
	const pgoff_t index = orig_file_offset >> PAGE_SHIFT;
	gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
	struct folio *folio;
	u64 folio_start;
@@ -2811,8 +2813,6 @@ static int relocate_one_folio(struct reloc_control *rc,
			return PTR_ERR(folio);
	}

	WARN_ON(folio_order(folio));

	if (folio_test_readahead(folio) && !use_rst)
		page_cache_async_readahead(inode->i_mapping, ra, NULL,
					   folio, last_index + 1 - index);
@@ -2841,7 +2841,7 @@ static int relocate_one_folio(struct reloc_control *rc,
		goto release_folio;

	folio_start = folio_pos(folio);
	folio_end = folio_start + PAGE_SIZE - 1;
	folio_end = folio_start + folio_size(folio) - 1;

	/*
	 * Start from the cluster, as for subpage case, the cluster can start
@@ -2889,7 +2889,8 @@ static int relocate_one_folio(struct reloc_control *rc,
		 * EXTENT_BOUNDARY bit prevents current extent from being merged
		 * with previous extent.
		 */
		if (in_range(cluster->boundary[*cluster_nr] - offset, folio_start, PAGE_SIZE)) {
		if (in_range(cluster->boundary[*cluster_nr] - offset,
			     folio_start, folio_size(folio))) {
			u64 boundary_start = cluster->boundary[*cluster_nr] -
						offset;
			u64 boundary_end = boundary_start +
@@ -2919,6 +2920,7 @@ static int relocate_one_folio(struct reloc_control *rc,
	btrfs_throttle(fs_info);
	if (btrfs_should_cancel_balance(fs_info))
		ret = -ECANCELED;
	*file_offset_ret = folio_end + 1;
	return ret;

release_folio:
@@ -2932,8 +2934,7 @@ static int relocate_file_extent_cluster(struct reloc_control *rc)
	struct inode *inode = rc->data_inode;
	const struct file_extent_cluster *cluster = &rc->cluster;
	u64 offset = BTRFS_I(inode)->reloc_block_group_start;
	pgoff_t index;
	pgoff_t last_index;
	u64 cur_file_offset = cluster->start - offset;
	struct file_ra_state *ra;
	int cluster_nr = 0;
	int ret = 0;
@@ -2955,10 +2956,11 @@ static int relocate_file_extent_cluster(struct reloc_control *rc)
	if (ret)
		goto out;

	last_index = (cluster->end - offset) >> PAGE_SHIFT;
	for (index = (cluster->start - offset) >> PAGE_SHIFT;
	     index <= last_index && !ret; index++)
		ret = relocate_one_folio(rc, ra, &cluster_nr, index);
	while (cur_file_offset < cluster->end - offset) {
		ret = relocate_one_folio(rc, ra, &cluster_nr, &cur_file_offset);
		if (ret)
			break;
	}
	if (ret == 0)
		WARN_ON(cluster_nr != cluster->nr);
out: