mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
synced 2025-09-14 11:19:08 +10:00
btrfs: reduce the number of arguments to btrfs_run_delalloc_range
Instead of a separate page_started argument that tells the callers that btrfs_run_delalloc_range already started writeback by itself, overload the return value with a positive 1 in additio to 0 and a negative error code to indicate that is has already started writeback, and remove the nr_written argument as that caller can calculate it directly based on the range, and in fact already does so for the case where writeback wasn't started yet. Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
2c73162d64
commit
c56cbe9059
@ -498,8 +498,7 @@ int btrfs_prealloc_file_range_trans(struct inode *inode,
|
|||||||
u64 start, u64 num_bytes, u64 min_size,
|
u64 start, u64 num_bytes, u64 min_size,
|
||||||
loff_t actual_len, u64 *alloc_hint);
|
loff_t actual_len, u64 *alloc_hint);
|
||||||
int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page,
|
int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page,
|
||||||
u64 start, u64 end, int *page_started,
|
u64 start, u64 end, struct writeback_control *wbc);
|
||||||
unsigned long *nr_written, struct writeback_control *wbc);
|
|
||||||
int btrfs_writepage_cow_fixup(struct page *page);
|
int btrfs_writepage_cow_fixup(struct page *page);
|
||||||
int btrfs_encoded_io_compression_from_extent(struct btrfs_fs_info *fs_info,
|
int btrfs_encoded_io_compression_from_extent(struct btrfs_fs_info *fs_info,
|
||||||
int compress_type);
|
int compress_type);
|
||||||
|
@ -1190,10 +1190,7 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
|
|||||||
u64 delalloc_start = page_start;
|
u64 delalloc_start = page_start;
|
||||||
u64 delalloc_end = page_end;
|
u64 delalloc_end = page_end;
|
||||||
u64 delalloc_to_write = 0;
|
u64 delalloc_to_write = 0;
|
||||||
/* How many pages are started by btrfs_run_delalloc_range() */
|
int ret = 0;
|
||||||
unsigned long nr_written = 0;
|
|
||||||
int ret;
|
|
||||||
int page_started = 0;
|
|
||||||
|
|
||||||
while (delalloc_start < page_end) {
|
while (delalloc_start < page_end) {
|
||||||
delalloc_end = page_end;
|
delalloc_end = page_end;
|
||||||
@ -1202,9 +1199,10 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
|
|||||||
delalloc_start = delalloc_end + 1;
|
delalloc_start = delalloc_end + 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = btrfs_run_delalloc_range(inode, page, delalloc_start,
|
ret = btrfs_run_delalloc_range(inode, page, delalloc_start,
|
||||||
delalloc_end, &page_started, &nr_written, wbc);
|
delalloc_end, wbc);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
delalloc_start = delalloc_end + 1;
|
delalloc_start = delalloc_end + 1;
|
||||||
@ -1216,6 +1214,16 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
|
|||||||
*/
|
*/
|
||||||
delalloc_to_write +=
|
delalloc_to_write +=
|
||||||
DIV_ROUND_UP(delalloc_end + 1 - page_start, PAGE_SIZE);
|
DIV_ROUND_UP(delalloc_end + 1 - page_start, PAGE_SIZE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If btrfs_run_dealloc_range() already started I/O and unlocked
|
||||||
|
* the pages, we just need to account for them here.
|
||||||
|
*/
|
||||||
|
if (ret == 1) {
|
||||||
|
wbc->nr_to_write -= delalloc_to_write;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (wbc->nr_to_write < delalloc_to_write) {
|
if (wbc->nr_to_write < delalloc_to_write) {
|
||||||
int thresh = 8192;
|
int thresh = 8192;
|
||||||
|
|
||||||
@ -1225,16 +1233,6 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
|
|||||||
thresh);
|
thresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Did btrfs_run_dealloc_range() already unlock and start the IO? */
|
|
||||||
if (page_started) {
|
|
||||||
/*
|
|
||||||
* We've unlocked the page, so we can't update the mapping's
|
|
||||||
* writeback index, just update nr_to_write.
|
|
||||||
*/
|
|
||||||
wbc->nr_to_write -= nr_written;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +127,7 @@ static int btrfs_truncate(struct btrfs_inode *inode, bool skip_writeback);
|
|||||||
|
|
||||||
static noinline int cow_file_range(struct btrfs_inode *inode,
|
static noinline int cow_file_range(struct btrfs_inode *inode,
|
||||||
struct page *locked_page,
|
struct page *locked_page,
|
||||||
u64 start, u64 end, int *page_started,
|
u64 start, u64 end, u64 *done_offset,
|
||||||
unsigned long *nr_written, u64 *done_offset,
|
|
||||||
bool keep_locked, bool no_inline);
|
bool keep_locked, bool no_inline);
|
||||||
static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start,
|
static struct extent_map *create_io_em(struct btrfs_inode *inode, u64 start,
|
||||||
u64 len, u64 orig_start, u64 block_start,
|
u64 len, u64 orig_start, u64 block_start,
|
||||||
@ -1130,8 +1129,6 @@ static void submit_uncompressed_range(struct btrfs_inode *inode,
|
|||||||
{
|
{
|
||||||
u64 start = async_extent->start;
|
u64 start = async_extent->start;
|
||||||
u64 end = async_extent->start + async_extent->ram_size - 1;
|
u64 end = async_extent->start + async_extent->ram_size - 1;
|
||||||
unsigned long nr_written = 0;
|
|
||||||
int page_started = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
struct writeback_control wbc = {
|
struct writeback_control wbc = {
|
||||||
.sync_mode = WB_SYNC_ALL,
|
.sync_mode = WB_SYNC_ALL,
|
||||||
@ -1147,10 +1144,9 @@ static void submit_uncompressed_range(struct btrfs_inode *inode,
|
|||||||
* Also we call cow_file_range() with @unlock_page == 0, so that we
|
* Also we call cow_file_range() with @unlock_page == 0, so that we
|
||||||
* can directly submit them without interruption.
|
* can directly submit them without interruption.
|
||||||
*/
|
*/
|
||||||
ret = cow_file_range(inode, locked_page, start, end, &page_started,
|
ret = cow_file_range(inode, locked_page, start, end, NULL, true, false);
|
||||||
&nr_written, NULL, true, false);
|
|
||||||
/* Inline extent inserted, page gets unlocked and everything is done */
|
/* Inline extent inserted, page gets unlocked and everything is done */
|
||||||
if (page_started)
|
if (ret == 1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -1360,8 +1356,8 @@ static u64 get_extent_allocation_hint(struct btrfs_inode *inode, u64 start,
|
|||||||
*
|
*
|
||||||
* When this function fails, it unlocks all pages except @locked_page.
|
* When this function fails, it unlocks all pages except @locked_page.
|
||||||
*
|
*
|
||||||
* When this function successfully creates an inline extent, it sets page_started
|
* When this function successfully creates an inline extent, it returns 1 and
|
||||||
* to 1 and unlocks all pages including locked_page and starts I/O on them.
|
* unlocks all pages including locked_page and starts I/O on them.
|
||||||
* (In reality inline extents are limited to a single page, so locked_page is
|
* (In reality inline extents are limited to a single page, so locked_page is
|
||||||
* the only page handled anyway).
|
* the only page handled anyway).
|
||||||
*
|
*
|
||||||
@ -1378,9 +1374,8 @@ static u64 get_extent_allocation_hint(struct btrfs_inode *inode, u64 start,
|
|||||||
* example.
|
* example.
|
||||||
*/
|
*/
|
||||||
static noinline int cow_file_range(struct btrfs_inode *inode,
|
static noinline int cow_file_range(struct btrfs_inode *inode,
|
||||||
struct page *locked_page,
|
struct page *locked_page, u64 start, u64 end,
|
||||||
u64 start, u64 end, int *page_started,
|
u64 *done_offset,
|
||||||
unsigned long *nr_written, u64 *done_offset,
|
|
||||||
bool keep_locked, bool no_inline)
|
bool keep_locked, bool no_inline)
|
||||||
{
|
{
|
||||||
struct btrfs_root *root = inode->root;
|
struct btrfs_root *root = inode->root;
|
||||||
@ -1440,9 +1435,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
|
|||||||
EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
|
EXTENT_DELALLOC_NEW | EXTENT_DEFRAG |
|
||||||
EXTENT_DO_ACCOUNTING, PAGE_UNLOCK |
|
EXTENT_DO_ACCOUNTING, PAGE_UNLOCK |
|
||||||
PAGE_START_WRITEBACK | PAGE_END_WRITEBACK);
|
PAGE_START_WRITEBACK | PAGE_END_WRITEBACK);
|
||||||
*nr_written = *nr_written +
|
|
||||||
(end - start + PAGE_SIZE) / PAGE_SIZE;
|
|
||||||
*page_started = 1;
|
|
||||||
/*
|
/*
|
||||||
* locked_page is locked by the caller of
|
* locked_page is locked by the caller of
|
||||||
* writepage_delalloc(), not locked by
|
* writepage_delalloc(), not locked by
|
||||||
@ -1452,11 +1444,11 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
|
|||||||
* as it doesn't have any subpage::writers recorded.
|
* as it doesn't have any subpage::writers recorded.
|
||||||
*
|
*
|
||||||
* Here we manually unlock the page, since the caller
|
* Here we manually unlock the page, since the caller
|
||||||
* can't use page_started to determine if it's an
|
* can't determine if it's an inline extent or a
|
||||||
* inline extent or a compressed extent.
|
* compressed extent.
|
||||||
*/
|
*/
|
||||||
unlock_page(locked_page);
|
unlock_page(locked_page);
|
||||||
goto out;
|
return 1;
|
||||||
} else if (ret < 0) {
|
} else if (ret < 0) {
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
@ -1570,7 +1562,6 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
out_drop_extent_cache:
|
out_drop_extent_cache:
|
||||||
@ -1721,10 +1712,8 @@ static noinline void async_cow_free(struct btrfs_work *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool run_delalloc_compressed(struct btrfs_inode *inode,
|
static bool run_delalloc_compressed(struct btrfs_inode *inode,
|
||||||
struct writeback_control *wbc,
|
struct page *locked_page, u64 start,
|
||||||
struct page *locked_page,
|
u64 end, struct writeback_control *wbc)
|
||||||
u64 start, u64 end, int *page_started,
|
|
||||||
unsigned long *nr_written)
|
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
||||||
struct cgroup_subsys_state *blkcg_css = wbc_blkcg_css(wbc);
|
struct cgroup_subsys_state *blkcg_css = wbc_blkcg_css(wbc);
|
||||||
@ -1806,34 +1795,25 @@ static bool run_delalloc_compressed(struct btrfs_inode *inode,
|
|||||||
|
|
||||||
btrfs_queue_work(fs_info->delalloc_workers, &async_chunk[i].work);
|
btrfs_queue_work(fs_info->delalloc_workers, &async_chunk[i].work);
|
||||||
|
|
||||||
*nr_written += nr_pages;
|
|
||||||
start = cur_end + 1;
|
start = cur_end + 1;
|
||||||
}
|
}
|
||||||
*page_started = 1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
|
static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
|
||||||
struct page *locked_page, u64 start,
|
struct page *locked_page, u64 start,
|
||||||
u64 end, int *page_started,
|
u64 end, struct writeback_control *wbc)
|
||||||
unsigned long *nr_written,
|
|
||||||
struct writeback_control *wbc)
|
|
||||||
{
|
{
|
||||||
u64 done_offset = end;
|
u64 done_offset = end;
|
||||||
int ret;
|
int ret;
|
||||||
bool locked_page_done = false;
|
bool locked_page_done = false;
|
||||||
|
|
||||||
while (start <= end) {
|
while (start <= end) {
|
||||||
ret = cow_file_range(inode, locked_page, start, end, page_started,
|
ret = cow_file_range(inode, locked_page, start, end, &done_offset,
|
||||||
nr_written, &done_offset, true, false);
|
true, false);
|
||||||
if (ret && ret != -EAGAIN)
|
if (ret && ret != -EAGAIN)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (*page_started) {
|
|
||||||
ASSERT(ret == 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
done_offset = end;
|
done_offset = end;
|
||||||
|
|
||||||
@ -1854,9 +1834,7 @@ static noinline int run_delalloc_zoned(struct btrfs_inode *inode,
|
|||||||
start = done_offset + 1;
|
start = done_offset + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*page_started = 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
|
static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
|
||||||
@ -1889,8 +1867,6 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page,
|
|||||||
const bool is_reloc_ino = btrfs_is_data_reloc_root(inode->root);
|
const bool is_reloc_ino = btrfs_is_data_reloc_root(inode->root);
|
||||||
const u64 range_bytes = end + 1 - start;
|
const u64 range_bytes = end + 1 - start;
|
||||||
struct extent_io_tree *io_tree = &inode->io_tree;
|
struct extent_io_tree *io_tree = &inode->io_tree;
|
||||||
int page_started = 0;
|
|
||||||
unsigned long nr_written;
|
|
||||||
u64 range_start = start;
|
u64 range_start = start;
|
||||||
u64 count;
|
u64 count;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1951,9 +1927,8 @@ static int fallback_to_cow(struct btrfs_inode *inode, struct page *locked_page,
|
|||||||
* is written out and unlocked directly and a normal NOCOW extent
|
* is written out and unlocked directly and a normal NOCOW extent
|
||||||
* doesn't work.
|
* doesn't work.
|
||||||
*/
|
*/
|
||||||
ret = cow_file_range(inode, locked_page, start, end, &page_started,
|
ret = cow_file_range(inode, locked_page, start, end, NULL, false, true);
|
||||||
&nr_written, NULL, false, true);
|
ASSERT(ret != 1);
|
||||||
ASSERT(!page_started);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2389,15 +2364,14 @@ static bool should_nocow(struct btrfs_inode *inode, u64 start, u64 end)
|
|||||||
* being touched for the first time.
|
* being touched for the first time.
|
||||||
*/
|
*/
|
||||||
int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page,
|
int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page,
|
||||||
u64 start, u64 end, int *page_started, unsigned long *nr_written,
|
u64 start, u64 end, struct writeback_control *wbc)
|
||||||
struct writeback_control *wbc)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
|
||||||
const bool zoned = btrfs_is_zoned(inode->root->fs_info);
|
const bool zoned = btrfs_is_zoned(inode->root->fs_info);
|
||||||
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The range must cover part of the @locked_page, or the returned
|
* The range must cover part of the @locked_page, or a return of 1
|
||||||
* @page_started can confuse the caller.
|
* can confuse the caller.
|
||||||
*/
|
*/
|
||||||
ASSERT(!(end <= page_offset(locked_page) ||
|
ASSERT(!(end <= page_offset(locked_page) ||
|
||||||
start >= page_offset(locked_page) + PAGE_SIZE));
|
start >= page_offset(locked_page) + PAGE_SIZE));
|
||||||
@ -2417,20 +2391,17 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page
|
|||||||
|
|
||||||
if (btrfs_inode_can_compress(inode) &&
|
if (btrfs_inode_can_compress(inode) &&
|
||||||
inode_need_compress(inode, start, end) &&
|
inode_need_compress(inode, start, end) &&
|
||||||
run_delalloc_compressed(inode, wbc, locked_page, start,
|
run_delalloc_compressed(inode, locked_page, start, end, wbc))
|
||||||
end, page_started, nr_written))
|
return 1;
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (zoned)
|
if (zoned)
|
||||||
ret = run_delalloc_zoned(inode, locked_page, start, end,
|
ret = run_delalloc_zoned(inode, locked_page, start, end, wbc);
|
||||||
page_started, nr_written, wbc);
|
|
||||||
else
|
else
|
||||||
ret = cow_file_range(inode, locked_page, start, end,
|
ret = cow_file_range(inode, locked_page, start, end, NULL,
|
||||||
page_started, nr_written, NULL, false, false);
|
false, false);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
ASSERT(ret <= 0);
|
if (ret < 0)
|
||||||
if (ret)
|
|
||||||
btrfs_cleanup_ordered_extents(inode, locked_page, start,
|
btrfs_cleanup_ordered_extents(inode, locked_page, start,
|
||||||
end - start + 1);
|
end - start + 1);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user