diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-08-28 10:40:33 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-08-28 10:40:33 -0400 |
commit | 55ad63bf3a30936aced50f13452735c2f58b234c (patch) | |
tree | 13733cfa690c83a0a75d8d38489e3cace096f9f9 /fs/ext4/extents.c | |
parent | a36b44988cef1fc007535107013571fa691a2d7f (diff) |
ext4: fix extent sanity checking code with AGGRESSIVE_TEST
The extents sanity-checking code depends on the ext4_ext_space_*()
functions returning the maximum alloable size for eh_max; however,
when the debugging #ifdef AGGRESSIVE_TEST is enabled to test the
extent tree handling code, this prevents a normally created ext4
filesystem from being mounted with the errors:
Aug 26 15:43:50 bsd086 kernel: [ 96.070277] EXT4-fs error (device sda8): ext4_ext_check_inode: bad header/extent in inode #8: too large eh_max - magic f30a, entries 1, max 4(3), depth 0(0)
Aug 26 15:43:50 bsd086 kernel: [ 96.070526] EXT4-fs (sda8): no journal found
Bug reported by Akira Fujita.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 60 |
1 files changed, 34 insertions, 26 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 8c20caf4aa5c..7a3832577923 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -229,57 +229,65 @@ ext4_ext_new_meta_block(handle_t *handle, struct inode *inode, | |||
229 | return newblock; | 229 | return newblock; |
230 | } | 230 | } |
231 | 231 | ||
232 | static int ext4_ext_space_block(struct inode *inode) | 232 | static inline int ext4_ext_space_block(struct inode *inode, int check) |
233 | { | 233 | { |
234 | int size; | 234 | int size; |
235 | 235 | ||
236 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) | 236 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) |
237 | / sizeof(struct ext4_extent); | 237 | / sizeof(struct ext4_extent); |
238 | if (!check) { | ||
238 | #ifdef AGGRESSIVE_TEST | 239 | #ifdef AGGRESSIVE_TEST |
239 | if (size > 6) | 240 | if (size > 6) |
240 | size = 6; | 241 | size = 6; |
241 | #endif | 242 | #endif |
243 | } | ||
242 | return size; | 244 | return size; |
243 | } | 245 | } |
244 | 246 | ||
245 | static int ext4_ext_space_block_idx(struct inode *inode) | 247 | static inline int ext4_ext_space_block_idx(struct inode *inode, int check) |
246 | { | 248 | { |
247 | int size; | 249 | int size; |
248 | 250 | ||
249 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) | 251 | size = (inode->i_sb->s_blocksize - sizeof(struct ext4_extent_header)) |
250 | / sizeof(struct ext4_extent_idx); | 252 | / sizeof(struct ext4_extent_idx); |
253 | if (!check) { | ||
251 | #ifdef AGGRESSIVE_TEST | 254 | #ifdef AGGRESSIVE_TEST |
252 | if (size > 5) | 255 | if (size > 5) |
253 | size = 5; | 256 | size = 5; |
254 | #endif | 257 | #endif |
258 | } | ||
255 | return size; | 259 | return size; |
256 | } | 260 | } |
257 | 261 | ||
258 | static int ext4_ext_space_root(struct inode *inode) | 262 | static inline int ext4_ext_space_root(struct inode *inode, int check) |
259 | { | 263 | { |
260 | int size; | 264 | int size; |
261 | 265 | ||
262 | size = sizeof(EXT4_I(inode)->i_data); | 266 | size = sizeof(EXT4_I(inode)->i_data); |
263 | size -= sizeof(struct ext4_extent_header); | 267 | size -= sizeof(struct ext4_extent_header); |
264 | size /= sizeof(struct ext4_extent); | 268 | size /= sizeof(struct ext4_extent); |
269 | if (!check) { | ||
265 | #ifdef AGGRESSIVE_TEST | 270 | #ifdef AGGRESSIVE_TEST |
266 | if (size > 3) | 271 | if (size > 3) |
267 | size = 3; | 272 | size = 3; |
268 | #endif | 273 | #endif |
274 | } | ||
269 | return size; | 275 | return size; |
270 | } | 276 | } |
271 | 277 | ||
272 | static int ext4_ext_space_root_idx(struct inode *inode) | 278 | static inline int ext4_ext_space_root_idx(struct inode *inode, int check) |
273 | { | 279 | { |
274 | int size; | 280 | int size; |
275 | 281 | ||
276 | size = sizeof(EXT4_I(inode)->i_data); | 282 | size = sizeof(EXT4_I(inode)->i_data); |
277 | size -= sizeof(struct ext4_extent_header); | 283 | size -= sizeof(struct ext4_extent_header); |
278 | size /= sizeof(struct ext4_extent_idx); | 284 | size /= sizeof(struct ext4_extent_idx); |
285 | if (!check) { | ||
279 | #ifdef AGGRESSIVE_TEST | 286 | #ifdef AGGRESSIVE_TEST |
280 | if (size > 4) | 287 | if (size > 4) |
281 | size = 4; | 288 | size = 4; |
282 | #endif | 289 | #endif |
290 | } | ||
283 | return size; | 291 | return size; |
284 | } | 292 | } |
285 | 293 | ||
@@ -293,9 +301,9 @@ int ext4_ext_calc_metadata_amount(struct inode *inode, int blocks) | |||
293 | int lcap, icap, rcap, leafs, idxs, num; | 301 | int lcap, icap, rcap, leafs, idxs, num; |
294 | int newextents = blocks; | 302 | int newextents = blocks; |
295 | 303 | ||
296 | rcap = ext4_ext_space_root_idx(inode); | 304 | rcap = ext4_ext_space_root_idx(inode, 0); |
297 | lcap = ext4_ext_space_block(inode); | 305 | lcap = ext4_ext_space_block(inode, 0); |
298 | icap = ext4_ext_space_block_idx(inode); | 306 | icap = ext4_ext_space_block_idx(inode, 0); |
299 | 307 | ||
300 | /* number of new leaf blocks needed */ | 308 | /* number of new leaf blocks needed */ |
301 | num = leafs = (newextents + lcap - 1) / lcap; | 309 | num = leafs = (newextents + lcap - 1) / lcap; |
@@ -320,14 +328,14 @@ ext4_ext_max_entries(struct inode *inode, int depth) | |||
320 | 328 | ||
321 | if (depth == ext_depth(inode)) { | 329 | if (depth == ext_depth(inode)) { |
322 | if (depth == 0) | 330 | if (depth == 0) |
323 | max = ext4_ext_space_root(inode); | 331 | max = ext4_ext_space_root(inode, 1); |
324 | else | 332 | else |
325 | max = ext4_ext_space_root_idx(inode); | 333 | max = ext4_ext_space_root_idx(inode, 1); |
326 | } else { | 334 | } else { |
327 | if (depth == 0) | 335 | if (depth == 0) |
328 | max = ext4_ext_space_block(inode); | 336 | max = ext4_ext_space_block(inode, 1); |
329 | else | 337 | else |
330 | max = ext4_ext_space_block_idx(inode); | 338 | max = ext4_ext_space_block_idx(inode, 1); |
331 | } | 339 | } |
332 | 340 | ||
333 | return max; | 341 | return max; |
@@ -626,7 +634,7 @@ int ext4_ext_tree_init(handle_t *handle, struct inode *inode) | |||
626 | eh->eh_depth = 0; | 634 | eh->eh_depth = 0; |
627 | eh->eh_entries = 0; | 635 | eh->eh_entries = 0; |
628 | eh->eh_magic = EXT4_EXT_MAGIC; | 636 | eh->eh_magic = EXT4_EXT_MAGIC; |
629 | eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode)); | 637 | eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0)); |
630 | ext4_mark_inode_dirty(handle, inode); | 638 | ext4_mark_inode_dirty(handle, inode); |
631 | ext4_ext_invalidate_cache(inode); | 639 | ext4_ext_invalidate_cache(inode); |
632 | return 0; | 640 | return 0; |
@@ -851,7 +859,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
851 | 859 | ||
852 | neh = ext_block_hdr(bh); | 860 | neh = ext_block_hdr(bh); |
853 | neh->eh_entries = 0; | 861 | neh->eh_entries = 0; |
854 | neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode)); | 862 | neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); |
855 | neh->eh_magic = EXT4_EXT_MAGIC; | 863 | neh->eh_magic = EXT4_EXT_MAGIC; |
856 | neh->eh_depth = 0; | 864 | neh->eh_depth = 0; |
857 | ex = EXT_FIRST_EXTENT(neh); | 865 | ex = EXT_FIRST_EXTENT(neh); |
@@ -927,7 +935,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
927 | neh = ext_block_hdr(bh); | 935 | neh = ext_block_hdr(bh); |
928 | neh->eh_entries = cpu_to_le16(1); | 936 | neh->eh_entries = cpu_to_le16(1); |
929 | neh->eh_magic = EXT4_EXT_MAGIC; | 937 | neh->eh_magic = EXT4_EXT_MAGIC; |
930 | neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode)); | 938 | neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0)); |
931 | neh->eh_depth = cpu_to_le16(depth - i); | 939 | neh->eh_depth = cpu_to_le16(depth - i); |
932 | fidx = EXT_FIRST_INDEX(neh); | 940 | fidx = EXT_FIRST_INDEX(neh); |
933 | fidx->ei_block = border; | 941 | fidx->ei_block = border; |
@@ -1052,9 +1060,9 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1052 | /* old root could have indexes or leaves | 1060 | /* old root could have indexes or leaves |
1053 | * so calculate e_max right way */ | 1061 | * so calculate e_max right way */ |
1054 | if (ext_depth(inode)) | 1062 | if (ext_depth(inode)) |
1055 | neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode)); | 1063 | neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0)); |
1056 | else | 1064 | else |
1057 | neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode)); | 1065 | neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); |
1058 | neh->eh_magic = EXT4_EXT_MAGIC; | 1066 | neh->eh_magic = EXT4_EXT_MAGIC; |
1059 | set_buffer_uptodate(bh); | 1067 | set_buffer_uptodate(bh); |
1060 | unlock_buffer(bh); | 1068 | unlock_buffer(bh); |
@@ -1069,7 +1077,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1069 | goto out; | 1077 | goto out; |
1070 | 1078 | ||
1071 | curp->p_hdr->eh_magic = EXT4_EXT_MAGIC; | 1079 | curp->p_hdr->eh_magic = EXT4_EXT_MAGIC; |
1072 | curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode)); | 1080 | curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0)); |
1073 | curp->p_hdr->eh_entries = cpu_to_le16(1); | 1081 | curp->p_hdr->eh_entries = cpu_to_le16(1); |
1074 | curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); | 1082 | curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); |
1075 | 1083 | ||
@@ -2348,7 +2356,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start) | |||
2348 | if (err == 0) { | 2356 | if (err == 0) { |
2349 | ext_inode_hdr(inode)->eh_depth = 0; | 2357 | ext_inode_hdr(inode)->eh_depth = 0; |
2350 | ext_inode_hdr(inode)->eh_max = | 2358 | ext_inode_hdr(inode)->eh_max = |
2351 | cpu_to_le16(ext4_ext_space_root(inode)); | 2359 | cpu_to_le16(ext4_ext_space_root(inode, 0)); |
2352 | err = ext4_ext_dirty(handle, inode, path); | 2360 | err = ext4_ext_dirty(handle, inode, path); |
2353 | } | 2361 | } |
2354 | } | 2362 | } |