+static void ldlm_failed_ast(struct ldlm_lock *lock, int rc,
+ const char *ast_type)
+{
+ struct ptlrpc_connection *conn = lock->l_export->exp_connection;
+ char *str = libcfs_nid2str(conn->c_peer.nid);
+
+ LCONSOLE_ERROR_MSG(0x138, "A client on nid %s was evicted from "
+ "service %s.\n", str,
+ lock->l_export->exp_obd->obd_name);
+
+ LCONSOLE_ERROR_MSG(0x012, "Lock %s callback to %s timed out for "
+ "resource %d\n", ast_type,
+ obd_export_nid2str(lock->l_export), rc);
+
+ if (obd_dump_on_timeout)
+ libcfs_debug_dumplog();
+#ifdef __KERNEL__
+ spin_lock_bh(&waiting_locks_spinlock);
+ list_add(&lock->l_pending_chain, &expired_lock_thread.elt_expired_locks);
+ cfs_waitq_signal(&expired_lock_thread.elt_waitq);
+ spin_unlock_bh(&waiting_locks_spinlock);
+#else
+ class_fail_export(lock->l_export);
+#endif
+}
+
+static int ldlm_handle_ast_error(struct ldlm_lock *lock,
+ struct ptlrpc_request *req, int rc,
+ const char *ast_type)
+{
+ lnet_process_id_t peer = req->rq_import->imp_connection->c_peer;
+
+ if (rc == -ETIMEDOUT || rc == -EINTR || rc == -ENOTCONN) {
+ LASSERT(lock->l_export);
+ if (lock->l_export->exp_libclient) {
+ LDLM_DEBUG(lock, "%s AST to liblustre client (nid %s)"
+ " timeout, just cancelling lock", ast_type,
+ libcfs_nid2str(peer.nid));
+ ldlm_lock_cancel(lock);
+ rc = -ERESTART;
+ } else if (lock->l_flags & LDLM_FL_CANCEL) {
+ LDLM_DEBUG(lock, "%s AST timeout from nid %s, but "
+ "cancel was received (AST reply lost?)",
+ ast_type, libcfs_nid2str(peer.nid));
+ ldlm_lock_cancel(lock);
+ rc = -ERESTART;
+ } else {
+ ldlm_del_waiting_lock(lock);
+ ldlm_failed_ast(lock, rc, ast_type);
+ }
+ } else if (rc) {
+ if (rc == -EINVAL)
+ LDLM_DEBUG(lock, "client (nid %s) returned %d"
+ " from %s AST - normal race",
+ libcfs_nid2str(peer.nid),
+ req->rq_repmsg ?
+ lustre_msg_get_status(req->rq_repmsg) : -1,
+ ast_type);
+ else
+ LDLM_ERROR(lock, "client (nid %s) returned %d "
+ "from %s AST", libcfs_nid2str(peer.nid),
+ (req->rq_repmsg != NULL) ?
+ lustre_msg_get_status(req->rq_repmsg) : 0,
+ ast_type);
+ ldlm_lock_cancel(lock);
+ /* Server-side AST functions are called from ldlm_reprocess_all,
+ * which needs to be told to please restart its reprocessing. */
+ rc = -ERESTART;
+ }
+
+ return rc;
+}
+
+static int ldlm_cb_interpret(const struct lu_env *env,
+ struct ptlrpc_request *req, void *data, int rc)
+{
+ struct ldlm_cb_set_arg *arg;
+ struct ldlm_lock *lock;
+ ENTRY;
+
+ LASSERT(data != NULL);
+
+ arg = req->rq_async_args.pointer_arg[0];
+ lock = req->rq_async_args.pointer_arg[1];
+ LASSERT(lock != NULL);
+ if (rc != 0) {
+ /* If client canceled the lock but the cancel has not
+ * been recieved yet, we need to update lvbo to have the
+ * proper attributes cached. */
+ if (rc == -EINVAL && arg->type == LDLM_BL_CALLBACK)
+ ldlm_res_lvbo_update(lock->l_resource, NULL,
+ 0, 1);
+ rc = ldlm_handle_ast_error(lock, req, rc,
+ arg->type == LDLM_BL_CALLBACK
+ ? "blocking" : "completion");
+ }
+
+ LDLM_LOCK_RELEASE(lock);
+
+ if (rc == -ERESTART)
+ atomic_set(&arg->restart, 1);
+
+ RETURN(0);
+}
+
+static inline int ldlm_bl_and_cp_ast_fini(struct ptlrpc_request *req,
+ struct ldlm_cb_set_arg *arg,
+ struct ldlm_lock *lock,
+ int instant_cancel)