1 From: "Amit K. Arora" <aarora@linux.vnet.ibm.com>
2 Subject: [PATCH 3/5] ext4: Extent overlap bugfix
3 Cc: linux-ext4@vger.kernel.org, suparna@in.ibm.com, cmm@us.ibm.com
5 This is a fix for an extent-overlap bug. The fallocate() implementation
6 on ext4 depends on this bugfix. Though this fix had been posted earlier,
7 but because it is still not part of mainline code, I have attached it
10 Signed-off-by: Amit Arora <aarora@in.ibm.com>
12 fs/ext4/extents.c | 50 ++++++++++++++++++++++++++++++++++++++--
13 include/linux/ext4_fs_extents.h | 1
14 2 files changed, 49 insertions(+), 2 deletions(-)
16 Index: linux-2.6.21/fs/ext4/extents.c
17 ===================================================================
18 --- linux-2.6.21.orig/fs/ext4/extents.c
19 +++ linux-2.6.21/fs/ext4/extents.c
20 @@ -1129,6 +1129,45 @@ ext4_can_extents_be_merged(struct inode
24 + * ext4_ext_check_overlap:
25 + * check if a portion of the "newext" extent overlaps with an
28 + * If there is an overlap discovered, it updates the length of the newext
29 + * such that there will be no overlap, and then returns 1.
30 + * If there is no overlap found, it returns 0.
32 +unsigned int ext4_ext_check_overlap(struct inode *inode,
33 + struct ext4_extent *newext,
34 + struct ext4_ext_path *path)
36 + unsigned long b1, b2;
37 + unsigned int depth, len1;
39 + b1 = le32_to_cpu(newext->ee_block);
40 + len1 = le16_to_cpu(newext->ee_len);
41 + depth = ext_depth(inode);
42 + if (!path[depth].p_ext)
44 + b2 = le32_to_cpu(path[depth].p_ext->ee_block);
46 + /* get the next allocated block if the extent in the path
47 + * is before the requested block(s) */
49 + b2 = ext4_ext_next_allocated_block(path);
50 + if (b2 == EXT_MAX_BLOCK)
54 + if (b1 + len1 > b2) {
55 + newext->ee_len = cpu_to_le16(b2 - b1);
63 * ext4_ext_insert_extent:
64 * tries to merge requsted extent into the existing extent or
65 * inserts requested extent as new one into the tree,
66 @@ -2032,7 +2071,15 @@ int ext4_ext_get_blocks(handle_t *handle
68 /* allocate new block */
69 goal = ext4_ext_find_goal(inode, path, iblock);
70 - allocated = max_blocks;
72 + /* Check if we can really insert (iblock)::(iblock+max_blocks) extent */
73 + newex.ee_block = cpu_to_le32(iblock);
74 + newex.ee_len = cpu_to_le16(max_blocks);
75 + err = ext4_ext_check_overlap(inode, &newex, path);
77 + allocated = le16_to_cpu(newex.ee_len);
79 + allocated = max_blocks;
80 newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err);
83 @@ -2040,7 +2087,6 @@ int ext4_ext_get_blocks(handle_t *handle
84 goal, newblock, allocated);
86 /* try to insert new extent into found leaf and return */
87 - newex.ee_block = cpu_to_le32(iblock);
88 ext4_ext_store_pblock(&newex, newblock);
89 newex.ee_len = cpu_to_le16(allocated);
90 err = ext4_ext_insert_extent(handle, inode, path, &newex);
91 Index: linux-2.6.21/include/linux/ext4_fs_extents.h
92 ===================================================================
93 --- linux-2.6.21.orig/include/linux/ext4_fs_extents.h
94 +++ linux-2.6.21/include/linux/ext4_fs_extents.h
95 @@ -190,6 +190,7 @@ ext4_ext_invalidate_cache(struct inode *
97 extern int ext4_extent_tree_init(handle_t *, struct inode *);
98 extern int ext4_ext_calc_credits_for_insert(struct inode *, struct ext4_ext_path *);
99 +extern unsigned int ext4_ext_check_overlap(struct inode *, struct ext4_extent *, struct ext4_ext_path *);
100 extern int ext4_ext_insert_extent(handle_t *, struct inode *, struct ext4_ext_path *, struct ext4_extent *);
101 extern int ext4_ext_walk_space(struct inode *, unsigned long, unsigned long, ext_prepare_callback, void *);
102 extern struct ext4_ext_path * ext4_ext_find_extent(struct inode *, int, struct ext4_ext_path *);
104 To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
105 the body of a message to majordomo@vger.kernel.org
106 More majordomo info at http://vger.kernel.org/majordomo-info.html
107 Please read the FAQ at http://www.tux.org/lkml/