ext4: Fix duplicate entries returned from getdents() system call

Fix a regression caused by commit d0156417, "ext4: fix ext4_dx_readdir
hash collision handling", where deleting files in a large directory
(requiring more than one getdents system call), results in some
filenames being returned twice. This was caused by a failure to
update info->curr_hash and info->curr_minor_hash, so that if the
directory had gotten modified since the last getdents() system call
(as would be the case if the user is running "rm -r" or "git clean"),
a directory entry would get returned twice to the userspace.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

This patch fixes the bug reported by Markus Trippelsdorf at:
http://bugzilla.kernel.org/show_bug.cgi?id=11844

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Tested-by: Markus Trippelsdorf <markus@trippelsdorf.de>

+8 -12
+8 -12
fs/ext4/dir.c
··· 459 459 if (info->extra_fname) { 460 460 if (call_filldir(filp, dirent, filldir, info->extra_fname)) 461 461 goto finished; 462 - 463 462 info->extra_fname = NULL; 464 - info->curr_node = rb_next(info->curr_node); 465 - if (!info->curr_node) { 466 - if (info->next_hash == ~0) { 467 - filp->f_pos = EXT4_HTREE_EOF; 468 - goto finished; 469 - } 470 - info->curr_hash = info->next_hash; 471 - info->curr_minor_hash = 0; 472 - } 463 + goto next_node; 473 464 } else if (!info->curr_node) 474 465 info->curr_node = rb_first(&info->root); 475 466 ··· 492 501 info->curr_minor_hash = fname->minor_hash; 493 502 if (call_filldir(filp, dirent, filldir, fname)) 494 503 break; 495 - 504 + next_node: 496 505 info->curr_node = rb_next(info->curr_node); 497 - if (!info->curr_node) { 506 + if (info->curr_node) { 507 + fname = rb_entry(info->curr_node, struct fname, 508 + rb_hash); 509 + info->curr_hash = fname->hash; 510 + info->curr_minor_hash = fname->minor_hash; 511 + } else { 498 512 if (info->next_hash == ~0) { 499 513 filp->f_pos = EXT4_HTREE_EOF; 500 514 break;