Commit 140a5250 authored by Jan Kara's avatar Jan Kara Committed by Theodore Ts'o

ext4: factor out determining of hole size

ext4_ext_put_gap_in_cache() determines hole size in the extent tree,
then trims this with possible delayed allocated blocks, and inserts the
result into the extent status tree. Factor out determination of the size
of the hole in the extent tree as we will need this information in
ext4_ext_map_blocks() as well.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 87d8a74b
...@@ -2299,59 +2299,69 @@ static int ext4_fill_fiemap_extents(struct inode *inode, ...@@ -2299,59 +2299,69 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
} }
/* /*
* ext4_ext_put_gap_in_cache: * ext4_ext_determine_hole - determine hole around given block
* calculate boundaries of the gap that the requested block fits into * @inode: inode we lookup in
* and cache this gap * @path: path in extent tree to @lblk
* @lblk: pointer to logical block around which we want to determine hole
*
* Determine hole length (and start if easily possible) around given logical
* block. We don't try too hard to find the beginning of the hole but @path
* actually points to extent before @lblk, we provide it.
*
* The function returns the length of a hole starting at @lblk. We update @lblk
* to the beginning of the hole if we managed to find it.
*/ */
static void static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode,
ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, struct ext4_ext_path *path,
ext4_lblk_t block) ext4_lblk_t *lblk)
{ {
int depth = ext_depth(inode); int depth = ext_depth(inode);
ext4_lblk_t len;
ext4_lblk_t lblock;
struct ext4_extent *ex; struct ext4_extent *ex;
struct extent_status es; ext4_lblk_t len;
ex = path[depth].p_ext; ex = path[depth].p_ext;
if (ex == NULL) { if (ex == NULL) {
/* there is no extent yet, so gap is [0;-] */ /* there is no extent yet, so gap is [0;-] */
lblock = 0; *lblk = 0;
len = EXT_MAX_BLOCKS; len = EXT_MAX_BLOCKS;
ext_debug("cache gap(whole file):"); } else if (*lblk < le32_to_cpu(ex->ee_block)) {
} else if (block < le32_to_cpu(ex->ee_block)) { len = le32_to_cpu(ex->ee_block) - *lblk;
lblock = block; } else if (*lblk >= le32_to_cpu(ex->ee_block)
len = le32_to_cpu(ex->ee_block) - block;
ext_debug("cache gap(before): %u [%u:%u]",
block,
le32_to_cpu(ex->ee_block),
ext4_ext_get_actual_len(ex));
} else if (block >= le32_to_cpu(ex->ee_block)
+ ext4_ext_get_actual_len(ex)) { + ext4_ext_get_actual_len(ex)) {
ext4_lblk_t next; ext4_lblk_t next;
lblock = le32_to_cpu(ex->ee_block)
+ ext4_ext_get_actual_len(ex);
*lblk = le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex);
next = ext4_ext_next_allocated_block(path); next = ext4_ext_next_allocated_block(path);
ext_debug("cache gap(after): [%u:%u] %u", BUG_ON(next == *lblk);
le32_to_cpu(ex->ee_block), len = next - *lblk;
ext4_ext_get_actual_len(ex),
block);
BUG_ON(next == lblock);
len = next - lblock;
} else { } else {
BUG(); BUG();
} }
return len;
}
ext4_es_find_delayed_extent_range(inode, lblock, lblock + len - 1, &es); /*
* ext4_ext_put_gap_in_cache:
* calculate boundaries of the gap that the requested block fits into
* and cache this gap
*/
static void
ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start,
ext4_lblk_t hole_len)
{
struct extent_status es;
ext4_es_find_delayed_extent_range(inode, hole_start,
hole_start + hole_len - 1, &es);
if (es.es_len) { if (es.es_len) {
/* There's delayed extent containing lblock? */ /* There's delayed extent containing lblock? */
if (es.es_lblk <= lblock) if (es.es_lblk <= hole_start)
return; return;
len = min(es.es_lblk - lblock, len); hole_len = min(es.es_lblk - hole_start, hole_len);
} }
ext_debug(" -> %u:%u\n", lblock, len); ext_debug(" -> %u:%u\n", hole_start, hole_len);
ext4_es_insert_extent(inode, lblock, len, ~0, EXTENT_STATUS_HOLE); ext4_es_insert_extent(inode, hole_start, hole_len, ~0,
EXTENT_STATUS_HOLE);
} }
/* /*
...@@ -4362,11 +4372,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, ...@@ -4362,11 +4372,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
* we couldn't try to create block if create flag is zero * we couldn't try to create block if create flag is zero
*/ */
if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
ext4_lblk_t hole_start, hole_len;
/* /*
* put just found gap into cache to speed up * put just found gap into cache to speed up
* subsequent requests * subsequent requests
*/ */
ext4_ext_put_gap_in_cache(inode, path, map->m_lblk); hole_start = map->m_lblk;
hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
ext4_ext_put_gap_in_cache(inode, hole_start, hole_len);
goto out2; goto out2;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment