aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2016-03-09 22:54:00 -0500
committerTheodore Ts'o <tytso@mit.edu>2016-03-09 22:54:00 -0500
commitfacab4d9711e7aa3532cb82643803e8f1b9518e8 (patch)
tree5c0f800db5aeb1fca6842c81cd3821ae847fcc0d
parent140a52508a68387e22486659ff9eaa89a24f6e40 (diff)
ext4: return hole from ext4_map_blocks()
Currently, ext4_map_blocks() just returns 0 when it finds a hole and allocation is not requested. However we have all the information available to tell how large the hole actually is and there are callers of ext4_map_blocks() which would save some block-by-block hole iteration if they knew this information. So fill in struct ext4_map_blocks even for holes with the information we have. We keep returning 0 for holes to maintain backward compatibility of the function. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--fs/ext4/extents.c11
-rw-r--r--fs/ext4/indirect.c19
-rw-r--r--fs/ext4/inode.c15
3 files changed, 36 insertions, 9 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 7858fc1d2501..2730039d4742 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4374,13 +4374,20 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
4374 if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) { 4374 if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
4375 ext4_lblk_t hole_start, hole_len; 4375 ext4_lblk_t hole_start, hole_len;
4376 4376
4377 hole_start = map->m_lblk;
4378 hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
4377 /* 4379 /*
4378 * put just found gap into cache to speed up 4380 * put just found gap into cache to speed up
4379 * subsequent requests 4381 * subsequent requests
4380 */ 4382 */
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); 4383 ext4_ext_put_gap_in_cache(inode, hole_start, hole_len);
4384
4385 /* Update hole_len to reflect hole size after map->m_lblk */
4386 if (hole_start != map->m_lblk)
4387 hole_len -= map->m_lblk - hole_start;
4388 map->m_pblk = 0;
4389 map->m_len = min_t(unsigned int, map->m_len, hole_len);
4390
4384 goto out2; 4391 goto out2;
4385 } 4392 }
4386 4393
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 1655ff195e0e..3027fa681de5 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -555,8 +555,23 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
555 goto got_it; 555 goto got_it;
556 } 556 }
557 557
558 /* Next simple case - plain lookup or failed read of indirect block */ 558 /* Next simple case - plain lookup failed */
559 if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO) 559 if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
560 unsigned epb = inode->i_sb->s_blocksize / sizeof(u32);
561 int i;
562
563 /* Count number blocks in a subtree under 'partial' */
564 count = 1;
565 for (i = 0; partial + i != chain + depth - 1; i++)
566 count *= epb;
567 /* Fill in size of a hole we found */
568 map->m_pblk = 0;
569 map->m_len = min_t(unsigned int, map->m_len, count);
570 goto cleanup;
571 }
572
573 /* Failed read of indirect block */
574 if (err == -EIO)
560 goto cleanup; 575 goto cleanup;
561 576
562 /* 577 /*
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 971892d7c213..1a156ec043a0 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -455,13 +455,13 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
455 * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping 455 * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping
456 * based files 456 * based files
457 * 457 *
458 * On success, it returns the number of blocks being mapped or allocated. 458 * On success, it returns the number of blocks being mapped or allocated. if
459 * if create==0 and the blocks are pre-allocated and unwritten block, 459 * create==0 and the blocks are pre-allocated and unwritten, the resulting @map
460 * the result buffer head is unmapped. If the create ==1, it will make sure 460 * is marked as unwritten. If the create == 1, it will mark @map as mapped.
461 * the buffer head is mapped.
462 * 461 *
463 * It returns 0 if plain look up failed (blocks have not been allocated), in 462 * It returns 0 if plain look up failed (blocks have not been allocated), in
464 * that case, buffer head is unmapped 463 * that case, @map is returned as unmapped but we still do fill map->m_len to
464 * indicate the length of a hole starting at map->m_lblk.
465 * 465 *
466 * It returns the error in case of allocation failure. 466 * It returns the error in case of allocation failure.
467 */ 467 */
@@ -504,6 +504,11 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
504 retval = map->m_len; 504 retval = map->m_len;
505 map->m_len = retval; 505 map->m_len = retval;
506 } else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) { 506 } else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) {
507 map->m_pblk = 0;
508 retval = es.es_len - (map->m_lblk - es.es_lblk);
509 if (retval > map->m_len)
510 retval = map->m_len;
511 map->m_len = retval;
507 retval = 0; 512 retval = 0;
508 } else { 513 } else {
509 BUG_ON(1); 514 BUG_ON(1);