Whamcloud - gitweb
LU-6427 osd: race between destroy and load LMV 46/14346/17
authorwang di <di.wang@intel.com>
Wed, 1 Apr 2015 19:57:57 +0000 (12:57 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Mon, 3 Aug 2015 01:54:02 +0000 (01:54 +0000)
Do not get LMVEA if the object has been destroyed,
because it needs to iterate the master object, which
is dangerous for ZFS OSD.

Add oo_destroyed flags to avoid accessing destroyed
directory.

Add sanityn.sh 83 to verify accessing destroyed striped
directory will not cause panic.

Signed-off-by: wang di <di.wang@intel.com>
Signed-off-by: John L. Hammond <john.hammond@intel.com>
Change-Id: I1ef6bf197eac0917fd649868235c96af2f64207c
Reviewed-on: http://review.whamcloud.com/14346
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-by: Lai Siyao <lai.siyao@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/mdd/mdd_object.c
lustre/osd-ldiskfs/osd_handler.c
lustre/osd-ldiskfs/osd_internal.h
lustre/osd-zfs/osd_index.c
lustre/osd-zfs/osd_internal.h
lustre/osd-zfs/osd_object.c
lustre/tests/sanityn.sh

index a526436..c46ff62 100644 (file)
@@ -229,6 +229,15 @@ static int mdd_xattr_get(const struct lu_env *env,
                 return -ENOENT;
         }
 
+       /* If the object has been destroyed, then do not get LMVEA, because
+        * it needs to load stripes from the iteration of the master object,
+        * and it will cause problem if master object has been destroyed, see
+        * LU-6427 */
+       if (unlikely((mdd_obj->mod_flags & DEAD_OBJ) &&
+                    !(mdd_obj->mod_flags & ORPHAN_OBJ) &&
+                     strcmp(name, XATTR_NAME_LMV) == 0))
+               RETURN(-ENOENT);
+
        /* If the object has been delete from the namespace, then
         * get linkEA should return -ENOENT as well */
        if (unlikely((mdd_obj->mod_flags & (DEAD_OBJ | ORPHAN_OBJ)) &&
index e5401f6..7ac3591 100644 (file)
@@ -2371,6 +2371,7 @@ static int osd_object_destroy(const struct lu_env *env,
 
        /* not needed in the cache anymore */
        set_bit(LU_OBJECT_HEARD_BANSHEE, &dt->do_lu.lo_header->loh_flags);
+       obj->oo_destroyed = 1;
 
        RETURN(0);
 }
@@ -4666,7 +4667,7 @@ static struct dt_it *osd_it_ea_init(const struct lu_env *env,
        struct dentry           *obj_dentry;
        ENTRY;
 
-       if (!dt_object_exists(dt))
+       if (!dt_object_exists(dt) || obj->oo_destroyed)
                RETURN(ERR_PTR(-ENOENT));
 
        OBD_SLAB_ALLOC_PTR_GFP(oie, osd_itea_cachep, GFP_NOFS);
index a9f7319..2bc26b9 100644 (file)
@@ -126,6 +126,8 @@ struct osd_object {
        struct osd_directory    *oo_dir;
        /** protects inode attributes. */
        spinlock_t              oo_guard;
+
+       __u32                   oo_destroyed:1;
         /**
          * Following two members are used to indicate the presence of dot and
          * dotdot in the given directory. This is required for interop mode
index 027b3c6..3d7aae7 100644 (file)
@@ -160,6 +160,9 @@ static struct dt_it *osd_index_it_init(const struct lu_env *env,
        int                      rc;
        ENTRY;
 
+       if (obj->oo_destroyed)
+               RETURN(ERR_PTR(-ENOENT));
+
        LASSERT(lu_object_exists(lo));
        LASSERT(obj->oo_db);
        LASSERT(osd_object_is_zap(obj->oo_db));
index 850290f..9f567d6 100644 (file)
@@ -330,6 +330,7 @@ struct osd_object {
        uint64_t                 oo_xattr;
        enum osd_destroy_type    oo_destroy;
 
+       __u32                    oo_destroyed:1;
        /* record size for index file */
        unsigned char            oo_keysize;
        unsigned char            oo_recsize;
index 51b218d..9b5e11f 100644 (file)
@@ -603,7 +603,8 @@ static int osd_object_destroy(const struct lu_env *env,
 out:
        /* not needed in the cache anymore */
        set_bit(LU_OBJECT_HEARD_BANSHEE, &dt->do_lu.lo_header->loh_flags);
-
+       if (rc == 0)
+               obj->oo_destroyed = 1;
        RETURN (0);
 }
 
index 1e65fda..099702b 100644 (file)
@@ -3169,6 +3169,39 @@ test_82() {
 }
 run_test 82 "fsetxattr and fgetxattr on orphan files"
 
+test_83() {
+       [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs" && return
+       local pid1
+       local pid2
+
+       (
+               cd $DIR1
+               while true; do
+                       $LFS mkdir -i1 -c2 $tdir
+                       rmdir $tdir
+               done
+       ) &
+       pid1=$!
+       echo "start pid $pid1 to create/unlink striped directory"
+
+       # Access the directory at the same time
+       (
+               cd $DIR2
+               while true; do
+                       stat $tdir > /dev/null 2>&1
+               done
+       ) &
+       pid2=$!
+       echo "start pid $pid2 to stat striped directory"
+
+       sleep 120
+       kill $pid1 $pid2
+       wait $pid1 $pid2
+
+       return 0
+}
+run_test 83 "access striped directory while it is being created/unlinked"
+
 log "cleanup: ======================================================"
 
 [ "$(mount | grep $MOUNT2)" ] && umount $MOUNT2