Fix a timeout deadlock that can occur when the process holding the
receive lock hasn't yet managed to send its own request. PR: kern/15055 Submitted by: Ian Dowse iedowse@maths.tcd.ie
This commit is contained in:
parent
5f070b6772
commit
4682c8eac9
@ -152,6 +152,7 @@ static void nfs_rcvunlock __P((struct nfsreq *));
|
||||
static void nfs_realign __P((struct mbuf **pm, int hsiz));
|
||||
static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
|
||||
struct mbuf **mp));
|
||||
static void nfs_softterm __P((struct nfsreq *rep));
|
||||
static int nfs_reconnect __P((struct nfsreq *rep));
|
||||
#ifndef NFS_NOSERVER
|
||||
static int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
@ -864,8 +865,10 @@ nfsmout:
|
||||
if (nmp->nm_cwnd > NFS_MAXCWND)
|
||||
nmp->nm_cwnd = NFS_MAXCWND;
|
||||
}
|
||||
rep->r_flags &= ~R_SENT;
|
||||
nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
if (rep->r_flags & R_SENT) {
|
||||
rep->r_flags &= ~R_SENT;
|
||||
nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
}
|
||||
/*
|
||||
* Update rtt using a gain of 0.125 on the mean
|
||||
* and a gain of 0.25 on the deviation.
|
||||
@ -1384,7 +1387,7 @@ nfs_timer(arg)
|
||||
if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
|
||||
continue;
|
||||
if (nfs_sigintr(nmp, rep, rep->r_procp)) {
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
if (rep->r_rtt >= 0) {
|
||||
@ -1412,7 +1415,7 @@ nfs_timer(arg)
|
||||
}
|
||||
if (rep->r_rexmit >= rep->r_retry) { /* too many */
|
||||
nfsstats.rpctimeouts++;
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
if (nmp->nm_sotype != SOCK_DGRAM) {
|
||||
@ -1491,6 +1494,23 @@ nfs_timer(arg)
|
||||
nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT).
|
||||
* The nm_send count is decremented now to avoid deadlocks when the process in
|
||||
* soreceive() hasn't yet managed to send its own request.
|
||||
*/
|
||||
|
||||
static void
|
||||
nfs_softterm(rep)
|
||||
struct nfsreq *rep;
|
||||
{
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
|
||||
if (rep->r_flags & R_SENT) {
|
||||
rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
rep->r_flags &= ~R_SENT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for a termination condition pending on the process.
|
||||
|
@ -152,6 +152,7 @@ static void nfs_rcvunlock __P((struct nfsreq *));
|
||||
static void nfs_realign __P((struct mbuf **pm, int hsiz));
|
||||
static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
|
||||
struct mbuf **mp));
|
||||
static void nfs_softterm __P((struct nfsreq *rep));
|
||||
static int nfs_reconnect __P((struct nfsreq *rep));
|
||||
#ifndef NFS_NOSERVER
|
||||
static int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
@ -864,8 +865,10 @@ nfsmout:
|
||||
if (nmp->nm_cwnd > NFS_MAXCWND)
|
||||
nmp->nm_cwnd = NFS_MAXCWND;
|
||||
}
|
||||
rep->r_flags &= ~R_SENT;
|
||||
nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
if (rep->r_flags & R_SENT) {
|
||||
rep->r_flags &= ~R_SENT;
|
||||
nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
}
|
||||
/*
|
||||
* Update rtt using a gain of 0.125 on the mean
|
||||
* and a gain of 0.25 on the deviation.
|
||||
@ -1384,7 +1387,7 @@ nfs_timer(arg)
|
||||
if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
|
||||
continue;
|
||||
if (nfs_sigintr(nmp, rep, rep->r_procp)) {
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
if (rep->r_rtt >= 0) {
|
||||
@ -1412,7 +1415,7 @@ nfs_timer(arg)
|
||||
}
|
||||
if (rep->r_rexmit >= rep->r_retry) { /* too many */
|
||||
nfsstats.rpctimeouts++;
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
if (nmp->nm_sotype != SOCK_DGRAM) {
|
||||
@ -1491,6 +1494,23 @@ nfs_timer(arg)
|
||||
nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT).
|
||||
* The nm_send count is decremented now to avoid deadlocks when the process in
|
||||
* soreceive() hasn't yet managed to send its own request.
|
||||
*/
|
||||
|
||||
static void
|
||||
nfs_softterm(rep)
|
||||
struct nfsreq *rep;
|
||||
{
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
|
||||
if (rep->r_flags & R_SENT) {
|
||||
rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
rep->r_flags &= ~R_SENT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for a termination condition pending on the process.
|
||||
|
@ -152,6 +152,7 @@ static void nfs_rcvunlock __P((struct nfsreq *));
|
||||
static void nfs_realign __P((struct mbuf **pm, int hsiz));
|
||||
static int nfs_receive __P((struct nfsreq *rep, struct sockaddr **aname,
|
||||
struct mbuf **mp));
|
||||
static void nfs_softterm __P((struct nfsreq *rep));
|
||||
static int nfs_reconnect __P((struct nfsreq *rep));
|
||||
#ifndef NFS_NOSERVER
|
||||
static int nfsrv_getstream __P((struct nfssvc_sock *,int));
|
||||
@ -864,8 +865,10 @@ nfsmout:
|
||||
if (nmp->nm_cwnd > NFS_MAXCWND)
|
||||
nmp->nm_cwnd = NFS_MAXCWND;
|
||||
}
|
||||
rep->r_flags &= ~R_SENT;
|
||||
nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
if (rep->r_flags & R_SENT) {
|
||||
rep->r_flags &= ~R_SENT;
|
||||
nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
}
|
||||
/*
|
||||
* Update rtt using a gain of 0.125 on the mean
|
||||
* and a gain of 0.25 on the deviation.
|
||||
@ -1384,7 +1387,7 @@ nfs_timer(arg)
|
||||
if (rep->r_mrep || (rep->r_flags & R_SOFTTERM))
|
||||
continue;
|
||||
if (nfs_sigintr(nmp, rep, rep->r_procp)) {
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
if (rep->r_rtt >= 0) {
|
||||
@ -1412,7 +1415,7 @@ nfs_timer(arg)
|
||||
}
|
||||
if (rep->r_rexmit >= rep->r_retry) { /* too many */
|
||||
nfsstats.rpctimeouts++;
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
nfs_softterm(rep);
|
||||
continue;
|
||||
}
|
||||
if (nmp->nm_sotype != SOCK_DGRAM) {
|
||||
@ -1491,6 +1494,23 @@ nfs_timer(arg)
|
||||
nfs_timer_handle = timeout(nfs_timer, (void *)0, nfs_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT).
|
||||
* The nm_send count is decremented now to avoid deadlocks when the process in
|
||||
* soreceive() hasn't yet managed to send its own request.
|
||||
*/
|
||||
|
||||
static void
|
||||
nfs_softterm(rep)
|
||||
struct nfsreq *rep;
|
||||
{
|
||||
rep->r_flags |= R_SOFTTERM;
|
||||
|
||||
if (rep->r_flags & R_SENT) {
|
||||
rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
|
||||
rep->r_flags &= ~R_SENT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test for a termination condition pending on the process.
|
||||
|
Loading…
x
Reference in New Issue
Block a user