add patch fix-compile-error-while-opening-the-macros-DOUBLE_CHECK
[ext4-patch-queue.git] / return-hole-from-ext4_map_blocks
blob2f5153e4ca60ecff6be1271f51c954e386a8eefc
1 ext4: return hole from ext4_map_blocks()
3 From: Jan Kara <jack@suse.cz>
5 Currently, ext4_map_blocks() just returns 0 when it finds a hole and
6 allocation is not requested. However we have all the information
7 available to tell how large the hole actually is and there are callers
8 of ext4_map_blocks() which would save some block-by-block hole iteration
9 if they knew this information. So fill in struct ext4_map_blocks even
10 for holes with the information we have. We keep returning 0 for holes to
11 maintain backward compatibility of the function.
13 Signed-off-by: Jan Kara <jack@suse.cz>
14 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
15 ---
16  fs/ext4/extents.c  | 11 +++++++++--
17  fs/ext4/indirect.c | 19 +++++++++++++++++--
18  fs/ext4/inode.c    | 15 ++++++++++-----
19  3 files changed, 36 insertions(+), 9 deletions(-)
21 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
22 index 2dc6261e247f..0e924ca153f9 100644
23 --- a/fs/ext4/extents.c
24 +++ b/fs/ext4/extents.c
25 @@ -4380,13 +4380,20 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
26         if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
27                 ext4_lblk_t hole_start, hole_len;
29 +               hole_start = map->m_lblk;
30 +               hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
31                 /*
32                  * put just found gap into cache to speed up
33                  * subsequent requests
34                  */
35 -               hole_start = map->m_lblk;
36 -               hole_len = ext4_ext_determine_hole(inode, path, &hole_start);
37                 ext4_ext_put_gap_in_cache(inode, hole_start, hole_len);
39 +               /* Update hole_len to reflect hole size after map->m_lblk */
40 +               if (hole_start != map->m_lblk)
41 +                       hole_len -= map->m_lblk - hole_start;
42 +               map->m_pblk = 0;
43 +               map->m_len = min_t(unsigned int, map->m_len, hole_len);
45                 goto out2;
46         }
48 diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
49 index 355ef9c36c87..7544d1047dc6 100644
50 --- a/fs/ext4/indirect.c
51 +++ b/fs/ext4/indirect.c
52 @@ -555,8 +555,23 @@ int ext4_ind_map_blocks(handle_t *handle, struct inode *inode,
53                 goto got_it;
54         }
56 -       /* Next simple case - plain lookup or failed read of indirect block */
57 -       if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO)
58 +       /* Next simple case - plain lookup failed */
59 +       if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) {
60 +               unsigned epb = inode->i_sb->s_blocksize / sizeof(u32);
61 +               int i;
63 +               /* Count number blocks in a subtree under 'partial' */
64 +               count = 1;
65 +               for (i = 0; partial + i != chain + depth - 1; i++)
66 +                       count *= epb;
67 +               /* Fill in size of a hole we found */
68 +               map->m_pblk = 0;
69 +               map->m_len = min_t(unsigned int, map->m_len, count);
70 +               goto cleanup;
71 +       }
73 +       /* Failed read of indirect block */
74 +       if (err == -EIO)
75                 goto cleanup;
77         /*
78 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
79 index 9cc57c3b4661..ef590607b4a7 100644
80 --- a/fs/ext4/inode.c
81 +++ b/fs/ext4/inode.c
82 @@ -458,13 +458,13 @@ static void ext4_map_blocks_es_recheck(handle_t *handle,
83   * Otherwise, call with ext4_ind_map_blocks() to handle indirect mapping
84   * based files
85   *
86 - * On success, it returns the number of blocks being mapped or allocated.
87 - * if create==0 and the blocks are pre-allocated and unwritten block,
88 - * the result buffer head is unmapped. If the create ==1, it will make sure
89 - * the buffer head is mapped.
90 + * On success, it returns the number of blocks being mapped or allocated.  if
91 + * create==0 and the blocks are pre-allocated and unwritten, the resulting @map
92 + * is marked as unwritten. If the create == 1, it will mark @map as mapped.
93   *
94   * It returns 0 if plain look up failed (blocks have not been allocated), in
95 - * that case, buffer head is unmapped
96 + * that case, @map is returned as unmapped but we still do fill map->m_len to
97 + * indicate the length of a hole starting at map->m_lblk.
98   *
99   * It returns the error in case of allocation failure.
100   */
101 @@ -507,6 +507,11 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
102                                 retval = map->m_len;
103                         map->m_len = retval;
104                 } else if (ext4_es_is_delayed(&es) || ext4_es_is_hole(&es)) {
105 +                       map->m_pblk = 0;
106 +                       retval = es.es_len - (map->m_lblk - es.es_lblk);
107 +                       if (retval > map->m_len)
108 +                               retval = map->m_len;
109 +                       map->m_len = retval;
110                         retval = 0;
111                 } else {
112                         BUG_ON(1);
113 -- 
114 2.6.2
117 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
118 the body of a message to majordomo@vger.kernel.org
119 More majordomo info at  http://vger.kernel.org/majordomo-info.html