aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2007-09-19 01:46:38 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-19 14:24:18 -0400
commit3d82abae9523c33d4a16fdfdfd2bdde316d7b56a (patch)
treee0059b667ac7ef765814a2ee9587f9e89015b387
parente67aa27a6179c287983c6c525beb5320f5cd1672 (diff)
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>
-rw-r--r--fs/ext3/namei.c34
-rw-r--r--fs/ext4/namei.c34
2 files changed, 60 insertions, 8 deletions
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 1586807b8177..9d4a89820e1e 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
379 379
380 entries = (struct dx_entry *) (((char *)&root->info) + 380 entries = (struct dx_entry *) (((char *)&root->info) +
381 root->info.info_length); 381 root->info.info_length);
382 assert(dx_get_limit(entries) == dx_root_limit(dir, 382
383 root->info.info_length)); 383 if (dx_get_limit(entries) != dx_root_limit(dir,
384 root->info.info_length)) {
385 ext3_warning(dir->i_sb, __FUNCTION__,
386 "dx entry: limit != root limit");
387 brelse(bh);
388 *err = ERR_BAD_DX_DIR;
389 goto fail;
390 }
391
384 dxtrace (printk("Look up %x", hash)); 392 dxtrace (printk("Look up %x", hash));
385 while (1) 393 while (1)
386 { 394 {
387 count = dx_get_count(entries); 395 count = dx_get_count(entries);
388 assert (count && count <= dx_get_limit(entries)); 396 if (!count || count > dx_get_limit(entries)) {
397 ext3_warning(dir->i_sb, __FUNCTION__,
398 "dx entry: no count or count > limit");
399 brelse(bh);
400 *err = ERR_BAD_DX_DIR;
401 goto fail2;
402 }
403
389 p = entries + 1; 404 p = entries + 1;
390 q = entries + count - 1; 405 q = entries + count - 1;
391 while (p <= q) 406 while (p <= q)
@@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
423 if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) 438 if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
424 goto fail2; 439 goto fail2;
425 at = entries = ((struct dx_node *) bh->b_data)->entries; 440 at = entries = ((struct dx_node *) bh->b_data)->entries;
426 assert (dx_get_limit(entries) == dx_node_limit (dir)); 441 if (dx_get_limit(entries) != dx_node_limit (dir)) {
442 ext3_warning(dir->i_sb, __FUNCTION__,
443 "dx entry: limit != node limit");
444 brelse(bh);
445 *err = ERR_BAD_DX_DIR;
446 goto fail2;
447 }
427 frame++; 448 frame++;
449 frame->bh = NULL;
428 } 450 }
429fail2: 451fail2:
430 while (frame >= frame_in) { 452 while (frame >= frame_in) {
@@ -432,6 +454,10 @@ fail2:
432 frame--; 454 frame--;
433 } 455 }
434fail: 456fail:
457 if (*err == ERR_BAD_DX_DIR)
458 ext3_warning(dir->i_sb, __FUNCTION__,
459 "Corrupt dir inode %ld, running e2fsck is "
460 "recommended.", dir->i_ino);
435 return NULL; 461 return NULL;
436} 462}
437 463
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index da224974af78..9468289637a5 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -379,13 +379,28 @@ dx_probe(struct dentry *dentry, struct inode *dir,
379 379
380 entries = (struct dx_entry *) (((char *)&root->info) + 380 entries = (struct dx_entry *) (((char *)&root->info) +
381 root->info.info_length); 381 root->info.info_length);
382 assert(dx_get_limit(entries) == dx_root_limit(dir, 382
383 root->info.info_length)); 383 if (dx_get_limit(entries) != dx_root_limit(dir,
384 root->info.info_length)) {
385 ext4_warning(dir->i_sb, __FUNCTION__,
386 "dx entry: limit != root limit");
387 brelse(bh);
388 *err = ERR_BAD_DX_DIR;
389 goto fail;
390 }
391
384 dxtrace (printk("Look up %x", hash)); 392 dxtrace (printk("Look up %x", hash));
385 while (1) 393 while (1)
386 { 394 {
387 count = dx_get_count(entries); 395 count = dx_get_count(entries);
388 assert (count && count <= dx_get_limit(entries)); 396 if (!count || count > dx_get_limit(entries)) {
397 ext4_warning(dir->i_sb, __FUNCTION__,
398 "dx entry: no count or count > limit");
399 brelse(bh);
400 *err = ERR_BAD_DX_DIR;
401 goto fail2;
402 }
403
389 p = entries + 1; 404 p = entries + 1;
390 q = entries + count - 1; 405 q = entries + count - 1;
391 while (p <= q) 406 while (p <= q)
@@ -423,8 +438,15 @@ dx_probe(struct dentry *dentry, struct inode *dir,
423 if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err))) 438 if (!(bh = ext4_bread (NULL,dir, dx_get_block(at), 0, err)))
424 goto fail2; 439 goto fail2;
425 at = entries = ((struct dx_node *) bh->b_data)->entries; 440 at = entries = ((struct dx_node *) bh->b_data)->entries;
426 assert (dx_get_limit(entries) == dx_node_limit (dir)); 441 if (dx_get_limit(entries) != dx_node_limit (dir)) {
442 ext4_warning(dir->i_sb, __FUNCTION__,
443 "dx entry: limit != node limit");
444 brelse(bh);
445 *err = ERR_BAD_DX_DIR;
446 goto fail2;
447 }
427 frame++; 448 frame++;
449 frame->bh = NULL;
428 } 450 }
429fail2: 451fail2:
430 while (frame >= frame_in) { 452 while (frame >= frame_in) {
@@ -432,6 +454,10 @@ fail2:
432 frame--; 454 frame--;
433 } 455 }
434fail: 456fail:
457 if (*err == ERR_BAD_DX_DIR)
458 ext4_warning(dir->i_sb, __FUNCTION__,
459 "Corrupt dir inode %ld, running e2fsck is "
460 "recommended.", dir->i_ino);
435 return NULL; 461 return NULL;
436} 462}
437 463