[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1455010041-23082-1-git-send-email-dmonakhov@openvz.org>
Date: Tue, 9 Feb 2016 13:27:21 +0400
From: Dmitry Monakhov <dmonakhov@...nvz.org>
To: linux-ext4@...r.kernel.org
Cc: tytso@....edu, Dmitry Monakhov <dmonakhov@...nvz.org>
Subject: [PATCH] ext4: fix extent cache fragmentation
Currently we populate extent-status inside ext4_map_blocks() by map's result
which is sub-optimal because usually map request are too small (few blocks),
even is extent itself is big (thousands of blocks).
In my case I have perfectly plain file:
File size of /mnt/static_exec_test is 889320 (218 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 217: 33024.. 33241: 218: last,eof
Test case performs exec in a loop which result in random page faults
W/o patch es_trace looks like follows (extent status tree contains 39 peaces):
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 198
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [198/1) mapped 33222 status W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 0
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 2 [0/1) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 197
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [197/1) mapped 33221 status W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 196
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [196/1) mapped 33220 status W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 17
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [17/1) mapped 33041 status W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 159
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [159/1) mapped 33183 status W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 18
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [18/1) mapped 33042 status W
With the patch it looks much more sane (extent status tree contains 1 peace)
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 198
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 0 [0/0) 0
ext4_es_insert_extent: dev 1,0 ino 12 es [0/218) mapped 33024 status W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 198
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 0
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 197
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 196
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 17
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 159
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 18
ext4_es_lookup_extent_exit: dev 1,0 ino 12 found 1 [0/218) 33024 W
ext4_es_lookup_extent_enter: dev 1,0 ino 12 lblk 59
Signed-off-by: Dmitry Monakhov <dmonakhov@...nvz.org>
---
fs/ext4/ext4.h | 1 +
fs/ext4/extents.c | 6 ++++++
fs/ext4/extents_status.c | 2 +-
fs/ext4/inode.c | 5 +++--
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0662b28..6dbdabc 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -567,6 +567,7 @@ enum {
#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0100
/* Write zeros to newly created written extents */
#define EXT4_GET_BLOCKS_ZERO 0x0200
+#define EXT4_GET_BLOCKS_CACHE 0x0400
#define EXT4_GET_BLOCKS_CREATE_ZERO (EXT4_GET_BLOCKS_CREATE |\
EXT4_GET_BLOCKS_ZERO)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 0ffabaf..7a8c610 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4328,7 +4328,13 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
* we split out initialized portions during a write.
*/
ee_len = ext4_ext_get_actual_len(ex);
+ if (flags & EXT4_GET_BLOCKS_CACHE) {
+ unsigned int status = EXTENT_STATUS_WRITTEN;
+ if (ext4_ext_is_unwritten(ex))
+ status = EXTENT_STATUS_UNWRITTEN;
+ ext4_es_cache_extent(inode, ee_block, ee_len, ee_start, status);
+ }
trace_ext4_ext_show_extent(inode, ee_block, ee_start, ee_len);
/* if found extent covers block, simply return it */
diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c
index ac748b3..79a29b9 100644
--- a/fs/ext4/extents_status.c
+++ b/fs/ext4/extents_status.c
@@ -811,7 +811,7 @@ int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
else if (lblk > ext4_es_end(es1))
node = node->rb_right;
else {
- found = 1;
+ found = 2;
break;
}
}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 83bc8bf..0096de2 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -524,8 +524,9 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
*/
down_read(&EXT4_I(inode)->i_data_sem);
if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
- retval = ext4_ext_map_blocks(handle, inode, map, flags &
- EXT4_GET_BLOCKS_KEEP_SIZE);
+ retval = ext4_ext_map_blocks(handle, inode, map,
+ (flags & EXT4_GET_BLOCKS_KEEP_SIZE) |
+ EXT4_GET_BLOCKS_CACHE);
} else {
retval = ext4_ind_map_blocks(handle, inode, map, flags &
EXT4_GET_BLOCKS_KEEP_SIZE);
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists