static Npfcall* np_flush(Npreq *req, Npfcall *tc) { u16 oldtag; Npreq *creq; Npconn *conn; Npfcall *ret; ret = NULL; conn = req->conn; oldtag = tc->oldtag; pthread_mutex_lock(&conn->srv->lock); // check pending requests for(creq = conn->srv->reqs_first; creq != NULL; creq = creq->next) { if (creq->conn==conn && creq->tag==oldtag) { np_srv_remove_request(conn->srv, creq); ret = np_create_rflush(); creq = NULL; goto done; } } // check working requests creq = conn->srv->workreqs; while (creq != NULL) { if (creq->conn==conn && creq->tag==oldtag) { req->flushreq = creq->flushreq; creq->flushreq = req; goto done; } creq = creq->next; } // if not found, return Rflush if (!creq) ret = np_create_rflush(); done: pthread_mutex_unlock(&conn->srv->lock); // if working request found, try to flush it if (creq && req->conn->srv->flush) (*req->conn->srv->flush)(creq); return ret; }
void np_respond(Npreq *req, Npfcall *rc) { Npsrv *srv; Npreq *freq, *freq1; Npconn *conn; req->rcall = rc; srv = req->conn->srv; pthread_mutex_lock(&srv->lock); if (req->prev) req->prev->next = req->next; else srv->workreqs = req->next; if (req->next) req->next->prev = req->prev; /* remove the flush requests from the working queue */ for(freq = req->flushreq; freq != NULL; freq = freq->flushreq) { if (freq->prev) freq->prev->next = freq->next; else srv->workreqs = freq->next; if (freq->next) freq->next->prev = freq->prev; } pthread_mutex_unlock(&srv->lock); if (req->rcall) { if (req->rcall->id==Rread && req->fid->type&Qtdir) req->fid->diroffset = req->tcall->offset + req->rcall->count; np_set_tag(req->rcall, req->tag); np_conn_send_fcall(req->conn, req->rcall); } freq = req->flushreq; while (freq != NULL) { rc = np_create_rflush(); np_set_tag(rc, freq->tag); conn = freq->conn; np_conn_send_fcall(freq->conn, rc); freq1 = freq->flushreq; np_conn_free_rcall(freq->conn, freq->tcall); reqfree(freq); freq = freq1; } np_conn_free_rcall(req->conn, req->tcall); reqfree(req); }
static void test_rflush (void) { Npfcall *fc, *fc2; if (!(fc = np_create_rflush ())) msg_exit ("out of memory in %s", __FUNCTION__); fc2 = _rcv_buf (fc, P9_RFLUSH, __FUNCTION__); free (fc); free (fc2); }
static void np_respond(Nptpool *tp, Npreq *req, Npfcall *rc) { Npreq *freq; xpthread_mutex_lock(&req->lock); if (req->responded) { free(rc); xpthread_mutex_unlock(&req->lock); np_req_unref(req); return; } req->responded = 1; xpthread_mutex_unlock(&req->lock); xpthread_mutex_lock(&tp->lock); np_srv_remove_workreq(tp, req); for(freq = req->flushreq; freq != NULL; freq = freq->flushreq) np_srv_remove_workreq(tp, freq); xpthread_mutex_unlock(&tp->lock); xpthread_mutex_lock(&req->lock); req->rcall = rc; if (req->rcall) { np_set_tag(req->rcall, req->tag); if (req->fid != NULL) { np_fid_decref(req->fid); req->fid = NULL; } np_conn_respond(req); } for(freq = req->flushreq; freq != NULL; freq = freq->flushreq) { xpthread_mutex_lock(&freq->lock); freq->rcall = np_create_rflush(); np_set_tag(freq->rcall, freq->tag); np_conn_respond(freq); xpthread_mutex_unlock(&freq->lock); np_req_unref(freq); } xpthread_mutex_unlock(&req->lock); np_req_unref(req); }
static void test_rflush (void) { Npfcall *fc, *fc2; char buf[STATIC_RFLUSH_SIZE]; if (!(fc = np_create_rflush ())) msg_exit ("out of memory in %s", __FUNCTION__); fc2 = _rcv_buf (fc, P9_RFLUSH, __FUNCTION__); free (fc); free (fc2); if (!(fc = np_create_rflush_static (buf, sizeof(buf)))) msg_exit ("out of memory in %s", __FUNCTION__); fc2 = _rcv_buf (fc, P9_RFLUSH, __FUNCTION__); free (fc2); }
Npfcall* np_flush(Npreq *req, Npfcall *tc) { u16 oldtag = tc->u.tflush.oldtag; Npreq *creq = NULL; Npconn *conn = req->conn; Npfcall *ret = NULL; Nptpool *tp; xpthread_mutex_lock(&conn->srv->lock); // check pending requests for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) { xpthread_mutex_lock(&tp->lock); for(creq = tp->reqs_first; creq != NULL; creq = creq->next) { if (creq->conn==conn && creq->tag==oldtag) { np_srv_remove_req(tp, creq); xpthread_mutex_lock(&creq->lock); np_conn_respond(creq); /* doesn't send anything */ xpthread_mutex_unlock(&creq->lock); np_req_unref(creq); ret = np_create_rflush(); creq = NULL; xpthread_mutex_unlock(&tp->lock); goto done; } } xpthread_mutex_unlock(&tp->lock); } // check working requests for (tp = conn->srv->tpool; tp != NULL; tp = tp->next) { xpthread_mutex_lock(&tp->lock); creq = tp->workreqs; while (creq != NULL) { if (creq->conn==conn && creq->tag==oldtag) { np_req_ref(creq); xpthread_mutex_lock(&creq->lock); req->flushreq = creq->flushreq; creq->flushreq = req; xpthread_mutex_unlock(&creq->lock); xpthread_mutex_unlock(&tp->lock); goto done; } creq = creq->next; } xpthread_mutex_unlock(&tp->lock); } // if not found, return P9_RFLUSH if (!creq) ret = np_create_rflush(); done: xpthread_mutex_unlock(&conn->srv->lock); // if working request found, try to flush it if (creq && req->conn->srv->flush) { (*req->conn->srv->flush)(creq); np_req_unref(creq); } return ret; }