diff options
Diffstat (limited to 'fs/ext3/dir.c')
-rw-r--r-- | fs/ext3/dir.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 2eea96ec78ed..4c82531ea0a8 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * filp, | |||
102 | int err; | 102 | int err; |
103 | struct inode *inode = filp->f_path.dentry->d_inode; | 103 | struct inode *inode = filp->f_path.dentry->d_inode; |
104 | int ret = 0; | 104 | int ret = 0; |
105 | int dir_has_error = 0; | ||
105 | 106 | ||
106 | sb = inode->i_sb; | 107 | sb = inode->i_sb; |
107 | 108 | ||
@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * filp, | |||
148 | * of recovering data when there's a bad sector | 149 | * of recovering data when there's a bad sector |
149 | */ | 150 | */ |
150 | if (!bh) { | 151 | if (!bh) { |
151 | ext3_error (sb, "ext3_readdir", | 152 | if (!dir_has_error) { |
152 | "directory #%lu contains a hole at offset %lu", | 153 | ext3_error(sb, __func__, "directory #%lu " |
153 | inode->i_ino, (unsigned long)filp->f_pos); | 154 | "contains a hole at offset %lld", |
155 | inode->i_ino, filp->f_pos); | ||
156 | dir_has_error = 1; | ||
157 | } | ||
154 | /* corrupt size? Maybe no more blocks to read */ | 158 | /* corrupt size? Maybe no more blocks to read */ |
155 | if (filp->f_pos > inode->i_blocks << 9) | 159 | if (filp->f_pos > inode->i_blocks << 9) |
156 | break; | 160 | break; |
@@ -410,7 +414,7 @@ static int call_filldir(struct file * filp, void * dirent, | |||
410 | get_dtype(sb, fname->file_type)); | 414 | get_dtype(sb, fname->file_type)); |
411 | if (error) { | 415 | if (error) { |
412 | filp->f_pos = curr_pos; | 416 | filp->f_pos = curr_pos; |
413 | info->extra_fname = fname->next; | 417 | info->extra_fname = fname; |
414 | return error; | 418 | return error; |
415 | } | 419 | } |
416 | fname = fname->next; | 420 | fname = fname->next; |
@@ -449,11 +453,21 @@ static int ext3_dx_readdir(struct file * filp, | |||
449 | * If there are any leftover names on the hash collision | 453 | * If there are any leftover names on the hash collision |
450 | * chain, return them first. | 454 | * chain, return them first. |
451 | */ | 455 | */ |
452 | if (info->extra_fname && | 456 | if (info->extra_fname) { |
453 | call_filldir(filp, dirent, filldir, info->extra_fname)) | 457 | if (call_filldir(filp, dirent, filldir, info->extra_fname)) |
454 | goto finished; | 458 | goto finished; |
455 | 459 | ||
456 | if (!info->curr_node) | 460 | info->extra_fname = NULL; |
461 | info->curr_node = rb_next(info->curr_node); | ||
462 | if (!info->curr_node) { | ||
463 | if (info->next_hash == ~0) { | ||
464 | filp->f_pos = EXT3_HTREE_EOF; | ||
465 | goto finished; | ||
466 | } | ||
467 | info->curr_hash = info->next_hash; | ||
468 | info->curr_minor_hash = 0; | ||
469 | } | ||
470 | } else if (!info->curr_node) | ||
457 | info->curr_node = rb_first(&info->root); | 471 | info->curr_node = rb_first(&info->root); |
458 | 472 | ||
459 | while (1) { | 473 | while (1) { |