return 0;
}
+static inline enum ldlm_mode mdt_open_lock_mode(struct mdt_thread_info *info,
+ struct mdt_object *p,
+ struct lu_name *name,
+ u64 open_flags)
+{
+ int result;
+ struct lu_fid fid;
+
+ /* We don't need to take the DLM lock for a volatile */
+ if (open_flags & MDS_OPEN_VOLATILE)
+ return LCK_NL;
+
+ if (!(open_flags & MDS_OPEN_CREAT))
+ return LCK_PR;
+
+ result = mdo_lookup(info->mti_env, mdt_object_child(p), name, &fid,
+ &info->mti_spec);
+
+ /* If the file exists we only need a read lock on the parent */
+ return (result == 0) ? LCK_PR : LCK_PW;
+}
+
int mdt_reint_open(struct mdt_thread_info *info, struct mdt_lock_handle *lhc)
{
struct mdt_device *mdt = info->mti_mdt;
int result, rc;
int created = 0;
int object_locked = 0;
- enum ldlm_mode lock_mode = LCK_PR;
+ enum ldlm_mode lock_mode;
u32 msg_flags;
ktime_t kstart = ktime_get();
GOTO(out, result);
}
- OBD_RACE(OBD_FAIL_MDS_REINT_OPEN);
-again_pw:
fid_zero(child_fid);
+ result = -ENOENT;
+ lock_mode = mdt_open_lock_mode(info, parent, &rr->rr_name, open_flags);
- if (open_flags & MDS_OPEN_VOLATILE) {
- lh = NULL;
- result = -ENOENT;
- } else {
+ OBD_RACE(OBD_FAIL_MDS_REINT_OPEN);
+again_pw:
+ if (lock_mode != LCK_NL) {
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);
- }
+ if (result != 0)
+ GOTO(out_parent, result);
result = mdo_lookup(info->mti_env, mdt_object_child(parent),
&rr->rr_name, child_fid, &info->mti_spec);
PFID(child_fid));
if (result != 0 && result != -ENOENT)
- GOTO(out_parent, result);
+ GOTO(out_parent_unlock, 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);
+ GOTO(out_parent_unlock, result);
if (mdt_rdonly(req->rq_export))
- GOTO(out_parent, result = -EROFS);
+ GOTO(out_parent_unlock, result = -EROFS);
- LASSERT(equi(lh == NULL, open_flags & MDS_OPEN_VOLATILE));
+ LASSERT(equi(lh == NULL, lock_mode == LCK_NL));
- if (lh != NULL && lock_mode == LCK_PR) {
- /* first pass: get write lock and restart */
+ if (lock_mode == LCK_PR) {
+ /* unlink vs create race: 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);
child = mdt_object_find(info->mti_env, mdt, child_fid);
}
if (IS_ERR(child))
- GOTO(out_parent, result = PTR_ERR(child));
+ GOTO(out_parent_unlock, result = PTR_ERR(child));
/** check version of child */
rc = mdt_version_get_check(info, child, 1);
mdt_object_put(info->mti_env, child);
if (result == 0)
mdt_pack_size2body(info, child_fid, &lhc->mlh_reg_lh);
-out_parent:
+out_parent_unlock:
if (lh != NULL)
mdt_object_unlock(info, parent, lh, result || !created);
+out_parent:
mdt_object_put(info->mti_env, parent);
out:
if (result)
}
test_41i() {
- [[ $MDS1_VERSION -le $(version_code 2.13.56) ]] ||
+ (( $MDS1_VERSION >= $(version_code 2.13.56) )) ||
skip "Need MDS version newer than 2.13.56"
local msg fail_loc
# cfs_race() if LCK_PW is taken on the parent by mdt_reint_unlink.
test_mkdir $DIR2/$tdir
touch $DIR2/$tdir/$tfile
+ pdo_lru_clear
do_nodes $(comma_list $(mdts_nodes)) \
"lctl set_param -n fail_loc=${fail_loc} || true" &>/dev/null
}
test_43k() {
- [[ $MDS1_VERSION -le $(version_code 2.13.56) ]] ||
+ (( $MDS1_VERSION >= $(version_code 2.13.56) )) ||
skip "Need MDS version newer than 2.13.56"
local msg fail_loc
test_mkdir $DIR2/$tdir
echo file1 > $DIR2/$tdir/$tfile
echo file2 > $DIR2/$tdir/$tfile-2
+ pdo_lru_clear
do_nodes $(comma_list $(mdts_nodes)) \
"lctl set_param -n fail_loc=${fail_loc} || true" &>/dev/null
}
test_45j() {
- [[ $MDS1_VERSION -le $(version_code 2.13.56) ]] ||
+ (( $MDS1_VERSION >= $(version_code 2.13.56) )) ||
skip "Need MDS version newer than 2.13.56"
local msg fail_loc