+ /* It is important to obtain modify RPC slot first (if applicable), so
+ * that threads that are waiting for a modify RPC slot are not polluting
+ * our rpcs in flight counter.
+ * We do not do flock request limiting, though */
+ if (it) {
+ mdc_get_mod_rpc_slot(req, it);
+ rc = obd_get_request_slot(&obddev->u.cli);
+ if (rc != 0) {
+ mdc_put_mod_rpc_slot(req, it);
+ mdc_clear_replay_flag(req, 0);
+ ptlrpc_req_finished(req);
+ RETURN(rc);
+ }
+ }
+
+ /* With Data-on-MDT the glimpse callback is needed too.
+ * It is set here in advance but not in mdc_finish_enqueue()
+ * to avoid possible races. It is safe to have glimpse handler
+ * for non-DOM locks and costs nothing.*/
+ if (einfo->ei_cb_gl == NULL)
+ einfo->ei_cb_gl = mdc_ldlm_glimpse_ast;
+
+ rc = ldlm_cli_enqueue(exp, &req, einfo, &res_id, policy, &flags, NULL,
+ 0, lvb_type, lockh, 0);
+ if (!it) {
+ /* For flock requests we immediatelly return without further
+ delay and let caller deal with the rest, since rest of
+ this function metadata processing makes no sense for flock
+ requests anyway. But in case of problem during comms with
+ Server (ETIMEDOUT) or any signal/kill attempt (EINTR), we
+ can not rely on caller and this mainly for F_UNLCKs
+ (explicits or automatically generated by Kernel to clean
+ current FLocks upon exit) that can't be trashed */
+ if (((rc == -EINTR) || (rc == -ETIMEDOUT)) &&
+ (einfo->ei_type == LDLM_FLOCK) &&
+ (einfo->ei_mode == LCK_NL))
+ goto resend;
+ RETURN(rc);
+ }
+
+ obd_put_request_slot(&obddev->u.cli);
+ mdc_put_mod_rpc_slot(req, it);
+
+ if (rc < 0) {
+ CDEBUG(D_INFO,
+ "%s: ldlm_cli_enqueue "DFID":"DFID"=%s failed: rc = %d\n",
+ obddev->obd_name, PFID(&op_data->op_fid1),
+ PFID(&op_data->op_fid2), op_data->op_name ?: "", rc);
+
+ mdc_clear_replay_flag(req, rc);
+ ptlrpc_req_finished(req);
+ RETURN(rc);
+ }
+
+ lockrep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP);
+ LASSERT(lockrep != NULL);
+
+ lockrep->lock_policy_res2 =
+ ptlrpc_status_ntoh(lockrep->lock_policy_res2);
+
+ /* Retry infinitely when the server returns -EINPROGRESS for the
+ * intent operation, when server returns -EINPROGRESS for acquiring
+ * intent lock, we'll retry in after_reply(). */
+ if (it && (int)lockrep->lock_policy_res2 == -EINPROGRESS) {
+ mdc_clear_replay_flag(req, rc);
+ ptlrpc_req_finished(req);
+ if (generation == obddev->u.cli.cl_import->imp_generation) {
+ if (signal_pending(current))
+ RETURN(-EINTR);
+
+ resends++;
+ CDEBUG(D_HA, "%s: resend:%d op:%d "DFID"/"DFID"\n",
+ obddev->obd_name, resends, it->it_op,
+ PFID(&op_data->op_fid1),
+ PFID(&op_data->op_fid2));
+ goto resend;
+ } else {
+ CDEBUG(D_HA, "resend cross eviction\n");
+ RETURN(-EIO);
+ }
+ }
+
+ if ((int)lockrep->lock_policy_res2 == -ERANGE &&
+ it->it_op & (IT_OPEN | IT_GETATTR | IT_LOOKUP) &&
+ acl_bufsize == LUSTRE_POSIX_ACL_MAX_SIZE_OLD) {
+ mdc_clear_replay_flag(req, -ERANGE);
+ ptlrpc_req_finished(req);
+ acl_bufsize = MIN(imp->imp_connect_data.ocd_max_easize,
+ XATTR_SIZE_MAX);
+ goto resend;
+ }
+
+ rc = mdc_finish_enqueue(exp, req, einfo, it, lockh, rc);
+ if (rc < 0) {
+ if (lustre_handle_is_used(lockh)) {
+ ldlm_lock_decref(lockh, einfo->ei_mode);
+ memset(lockh, 0, sizeof(*lockh));
+ }
+ ptlrpc_req_finished(req);
+
+ it->it_lock_handle = 0;
+ it->it_lock_mode = 0;
+ it->it_request = NULL;
+ }
+
+ RETURN(rc);
+}