static int _get_working_reqs (Npconn *conn, Npreq ***rp, int *lp) { Npsrv *srv = conn->srv; Npreq *req, **reqs = NULL; Nptpool *tp; int n; /* assert: srv->lock held */ n = _count_working_reqs (conn, 0); if ((reqs = malloc(n * sizeof(Npreq *)))) goto error; for (n = 0, tp = srv->tpool; tp != NULL; tp = tp->next) { xpthread_mutex_lock (&tp->lock); for (req = tp->workreqs; req != NULL; req = req->next) { if (req->conn != conn) continue; if (req->tcall->type != P9_TVERSION) reqs[n++] = np_req_ref (req); } xpthread_mutex_unlock (&tp->lock); } *lp = n; *rp = reqs; return 0; error: if (reqs) free (reqs); return -1; }
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; }