[Devel] [PATCH rh7 3/4] ms/ext4: return hole from ext4_map_blocks()
Andrey Ryabinin
aryabinin at virtuozzo.com
Thu Apr 27 01:00:26 PDT 2017
From: Jan Kara <jack at suse.cz>
commit facab4d9711e7aa3532cb82643803e8f1b9518e8 upstream.
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 at suse.cz>
Signed-off-by: Theodore Ts'o <tytso at mit.edu>
https://jira.sw.ru/browse/PSBM-65551
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
fs/ext4/extents.c | 11 +++++++++--
fs/ext4/indirect.c | 19 +++++++++++++++++--
fs/ext4/inode.c | 15 ++++++++++-----
3 files changed, 36 insertions(+), 9 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 04148a4..0f7c73f 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4390,13 +4390,20 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
ext4_lblk_t hole_start, hole_len;
+ hole_start = map->m_lblk;
+ hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
/*
* put just found gap into cache to speed up
* subsequent requests
*/
- 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);
+
+ /* Update hole_len to reflect hole size after map->m_lblk */
+ if (hole_start != map->m_lblk)
+ hole_len -= map->m_lblk - hole_start;
+ map->m_pblk = 0;
+ map->m_len = min_t(unsigned int, map->m_len, hole_len);
+
goto out2;
}
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 0d8967a..c0915c5 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -566,8 +566,23 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
goto got_it;
}
- /* Next simple case - plain lookup or failed read of indirect block */
- if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO)
+ /* Next simple case - plain lookup failed */
+ if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
+ unsigned epb = inode->i_sb->s_blocksize / sizeof(u32);
+ int i;
+
+ /* Count number blocks in a subtree under 'partial' */
+ count = 1;
+ for (i = 0; partial + i != chain + depth - 1; i++)
+ count *= epb;
+ /* Fill in size of a hole we found */
+ map->m_pblk = 0;
+ map->m_len = min_t(unsigned int, map->m_len, count);
+ goto cleanup;
+ }
+
+ /* Failed read of indirect block */
+ if (err == -EIO)
goto cleanup;
/*
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 33eee14..83b58ae 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -461,13 +461,13 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
* Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping
* based files
*
- * On success, it returns the number of blocks being mapped or allocated.
- * if create==0 and the blocks are pre-allocated and unwritten block,
- * the result buffer head is unmapped. If the create ==1, it will make sure
- * the buffer head is mapped.
+ * On success, it returns the number of blocks being mapped or allocated. if
+ * create==0 and the blocks are pre-allocated and unwritten, the resulting @map
+ * is marked as unwritten. If the create == 1, it will mark @map as mapped.
*
* It returns 0 if plain look up failed (blocks have not been allocated), in
- * that case, buffer head is unmapped
+ * that case, @map is returned as unmapped but we still do fill map->m_len to
+ * indicate the length of a hole starting at map->m_lblk.
*
* It returns the error in case of allocation failure.
*/
@@ -511,6 +511,11 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
retval = map->m_len;
map->m_len = retval;
} else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) {
+ map->m_pblk = 0;
+ retval = es.es_len - (map->m_lblk - es.es_lblk);
+ if (retval > map->m_len)
+ retval = map->m_len;
+ map->m_len = retval;
retval = 0;
} else {
BUG_ON(1);
--
2.10.2
More information about the Devel
mailing list