+
+struct ptlrpc_request *ptlrpc_prep_req(struct ptlrpc_client *cl,
+ int opcode, int namelen, char *name,
+ int tgtlen, char *tgt)
+{
+ struct ptlrpc_request *request;
+ int rc;
+ ENTRY;
+
+ OBD_ALLOC(request, sizeof(*request));
+ if (!request) {
+ CERROR("request allocation out of memory\n");
+ return NULL;
+ }
+
+ memset(request, 0, sizeof(*request));
+ request->rq_xid = cl->cli_xid++;
+
+ rc = cl->cli_req_pack(name, namelen, tgt, tgtlen,
+ &request->rq_reqhdr, &request->rq_req,
+ &request->rq_reqlen, &request->rq_reqbuf);
+ if (rc) {
+ CERROR("cannot pack request %d\n", rc);
+ return NULL;
+ }
+ request->rq_reqhdr->opc = opcode;
+
+ EXIT;
+ return request;
+}
+
+void ptlrpc_free_req(struct ptlrpc_request *request)
+{
+ OBD_FREE(request, sizeof(*request));
+}
+
+int ptlrpc_queue_wait(struct ptlrpc_request *req,
+ struct ptlrpc_client *cl)
+{
+ int rc;
+ DECLARE_WAITQUEUE(wait, current);
+
+ init_waitqueue_head(&req->rq_wait_for_rep);
+
+ if (cl->cli_enqueue) {
+ /* Local delivery */
+ ENTRY;
+ rc = cl->cli_enqueue(req);
+ } else {
+ /* Remote delivery via portals. */
+ req->rq_req_portal = cl->cli_request_portal;
+ req->rq_reply_portal = cl->cli_reply_portal;
+ rc = ptl_send_rpc(req, &cl->cli_server);
+ }
+ if (rc) {
+ CERROR("error %d, opcode %d\n", rc,
+ req->rq_reqhdr->opc);
+ return -rc;
+ }
+
+ CDEBUG(0, "-- sleeping\n");
+ add_wait_queue(&req->rq_wait_for_rep, &wait);
+ while (req->rq_repbuf == NULL) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ /* if this process really wants to die, let it go */
+ if (sigismember(&(current->pending.signal), SIGKILL) ||
+ sigismember(&(current->pending.signal), SIGINT))
+ break;
+
+ schedule();
+ }
+ remove_wait_queue(&req->rq_wait_for_rep, &wait);
+ set_current_state(TASK_RUNNING);
+ CDEBUG(0, "-- done\n");
+
+ if (req->rq_repbuf == NULL) {
+ /* We broke out because of a signal */
+ EXIT;
+ return -EINTR;
+ }
+
+ rc = cl->cli_rep_unpack(req->rq_repbuf, req->rq_replen, &req->rq_rephdr, &req->rq_rep);
+ if (rc) {
+ CERROR("unpack_rep failed: %d\n", rc);
+ return rc;
+ }
+
+ if ( req->rq_rephdr->status == 0 )
+ CDEBUG(0, "--> buf %p len %d status %d\n",
+ req->rq_repbuf, req->rq_replen,
+ req->rq_rephdr->status);
+
+ EXIT;
+ return 0;
+}