From 0d03c3a9e6c0ed2fcd37ca8e71056cd1bf7d200b Mon Sep 17 00:00:00 2001 From: Lai Siyao Date: Mon, 24 Feb 2014 18:13:35 +0800 Subject: [PATCH] LU-4659 mdd: rename forgets updating target linkea MDD rename forgets updating target LinkEA if target is not unlinked, which will cause LinkEA inconsistency. Lustre-commit: 2d6315fbeab3c815efa3ea7b953ff34e6f3fa3fc Lustre-change: http://review.whamcloud.com/9745 Signed-off-by: Lai Siyao Signed-off-by: Bob Glossman Reviewed-by: Fan Yong Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Change-Id: I348c58e4a11e7b0ba31befef8922dfe47cee755c Reviewed-on: http://review.whamcloud.com/10409 Tested-by: Jenkins Tested-by: Maloo --- lustre/mdd/mdd_dir.c | 38 ++++++++++++++++++-------------------- lustre/mdd/mdd_internal.h | 3 ++- lustre/tests/sanity.sh | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/lustre/mdd/mdd_dir.c b/lustre/mdd/mdd_dir.c index a8a0caa..33a4d1c 100644 --- a/lustre/mdd/mdd_dir.c +++ b/lustre/mdd/mdd_dir.c @@ -1293,16 +1293,22 @@ int mdd_declare_finish_unlink(const struct lu_env *env, int rc; rc = orph_declare_index_insert(env, obj, mdd_object_type(obj), handle); - if (rc) + if (rc != 0) + return rc; + + rc = mdo_declare_destroy(env, obj, handle); + if (rc != 0) return rc; - return mdo_declare_destroy(env, obj, handle); + return mdd_declare_links_del(env, obj, handle); } /* caller should take a lock before calling */ int mdd_finish_unlink(const struct lu_env *env, - struct mdd_object *obj, struct md_attr *ma, - struct thandle *th) + struct mdd_object *obj, struct md_attr *ma, + const struct mdd_object *pobj, + const struct lu_name *lname, + struct thandle *th) { int rc = 0; int is_dir = S_ISDIR(ma->ma_attr.la_mode); @@ -1330,8 +1336,11 @@ int mdd_finish_unlink(const struct lu_env *env, obj->mod_count); } else { rc = mdo_destroy(env, obj, th); - } - } + } + } else if (!is_dir) { + /* old files may not have link ea; ignore errors */ + mdd_links_del(env, obj, mdo2fid(pobj), lname, th); + } RETURN(rc); } @@ -1394,10 +1403,6 @@ static int mdd_declare_unlink(const struct lu_env *env, struct mdd_device *mdd, if (rc) return rc; - rc = mdd_declare_links_del(env, c, handle); - if (rc != 0) - return rc; - /* FIXME: need changelog for remove entry */ rc = mdd_declare_changelog_store(env, mdd, name, handle); } @@ -1552,17 +1557,13 @@ static int mdd_unlink(const struct lu_env *env, struct md_object *pobj, /* XXX: this transfer to ma will be removed with LOD/OSP */ ma->ma_attr = *cattr; ma->ma_valid |= MA_INODE; - rc = mdd_finish_unlink(env, mdd_cobj, ma, handle); + rc = mdd_finish_unlink(env, mdd_cobj, ma, mdd_pobj, lname, handle); /* fetch updated nlink */ if (rc == 0) rc = mdd_la_get(env, mdd_cobj, cattr, mdd_object_capa(env, mdd_cobj)); - if (!is_dir) - /* old files may not have link ea; ignore errors */ - mdd_links_del(env, mdd_cobj, mdo2fid(mdd_pobj), lname, handle); - /* if object is removed then we can't get its attrs, use last get */ if (cattr->la_nlink == 0) { ma->ma_attr = *cattr; @@ -2428,10 +2429,6 @@ static int mdd_declare_rename(const struct lu_env *env, if (rc) return rc; - rc = mdd_declare_links_del(env, mdd_tobj, handle); - if (rc) - return rc; - rc = mdd_declare_finish_unlink(env, mdd_tobj, ma, handle); if (rc) return rc; @@ -2613,7 +2610,8 @@ static int mdd_rename(const struct lu_env *env, /* XXX: this transfer to ma will be removed with LOD/OSP */ ma->ma_attr = *tg_attr; ma->ma_valid |= MA_INODE; - rc = mdd_finish_unlink(env, mdd_tobj, ma, handle); + rc = mdd_finish_unlink(env, mdd_tobj, ma, mdd_tpobj, ltname, + handle); if (rc != 0) { CERROR("%s: Failed to unlink tobj " DFID": rc = %d\n", diff --git a/lustre/mdd/mdd_internal.h b/lustre/mdd/mdd_internal.h index 4f5d0a6..3353641 100644 --- a/lustre/mdd/mdd_internal.h +++ b/lustre/mdd/mdd_internal.h @@ -269,7 +269,8 @@ int mdd_may_delete(const struct lu_env *env, struct mdd_object *pobj, int mdd_unlink_sanity_check(const struct lu_env *env, struct mdd_object *pobj, struct mdd_object *cobj, struct lu_attr *cattr); int mdd_finish_unlink(const struct lu_env *env, struct mdd_object *obj, - struct md_attr *ma, struct thandle *th); + struct md_attr *ma, const struct mdd_object *pobj, + const struct lu_name *lname, struct thandle *th); int mdd_link_sanity_check(const struct lu_env *env, struct mdd_object *tgt_obj, const struct lu_name *lname, struct mdd_object *src_obj); diff --git a/lustre/tests/sanity.sh b/lustre/tests/sanity.sh index f90252f..97178c5 100644 --- a/lustre/tests/sanity.sh +++ b/lustre/tests/sanity.sh @@ -12050,6 +12050,22 @@ test_236() { } run_test 236 "Layout swap on open unlinked file" +# LU-4659 linkea consistency +test_238() { + touch $DIR/$tfile + ln $DIR/$tfile $DIR/$tfile.lnk + touch $DIR/$tfile.new + mv $DIR/$tfile.new $DIR/$tfile + local fid1=$(lfs path2fid $DIR/$tfile) + local fid2=$(lfs path2fid $DIR/$tfile.lnk) + local path1=$(lfs fid2path $FSNAME $fid1) + [ $tfile == $path1 ] || error "linkea inconsistent: $tfile $fid1 $path1" + local path2=$(lfs fid2path $FSNAME $fid2) + [ $tfile.lnk == $path2 ] || + error "linkea inconsistent: $tfile.lnk $fid2 $path2!" + rm -f $DIR/$tfile* +} +run_test 238 "Verify linkea consistency" # # tests that do cleanup/setup should be run at the end # -- 1.8.3.1