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();
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;
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));
}
run_test 41h "pdirops: create vs readdir =============="
+sub_test_41i() {
+ local PID1 PID2
+ local fail_loc="$1"
+ local ret=0
+
+ do_nodes $(comma_list $(mdts_nodes)) \
+ "lctl set_param -n fail_loc=${fail_loc} || true" &>/dev/null
+
+ $MULTIOP $DIR1/$tfile oO_CREAT:O_EXCL:c 2>/dev/null &
+ PID1=$!
+ sleep 0.2
+ $MULTIOP $DIR2/$tfile oO_CREAT:O_EXCL:c 2>/dev/null &
+ PID2=$!
+
+ if ! wait $PID1 && ! wait $PID2; then
+ echo "Both creates failed (1 should fail, 1 should succeed)"
+ ret=1
+ elif wait $PID1 && wait $PID2; then
+ echo "Both creates succeeded (1 should fail, 1 should succeed)"
+ ret=2
+ fi
+
+ #Clean
+ do_nodes $(comma_list $(mdts_nodes)) \
+ "lctl set_param -n fail_loc=0x0 || true" &>/dev/null
+ rm -f $DIR/$tfile
+
+ return $ret
+}
+
+test_41i() {
+ [[ $MDS1_VERSION -le $(version_code 2.13.56) ]] ||
+ skip "Need MDS version newer than 2.13.56"
+ local msg fail_loc
+
+#define OBD_FAIL_ONCE|OBD_FAIL_MDS_REINT_OPEN 0x169
+#define OBD_FAIL_ONCE|OBD_FAIL_MDS_REINT_OPEN2 0x16a
+ for fail_loc in "0x80000169" "0x8000016a"; do
+ echo "Begin 100 tests with fail_loc=$fail_loc"
+ printf "Progress: "
+ for i in {1..100}; do
+ printf "*"
+ msg=$(sub_test_41i "$fail_loc") ||
+ { echo; error "iter=$i : $msg"; }
+ done
+ echo
+ done
+}
+run_test 41i "reint_open: create vs create"
+
+
# test 42: unlink and blocking operations
test_42a() {
pdo_lru_clear
}
run_test 43j "racy mkdir return EEXIST =============="
+sub_test_43k() {
+ local PID1 PID2
+ local fail_loc="$1"
+ local ret=0
+
+ # We test in a separate directory to be able to unblock server thread in
+ # cfs_race() if LCK_PW is taken on the parent by mdt_reint_unlink.
+ test_mkdir $DIR2/$tdir
+ touch $DIR2/$tdir/$tfile
+
+ do_nodes $(comma_list $(mdts_nodes)) \
+ "lctl set_param -n fail_loc=${fail_loc} || true" &>/dev/null
+ echo content > $DIR1/$tdir/$tfile & PID1=$!
+ pdo_sched
+ multiop $DIR2/$tdir/$tfile u & PID2=$!
+
+ wait $PID1 ||
+ { ret=$?; \
+ echo -n "overwriting $tfile should succeed (err=$ret); "; }
+ wait $PID2 ||
+ { ret=$?; \
+ echo -n "unlinking $tfile should succeed (err=$ret);"; }
+
+ #Clean
+ do_nodes $(comma_list $(mdts_nodes)) \
+ "lctl set_param -n fail_loc=0x0 || true" &>/dev/null
+ rm -rf $DIR/$tdir
+
+ return $ret
+}
+
+test_43k() {
+ [[ $MDS1_VERSION -le $(version_code 2.13.56) ]] ||
+ skip "Need MDS version newer than 2.13.56"
+ local msg fail_loc
+
+#define OBD_FAIL_ONCE|OBD_FAIL_MDS_REINT_OPEN 0x169
+#define OBD_FAIL_ONCE|OBD_FAIL_MDS_REINT_OPEN2 0x16a
+ for fail_loc in "0x80000169" "0x8000016a"; do
+ echo "Begin 100 tests with fail_loc=$fail_loc"
+ printf "Progress: "
+ for i in {1..100}; do
+ printf "*"
+ msg=$(sub_test_43k "$fail_loc") ||
+ { echo; error "iter=$i : $msg"; }
+ done
+ echo
+ done
+
+ #Clean
+ reset_fail_loc
+
+ return 0
+}
+run_test 43k "unlink vs create"
+
# test 44: rename tgt and blocking operations
test_44a() {
pdo_lru_clear
}
run_test 45i "pdirops: rename src vs remote mkdir"
+sub_test_45j() {
+ local PID1 PID2
+ local fail_loc="$1"
+ local ret=0
+
+ # We test in a sparate directory to be able to unblock server thread in
+ # cfs_race if LCK_PW is taken on the parent by mdt_reint_rename.
+ test_mkdir $DIR2/$tdir
+ echo file1 > $DIR2/$tdir/$tfile
+ echo file2 > $DIR2/$tdir/$tfile-2
+
+ do_nodes $(comma_list $(mdts_nodes)) \
+ "lctl set_param -n fail_loc=${fail_loc} || true" &>/dev/null
+
+ cat $DIR1/$tdir/$tfile >/dev/null &
+ PID1=$!
+ pdo_sched
+ mrename $DIR2/$tdir/$tfile-2 $DIR2/$tdir/$tfile > /dev/null &
+ PID2=$!
+
+ wait $PID1 ||
+ { ret=$?; echo -n "cat $tfile should succeed (err=$ret); "; }
+ wait $PID2 ||
+ { ret=$?; \
+ echo -n "mrename $tfile-2 to $tfile failed (err=$ret);"; }
+
+ #Clean
+ do_nodes $(comma_list $(mdts_nodes)) \
+ "lctl set_param -n fail_loc=0x0 || true" &>/dev/null
+ rm -rf $DIR/$tdir
+
+ return $ret
+}
+
+test_45j() {
+ [[ $MDS1_VERSION -le $(version_code 2.13.56) ]] ||
+ skip "Need MDS version newer than 2.13.56"
+ local msg fail_loc
+
+#define OBD_FAIL_ONCE|OBD_FAIL_MDS_REINT_OPEN 0x169
+#define OBD_FAIL_ONCE|OBD_FAIL_MDS_REINT_OPEN2 0x16a
+ for fail_loc in "0x80000169" "0x8000016a"; do
+ echo "Begin 100 tests with fail_loc=$fail_loc"
+ printf "Progress: "
+ for i in {1..100}; do
+ printf "*"
+ msg=$(sub_test_45j "$fail_loc") ||
+ { echo; error "iter=$i : $msg"; }
+ done
+ echo
+ done
+}
+run_test 45j "read vs rename =============="
+
# test 46: link and blocking operations
test_46a() {
pdo_lru_clear