From ad83b289c4b0b24ec5edb6d6677ef9ba7403464b Mon Sep 17 00:00:00 2001 From: Ned Bass Date: Mon, 20 May 2013 18:50:47 -0700 Subject: [PATCH] LU-3182 lmv: fix duplicate directory entries In 4e57f6dd3a156e35ccb587fc5c003805dd73ecb7, I accidentally introduced a new way for duplicate directory entries to be returned from readdir(). That patch fails to properly decrement the nlupgs counter when breaking out of the inner-for loop. This accounting error causes an extra iteration of the inner-for loop when processing the next cfs page and a bad ldp_hash_end value is then saved in the lu_dirpage. To fix this, always decrement the nlupgs counter on entry into the inner loop. Note: this bug only affects architectures with > 4k-sized pages, e.g. PowerPC. Signed-off-by: Ned Bass Change-Id: I9fa0fd8f34081f834f1d8b4df633d6e08926dcc9 Reviewed-on: http://review.whamcloud.com/6405 Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Bobi Jam Tested-by: Hudson Tested-by: Maloo --- lustre/lmv/lmv_obd.c | 3 ++- lustre/tests/sanity.sh | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lustre/lmv/lmv_obd.c b/lustre/lmv/lmv_obd.c index c3a93bf..5f8a2ee 100644 --- a/lustre/lmv/lmv_obd.c +++ b/lustre/lmv/lmv_obd.c @@ -2186,7 +2186,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) __u64 hash_end = dp->ldp_hash_end; __u32 flags = dp->ldp_flags; - for (; nlupgs > 1; nlupgs--) { + while (--nlupgs > 0) { ent = lu_dirent_start(dp); for (end_dirent = ent; ent != NULL; end_dirent = ent, ent = lu_dirent_next(ent)); @@ -2220,6 +2220,7 @@ static void lmv_adjust_dirpages(struct page **pages, int ncfspgs, int nlupgs) kunmap(pages[i]); } + LASSERTF(nlupgs == 0, "left = %d", nlupgs); } #else #define lmv_adjust_dirpages(pages, ncfspgs, nlupgs) do {} while (0) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index d64d161..a489aba 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -1114,6 +1114,21 @@ test_24z() { } run_test 24z "rename one remote dir to another remote dir should fail" +test_24A() { # LU-3182 + local NFILES=5000 + + mkdir -p $DIR/$tdir + createmany -m $DIR/$tdir/$tfile $NFILES + local t=`ls $DIR/$tdir | wc -l` + local u=`ls $DIR/$tdir | sort -u | wc -l` + if [ $t -ne $NFILES -o $u -ne $NFILES ] ; then + error "Expected $NFILES files, got $t ($u unique)" + fi + + rm -rf $DIR/$tdir || error "Can not delete directories" +} +run_test 24A "readdir() returns correct number of entries." + test_25a() { echo '== symlink sanity =============================================' -- 1.8.3.1