Commit 395a87bf authored by Eric Sandeen's avatar Eric Sandeen Committed by Theodore Ts'o

ext4: fix header check in ext4_ext_search_right() for deep extent trees.

The ext4_ext_search_right() function is confusing; it uses a
"depth" variable which is 0 at the root and maximum at the leaves, 
but the on-disk metadata uses a "depth" (actually eh_depth) which
is opposite: maximum at the root, and 0 at the leaves.

The ext4_ext_check_header() function is given a depth and checks
the header agaisnt that depth; it expects the on-disk semantics,
but we are giving it the opposite in the while loop in this 
function.  We should be giving it the on-disk notion of "depth"
which we can get from (p_depth - depth) - and if you look, the last
(more commonly hit) call to ext4_ext_check_header() does just this.

Sending in the wrong depth results in (incorrect) messages
about corruption:

EXT4-fs error (device sdb1): ext4_ext_search_right: bad header
in inode #2621457: unexpected eh_depth - magic f30a, entries 340,
max 340(0), depth 1(2)

http://bugzilla.kernel.org/show_bug.cgi?id=12821Reported-by: default avatarDavid Dindorp <ddi@dubex.dk>
Signed-off-by: default avatarEric Sandeen <sandeen@redhat.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 041b6237
...@@ -1122,7 +1122,8 @@ ext4_ext_search_right(struct inode *inode, struct ext4_ext_path *path, ...@@ -1122,7 +1122,8 @@ ext4_ext_search_right(struct inode *inode, struct ext4_ext_path *path,
struct ext4_extent_idx *ix; struct ext4_extent_idx *ix;
struct ext4_extent *ex; struct ext4_extent *ex;
ext4_fsblk_t block; ext4_fsblk_t block;
int depth, ee_len; int depth; /* Note, NOT eh_depth; depth from top of tree */
int ee_len;
BUG_ON(path == NULL); BUG_ON(path == NULL);
depth = path->p_depth; depth = path->p_depth;
...@@ -1179,7 +1180,8 @@ got_index: ...@@ -1179,7 +1180,8 @@ got_index:
if (bh == NULL) if (bh == NULL)
return -EIO; return -EIO;
eh = ext_block_hdr(bh); eh = ext_block_hdr(bh);
if (ext4_ext_check_header(inode, eh, depth)) { /* subtract from p_depth to get proper eh_depth */
if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) {
put_bh(bh); put_bh(bh);
return -EIO; return -EIO;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment