btrfs: factor out btree page submission code to a helper

In btree_write_cache_pages() we have a btree page submission routine
buried deeply in a nested loop.

This patch will extract that part of code into a helper function,
submit_eb_page(), to do the same work.

Since submit_eb_page() now can return >0 for successful extent
buffer submission, remove the "ASSERT(ret <= 0);" line.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2020-12-02 14:48:00 +08:00 committed by David Sterba
parent f44cf41075
commit f91e0d0c4c
1 changed files with 75 additions and 47 deletions

View File

@ -3987,10 +3987,81 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb,
return ret;
}
/*
* Submit all page(s) of one extent buffer.
*
* @page: the page of one extent buffer
* @eb_context: to determine if we need to submit this page, if current page
* belongs to this eb, we don't need to submit
*
* The caller should pass each page in their bytenr order, and here we use
* @eb_context to determine if we have submitted pages of one extent buffer.
*
* If we have, we just skip until we hit a new page that doesn't belong to
* current @eb_context.
*
* If not, we submit all the page(s) of the extent buffer.
*
* Return >0 if we have submitted the extent buffer successfully.
* Return 0 if we don't need to submit the page, as it's already submitted by
* previous call.
* Return <0 for fatal error.
*/
static int submit_eb_page(struct page *page, struct writeback_control *wbc,
struct extent_page_data *epd,
struct extent_buffer **eb_context)
{
struct address_space *mapping = page->mapping;
struct extent_buffer *eb;
int ret;
if (!PagePrivate(page))
return 0;
spin_lock(&mapping->private_lock);
if (!PagePrivate(page)) {
spin_unlock(&mapping->private_lock);
return 0;
}
eb = (struct extent_buffer *)page->private;
/*
* Shouldn't happen and normally this would be a BUG_ON but no point
* crashing the machine for something we can survive anyway.
*/
if (WARN_ON(!eb)) {
spin_unlock(&mapping->private_lock);
return 0;
}
if (eb == *eb_context) {
spin_unlock(&mapping->private_lock);
return 0;
}
ret = atomic_inc_not_zero(&eb->refs);
spin_unlock(&mapping->private_lock);
if (!ret)
return 0;
*eb_context = eb;
ret = lock_extent_buffer_for_io(eb, epd);
if (ret <= 0) {
free_extent_buffer(eb);
return ret;
}
ret = write_one_eb(eb, wbc, epd);
free_extent_buffer(eb);
if (ret < 0)
return ret;
return 1;
}
int btree_write_cache_pages(struct address_space *mapping,
struct writeback_control *wbc)
{
struct extent_buffer *eb, *prev_eb = NULL;
struct extent_buffer *eb_context = NULL;
struct extent_page_data epd = {
.bio = NULL,
.extent_locked = 0,
@ -4036,56 +4107,14 @@ retry:
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
if (!PagePrivate(page))
ret = submit_eb_page(page, wbc, &epd, &eb_context);
if (ret == 0)
continue;
spin_lock(&mapping->private_lock);
if (!PagePrivate(page)) {
spin_unlock(&mapping->private_lock);
continue;
}
eb = (struct extent_buffer *)page->private;
/*
* Shouldn't happen and normally this would be a BUG_ON
* but no sense in crashing the users box for something
* we can survive anyway.
*/
if (WARN_ON(!eb)) {
spin_unlock(&mapping->private_lock);
continue;
}
if (eb == prev_eb) {
spin_unlock(&mapping->private_lock);
continue;
}
ret = atomic_inc_not_zero(&eb->refs);
spin_unlock(&mapping->private_lock);
if (!ret)
continue;
prev_eb = eb;
ret = lock_extent_buffer_for_io(eb, &epd);
if (!ret) {
free_extent_buffer(eb);
continue;
} else if (ret < 0) {
if (ret < 0) {
done = 1;
free_extent_buffer(eb);
break;
}
ret = write_one_eb(eb, wbc, &epd);
if (ret) {
done = 1;
free_extent_buffer(eb);
break;
}
free_extent_buffer(eb);
/*
* the filesystem may choose to bump up nr_to_write.
* We have to make sure to honor the new nr_to_write
@ -4105,7 +4134,6 @@ retry:
index = 0;
goto retry;
}
ASSERT(ret <= 0);
if (ret < 0) {
end_write_bio(&epd, ret);
return ret;