diff --git a/sys/nfs/nfs_srvcache.c b/sys/nfs/nfs_srvcache.c index b866cbe67813..6f9d42f422af 100644 --- a/sys/nfs/nfs_srvcache.c +++ b/sys/nfs/nfs_srvcache.c @@ -293,6 +293,18 @@ nfsrv_updatecache(nd, repvalid, repmbuf) goto loop; } rp->rc_flag |= RC_LOCKED; + if (rp->rc_state == RC_DONE) { + /* + * This can occur if the cache is too small. + * Retransmits of the same request aren't + * dropped so we may see the operation + * complete more then once. + */ + if (rp->rc_flag & RC_REPMBUF) { + m_freem(rp->rc_reply); + rp->rc_flag &= ~RC_REPMBUF; + } + } rp->rc_state = RC_DONE; /* * If we have a valid reply update status and save @@ -332,6 +344,10 @@ nfsrv_cleancache() nextrp = rp->rc_lru.tqe_next; LIST_REMOVE(rp, rc_hash); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); + if (rp->rc_flag & RC_REPMBUF) + m_freem(rp->rc_reply); + if (rp->rc_flag & RC_NAM) + free(rp->rc_nam, M_SONAME); free(rp, M_NFSD); } numnfsrvcache = 0; diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c index b866cbe67813..6f9d42f422af 100644 --- a/sys/nfsserver/nfs_srvcache.c +++ b/sys/nfsserver/nfs_srvcache.c @@ -293,6 +293,18 @@ nfsrv_updatecache(nd, repvalid, repmbuf) goto loop; } rp->rc_flag |= RC_LOCKED; + if (rp->rc_state == RC_DONE) { + /* + * This can occur if the cache is too small. + * Retransmits of the same request aren't + * dropped so we may see the operation + * complete more then once. + */ + if (rp->rc_flag & RC_REPMBUF) { + m_freem(rp->rc_reply); + rp->rc_flag &= ~RC_REPMBUF; + } + } rp->rc_state = RC_DONE; /* * If we have a valid reply update status and save @@ -332,6 +344,10 @@ nfsrv_cleancache() nextrp = rp->rc_lru.tqe_next; LIST_REMOVE(rp, rc_hash); TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru); + if (rp->rc_flag & RC_REPMBUF) + m_freem(rp->rc_reply); + if (rp->rc_flag & RC_NAM) + free(rp->rc_nam, M_SONAME); free(rp, M_NFSD); } numnfsrvcache = 0;