aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2016-03-09 22:46:57 -0500
committerTheodore Ts'o <tytso@mit.edu>2016-03-09 22:46:57 -0500
commit140a52508a68387e22486659ff9eaa89a24f6e40 (patch)
tree8326fcc3d156921d8e07287840632b058d671068 /fs/ext4
parent87d8a74b56746d4b6125602365b10995116afd00 (diff)
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: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/extents.c80
1 files changed, 47 insertions, 33 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index f1b3c2586a1a..7858fc1d2501 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2299,59 +2299,69 @@ static int ext4_fill_fiemap_extents(struct inode *inode,
2299} 2299}
2300 2300
2301/* 2301/*
2302 * ext4_ext_put_gap_in_cache: 2302 * ext4_ext_determine_hole - determine hole around given block
2303 * calculate boundaries of the gap that the requested block fits into 2303 * @inode: inode we lookup in
2304 * and cache this gap 2304 * @path: path in extent tree to @lblk
2305 * @lblk: pointer to logical block around which we want to determine hole
2306 *
2307 * Determine hole length (and start if easily possible) around given logical
2308 * block. We don't try too hard to find the beginning of the hole but @path
2309 * actually points to extent before @lblk, we provide it.
2310 *
2311 * The function returns the length of a hole starting at @lblk. We update @lblk
2312 * to the beginning of the hole if we managed to find it.
2305 */ 2313 */
2306static void 2314static ext4_lblk_t ext4_ext_determine_hole(struct inode *inode,
2307ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, 2315 struct ext4_ext_path *path,
2308 ext4_lblk_t block) 2316 ext4_lblk_t *lblk)
2309{ 2317{
2310 int depth = ext_depth(inode); 2318 int depth = ext_depth(inode);
2311 ext4_lblk_t len;
2312 ext4_lblk_t lblock;
2313 struct ext4_extent *ex; 2319 struct ext4_extent *ex;
2314 struct extent_status es; 2320 ext4_lblk_t len;
2315 2321
2316 ex = path[depth].p_ext; 2322 ex = path[depth].p_ext;
2317 if (ex == NULL) { 2323 if (ex == NULL) {
2318 /* there is no extent yet, so gap is [0;-] */ 2324 /* there is no extent yet, so gap is [0;-] */
2319 lblock = 0; 2325 *lblk = 0;
2320 len = EXT_MAX_BLOCKS; 2326 len = EXT_MAX_BLOCKS;
2321 ext_debug("cache gap(whole file):"); 2327 } else if (*lblk < le32_to_cpu(ex->ee_block)) {
2322 } else if (block < le32_to_cpu(ex->ee_block)) { 2328 len = le32_to_cpu(ex->ee_block) - *lblk;
2323 lblock = block; 2329 } else if (*lblk >= le32_to_cpu(ex->ee_block)
2324 len = le32_to_cpu(ex->ee_block) - block;
2325 ext_debug("cache gap(before): %u [%u:%u]",
2326 block,
2327 le32_to_cpu(ex->ee_block),
2328 ext4_ext_get_actual_len(ex));
2329 } else if (block >= le32_to_cpu(ex->ee_block)
2330 + ext4_ext_get_actual_len(ex)) { 2330 + ext4_ext_get_actual_len(ex)) {
2331 ext4_lblk_t next; 2331 ext4_lblk_t next;
2332 lblock = le32_to_cpu(ex->ee_block)
2333 + ext4_ext_get_actual_len(ex);
2334 2332
2333 *lblk = le32_to_cpu(ex->ee_block) + ext4_ext_get_actual_len(ex);
2335 next = ext4_ext_next_allocated_block(path); 2334 next = ext4_ext_next_allocated_block(path);
2336 ext_debug("cache gap(after): [%u:%u] %u", 2335 BUG_ON(next == *lblk);
2337 le32_to_cpu(ex->ee_block), 2336 len = next - *lblk;
2338 ext4_ext_get_actual_len(ex),
2339 block);
2340 BUG_ON(next == lblock);
2341 len = next - lblock;
2342 } else { 2337 } else {
2343 BUG(); 2338 BUG();
2344 } 2339 }
2340 return len;
2341}
2345 2342
2346 ext4_es_find_delayed_extent_range(inode, lblock, lblock + len - 1, &es); 2343/*
2344 * ext4_ext_put_gap_in_cache:
2345 * calculate boundaries of the gap that the requested block fits into
2346 * and cache this gap
2347 */
2348static void
2349ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start,
2350 ext4_lblk_t hole_len)
2351{
2352 struct extent_status es;
2353
2354 ext4_es_find_delayed_extent_range(inode, hole_start,
2355 hole_start + hole_len - 1, &es);
2347 if (es.es_len) { 2356 if (es.es_len) {
2348 /* There's delayed extent containing lblock? */ 2357 /* There's delayed extent containing lblock? */
2349 if (es.es_lblk <= lblock) 2358 if (es.es_lblk <= hole_start)
2350 return; 2359 return;
2351 len = min(es.es_lblk - lblock, len); 2360 hole_len = min(es.es_lblk - hole_start, hole_len);
2352 } 2361 }
2353 ext_debug(" -> %u:%u\n", lblock, len); 2362 ext_debug(" -> %u:%u\n", hole_start, hole_len);
2354 ext4_es_insert_extent(inode, lblock, len, ~0, EXTENT_STATUS_HOLE); 2363 ext4_es_insert_extent(inode, hole_start, hole_len, ~0,
2364 EXTENT_STATUS_HOLE);
2355} 2365}
2356 2366
2357/* 2367/*
@@ -4362,11 +4372,15 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
4362 * we couldn't try to create block if create flag is zero 4372 * we couldn't try to create block if create flag is zero
4363 */ 4373 */
4364 if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { 4374 if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
4375 ext4_lblk_t hole_start, hole_len;
4376
4365 /* 4377 /*
4366 * put just found gap into cache to speed up 4378 * put just found gap into cache to speed up
4367 * subsequent requests 4379 * subsequent requests
4368 */ 4380 */
4369 ext4_ext_put_gap_in_cache(inode, path, map->m_lblk); 4381 hole_start = map->m_lblk;
4382 hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
4383 ext4_ext_put_gap_in_cache(inode, hole_start, hole_len);
4370 goto out2; 4384 goto out2;
4371 } 4385 }
4372 4386