1 Index: linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c
2 ===================================================================
3 --- linux-2.6.9-42.0.10.EL_lustre.1.4.10.orig/fs/ext3/extents.c 2007-07-17 22:14:08.000000000 +0200
4 +++ linux-2.6.9-42.0.10.EL_lustre.1.4.10/fs/ext3/extents.c 2007-07-17 22:40:57.000000000 +0200
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, 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";
59 + ext3_error(inode->i_sb, function,
60 + "bad header in inode #%lu: %s - magic %x, "
61 + "entries %u, max %u(%u), depth %u(%u)",
62 + inode->i_ino, error_msg, eh->eh_magic,
63 + eh->eh_entries, eh->eh_max, max,
64 + eh->eh_depth, depth);
69 +#define ext3_ext_check_header(inode,eh,depth,max) \
70 + __ext3_ext_check_header(__FUNCTION__,inode,eh,depth,max)
73 static handle_t *ext3_ext_journal_restart(handle_t *handle, int needed)
76 @@ -227,6 +257,26 @@ static inline int ext3_ext_space_root_id
81 +ext3_ext_max_entries(struct ext3_extents_tree *tree, int root, int depth)
87 + max = ext3_ext_space_root(tree);
89 + max = ext3_ext_space_root_idx(tree);
92 + max = ext3_ext_space_block(tree);
94 + max = ext3_ext_space_block_idx(tree);
100 static void ext3_ext_show_path(struct ext3_extents_tree *tree,
101 struct ext3_ext_path *path)
103 @@ -297,10 +347,6 @@ ext3_ext_binsearch_idx(struct ext3_exten
104 struct ext3_extent_idx *ix;
107 - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
108 - EXT_ASSERT(eh->eh_entries <= eh->eh_max);
109 - EXT_ASSERT(eh->eh_entries > 0);
111 ext_debug(tree, "binsearch for %d(idx): ", block);
113 path->p_idx = ix = EXT_FIRST_INDEX(eh);
114 @@ -360,9 +406,6 @@ ext3_ext_binsearch(struct ext3_extents_t
115 struct ext3_extent *ex;
118 - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
119 - EXT_ASSERT(eh->eh_entries <= eh->eh_max);
121 if (eh->eh_entries == 0) {
123 * this leaf is empty yet:
124 @@ -437,6 +480,7 @@ ext3_ext_find_extent(struct ext3_extents
125 struct ext3_extent_header *eh;
126 struct buffer_head *bh;
127 int depth, i, ppos = 0;
131 EXT_ASSERT(tree->inode);
132 @@ -444,17 +488,15 @@ ext3_ext_find_extent(struct ext3_extents
134 eh = EXT_ROOT_HDR(tree);
136 - if (ext3_ext_check_header(eh)) {
137 + i = depth = EXT_DEPTH(tree);
138 + max = ext3_ext_max_entries(tree, 1, i);
139 + if (ext3_ext_check_header(tree->inode, eh, i, max)) {
140 /* don't free previously allocated path
141 * -- caller should take care */
146 - i = depth = EXT_DEPTH(tree);
147 - EXT_ASSERT(eh->eh_max);
148 - EXT_ASSERT(eh->eh_magic == EXT3_EXT_MAGIC);
150 /* account possible depth increase */
152 path = kmalloc(sizeof(struct ext3_ext_path) * (depth + 2),
153 @@ -485,7 +527,8 @@ ext3_ext_find_extent(struct ext3_extents
154 path[ppos].p_hdr = eh;
157 - if (ext3_ext_check_header(eh))
158 + max = ext3_ext_max_entries(tree, 0, i);
159 + if (ext3_ext_check_header(tree->inode, eh, i, max))
163 @@ -494,9 +537,6 @@ ext3_ext_find_extent(struct ext3_extents
164 path[ppos].p_ext = NULL;
165 path[ppos].p_idx = NULL;
167 - if (ext3_ext_check_header(eh))
171 ext3_ext_binsearch(tree, path + ppos, block);
173 @@ -993,7 +1033,7 @@ ext3_ext_search_right(struct ext3_extent
174 struct ext3_extent_idx *ix;
175 struct ext3_extent *ex;
180 BUG_ON(path == NULL);
181 depth = path->p_depth;
182 @@ -1051,7 +1091,9 @@ ext3_ext_search_right(struct ext3_extent
185 eh = EXT_BLOCK_HDR(bh);
186 - if (ext3_ext_check_header(eh)) {
187 + max = ext3_ext_max_entries(tree, 0, depth);
188 + if (ext3_ext_check_header(tree->inode, eh,
189 + path->p_depth - depth, max)) {
193 @@ -1064,7 +1106,8 @@ ext3_ext_search_right(struct ext3_extent
196 eh = EXT_BLOCK_HDR(bh);
197 - if (ext3_ext_check_header(eh)) {
198 + max = ext3_ext_max_entries(tree, 0, depth);
199 + if (ext3_ext_check_header(tree->inode, eh, 0, max)) {
203 @@ -1694,6 +1737,8 @@ ext3_ext_rm_leaf(handle_t *handle, struc
204 ext_debug(tree, "remove [%lu:%lu] in leaf\n", start, end);
205 if (!path[depth].p_hdr)
206 path[depth].p_hdr = EXT_BLOCK_HDR(path[depth].p_bh);
208 + /* the header must be checked already in ext3_ext_remove_space() */
209 eh = path[depth].p_hdr;
211 EXT_ASSERT(eh->eh_entries <= eh->eh_max);
212 @@ -1856,7 +1901,7 @@ int ext3_ext_remove_space(struct ext3_ex
213 int depth = EXT_DEPTH(tree);
214 struct ext3_ext_path *path;
216 - int i = 0, err = 0;
217 + int i = 0, err = 0, max;
219 ext_debug(tree, "space to be removed: %lu:%lu\n", start, end);
221 @@ -1879,7 +1924,13 @@ int ext3_ext_remove_space(struct ext3_ex
223 memset(path, 0, sizeof(struct ext3_ext_path) * (depth + 1));
224 path[i].p_hdr = EXT_ROOT_HDR(tree);
227 + max = ext3_ext_max_entries(tree, 1, depth);
228 + if (ext3_ext_check_header(inode, path[i].p_hdr, depth, max)) {
233 while (i >= 0 && err == 0) {
235 /* this is leaf block */
236 @@ -1889,16 +1940,13 @@ int ext3_ext_remove_space(struct ext3_ex
242 /* this is index block */
243 if (!path[i].p_hdr) {
244 ext_debug(tree, "initialize header\n");
245 path[i].p_hdr = EXT_BLOCK_HDR(path[i].p_bh);
248 - EXT_ASSERT(path[i].p_hdr->eh_entries <= path[i].p_hdr->eh_max);
249 - EXT_ASSERT(path[i].p_hdr->eh_magic == EXT3_EXT_MAGIC);
251 if (!path[i].p_idx) {
252 /* this level hasn't touched yet */
254 @@ -1925,6 +1973,14 @@ int ext3_ext_remove_space(struct ext3_ex
258 + BUG_ON(i + 1 > depth);
259 + max = ext3_ext_max_entries(tree, 0, depth - i - 1);
260 + if (ext3_ext_check_header(inode,
261 + EXT_BLOCK_HDR(path[i+1].p_bh),
262 + depth - i - 1, max)) {
266 /* put actual number of indexes to know is this
267 * number got changed at the next iteration */
268 path[i].p_block = path[i].p_hdr->eh_entries;
269 @@ -1945,7 +2001,7 @@ int ext3_ext_remove_space(struct ext3_ex
272 /* TODO: flexible tree reduction should be here */
273 - if (path->p_hdr->eh_entries == 0) {
274 + if (err == 0 && path->p_hdr->eh_entries == 0) {
276 * truncate to zero freed all the tree
277 * so, we need to correct eh_depth
278 @@ -1959,6 +2015,7 @@ int ext3_ext_remove_space(struct ext3_ex
280 ext3_ext_tree_changed(tree);
284 ext3_journal_stop(handle);