--- fs/nfs/nfs_var.h.sav2 2015-11-18 16:52:47.038896000 -0500 +++ fs/nfs/nfs_var.h 2015-11-18 16:53:27.037091000 -0500 @@ -135,6 +135,7 @@ int nfsrv_checksequence(struct nfsrv_des uint32_t *, int, uint32_t *, NFSPROC_T *); int nfsrv_checkreclaimcomplete(struct nfsrv_descript *); void nfsrv_cache_session(uint8_t *, uint32_t, int, struct mbuf **); +void nfsrv_freeallbackchannel_xprts(void); /* nfs_nfsdserv.c */ int nfsrvd_access(struct nfsrv_descript *, int, --- fs/nfsserver/nfs_nfsdkrpc.c.sav2 2015-11-18 16:50:04.226457000 -0500 +++ fs/nfsserver/nfs_nfsdkrpc.c 2015-11-18 16:51:41.813955000 -0500 @@ -544,6 +544,7 @@ nfsrvd_init(int terminating) if (terminating) { nfsd_master_proc = NULL; NFSD_UNLOCK(); + nfsrv_freeallbackchannel_xprts(); svcpool_destroy(nfsrvd_pool); nfsrvd_pool = NULL; NFSD_LOCK(); --- fs/nfsserver/nfs_nfsdstate.c.sav2 2015-11-18 16:49:54.912498000 -0500 +++ fs/nfsserver/nfs_nfsdstate.c 2015-11-18 16:50:28.940642000 -0500 @@ -5784,14 +5784,16 @@ nfsrv_checksequence(struct nfsrv_descrip * If this session handles the backchannel, save the nd_xprt for this * RPC, since this is the one being used. */ - if (sep->sess_cbsess.nfsess_xprt != NULL && + if (sep->sess_clp->lc_req.nr_client != NULL && (sep->sess_crflags & NFSV4CRSESS_CONNBACKCHAN) != 0) { savxprt = sep->sess_cbsess.nfsess_xprt; SVC_ACQUIRE(nd->nd_xprt); - nd->nd_xprt->xp_p2 = savxprt->xp_p2; + nd->nd_xprt->xp_p2 = + sep->sess_clp->lc_req.nr_client->cl_private; nd->nd_xprt->xp_idletimeout = 0; /* Disable timeout. */ sep->sess_cbsess.nfsess_xprt = nd->nd_xprt; - SVC_RELEASE(savxprt); + if (savxprt != NULL) + SVC_RELEASE(savxprt); } *sflagsp = 0; @@ -6050,3 +6052,29 @@ nfsv4_getcbsession(struct nfsclient *clp return (0); } +/* + * Free up all backchannel xprts. This needs to be done when the nfsd threads + * exit, since those transports will all be going away. + * This is only called after all the nfsd threads are done performing RPCs, + * so locking shouldn't be an issue. + */ +APPLESTATIC void +nfsrv_freeallbackchannel_xprts(void) +{ + struct nfsdsession *sep; + struct nfsclient *clp; + SVCXPRT *xprt; + int i; + + for (i = 0; i < nfsrv_clienthashsize; i++) { + LIST_FOREACH(clp, &nfsclienthash[i], lc_hash) { + LIST_FOREACH(sep, &clp->lc_session, sess_list) { + xprt = sep->sess_cbsess.nfsess_xprt; + sep->sess_cbsess.nfsess_xprt = NULL; + if (xprt != NULL) + SVC_RELEASE(xprt); + } + } + } +} +