From fb75af7d45d1217c877f75c4296f9df0cc731604 Mon Sep 17 00:00:00 2001 From: Alex Zhuravlev Date: Thu, 24 Jan 2019 08:04:09 +0300 Subject: [PATCH] LU-11330 osd-zfs: hash for ./.. must be 0 do not use current iterator position as hash source for dot and dotdot. instead just return 0 as hash for these entries. Change-Id: I5ee439b237e8ed98d295f5672b1d0e8a6b48a55b Signed-off-by: Alex Zhuravlev Reviewed-on: https://review.whamcloud.com/34098 Reviewed-by: Andreas Dilger Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Nathaniel Clark Reviewed-by: Oleg Drokin --- lustre/osd-zfs/osd_index.c | 57 +++++++++++++++++++++++-------------------- lustre/osd-zfs/osd_internal.h | 15 +++++++----- lustre/tests/replay-single.sh | 4 --- lustre/tests/sanity.sh | 20 +++++++++++++++ 4 files changed, 60 insertions(+), 36 deletions(-) diff --git a/lustre/osd-zfs/osd_index.c b/lustre/osd-zfs/osd_index.c index 115c247..c4e397b 100644 --- a/lustre/osd-zfs/osd_index.c +++ b/lustre/osd-zfs/osd_index.c @@ -1219,7 +1219,7 @@ static struct dt_it *osd_dir_it_init(const struct lu_env *env, it = (struct osd_zap_it *)osd_index_it_init(env, dt, unused); if (!IS_ERR(it)) - it->ozi_pos = 0; + it->ozi_pos = OZI_POS_INIT; RETURN((struct dt_it *)it); } @@ -1254,22 +1254,22 @@ static int osd_dir_it_get(const struct lu_env *env, LASSERT(((const char *)key)[0] == 0); if (name[0] == 0) { - it->ozi_pos = 0; + it->ozi_pos = OZI_POS_INIT; RETURN(1); } if (name[0] == '.') { if (name[1] == 0) { - it->ozi_pos = 1; + it->ozi_pos = OZI_POS_DOT; GOTO(out, rc = 1); } else if (name[1] == '.' && name[2] == 0) { - it->ozi_pos = 2; + it->ozi_pos = OZI_POS_DOTDOT; GOTO(out, rc = 1); } } /* neither . nor .. - some real record */ - it->ozi_pos = 3; + it->ozi_pos = OZI_POS_REAL; rc = +1; out: @@ -1337,9 +1337,9 @@ static int osd_dir_it_next(const struct lu_env *env, struct dt_it *di) * the second ->next() moves the cursor to .. * then we get to the real records and have to verify any exist */ - if (it->ozi_pos <= 2) { + if (it->ozi_pos <= OZI_POS_DOTDOT) { it->ozi_pos++; - if (it->ozi_pos <=2) + if (it->ozi_pos <= OZI_POS_DOTDOT) RETURN(0); } else { @@ -1368,10 +1368,10 @@ static struct dt_key *osd_dir_it_key(const struct lu_env *env, int rc = 0; ENTRY; - if (it->ozi_pos <= 1) { - it->ozi_pos = 1; + if (it->ozi_pos <= OZI_POS_DOT) { + it->ozi_pos = OZI_POS_DOT; RETURN((struct dt_key *)"."); - } else if (it->ozi_pos == 2) { + } else if (it->ozi_pos == OZI_POS_DOTDOT) { RETURN((struct dt_key *)".."); } @@ -1390,10 +1390,10 @@ static int osd_dir_it_key_size(const struct lu_env *env, const struct dt_it *di) int rc; ENTRY; - if (it->ozi_pos <= 1) { - it->ozi_pos = 1; + if (it->ozi_pos <= OZI_POS_DOT) { + it->ozi_pos = OZI_POS_DOT; RETURN(2); - } else if (it->ozi_pos == 2) { + } else if (it->ozi_pos == OZI_POS_DOTDOT) { RETURN(3); } @@ -1481,8 +1481,12 @@ static int osd_dir_it_rec(const struct lu_env *env, const struct dt_it *di, ENTRY; lde->lde_attrs = 0; - if (it->ozi_pos <= 1) { - lde->lde_hash = cpu_to_le64(1); + if (it->ozi_pos <= OZI_POS_DOT) { + /* notice hash=0 here, this is needed to avoid + * case when some real entry (after ./..) may + * have hash=0. in this case the client would + * be confused having records out of hash order. */ + lde->lde_hash = cpu_to_le64(0); strcpy(lde->lde_name, "."); lde->lde_namelen = cpu_to_le16(1); fid_cpu_to_le(&lde->lde_fid, @@ -1491,10 +1495,11 @@ static int osd_dir_it_rec(const struct lu_env *env, const struct dt_it *di, /* append lustre attributes */ osd_it_append_attrs(lde, attr, 1, IFTODT(S_IFDIR)); lde->lde_reclen = cpu_to_le16(lu_dirent_calc_size(1, attr)); - it->ozi_pos = 1; + it->ozi_pos = OZI_POS_DOT; RETURN(0); - } else if (it->ozi_pos == 2) { - lde->lde_hash = cpu_to_le64(2); + } else if (it->ozi_pos == OZI_POS_DOTDOT) { + /* same as for . above */ + lde->lde_hash = cpu_to_le64(0); strcpy(lde->lde_name, ".."); lde->lde_namelen = cpu_to_le16(2); rc = osd_find_parent_fid(env, &it->ozi_obj->oo_dt, fid, NULL); @@ -1607,9 +1612,9 @@ static int osd_dir_it_rec_size(const struct lu_env *env, const struct dt_it *di, int rc; ENTRY; - if (it->ozi_pos <= 1) + if (it->ozi_pos <= OZI_POS_DOT) namelen = 1; - else if (it->ozi_pos == 2) + else if (it->ozi_pos == OZI_POS_DOTDOT) namelen = 2; if (namelen > 0) { @@ -1643,8 +1648,8 @@ static __u64 osd_dir_it_store(const struct lu_env *env, const struct dt_it *di) __u64 pos; ENTRY; - if (it->ozi_pos <= 2) - pos = it->ozi_pos; + if (it->ozi_pos <= OZI_POS_DOTDOT) + pos = 0; else pos = osd_zap_cursor_serialize(it->ozi_zc); @@ -1670,11 +1675,11 @@ static int osd_dir_it_load(const struct lu_env *env, zap_cursor_fini(it->ozi_zc); osd_obj_cursor_init_serialized(it->ozi_zc, obj, hash); - if (hash <= 2) { - it->ozi_pos = hash; - rc = +1; + if (hash == 0) { + it->ozi_pos = OZI_POS_INIT; + rc = +1; /* there will be ./.. at least */ } else { - it->ozi_pos = 3; + it->ozi_pos = OZI_POS_REAL; /* to return whether the end has been reached */ rc = osd_index_retrieve_skip_dots(it, za); if (rc == 0) diff --git a/lustre/osd-zfs/osd_internal.h b/lustre/osd-zfs/osd_internal.h index b1bec9e..1fa1f76 100644 --- a/lustre/osd-zfs/osd_internal.h +++ b/lustre/osd-zfs/osd_internal.h @@ -119,6 +119,13 @@ struct osd_it_quota { unsigned oiq_reset:1; /* 1 -- no need to advance */ }; +enum osd_zap_pos { + OZI_POS_INIT = 0, + OZI_POS_DOT = 1, /* cursor at . */ + OZI_POS_DOTDOT = 2, /* cursor at .. */ + OZI_POS_REAL = 3, /* cursor at real entries */ +}; + /** * Iterator's in-memory data structure for ZAPs * @@ -130,12 +137,8 @@ struct osd_zap_it { zap_cursor_t *ozi_zc; struct osd_object *ozi_obj; unsigned ozi_reset:1; /* 1 -- no need to advance */ - /* ozi_pos - position of the cursor: - * 0 - before any record - * 1 - "." - * 2 - ".." - * 3 - real records */ - unsigned ozi_pos:3; + /* ozi_pos - position of the cursor */ + enum osd_zap_pos ozi_pos; union { char ozi_name[MAXNAMELEN]; /* file name for dir */ __u64 ozi_key; /* binary key for index files */ diff --git a/lustre/tests/replay-single.sh b/lustre/tests/replay-single.sh index 4ce89a2..ff8d25d 100755 --- a/lustre/tests/replay-single.sh +++ b/lustre/tests/replay-single.sh @@ -31,10 +31,6 @@ ALWAYS_EXCEPT="$REPLAY_SINGLE_EXCEPT " if [ $(facet_fstype $SINGLEMDS) = "zfs" ]; then # bug number for skipped test: LU-11388 ALWAYS_EXCEPT+="131b" - if [ $MDSCOUNT -gt 1 ]; then -# bug number for skipped test: LU-11330 - ALWAYS_EXCEPT+=" 70d" - fi fi if $SHARED_KEY; then # bug number for skipped tests: LU-9795 (all below) diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index daa8994..739df27 100755 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -1387,6 +1387,26 @@ test_24E() { } run_test 24E "cross MDT rename/link" +test_24F () { + [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return 0 + + local repeats=1000 + [ "$SLOW" = "no" ] && repeats=100 + + mkdir -p $DIR/$tdir + + echo "$repeats repeats" + for ((i = 0; i < repeats; i++)); do + $LFS mkdir -i0 -c2 $DIR/$tdir/test || error "mkdir fails" + touch $DIR/$tdir/test/a || error "touch fails" + mkdir $DIR/$tdir/test/b || error "mkdir fails" + rm -rf $DIR/$tdir/test || error "rmdir fails" + done + + true +} +run_test 24F "hash order vs readdir (LU-11330)" + test_25a() { echo '== symlink sanity =============================================' -- 1.8.3.1