1 ext4: cache extent hole in extent status tree for ext4_da_map_blocks()
3 From: Zheng Liu <wenqing.lz@taobao.com>
5 Currently extent status tree doesn't cache extent hole when a write
6 looks up in extent tree to make sure whether a block has been allocated
7 or not. In this case, we don't put extent hole in extent cache because
8 later this extent might be removed and a new delayed extent might be
9 added back. But it will cause a defect when we do a lot of writes.
10 If we don't put extent hole in extent cache, the following writes also
11 need to access extent tree to look at whether or not a block has been
12 allocated. It brings a cache miss. This commit fixes this defect.
13 Meanwhile, if an inode has no any extent, this extent hole also will
16 Cc: Andreas Dilger <adilger.kernel@dilger.ca>
17 Cc: Jan Kara <jack@suse.cz>
18 Signed-off-by: Zheng Liu <wenqing.lz@taobao.com>
19 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
21 fs/ext4/ext4.h | 4 +---
22 fs/ext4/extents.c | 23 +++++++++--------------
23 fs/ext4/inode.c | 6 ++----
24 include/trace/events/ext4.h | 3 +--
25 4 files changed, 13 insertions(+), 23 deletions(-)
27 diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
28 index 6f294d3..7df9220 100644
31 @@ -565,10 +565,8 @@ enum {
32 #define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080
33 /* Do not take i_data_sem locking in ext4_map_blocks */
34 #define EXT4_GET_BLOCKS_NO_LOCK 0x0100
35 - /* Do not put hole in extent cache */
36 -#define EXT4_GET_BLOCKS_NO_PUT_HOLE 0x0200
37 /* Convert written extents to unwritten */
38 -#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0400
39 +#define EXT4_GET_BLOCKS_CONVERT_UNWRITTEN 0x0200
42 * The bit position of these flags must not overlap with any of the
43 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
44 index 76c2df3..6463d34 100644
45 --- a/fs/ext4/extents.c
46 +++ b/fs/ext4/extents.c
47 @@ -2284,16 +2284,15 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
50 int depth = ext_depth(inode);
51 - unsigned long len = 0;
52 - ext4_lblk_t lblock = 0;
55 struct ext4_extent *ex;
57 ex = path[depth].p_ext;
60 - * there is no extent yet, so gap is [0;-] and we
63 + /* there is no extent yet, so gap is [0;-] */
65 + len = EXT_MAX_BLOCKS;
66 ext_debug("cache gap(whole file):");
67 } else if (block < le32_to_cpu(ex->ee_block)) {
69 @@ -2302,9 +2301,6 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
71 le32_to_cpu(ex->ee_block),
72 ext4_ext_get_actual_len(ex));
73 - if (!ext4_find_delalloc_range(inode, lblock, lblock + len - 1))
74 - ext4_es_insert_extent(inode, lblock, len, ~0,
75 - EXTENT_STATUS_HOLE);
76 } else if (block >= le32_to_cpu(ex->ee_block)
77 + ext4_ext_get_actual_len(ex)) {
79 @@ -2318,14 +2314,14 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
81 BUG_ON(next == lblock);
83 - if (!ext4_find_delalloc_range(inode, lblock, lblock + len - 1))
84 - ext4_es_insert_extent(inode, lblock, len, ~0,
85 - EXTENT_STATUS_HOLE);
90 ext_debug(" -> %u:%lu\n", lblock, len);
91 + if (!ext4_find_delalloc_range(inode, lblock, lblock + len - 1))
92 + ext4_es_insert_extent(inode, lblock, len, ~0,
93 + EXTENT_STATUS_HOLE);
97 @@ -4362,8 +4358,7 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
98 * put just found gap into cache to speed up
101 - if ((flags & EXT4_GET_BLOCKS_NO_PUT_HOLE) == 0)
102 - ext4_ext_put_gap_in_cache(inode, path, map->m_lblk);
103 + ext4_ext_put_gap_in_cache(inode, path, map->m_lblk);
107 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
108 index 367a60c..d1ad9f9 100644
109 --- a/fs/ext4/inode.c
110 +++ b/fs/ext4/inode.c
111 @@ -1485,11 +1485,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
112 map->m_flags |= EXT4_MAP_FROM_CLUSTER;
114 } else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
115 - retval = ext4_ext_map_blocks(NULL, inode, map,
116 - EXT4_GET_BLOCKS_NO_PUT_HOLE);
117 + retval = ext4_ext_map_blocks(NULL, inode, map, 0);
119 - retval = ext4_ind_map_blocks(NULL, inode, map,
120 - EXT4_GET_BLOCKS_NO_PUT_HOLE);
121 + retval = ext4_ind_map_blocks(NULL, inode, map, 0);
125 diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
126 index ff4bd1b..9337d36 100644
127 --- a/include/trace/events/ext4.h
128 +++ b/include/trace/events/ext4.h
129 @@ -43,8 +43,7 @@ struct extent_status;
130 { EXT4_GET_BLOCKS_METADATA_NOFAIL, "METADATA_NOFAIL" }, \
131 { EXT4_GET_BLOCKS_NO_NORMALIZE, "NO_NORMALIZE" }, \
132 { EXT4_GET_BLOCKS_KEEP_SIZE, "KEEP_SIZE" }, \
133 - { EXT4_GET_BLOCKS_NO_LOCK, "NO_LOCK" }, \
134 - { EXT4_GET_BLOCKS_NO_PUT_HOLE, "NO_PUT_HOLE" })
135 + { EXT4_GET_BLOCKS_NO_LOCK, "NO_LOCK" })
137 #define show_mflags(flags) __print_flags(flags, "", \
138 { EXT4_MAP_NEW, "N" }, \