aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2009-03-10 18:18:47 -0400
committerTheodore Ts'o <tytso@mit.edu>2009-03-10 18:18:47 -0400
commit395a87bfefbc400011417e9eaae33169f9f036c0 (patch)
tree1f0d0f85f33166c9d6187102573a683c27d3e849 /fs/ext4/extents.c
parent041b62374c7fedc11a8a1eeda2868612d3d1436c (diff)
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=12821 Reported-by: David Dindorp <ddi@dubex.dk> Signed-off-by: Eric Sandeen <sandeen@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index e2eab196875f..e0aa4fe4f596 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -1122,7 +1122,8 @@ ext4_ext_search_right(struct inode *inode, struct ext4_ext_path *path,
1122 struct ext4_extent_idx *ix; 1122 struct ext4_extent_idx *ix;
1123 struct ext4_extent *ex; 1123 struct ext4_extent *ex;
1124 ext4_fsblk_t block; 1124 ext4_fsblk_t block;
1125 int depth, ee_len; 1125 int depth; /* Note, NOT eh_depth; depth from top of tree */
1126 int ee_len;
1126 1127
1127 BUG_ON(path == NULL); 1128 BUG_ON(path == NULL);
1128 depth = path->p_depth; 1129 depth = path->p_depth;
@@ -1179,7 +1180,8 @@ got_index:
1179 if (bh == NULL) 1180 if (bh == NULL)
1180 return -EIO; 1181 return -EIO;
1181 eh = ext_block_hdr(bh); 1182 eh = ext_block_hdr(bh);
1182 if (ext4_ext_check_header(inode, eh, depth)) { 1183 /* subtract from p_depth to get proper eh_depth */
1184 if (ext4_ext_check_header(inode, eh, path->p_depth - depth)) {
1183 put_bh(bh); 1185 put_bh(bh);
1184 return -EIO; 1186 return -EIO;
1185 } 1187 }