Whamcloud - gitweb
LU-11330 osd-zfs: hash for ./.. must be 0 98/34098/10
authorAlex Zhuravlev <bzzz@whamcloud.com>
Thu, 24 Jan 2019 05:04:09 +0000 (08:04 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 27 Feb 2019 02:01:07 +0000 (02:01 +0000)
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 <bzzz@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/34098
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Nathaniel Clark <nclark@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/osd-zfs/osd_index.c
lustre/osd-zfs/osd_internal.h
lustre/tests/replay-single.sh
lustre/tests/sanity.sh

index 115c247..c4e397b 100644 (file)
@@ -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)
index b1bec9e..1fa1f76 100644 (file)
@@ -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 */
index 4ce89a2..ff8d25d 100755 (executable)
@@ -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)
index daa8994..739df27 100755 (executable)
@@ -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 ============================================='