- if (rc == 0) {
- struct ldlm_res_id res_id = { . name = {0} };
- ldlm_policy_data_t policy;
- int flags = 0;
- res_id.name[0] = dchild->d_inode->i_ino;
- res_id.name[1] = dchild->d_inode->i_generation;
- policy.l_inodebits.bits = MDS_INODELOCK_LOOKUP |
- MDS_INODELOCK_UPDATE;
- rc = ldlm_cli_enqueue(NULL, NULL, obd->obd_namespace,
- res_id, LDLM_IBITS, &policy,
- LCK_PR, &flags,
- mds_blocking_ast,
- ldlm_completion_ast, NULL, NULL,
- NULL, 0, NULL, child_lockh);
- if (rc == 0)
- cleanup_phase = 3;
+ if (OBD_FAIL_CHECK_RESET(OBD_FAIL_MDS_OPEN_CREATE,
+ OBD_FAIL_LDLM_REPLY | OBD_FAIL_ONCE)) {
+ GOTO(cleanup, rc = -EAGAIN);
+ }
+
+ /* Obtain OPEN lock as well */
+ policy.l_inodebits.bits |= MDS_INODELOCK_OPEN;
+
+ /* We cannot use acc_mode here, because it is zeroed in case of
+ creating a file, so we get wrong lockmode */
+ if (accmode(dchild->d_inode, rec->ur_flags) & MAY_WRITE)
+ child_mode = LCK_CW;
+ else if (accmode(dchild->d_inode, rec->ur_flags) & MAY_EXEC)
+ child_mode = LCK_PR;
+ else
+ child_mode = LCK_CR;
+
+ if (!(lustre_msg_get_flags(req->rq_reqmsg) & MSG_REPLAY) &&
+ (rec->ur_flags & MDS_OPEN_LOCK)) {
+ /* In case of replay we do not get a lock assuming that the
+ caller has it already */
+ child_res_id.name[0] = dchild->d_inode->i_ino;
+ child_res_id.name[1] = dchild->d_inode->i_generation;
+
+ rc = ldlm_cli_enqueue_local(obd->obd_namespace, &child_res_id,
+ LDLM_IBITS, &policy, child_mode,
+ &lock_flags, ldlm_blocking_ast,
+ ldlm_completion_ast, NULL, NULL,
+ 0, NULL, child_lockh);
+ if (rc != ELDLM_OK)
+ GOTO(cleanup, rc);
+
+ /* Let mds_intent_policy know that we have a lock to return */
+ intent_set_disposition(rep, DISP_OPEN_LOCK);
+ cleanup_phase = 3;
+ }
+
+ if (!S_ISREG(dchild->d_inode->i_mode) &&
+ !S_ISDIR(dchild->d_inode->i_mode) &&
+ (req->rq_export->exp_connect_flags & OBD_CONNECT_NODEVOH)) {
+ /* If client supports this, do not return open handle for
+ * special device nodes */
+ GOTO(cleanup_no_trans, rc = 0);