Whamcloud - gitweb
LU-10262 mdt: mdt_reint_open: check EEXIST without lock
[fs/lustre-release.git] / lustre / mdt / mdt_open.c
index 5b474a4..ef12eb1 100644 (file)
@@ -1313,6 +1313,7 @@ int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
        int result, rc;
        int created = 0;
        int object_locked = 0;
+       enum ldlm_mode lock_mode = LCK_PR;
        u32 msg_flags;
        ktime_t kstart = ktime_get();
 
@@ -1390,25 +1391,27 @@ int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
        if (result < 0)
                GOTO(out, result);
 
-       lh = &info->mti_lh[MDT_LH_PARENT];
-       mdt_lock_pdo_init(lh, (open_flags & MDS_OPEN_CREAT) ? LCK_PW : LCK_PR,
-                         &rr->rr_name);
-
        parent = mdt_object_find(info->mti_env, mdt, rr->rr_fid1);
        if (IS_ERR(parent))
                GOTO(out, result = PTR_ERR(parent));
 
-       result = mdt_object_lock(info, parent, lh, MDS_INODELOCK_UPDATE);
-       if (result != 0) {
+       /* get and check version of parent */
+       result = mdt_version_get_check(info, parent, 0);
+       if (result) {
                mdt_object_put(info->mti_env, parent);
                GOTO(out, result);
        }
 
-       /* get and check version of parent */
-       result = mdt_version_get_check(info, parent, 0);
-       if (result)
-               GOTO(out_parent, result);
+       OBD_RACE(OBD_FAIL_MDS_REINT_OPEN);
+again_pw:
+       lh = &info->mti_lh[MDT_LH_PARENT];
+       mdt_lock_pdo_init(lh, lock_mode, &rr->rr_name);
 
+       result = mdt_object_lock(info, parent, lh, MDS_INODELOCK_UPDATE);
+       if (result != 0) {
+               mdt_object_put(info->mti_env, parent);
+               GOTO(out, result);
+       }
        fid_zero(child_fid);
 
        result = -ENOENT;
@@ -1424,12 +1427,24 @@ int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
        if (result != 0 && result != -ENOENT)
                GOTO(out_parent, result);
 
+       OBD_RACE(OBD_FAIL_MDS_REINT_OPEN2);
+
        if (result == -ENOENT) {
                mdt_set_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
                if (!(open_flags & MDS_OPEN_CREAT))
                        GOTO(out_parent, result);
                if (mdt_rdonly(req->rq_export))
                        GOTO(out_parent, result = -EROFS);
+
+               if (lock_mode == LCK_PR) {
+                       /* first pass: get write lock and restart */
+                       mdt_object_unlock(info, parent, lh, 1);
+                       mdt_clear_disposition(info, ldlm_rep, DISP_LOOKUP_NEG);
+                       mdt_lock_handle_init(lh);
+                       lock_mode = LCK_PW;
+                       goto again_pw;
+               }
+
                *child_fid = *info->mti_rr.rr_fid2;
                LASSERTF(fid_is_sane(child_fid), "fid="DFID"\n",
                         PFID(child_fid));