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 _flush_waiting_reqs (Npreq *reqs) { Npreq *req = reqs; Npreq *req1; while (req != NULL) { req1 = req->next; np_conn_respond(req); np_req_unref(req); req = req1; } }
static void np_respond(Nptpool *tp, Npreq *req, Npfcall *rc) { xpthread_mutex_lock(&tp->srv->lock); np_srv_remove_workreq(tp, req); xpthread_mutex_unlock(&tp->srv->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); } xpthread_mutex_unlock(&req->lock); np_req_unref(req); }
void np_conn_reset(Npconn *conn, u32 msize, int dotu) { int i, n; Npsrv *srv; Npreq *req, *req1, *preqs, **reqs; Npfcall *fc, *fc1; pthread_mutex_lock(&conn->lock); conn->resetting = 1; pthread_mutex_unlock(&conn->lock); pthread_mutex_lock(&conn->srv->lock); srv = conn->srv; // first flush all outstanding requests preqs = NULL; req = srv->reqs_first; while (req != NULL) { req1 = req->next; if (req->conn == conn) { np_srv_remove_req(srv, req); req->next = preqs; preqs = req; } req = req1; } // then flush all working requests n = 0; req = conn->srv->workreqs; while (req != NULL) { if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) n++; req = req->next; } reqs = malloc(n * sizeof(Npreq *)); n = 0; req = conn->srv->workreqs; while (req != NULL) { if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) reqs[n++] = np_req_ref(req); req = req->next; } pthread_mutex_unlock(&conn->srv->lock); req = preqs; while (req != NULL) { req1 = req->next; np_conn_respond(req); np_req_unref(req); req = req1; } for(i = 0; i < n; i++) { req = reqs[i]; if (req->conn->srv->flush) (*req->conn->srv->flush)(req); } /* wait until all working requests finish */ /* pthread_mutex_lock(&conn->lock); while (1) { for(i = 0; i < n; i++) if (!reqs[i]->responded) break; if (i >= n) break; pthread_cond_wait(&conn->resetcond, &conn->lock); } */ pthread_mutex_lock(&srv->lock); while (1) { for(req = srv->workreqs; req != NULL; req = req->next) if (req->conn == conn && (msize==0 || req->tcall->type != Tversion)) break; if (req == NULL) break; while(conn->resetting) pthread_cond_wait(&conn->resetcond, &srv->lock); } pthread_mutex_unlock(&srv->lock); /* free old pool of fcalls */ fc = conn->freerclist; conn->freerclist = NULL; while (fc != NULL) { fc1 = fc->next; free(fc); fc = fc1; } if (conn->fidpool) { np_fidpool_destroy(conn->fidpool); conn->fidpool = NULL; } if (msize) { conn->dotu = dotu; conn->resetting = 0; conn->fidpool = np_fidpool_create(); pthread_cond_broadcast(&conn->resetdonecond); } conn->resetting = 0; pthread_mutex_unlock(&conn->lock); /* free the working requests */ for(i = 0; i < n; i++) np_req_unref(reqs[i]); free(reqs); }
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; }