1 Index: linux-2.6.16.54-0.2.5/fs/ext3/extents.c
2 ===================================================================
3 --- linux-2.6.16.54-0.2.5.orig/fs/ext3/extents.c
4 +++ linux-2.6.16.54-0.2.5/fs/ext3/extents.c
6 #include <asm/uaccess.h>
9 -static inline int ext3_ext_check_header(struct ext3_extent_header *eh)
11 - if (eh->eh_magic != EXT3_EXT_MAGIC) {
12 - printk(KERN_ERR "EXT3-fs: invalid magic = 0x%x\n",
13 - (unsigned)eh->eh_magic);
15 +static int __ext3_ext_check_header(const char *function, int line, struct inode *inode,
16 + struct ext3_extent_header *eh, int depth,
19 + const char *error_msg = NULL;
21 + if (unlikely(eh->eh_magic != EXT3_EXT_MAGIC)) {
22 + error_msg = "invalid magic";
25 + if (unlikely(eh->eh_depth != depth)) {
26 + error_msg = "unexpected eh_depth";
29 + if (unlikely(eh->eh_max == 0)) {
30 + error_msg = "too small eh_max";
33 - if (eh->eh_max == 0) {
34 - printk(KERN_ERR "EXT3-fs: invalid eh_max = %u\n",
35 - (unsigned)eh->eh_max);
37 +#ifdef AGRESSIVE_TEST
38 + if (eh->eh_max > 3) {
39 + /* inode probably got its extent without defining
43 - if (eh->eh_entries > eh->eh_max) {
44 - printk(KERN_ERR "EXT3-fs: invalid eh_entries = %u\n",
45 - (unsigned)eh->eh_entries);
48 + if (unlikely(eh->eh_max > max)) {
49 + error_msg = "too large eh_max";
52 + if (unlikely(eh->eh_entries > eh->eh_max)) {
53 + error_msg = "invalid eh_entries";
56 + if (unlikely((eh->eh_entries == 0) && (eh->eh_depth != 0))) {
57 + error_msg = "invalid index, eh_entries=0 && eh_depth != 0";
63 + ext3_error(inode->i_sb, function,
64 + ":%d: bad header in inode #%lu: %s - magic %x, "
65 + "entries %u, max %u(%u), depth %u(%u)", line,
66 + inode->i_ino, error_msg, eh->eh_magic,
67 + eh->eh_entries, eh->eh_max, max,
68 + eh->eh_depth, depth);
73 +#define ext3_ext_check_header(inode,eh,depth,max) \
74 + __ext3_ext_check_header(__FUNCTION__,__LINE__,inode,eh,depth,max)
77 static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
80 @@ -226,6 +260,26 @@ static inline int ext3_ext_space_root_id
85 +ext3_ext_max_entries(struct ext3_extents_tree *tree, int root, int depth)
91 + max = ext3_ext_space_root(tree);
93 + max = ext3_ext_space_root_idx(tree);
96 + max = ext3_ext_space_block(tree);
98 + max = ext3_ext_space_block_idx(tree);
104 static void ext3_ext_show_path(struct ext3_extents_tree *tree,
105 struct ext3_ext_path *path)
107 @@ -296,10 +350,6 @@ ext3_ext_binsearch_idx(struct ext3_exten
108 struct ext3_extent_idx *ix;
111 - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
112 - EXT_ASSERT(eh->eh_entries <= eh->eh_max);
113 - EXT_ASSERT(eh->eh_entries > 0);
115 ext_debug(tree, "binsearch for %d(idx): ", block);
117 path->p_idx = ix = EXT_FIRST_INDEX(eh);
118 @@ -359,9 +409,6 @@ ext3_ext_binsearch(struct ext3_extents_t
119 struct ext3_extent *ex;
122 - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
123 - EXT_ASSERT(eh->eh_entries <= eh->eh_max);
125 if (eh->eh_entries == 0) {
127 * this leaf is empty yet:
128 @@ -436,6 +483,7 @@ ext3_ext_find_extent(struct ext3_extents
129 struct ext3_extent_header *eh;
130 struct buffer_head *bh;
131 int depth, i, ppos = 0;
135 EXT_ASSERT(tree->inode);
136 @@ -443,17 +491,15 @@ ext3_ext_find_extent(struct ext3_extents
138 eh = EXT_ROOT_HDR(tree);
140 - if (ext3_ext_check_header(eh)) {
141 + i = depth = EXT_DEPTH(tree);
142 + max = ext3_ext_max_entries(tree, 1, i);
143 + if (ext3_ext_check_header(tree->inode, eh, i, max)) {
144 /* don't free previously allocated path
145 * -- caller should take care */
150 - i = depth = EXT_DEPTH(tree);
151 - EXT_ASSERT(eh->eh_max);
152 - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
154 /* account possible depth increase */
156 path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
157 @@ -484,7 +530,8 @@ ext3_ext_find_extent(struct ext3_extents
158 path[ppos].p_hdr = eh;
161 - if (ext3_ext_check_header(eh))
162 + max = ext3_ext_max_entries(tree, 0, i);
163 + if (ext3_ext_check_header(tree->inode, eh, i, max))
167 @@ -493,9 +540,6 @@ ext3_ext_find_extent(struct ext3_extents
168 path[ppos].p_ext = NULL;
169 path[ppos].p_idx = NULL;
171 - if (ext3_ext_check_header(eh))
175 ext3_ext_binsearch(tree, path + ppos, block);
177 @@ -992,7 +1036,7 @@ ext3_ext_search_right(struct ext3_extent
178 struct ext3_extent_idx *ix;
179 struct ext3_extent *ex;
184 BUG_ON(path == NULL);
185 depth = path->p_depth;
186 @@ -1050,7 +1094,9 @@ ext3_ext_search_right(struct ext3_extent
189 eh = EXT_BLOCK_HDR(bh);
190 - if (ext3_ext_check_header(eh)) {
191 + max = ext3_ext_max_entries(tree, 0, depth);
192 + if (ext3_ext_check_header(tree->inode, eh,
193 + path->p_depth - depth, max)) {
197 @@ -1063,7 +1109,8 @@ ext3_ext_search_right(struct ext3_extent
200 eh = EXT_BLOCK_HDR(bh);
201 - if (ext3_ext_check_header(eh)) {
202 + max = ext3_ext_max_entries(tree, 0, depth);
203 + if (ext3_ext_check_header(tree->inode, eh, 0, max)) {
207 @@ -1693,6 +1740,8 @@ ext3_ext_rm_leaf(handle_t *handle, struc
208 ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
209 if (!path[depth].p_hdr)
210 path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
212 + /* the header must be checked already in ext3_ext_remove_space() */
213 eh = path[depth].p_hdr;
215 EXT_ASSERT(eh->eh_entries <= eh->eh_max);
216 @@ -1855,7 +1904,7 @@ int ext3_ext_remove_space(struct ext3_ex
217 int depth = EXT_DEPTH(tree);
218 struct ext3_ext_path *path;
220 - int i = 0, err = 0;
221 + int i = 0, err = 0, max;
223 ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
225 @@ -1878,7 +1927,13 @@ int ext3_ext_remove_space(struct ext3_ex
227 memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
228 path[i].p_hdr = EXT_ROOT_HDR(tree);
231 + max = ext3_ext_max_entries(tree, 1, depth);
232 + if (ext3_ext_check_header(inode, path[i].p_hdr, depth, max)) {
237 while (i >= 0 && err == 0) {
239 /* this is leaf block */
240 @@ -1888,16 +1943,13 @@ int ext3_ext_remove_space(struct ext3_ex
246 /* this is index block */
247 if (!path[i].p_hdr) {
248 ext_debug(tree, "initialize header\n");
249 path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
252 - EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
253 - EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
255 if (!path[i].p_idx) {
256 /* this level hasn't touched yet */
258 @@ -1924,6 +1976,14 @@ int ext3_ext_remove_space(struct ext3_ex
262 + BUG_ON(i + 1 > depth);
263 + max = ext3_ext_max_entries(tree, 0, depth - i - 1);
264 + if (ext3_ext_check_header(inode,
265 + EXT_BLOCK_HDR(path[i+1].p_bh),
266 + depth - i - 1, max)) {
270 /* put actual number of indexes to know is this
271 * number got changed at the next iteration */
272 path[i].p_block = path[i].p_hdr->eh_entries;
273 @@ -1944,7 +2004,7 @@ int ext3_ext_remove_space(struct ext3_ex
276 /* TODO: flexible tree reduction should be here */
277 - if (path->p_hdr->eh_entries == 0) {
278 + if (err == 0 && path->p_hdr->eh_entries == 0) {
280 * truncate to zero freed all the tree
281 * so, we need to correct eh_depth
282 @@ -1958,6 +2018,7 @@ int ext3_ext_remove_space(struct ext3_ex
284 ext3_ext_tree_changed(tree);
288 ext3_journal_stop(handle);