mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 23:32:14 +00:00
ext4: fix fio regression
We (Linux Kernel Performance project) found a regression introduced
by commit:
f7fec032aa
ext4: track all extent status in extent status tree
The commit causes about 20% performance decrease in fio random write
test. Profiler shows that rb_next() uses a lot of CPU time. The call
stack is:
rb_next
ext4_es_find_delayed_extent
ext4_map_blocks
_ext4_get_block
ext4_get_block_write
__blockdev_direct_IO
ext4_direct_IO
generic_file_direct_write
__generic_file_aio_write
ext4_file_write
aio_rw_vect_retry
aio_run_iocb
do_io_submit
sys_io_submit
system_call_fastpath
io_submit
td_io_getevents
io_u_queued_complete
thread_main
main
__libc_start_main
The cause is that ext4_es_find_delayed_extent() doesn't have an
upper bound, it keeps searching until a delayed extent is found.
When there are a lots of non-delayed entries in the extent state
tree, ext4_es_find_delayed_extent() may uses a lot of CPU time.
Reported-by: LKP project <lkp@linux.intel.com>
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
Cc: "Theodore Ts'o" <tytso@mit.edu>
This commit is contained in:
parent
0d606e2c9f
commit
e30b5dca15
5 changed files with 23 additions and 14 deletions
|
@ -232,14 +232,16 @@ static struct extent_status *__es_tree_search(struct rb_root *root,
|
|||
}
|
||||
|
||||
/*
|
||||
* ext4_es_find_delayed_extent: find the 1st delayed extent covering @es->lblk
|
||||
* if it exists, otherwise, the next extent after @es->lblk.
|
||||
* ext4_es_find_delayed_extent_range: find the 1st delayed extent covering
|
||||
* @es->lblk if it exists, otherwise, the next extent after @es->lblk.
|
||||
*
|
||||
* @inode: the inode which owns delayed extents
|
||||
* @lblk: the offset where we start to search
|
||||
* @end: the offset where we stop to search
|
||||
* @es: delayed extent that we found
|
||||
*/
|
||||
void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
|
||||
void ext4_es_find_delayed_extent_range(struct inode *inode,
|
||||
ext4_lblk_t lblk, ext4_lblk_t end,
|
||||
struct extent_status *es)
|
||||
{
|
||||
struct ext4_es_tree *tree = NULL;
|
||||
|
@ -247,7 +249,8 @@ void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
|
|||
struct rb_node *node;
|
||||
|
||||
BUG_ON(es == NULL);
|
||||
trace_ext4_es_find_delayed_extent_enter(inode, lblk);
|
||||
BUG_ON(end < lblk);
|
||||
trace_ext4_es_find_delayed_extent_range_enter(inode, lblk);
|
||||
|
||||
read_lock(&EXT4_I(inode)->i_es_lock);
|
||||
tree = &EXT4_I(inode)->i_es_tree;
|
||||
|
@ -270,6 +273,10 @@ out:
|
|||
if (es1 && !ext4_es_is_delayed(es1)) {
|
||||
while ((node = rb_next(&es1->rb_node)) != NULL) {
|
||||
es1 = rb_entry(node, struct extent_status, rb_node);
|
||||
if (es1->es_lblk > end) {
|
||||
es1 = NULL;
|
||||
break;
|
||||
}
|
||||
if (ext4_es_is_delayed(es1))
|
||||
break;
|
||||
}
|
||||
|
@ -285,7 +292,7 @@ out:
|
|||
read_unlock(&EXT4_I(inode)->i_es_lock);
|
||||
|
||||
ext4_es_lru_add(inode);
|
||||
trace_ext4_es_find_delayed_extent_exit(inode, es);
|
||||
trace_ext4_es_find_delayed_extent_range_exit(inode, es);
|
||||
}
|
||||
|
||||
static struct extent_status *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue