+ struct obd_export *exp = req->rq_export;
+ struct ldlm_reply *dlm_rep;
+ struct ldlm_lock *lock;
+ __u64 bits;
+ __u64 new_bits;
+ int rc;
+
+ ENTRY;
+
+ if (exp && exp->exp_nid_stats && exp->exp_nid_stats->nid_ldlm_stats)
+ lprocfs_counter_incr(exp->exp_nid_stats->nid_ldlm_stats,
+ LDLM_CONVERT - LDLM_FIRST_OPC);
+
+ rc = req_capsule_server_pack(&req->rq_pill);
+ if (rc)
+ RETURN(rc);
+
+ dlm_rep = req_capsule_server_get(&req->rq_pill, &RMF_DLM_REP);
+ dlm_rep->lock_flags = dlm_req->lock_flags;
+
+ lock = ldlm_handle2lock(&dlm_req->lock_handle[0]);
+ if (!lock) {
+ LDLM_DEBUG_NOLOCK("server lock is canceled already");
+ req->rq_status = ELDLM_NO_LOCK_DATA;
+ RETURN(0);
+ }
+
+ LDLM_DEBUG(lock, "server-side convert handler START");
+
+ lock_res_and_lock(lock);
+ bits = lock->l_policy_data.l_inodebits.bits;
+ new_bits = dlm_req->lock_desc.l_policy_data.l_inodebits.bits;
+
+ if (ldlm_is_cancel(lock)) {
+ LDLM_DEBUG(lock, "convert on canceled lock!");
+ unlock_res_and_lock(lock);
+ GOTO(out_put, rc = ELDLM_NO_LOCK_DATA);
+ }
+
+ if (dlm_req->lock_desc.l_req_mode != lock->l_granted_mode) {
+ LDLM_ERROR(lock, "lock mode differs!");
+ unlock_res_and_lock(lock);
+ GOTO(out_put, rc = -EPROTO);
+ }
+
+ if (bits == new_bits) {
+ /*
+ * This can be valid situation if CONVERT RPCs are
+ * re-ordered. Just finish silently
+ */
+ LDLM_DEBUG(lock, "lock is converted already!");
+ unlock_res_and_lock(lock);
+ } else {
+ if (ldlm_is_waited(lock))
+ ldlm_del_waiting_lock(lock);
+
+ ldlm_clear_cbpending(lock);
+ lock->l_policy_data.l_inodebits.cancel_bits = 0;
+ ldlm_inodebits_drop(lock, bits & ~new_bits);
+
+ ldlm_clear_blocking_data(lock);
+ unlock_res_and_lock(lock);
+
+ /* All old bits should be reprocessed to send new BL AST if
+ * it wasn't sent earlier due to LDLM_FL_AST_SENT bit set.
+ * */
+ ldlm_reprocess_all(lock->l_resource, bits);
+ }
+
+ dlm_rep->lock_handle = lock->l_remote_handle;
+ ldlm_ibits_policy_local_to_wire(&lock->l_policy_data,
+ &dlm_rep->lock_desc.l_policy_data);
+ rc = ELDLM_OK;
+ EXIT;
+out_put:
+ LDLM_DEBUG(lock, "server-side convert handler END, rc = %d", rc);
+ LDLM_LOCK_PUT(lock);
+ req->rq_status = rc;
+ return 0;