ext4: Fix ext4_dx_readdir hash collision handling

This fixes a bug where readdir() would return a directory entry twice
if there was a hash collision in an hash tree indexed directory.

Signed-off-by: Eugene Dashevsky <eugene@ibrix.com>
Signed-off-by: Mike Snitzer <msnitzer@ibrix.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

+15 -5
+15 -5
fs/ext4/dir.c
··· 411 411 get_dtype(sb, fname->file_type)); 412 412 if (error) { 413 413 filp->f_pos = curr_pos; 414 - info->extra_fname = fname->next; 414 + info->extra_fname = fname; 415 415 return error; 416 416 } 417 417 fname = fname->next; ··· 450 450 * If there are any leftover names on the hash collision 451 451 * chain, return them first. 452 452 */ 453 - if (info->extra_fname && 454 - call_filldir(filp, dirent, filldir, info->extra_fname)) 455 - goto finished; 453 + if (info->extra_fname) { 454 + if (call_filldir(filp, dirent, filldir, info->extra_fname)) 455 + goto finished; 456 456 457 - if (!info->curr_node) 457 + info->extra_fname = NULL; 458 + info->curr_node = rb_next(info->curr_node); 459 + if (!info->curr_node) { 460 + if (info->next_hash == ~0) { 461 + filp->f_pos = EXT4_HTREE_EOF; 462 + goto finished; 463 + } 464 + info->curr_hash = info->next_hash; 465 + info->curr_minor_hash = 0; 466 + } 467 + } else if (!info->curr_node) 458 468 info->curr_node = rb_first(&info->root); 459 469 460 470 while (1) {