summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-01-14 20:18:38 +0000
committermav <mav@FreeBSD.org>2014-01-14 20:18:38 +0000
commitf63cb2f402153eb98e1cd773f6207b1cf5d05cc2 (patch)
treeaadf9159aea83201b8a770d7bec372eff9adf854 /sys/fs
parentfa7f47e2d526cf0746370e2a3b6f1fd94a20028d (diff)
downloadFreeBSD-src-f63cb2f402153eb98e1cd773f6207b1cf5d05cc2.zip
FreeBSD-src-f63cb2f402153eb98e1cd773f6207b1cf5d05cc2.tar.gz
Fix lock leak in purely hypothetical case of TCP connection without SVC_ACK
method. This change should be NOP now, but it is better to be future safe. Reported by: rmacklem
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfs/nfs_var.h2
-rw-r--r--sys/fs/nfsserver/nfs_nfsdcache.c18
-rw-r--r--sys/fs/nfsserver/nfs_nfsdkrpc.c4
3 files changed, 13 insertions, 11 deletions
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index 71daeaf..895829d 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -220,7 +220,7 @@ void nfsrvd_dorpc(struct nfsrv_descript *, int, NFSPROC_T *);
void nfsrvd_initcache(void);
int nfsrvd_getcache(struct nfsrv_descript *);
struct nfsrvcache *nfsrvd_updatecache(struct nfsrv_descript *);
-void nfsrvd_sentcache(struct nfsrvcache *, uint32_t);
+void nfsrvd_sentcache(struct nfsrvcache *, int, uint32_t);
void nfsrvd_cleancache(void);
void nfsrvd_refcache(struct nfsrvcache *);
void nfsrvd_derefcache(struct nfsrvcache *);
diff --git a/sys/fs/nfsserver/nfs_nfsdcache.c b/sys/fs/nfsserver/nfs_nfsdcache.c
index 23d5d28..2c4a654 100644
--- a/sys/fs/nfsserver/nfs_nfsdcache.c
+++ b/sys/fs/nfsserver/nfs_nfsdcache.c
@@ -576,18 +576,20 @@ nfsrvd_delcache(struct nfsrvcache *rp)
* the pointer returned by nfsrvd_updatecache().
*/
APPLESTATIC void
-nfsrvd_sentcache(struct nfsrvcache *rp, uint32_t seq)
+nfsrvd_sentcache(struct nfsrvcache *rp, int have_seq, uint32_t seq)
{
struct nfsrchash_bucket *hbp;
KASSERT(rp->rc_flag & RC_LOCKED, ("nfsrvd_sentcache not locked"));
- hbp = NFSRCAHASH(rp->rc_sockref);
- mtx_lock(&hbp->mtx);
- rp->rc_tcpseq = seq;
- if (rp->rc_acked != RC_NO_ACK)
- LIST_INSERT_HEAD(&hbp->tbl, rp, rc_ahash);
- rp->rc_acked = RC_NO_ACK;
- mtx_unlock(&hbp->mtx);
+ if (have_seq) {
+ hbp = NFSRCAHASH(rp->rc_sockref);
+ mtx_lock(&hbp->mtx);
+ rp->rc_tcpseq = seq;
+ if (rp->rc_acked != RC_NO_ACK)
+ LIST_INSERT_HEAD(&hbp->tbl, rp, rc_ahash);
+ rp->rc_acked = RC_NO_ACK;
+ mtx_unlock(&hbp->mtx);
+ }
nfsrc_unlock(rp);
}
diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c
index 96cb833..9649093 100644
--- a/sys/fs/nfsserver/nfs_nfsdkrpc.c
+++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c
@@ -287,8 +287,8 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
svcerr_systemerr(rqst);
}
if (rp != NULL) {
- if (rqst->rq_reply_seq != 0 || SVC_ACK(xprt, NULL))
- nfsrvd_sentcache(rp, rqst->rq_reply_seq);
+ nfsrvd_sentcache(rp, (rqst->rq_reply_seq != 0 ||
+ SVC_ACK(xprt, NULL)), rqst->rq_reply_seq);
}
svc_freereq(rqst);
OpenPOWER on IntegriCloud