Whamcloud - gitweb
LU-1951 mdd: fix for error handler of mdd_rename
authorLiang Zhen <liang@whamcloud.com>
Fri, 5 Oct 2012 12:16:19 +0000 (20:16 +0800)
committerOleg Drokin <green@whamcloud.com>
Tue, 9 Oct 2012 01:03:24 +0000 (21:03 -0400)
If mdd_rename() failed to unlink target file/dir, it will try to
revert everything including insert target file/dir back into target
directory, but it didn't restore nlink count of target, which will
leave a file/dir under target directory with wrong nlink number.

Another thing is fixed by this patch is, mdd_attr_check_set_internal()
didn't release mdd_write_lock() while jumping to error handler.

Signed-off-by: Liang Zhen <liang@whamcloud.com>
Change-Id: I18776a8415933a1ce125f91a96deb11436057ec9
Reviewed-on: http://review.whamcloud.com/4197
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/mdd/mdd_dir.c

index 8508ddb..d152643 100644 (file)
@@ -2532,6 +2532,7 @@ static int mdd_rename(const struct lu_env *env,
         const struct lu_fid *tpobj_fid = mdo2fid(mdd_tpobj);
         const struct lu_fid *spobj_fid = mdo2fid(mdd_spobj);
         int is_dir;
+       int tobj_ref = 0;
        unsigned cl_flags = 0;
         int rc, rc2;
 
@@ -2695,16 +2696,23 @@ static int mdd_rename(const struct lu_env *env,
                 /* Remove dot reference. */
                 if (is_dir)
                         mdo_ref_del(env, mdd_tobj, handle);
+               tobj_ref = 1;
+
+               la->la_valid = LA_CTIME;
+               rc = mdd_attr_check_set_internal(env, mdd_tobj, la, handle, 0);
+               if (rc != 0) {
+                       mdd_write_unlock(env, mdd_tobj);
+                       CERROR("Failed to set ctime for tobj: %d\n", rc);
+                       GOTO(fixup_tpobj, rc);
+               }
 
-                la->la_valid = LA_CTIME;
-                rc = mdd_attr_check_set_internal(env, mdd_tobj, la, handle, 0);
-                if (rc)
-                        GOTO(fixup_tpobj, rc);
+               rc = mdd_finish_unlink(env, mdd_tobj, ma, handle);
 
-                rc = mdd_finish_unlink(env, mdd_tobj, ma, handle);
-                mdd_write_unlock(env, mdd_tobj);
-                if (rc)
-                        GOTO(fixup_tpobj, rc);
+               mdd_write_unlock(env, mdd_tobj);
+               if (rc != 0) {
+                       CERROR("Failed to unlink tobj: %d\n", rc);
+                       GOTO(fixup_tpobj, rc);
+               }
 
                if (ma->ma_valid & MA_INODE && ma->ma_attr.la_nlink == 0) {
                        cl_flags |= CLF_RENAME_LAST;
@@ -2753,6 +2761,14 @@ fixup_tpobj:
 
                 if (mdd_tobj && mdd_object_exists(mdd_tobj) &&
                     !mdd_is_dead_obj(mdd_tobj)) {
+                       if (tobj_ref) {
+                               mdd_write_lock(env, mdd_tobj, MOR_TGT_CHILD);
+                               mdo_ref_add(env, mdd_tobj, handle);
+                               if (is_dir)
+                                       mdo_ref_add(env, mdd_tobj, handle);
+                               mdd_write_unlock(env, mdd_tobj);
+                       }
+
                         rc2 = __mdd_index_insert(env, mdd_tpobj,
                                          mdo2fid(mdd_tobj), tname,
                                          is_dir, handle,