dir_index: error out instead of BUG on corrupt dx dirs
Convert asserts (BUGs) in dx_probe from bad on-disk data to recoverable errors with helpful warnings. With help catching other asserts from Duane Griffin <duaneg@dghda.com> Signed-off-by: Eric Sandeen <sandeen@redhat.com> Acked-by: Duane Griffin <duaneg@dghda.com> Acked-by: Theodore Ts'o <tytso@mit.edu> Cc: <stable@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
e67aa27a61
commit
3d82abae95
2 changed files with 60 additions and 8 deletions
|
@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
|
|||
|
||||
entries = (struct dx_entry *) (((char *)&root->info) +
|
||||
root->info.info_length);
|
||||
assert(dx_get_limit(entries) == dx_root_limit(dir,
|
||||
root->info.info_length));
|
||||
|
||||
if (dx_get_limit(entries) != dx_root_limit(dir,
|
||||
root->info.info_length)) {
|
||||
ext3_warning(dir->i_sb, __FUNCTION__,
|
||||
"dx entry: limit != root limit");
|
||||
brelse(bh);
|
||||
*err = ERR_BAD_DX_DIR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dxtrace (printk("Look up %x", hash));
|
||||
while (1)
|
||||
{
|
||||
count = dx_get_count(entries);
|
||||
assert (count && count <= dx_get_limit(entries));
|
||||
if (!count || count > dx_get_limit(entries)) {
|
||||
ext3_warning(dir->i_sb, __FUNCTION__,
|
||||
"dx entry: no count or count > limit");
|
||||
brelse(bh);
|
||||
*err = ERR_BAD_DX_DIR;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
p = entries + 1;
|
||||
q = entries + count - 1;
|
||||
while (p <= q)
|
||||
|
@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
|
|||
if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
|
||||
goto fail2;
|
||||
at = entries = ((struct dx_node *) bh->b_data)->entries;
|
||||
assert (dx_get_limit(entries) == dx_node_limit (dir));
|
||||
if (dx_get_limit(entries) != dx_node_limit (dir)) {
|
||||
ext3_warning(dir->i_sb, __FUNCTION__,
|
||||
"dx entry: limit != node limit");
|
||||
brelse(bh);
|
||||
*err = ERR_BAD_DX_DIR;
|
||||
goto fail2;
|
||||
}
|
||||
frame++;
|
||||
frame->bh = NULL;
|
||||
}
|
||||
fail2:
|
||||
while (frame >= frame_in) {
|
||||
|
@ -432,6 +454,10 @@ dx_probe(struct dentry *dentry, struct inode *dir,
|
|||
frame--;
|
||||
}
|
||||
fail:
|
||||
if (*err == ERR_BAD_DX_DIR)
|
||||
ext3_warning(dir->i_sb, __FUNCTION__,
|
||||
"Corrupt dir inode %ld, running e2fsck is "
|
||||
"recommended.", dir->i_ino);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
|
|||
|
||||
entries = (struct dx_entry *) (((char *)&root->info) +
|
||||
root->info.info_length);
|
||||
assert(dx_get_limit(entries) == dx_root_limit(dir,
|
||||
root->info.info_length));
|
||||
|
||||
if (dx_get_limit(entries) != dx_root_limit(dir,
|
||||
root->info.info_length)) {
|
||||
ext4_warning(dir->i_sb, __FUNCTION__,
|
||||
"dx entry: limit != root limit");
|
||||
brelse(bh);
|
||||
*err = ERR_BAD_DX_DIR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dxtrace (printk("Look up %x", hash));
|
||||
while (1)
|
||||
{
|
||||
count = dx_get_count(entries);
|
||||
assert (count && count <= dx_get_limit(entries));
|
||||
if (!count || count > dx_get_limit(entries)) {
|
||||
ext4_warning(dir->i_sb, __FUNCTION__,
|
||||
"dx entry: no count or count > limit");
|
||||
brelse(bh);
|
||||
*err = ERR_BAD_DX_DIR;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
p = entries + 1;
|
||||
q = entries + count - 1;
|
||||
while (p <= q)
|
||||
|
@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
|
|||
if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
|
||||
goto fail2;
|
||||
at = entries = ((struct dx_node *) bh->b_data)->entries;
|
||||
assert (dx_get_limit(entries) == dx_node_limit (dir));
|
||||
if (dx_get_limit(entries) != dx_node_limit (dir)) {
|
||||
ext4_warning(dir->i_sb, __FUNCTION__,
|
||||
"dx entry: limit != node limit");
|
||||
brelse(bh);
|
||||
*err = ERR_BAD_DX_DIR;
|
||||
goto fail2;
|
||||
}
|
||||
frame++;
|
||||
frame->bh = NULL;
|
||||
}
|
||||
fail2:
|
||||
while (frame >= frame_in) {
|
||||
|
@ -432,6 +454,10 @@ dx_probe(struct dentry *dentry, struct inode *dir,
|
|||
frame--;
|
||||
}
|
||||
fail:
|
||||
if (*err == ERR_BAD_DX_DIR)
|
||||
ext4_warning(dir->i_sb, __FUNCTION__,
|
||||
"Corrupt dir inode %ld, running e2fsck is "
|
||||
"recommended.", dir->i_ino);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue