From: wang di Date: Wed, 1 Apr 2015 19:57:57 +0000 (-0700) Subject: LU-6427 osd: race between destroy and load LMV X-Git-Tag: 2.7.58~44 X-Git-Url: https://git.whamcloud.com/?a=commitdiff_plain;h=11b048aaffd6ced90892c4e6e9b763aa3a81fd6f;p=fs%2Flustre-release.git LU-6427 osd: race between destroy and load LMV 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 Signed-off-by: John L. Hammond Change-Id: I1ef6bf197eac0917fd649868235c96af2f64207c Reviewed-on: http://review.whamcloud.com/14346 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Lai Siyao Reviewed-by: Oleg Drokin --- diff --git a/lustre/mdd/mdd_object.c b/lustre/mdd/mdd_object.c index a526436..c46ff62 100644 --- a/lustre/mdd/mdd_object.c +++ b/lustre/mdd/mdd_object.c @@ -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)) && diff --git a/lustre/osd-ldiskfs/osd_handler.c b/lustre/osd-ldiskfs/osd_handler.c index e5401f6..7ac3591 100644 --- a/lustre/osd-ldiskfs/osd_handler.c +++ b/lustre/osd-ldiskfs/osd_handler.c @@ -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); diff --git a/lustre/osd-ldiskfs/osd_internal.h b/lustre/osd-ldiskfs/osd_internal.h index a9f7319..2bc26b9 100644 --- a/lustre/osd-ldiskfs/osd_internal.h +++ b/lustre/osd-ldiskfs/osd_internal.h @@ -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 diff --git a/lustre/osd-zfs/osd_index.c b/lustre/osd-zfs/osd_index.c index 027b3c6..3d7aae7 100644 --- a/lustre/osd-zfs/osd_index.c +++ b/lustre/osd-zfs/osd_index.c @@ -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)); diff --git a/lustre/osd-zfs/osd_internal.h b/lustre/osd-zfs/osd_internal.h index 850290f..9f567d6 100644 --- a/lustre/osd-zfs/osd_internal.h +++ b/lustre/osd-zfs/osd_internal.h @@ -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; diff --git a/lustre/osd-zfs/osd_object.c b/lustre/osd-zfs/osd_object.c index 51b218d..9b5e11f 100644 --- a/lustre/osd-zfs/osd_object.c +++ b/lustre/osd-zfs/osd_object.c @@ -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); } diff --git a/lustre/tests/sanityn.sh b/lustre/tests/sanityn.sh index 1e65fda..099702b 100644 --- a/lustre/tests/sanityn.sh +++ b/lustre/tests/sanityn.sh @@ -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