static int npc_rpc(Npcfsys *fs, Npfcall *tc, Npfcall **rcp) { Npfcall *rc = NULL; u16 tag = P9_NOTAG; int n, ret = -1; if (!fs->trans) { np_uerror(ECONNABORTED); goto done; } if (tc->type != P9_TVERSION) tag = npc_get_id(fs->tagpool); np_set_tag(tc, tag); xpthread_mutex_lock(&fs->lock); n = np_trans_send (fs->trans, tc); if (n >= 0) n = np_trans_recv(fs->trans, &rc, fs->msize); xpthread_mutex_unlock(&fs->lock); if (n < 0) goto done; if (rc == NULL) { np_uerror (EPROTO); /* premature EOF */ goto done; } if (tc->tag != rc->tag) { np_uerror (EPROTO); /* unmatched response */ goto done; } if (rc->type == P9_RLERROR) { np_uerror (rc->u.rlerror.ecode); goto done; } *rcp = rc; ret = 0; done: if (tag != P9_NOTAG) npc_put_id(fs->tagpool, tag); if (ret < 0 && rc != NULL) free (rc); return ret; }
/* Per-connection read thread. */ static void * np_conn_read_proc(void *a) { Npconn *conn = (Npconn *)a; Npsrv *srv = conn->srv; Npreq *req; Npfcall *fc; pthread_detach(pthread_self()); for (;;) { if (np_trans_recv(conn->trans, &fc, conn->msize) < 0) { np_logerr (srv, "recv error - " "dropping connection to '%s'", conn->client_id); break; } if (!fc) /* EOF */ break; _debug_trace (srv, fc); /* Encapsulate fc in a request and hand to srv worker threads. * In np_req_alloc, req->fid is looked up/initialized. */ req = np_req_alloc(conn, fc); if (!req) { np_logmsg (srv, "out of memory in receive path - " "dropping connection to '%s'", conn->client_id); free (fc); break; } /* Enqueue request for processing by next available worker * thread, except P9_TFLUSH which is handled immediately. */ if (fc->type == P9_TFLUSH) { if (np_flush (req, fc)) { np_req_respond_flush (req); np_req_unref(req); } xpthread_mutex_lock (&srv->lock); srv->tpool->stats.nreqs[P9_TFLUSH]++; xpthread_mutex_unlock (&srv->lock); } else { xpthread_mutex_lock(&srv->lock); np_srv_add_req(srv, req); xpthread_mutex_unlock(&srv->lock); } } /* Just got EOF on read, or some other fatal error for the * connection like out of memory. */ np_conn_flush (conn); xpthread_mutex_lock(&conn->lock); while (conn->refcount > 0) xpthread_cond_wait(&conn->refcond, &conn->lock); xpthread_mutex_unlock(&conn->lock); np_conn_destroy(conn); return NULL; }