diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2011-06-19 23:54:01 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2011-06-19 23:54:01 +0000 |
commit | f6fd5d6a6aea848a1e53be67ba361c411f2ab7bd (patch) | |
tree | ac597b296a43ae7e90faa825defed72566cdf41f | |
parent | 93e25d21048ed910fa01fa7151fd0742b7f880b1 (diff) | |
download | FreeBSD-src-f6fd5d6a6aea848a1e53be67ba361c411f2ab7bd.zip FreeBSD-src-f6fd5d6a6aea848a1e53be67ba361c411f2ab7bd.tar.gz |
Fix a number of places where the new NFS server did not
lock the mutex when manipulating rc_flag in the DRC cache.
This is believed to fix a hung server that was reported
to the freebsd-fs@ list on June 9 under the subject heading
"New NFS server stress test hang", where all the threads
were waiting for the RC_LOCKED flag to clear.
Tested by: jwd at slowblink.com
MFC after: 2 weeks
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdcache.c | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdcache.c b/sys/fs/nfsserver/nfs_nfsdcache.c index bcffd6c..fc513a3 100644 --- a/sys/fs/nfsserver/nfs_nfsdcache.c +++ b/sys/fs/nfsserver/nfs_nfsdcache.c @@ -405,6 +405,7 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so) { struct nfsrvcache *rp; struct nfsrvcache *retrp = NULL; + mbuf_t m; rp = nd->nd_rp; if (!rp) @@ -457,9 +458,9 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so) } if ((nd->nd_flag & ND_NFSV2) && nfsv2_repstat[newnfsv2_procid[nd->nd_procnum]]) { - NFSUNLOCKCACHE(); rp->rc_status = nd->nd_repstat; rp->rc_flag |= RC_REPSTATUS; + NFSUNLOCKCACHE(); } else { if (!(rp->rc_flag & RC_UDP)) { nfsrc_tcpsavedreplies++; @@ -469,9 +470,11 @@ nfsrvd_updatecache(struct nfsrv_descript *nd, struct socket *so) nfsrc_tcpsavedreplies; } NFSUNLOCKCACHE(); - rp->rc_reply = m_copym(nd->nd_mreq, 0, M_COPYALL, - M_WAIT); + m = m_copym(nd->nd_mreq, 0, M_COPYALL, M_WAIT); + NFSLOCKCACHE(); + rp->rc_reply = m; rp->rc_flag |= RC_REPMBUF; + NFSUNLOCKCACHE(); } if (rp->rc_flag & RC_UDP) { rp->rc_timestamp = NFSD_MONOSEC + @@ -518,6 +521,7 @@ nfsrvd_delcache(struct nfsrvcache *rp) APPLESTATIC void nfsrvd_sentcache(struct nfsrvcache *rp, struct socket *so, int err) { + tcp_seq tmp_seq; if (!(rp->rc_flag & RC_LOCKED)) panic("nfsrvd_sentcache not locked"); @@ -526,8 +530,12 @@ nfsrvd_sentcache(struct nfsrvcache *rp, struct socket *so, int err) so->so_proto->pr_domain->dom_family != AF_INET6) || so->so_proto->pr_protocol != IPPROTO_TCP) panic("nfs sent cache"); - if (nfsrv_getsockseqnum(so, &rp->rc_tcpseq)) + if (nfsrv_getsockseqnum(so, &tmp_seq)) { + NFSLOCKCACHE(); + rp->rc_tcpseq = tmp_seq; rp->rc_flag |= RC_TCPSEQ; + NFSUNLOCKCACHE(); + } } nfsrc_unlock(rp); } @@ -687,8 +695,11 @@ nfsrc_lock(struct nfsrvcache *rp) static void nfsrc_unlock(struct nfsrvcache *rp) { + + NFSLOCKCACHE(); rp->rc_flag &= ~RC_LOCKED; nfsrc_wanted(rp); + NFSUNLOCKCACHE(); } /* |