+ if (mode == LCK_PW) {
+ rc = ldlm_lock_match(obd->obd_namespace, 0, &res_id, type,
+ policy, LCK_PR, lockh);
+ if (rc == 1) {
+ rc = ldlm_cli_convert(lockh, mode, flags);
+ if (!rc) {
+ /* Update readers/writers accounting */
+ ldlm_lock_addref(lockh, LCK_PW);
+ ldlm_lock_decref(lockh, LCK_PR);
+ osc_set_data_with_check(lockh, data);
+ RETURN(ELDLM_OK);
+ }
+ /* If the conversion failed, we need to drop refcount
+ on matched lock before we get new one */
+ /* XXX Won't it save us some efforts if we cancel PR
+ lock here? We are going to take PW lock anyway and it
+ will invalidate PR lock */
+ ldlm_lock_decref(lockh, LCK_PR);
+ if (rc != EDEADLOCK) {
+ RETURN(rc);
+ }
+ }
+ }
+
+ if (mode == LCK_PW) {
+ rc = ldlm_lock_match(obd->obd_namespace, 0, &res_id, type,
+ policy, LCK_PR, lockh);
+ if (rc == 1) {
+ rc = ldlm_cli_convert(lockh, mode, flags);
+ if (!rc) {
+ /* Update readers/writers accounting */
+ ldlm_lock_addref(lockh, LCK_PW);
+ ldlm_lock_decref(lockh, LCK_PR);
+ osc_set_data_with_check(lockh, data);
+ RETURN(ELDLM_OK);
+ }
+ /* If the conversion failed, we need to drop refcount
+ on matched lock before we get new one */
+ /* XXX Won't it save us some efforts if we cancel PR
+ lock here? We are going to take PW lock anyway and it
+ will invalidate PR lock */
+ ldlm_lock_decref(lockh, LCK_PR);
+ if (rc != EDEADLOCK) {
+ RETURN(rc);
+ }
+ }
+ }
+
+ no_match:
+ if (*flags & LDLM_FL_HAS_INTENT) {
+ int size[2] = {0, sizeof(struct ldlm_request)};
+
+ req = ptlrpc_prep_req(class_exp2cliimp(exp), LUSTRE_DLM_VERSION,
+ LDLM_ENQUEUE, 2, size, NULL);
+ if (req == NULL)
+ RETURN(-ENOMEM);
+
+ size[0] = sizeof(*rep);
+ size[1] = sizeof(lvb);
+ req->rq_replen = lustre_msg_size(2, size);
+ }
+ rc = ldlm_cli_enqueue(exp, req, obd->obd_namespace, res_id, type,
+ policy, mode, flags, bl_cb, cp_cb, gl_cb, data,
+ &lvb, sizeof(lvb), lustre_swab_ost_lvb, lockh);
+ if (req != NULL) {
+ if (rc == ELDLM_LOCK_ABORTED) {
+ /* swabbed by ldlm_cli_enqueue() */
+ LASSERT_REPSWABBED(req, 0);
+ rep = lustre_msg_buf(req->rq_repmsg, 0, sizeof(*rep));
+ LASSERT(rep != NULL);
+ if (rep->lock_policy_res1)
+ rc = rep->lock_policy_res1;
+ }
+ ptlrpc_req_finished(req);
+ }
+
+ if ((*flags & LDLM_FL_HAS_INTENT && rc == ELDLM_LOCK_ABORTED) || !rc) {
+ CDEBUG(D_INODE, "received kms == "LPU64", blocks == "LPU64"\n",
+ lvb.lvb_size, lvb.lvb_blocks);
+ lsm->lsm_oinfo->loi_rss = lvb.lvb_size;
+ lsm->lsm_oinfo->loi_blocks = lvb.lvb_blocks;
+ }