+static int interrupted_completion_wait(void *data)
+{
+ RETURN(1);
+}
+
+static int expired_completion_wait(void *data)
+{
+ struct ldlm_lock *lock = data;
+ struct ptlrpc_connection *conn;
+ struct obd_device *obd;
+
+ if (!lock)
+ CERROR("NULL lock\n");
+ else if (!lock->l_connh)
+ CERROR("lock %p has NULL connh\n", lock);
+ else if (!(obd = class_conn2obd(lock->l_connh)))
+ CERROR("lock %p has NULL obd\n", lock);
+ else if (!(conn = obd->u.cli.cl_import.imp_connection))
+ CERROR("lock %p has NULL connection\n", lock);
+ else {
+ class_signal_connection_failure(conn);
+ }
+ RETURN(0);
+}
+
+#if 0
+static int expired_completion_wait(void *data)
+{
+ struct ldlm_lock *lock = data;
+ struct ptlrpc_connection *conn =
+ class_conn2cliimp(lock->l_connh)->imp_connection;
+
+ if (!conn) {
+ CERROR("lock %p has NULL import connection\n", lock);
+ RETURN(1);
+ }
+
+ class_signal_connection_failure(conn);
+ RETURN(0);
+}
+#endif
+
+int ldlm_completion_ast(struct ldlm_lock *lock, int flags)
+{
+ struct l_wait_info lwi =
+ LWI_TIMEOUT_INTR(obd_timeout * HZ, expired_completion_wait,
+ interrupted_completion_wait, lock);
+ int rc = 0;
+ ENTRY;
+
+ if (flags & (LDLM_FL_BLOCK_WAIT | LDLM_FL_BLOCK_GRANTED |
+ LDLM_FL_BLOCK_CONV)) {
+ /* Go to sleep until the lock is granted. */
+ /* FIXME: or cancelled. */
+ LDLM_DEBUG(lock, "client-side enqueue returned a blocked lock,"
+ " sleeping");
+ ldlm_lock_dump(lock);
+ ldlm_reprocess_all(lock->l_resource);
+ rc = l_wait_event(lock->l_waitq,
+ (lock->l_req_mode == lock->l_granted_mode),
+ &lwi);
+ if (rc) {
+ LDLM_DEBUG(lock,
+ "client-side enqueue waking up: failed (%d)",
+ rc);
+ } else {
+ LDLM_DEBUG(lock,
+ "client-side enqueue waking up: granted");
+ }
+ } else if (flags == LDLM_FL_WAIT_NOREPROC) {
+ rc = l_wait_event(lock->l_waitq,
+ (lock->l_req_mode == lock->l_granted_mode),
+ &lwi);
+ } else if (flags == 0) {
+ wake_up(&lock->l_waitq);
+ }
+
+ RETURN(rc);
+}
+
+static int ldlm_cli_enqueue_local(struct ldlm_namespace *ns,
+ struct lustre_handle *parent_lockh,
+ __u64 *res_id,
+ __u32 type,
+ void *cookie, int cookielen,
+ ldlm_mode_t mode,
+ int *flags,
+ ldlm_completion_callback completion,
+ ldlm_blocking_callback blocking,
+ void *data,
+ __u32 data_len,
+ struct lustre_handle *lockh)
+{
+ struct ldlm_lock *lock;
+ int err;
+
+ if (ns->ns_client) {
+ CERROR("Trying to cancel local lock\n");
+ LBUG();
+ }
+
+ lock = ldlm_lock_create(ns, parent_lockh, res_id, type, mode, data, data_len);
+ if (!lock)
+ GOTO(out_nolock, err = -ENOMEM);
+ LDLM_DEBUG(lock, "client-side local enqueue handler, new lock created");
+
+ ldlm_lock_addref_internal(lock, mode);
+ ldlm_lock2handle(lock, lockh);
+ lock->l_connh = NULL;
+
+ err = ldlm_lock_enqueue(lock, cookie, cookielen, flags, completion,
+ blocking);
+ if (err != ELDLM_OK)
+ GOTO(out, err);
+
+ if (type == LDLM_EXTENT)
+ memcpy(cookie, &lock->l_extent, sizeof(lock->l_extent));
+ if ((*flags) & LDLM_FL_LOCK_CHANGED)
+ memcpy(res_id, lock->l_resource->lr_name, sizeof(*res_id));
+
+ LDLM_DEBUG_NOLOCK("client-side local enqueue handler END (lock %p)",
+ lock);
+
+ if (lock->l_completion_ast)
+ lock->l_completion_ast(lock, *flags);
+
+ LDLM_DEBUG(lock, "client-side local enqueue END");
+ EXIT;
+ out:
+ LDLM_LOCK_PUT(lock);
+ out_nolock:
+ return err;
+}
+
+int ldlm_cli_enqueue(struct lustre_handle *connh,