Commit f47960f4 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: reloc: factor out relocation page read and dirty part

In function relocate_file_extent_cluster(), we have a big loop for
marking all involved page delalloc.

That part is long enough to be contained in one function, so this patch
will move that code chunk into a new function, relocate_one_page().

This also provides enough space for later subpage work.
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent a6e66e6f
...@@ -2886,91 +2886,48 @@ noinline int btrfs_should_cancel_balance(struct btrfs_fs_info *fs_info) ...@@ -2886,91 +2886,48 @@ noinline int btrfs_should_cancel_balance(struct btrfs_fs_info *fs_info)
} }
ALLOW_ERROR_INJECTION(btrfs_should_cancel_balance, TRUE); ALLOW_ERROR_INJECTION(btrfs_should_cancel_balance, TRUE);
static int relocate_file_extent_cluster(struct inode *inode, static int relocate_one_page(struct inode *inode, struct file_ra_state *ra,
struct file_extent_cluster *cluster) struct file_extent_cluster *cluster,
int *cluster_nr, unsigned long page_index)
{ {
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
u64 page_start;
u64 page_end;
u64 offset = BTRFS_I(inode)->index_cnt; u64 offset = BTRFS_I(inode)->index_cnt;
unsigned long index; const unsigned long last_index = (cluster->end - offset) >> PAGE_SHIFT;
unsigned long last_index;
struct page *page;
struct file_ra_state *ra;
gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping); gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int nr = 0; struct page *page;
int ret = 0; u64 page_start;
u64 page_end;
if (!cluster->nr) int ret;
return 0;
ra = kzalloc(sizeof(*ra), GFP_NOFS);
if (!ra)
return -ENOMEM;
ret = prealloc_file_extent_cluster(BTRFS_I(inode), cluster);
if (ret)
goto out;
file_ra_state_init(ra, inode->i_mapping);
ret = setup_extent_mapping(inode, cluster->start - offset,
cluster->end - offset, cluster->start);
if (ret)
goto out;
index = (cluster->start - offset) >> PAGE_SHIFT; ASSERT(page_index <= last_index);
last_index = (cluster->end - offset) >> PAGE_SHIFT; ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode), PAGE_SIZE);
while (index <= last_index) {
ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode),
PAGE_SIZE);
if (ret) if (ret)
goto out; return ret;
page = find_lock_page(inode->i_mapping, index); page = find_lock_page(inode->i_mapping, page_index);
if (!page) { if (!page) {
page_cache_sync_readahead(inode->i_mapping, page_cache_sync_readahead(inode->i_mapping, ra, NULL,
ra, NULL, index, page_index, last_index + 1 - page_index);
last_index + 1 - index); page = find_or_create_page(inode->i_mapping, page_index, mask);
page = find_or_create_page(inode->i_mapping, index,
mask);
if (!page) { if (!page) {
btrfs_delalloc_release_metadata(BTRFS_I(inode),
PAGE_SIZE, true);
btrfs_delalloc_release_extents(BTRFS_I(inode),
PAGE_SIZE);
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto release_delalloc;
} }
} }
ret = set_page_extent_mapped(page); ret = set_page_extent_mapped(page);
if (ret < 0) { if (ret < 0)
btrfs_delalloc_release_metadata(BTRFS_I(inode), goto release_page;
PAGE_SIZE, true);
btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
unlock_page(page);
put_page(page);
goto out;
}
if (PageReadahead(page)) { if (PageReadahead(page))
page_cache_async_readahead(inode->i_mapping, page_cache_async_readahead(inode->i_mapping, ra, NULL, page,
ra, NULL, page, index, page_index, last_index + 1 - page_index);
last_index + 1 - index);
}
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
btrfs_readpage(NULL, page); btrfs_readpage(NULL, page);
lock_page(page); lock_page(page);
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
unlock_page(page);
put_page(page);
btrfs_delalloc_release_metadata(BTRFS_I(inode),
PAGE_SIZE, true);
btrfs_delalloc_release_extents(BTRFS_I(inode),
PAGE_SIZE);
ret = -EIO; ret = -EIO;
goto out; goto release_page;
} }
} }
...@@ -2979,49 +2936,80 @@ static int relocate_file_extent_cluster(struct inode *inode, ...@@ -2979,49 +2936,80 @@ static int relocate_file_extent_cluster(struct inode *inode,
lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end); lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end);
if (nr < cluster->nr && if (*cluster_nr < cluster->nr &&
page_start + offset == cluster->boundary[nr]) { page_start + offset == cluster->boundary[*cluster_nr]) {
set_extent_bits(&BTRFS_I(inode)->io_tree, set_extent_bits(&BTRFS_I(inode)->io_tree, page_start, page_end,
page_start, page_end,
EXTENT_BOUNDARY); EXTENT_BOUNDARY);
nr++; (*cluster_nr)++;
} }
ret = btrfs_set_extent_delalloc(BTRFS_I(inode), page_start, ret = btrfs_set_extent_delalloc(BTRFS_I(inode), page_start, page_end,
page_end, 0, NULL); 0, NULL);
if (ret) { if (ret) {
unlock_page(page); clear_extent_bits(&BTRFS_I(inode)->io_tree, page_start,
put_page(page); page_end, EXTENT_LOCKED | EXTENT_BOUNDARY);
btrfs_delalloc_release_metadata(BTRFS_I(inode), goto release_page;
PAGE_SIZE, true);
btrfs_delalloc_release_extents(BTRFS_I(inode),
PAGE_SIZE);
clear_extent_bits(&BTRFS_I(inode)->io_tree,
page_start, page_end,
EXTENT_LOCKED | EXTENT_BOUNDARY);
goto out;
} }
set_page_dirty(page); set_page_dirty(page);
unlock_extent(&BTRFS_I(inode)->io_tree, unlock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end);
page_start, page_end);
unlock_page(page); unlock_page(page);
put_page(page); put_page(page);
index++;
btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE); btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
balance_dirty_pages_ratelimited(inode->i_mapping); balance_dirty_pages_ratelimited(inode->i_mapping);
btrfs_throttle(fs_info); btrfs_throttle(fs_info);
if (btrfs_should_cancel_balance(fs_info)) { if (btrfs_should_cancel_balance(fs_info))
ret = -ECANCELED; ret = -ECANCELED;
return ret;
release_page:
unlock_page(page);
put_page(page);
release_delalloc:
btrfs_delalloc_release_metadata(BTRFS_I(inode), PAGE_SIZE, true);
btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE);
return ret;
}
static int relocate_file_extent_cluster(struct inode *inode,
struct file_extent_cluster *cluster)
{
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
u64 offset = BTRFS_I(inode)->index_cnt;
unsigned long index;
unsigned long last_index;
struct file_ra_state *ra;
int cluster_nr = 0;
int ret = 0;
if (!cluster->nr)
return 0;
ra = kzalloc(sizeof(*ra), GFP_NOFS);
if (!ra)
return -ENOMEM;
ret = prealloc_file_extent_cluster(BTRFS_I(inode), cluster);
if (ret)
goto out; goto out;
}
} file_ra_state_init(ra, inode->i_mapping);
WARN_ON(nr != cluster->nr);
ret = setup_extent_mapping(inode, cluster->start - offset,
cluster->end - offset, cluster->start);
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_page(inode, ra, cluster, &cluster_nr, index);
if (btrfs_is_zoned(fs_info) && !ret) if (btrfs_is_zoned(fs_info) && !ret)
ret = btrfs_wait_ordered_range(inode, 0, (u64)-1); ret = btrfs_wait_ordered_range(inode, 0, (u64)-1);
if (ret == 0)
WARN_ON(cluster_nr != cluster->nr);
out: out:
kfree(ra); kfree(ra);
return ret; return ret;
......
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