+ 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) {
+ __u64 bits;
+ __u64 new;
+
+ bits = lock->l_policy_data.l_inodebits.bits;
+ new = dlm_req->lock_desc.l_policy_data.l_inodebits.bits;
+ LDLM_DEBUG(lock, "server-side convert handler START");
+
+ if (ldlm_is_cancel(lock)) {
+ LDLM_ERROR(lock, "convert on canceled lock!");
+ rc = ELDLM_NO_LOCK_DATA;
+ } else if (dlm_req->lock_desc.l_req_mode !=
+ lock->l_granted_mode) {
+ LDLM_ERROR(lock, "lock mode differs!");
+ rc = ELDLM_NO_LOCK_DATA;
+ } else if (bits == new) {
+ /* This can be valid situation if CONVERT RPCs are
+ * re-ordered. Just finish silently */
+ LDLM_DEBUG(lock, "lock is converted already!");
+ rc = ELDLM_OK;
+ } else {
+ lock_res_and_lock(lock);
+ 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);
+ /* if lock is in a bl_ast list, remove it from the list
+ * here before reprocessing.
+ */
+ if (!list_empty(&lock->l_bl_ast)) {
+ ldlm_discard_bl_lock(lock);
+ } else {
+ /* in this case lock was taken from bl_ast list
+ * already by ldlm_work_bl_ast_lock() and lock
+ * must clear only some remaining states.
+ */
+ ldlm_clear_ast_sent(lock);
+ lock->l_bl_ast_run = 0;
+ ldlm_clear_blocking_lock(lock);
+ }
+ unlock_res_and_lock(lock);