Commit 332d2f06 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix ext3_dx_readdir

When there are more than one entry in fname linked list, the current
implementation of ext3_dx_readdir() can not traverse all entries correctly
in the case that call_filldir() fails.

If we use system call readdir() to read entries in a directory which
happens that "." and ".." in the same fname linked list.  Each time we call
readdir(), it will return the "." entry and never returns 0 which indicates
that all entries are read.

Although chances that more than one entry are in one fname linked list are
very slim, it does exist.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 22d1d71a
...@@ -418,7 +418,7 @@ static int call_filldir(struct file * filp, void * dirent, ...@@ -418,7 +418,7 @@ static int call_filldir(struct file * filp, void * dirent,
get_dtype(sb, fname->file_type)); get_dtype(sb, fname->file_type));
if (error) { if (error) {
filp->f_pos = curr_pos; filp->f_pos = curr_pos;
info->extra_fname = fname->next; info->extra_fname = fname;
return error; return error;
} }
fname = fname->next; fname = fname->next;
...@@ -457,9 +457,12 @@ static int ext3_dx_readdir(struct file * filp, ...@@ -457,9 +457,12 @@ static int ext3_dx_readdir(struct file * filp,
* If there are any leftover names on the hash collision * If there are any leftover names on the hash collision
* chain, return them first. * chain, return them first.
*/ */
if (info->extra_fname && if (info->extra_fname) {
call_filldir(filp, dirent, filldir, info->extra_fname)) if(call_filldir(filp, dirent, filldir, info->extra_fname))
goto finished; goto finished;
else
goto next_entry;
}
if (!info->curr_node) if (!info->curr_node)
info->curr_node = rb_first(&info->root); info->curr_node = rb_first(&info->root);
...@@ -492,7 +495,7 @@ static int ext3_dx_readdir(struct file * filp, ...@@ -492,7 +495,7 @@ static int ext3_dx_readdir(struct file * filp,
info->curr_minor_hash = fname->minor_hash; info->curr_minor_hash = fname->minor_hash;
if (call_filldir(filp, dirent, filldir, fname)) if (call_filldir(filp, dirent, filldir, fname))
break; break;
next_entry:
info->curr_node = rb_next(info->curr_node); info->curr_node = rb_next(info->curr_node);
if (!info->curr_node) { if (!info->curr_node) {
if (info->next_hash == ~0) { if (info->next_hash == ~0) {
......
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