diff options
Diffstat (limited to 'sys/fs/nfsserver/nfs_nfsdstate.c')
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdstate.c | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdstate.c b/sys/fs/nfsserver/nfs_nfsdstate.c index c0e05b9..0e8a743 100644 --- a/sys/fs/nfsserver/nfs_nfsdstate.c +++ b/sys/fs/nfsserver/nfs_nfsdstate.c @@ -4191,10 +4191,23 @@ nfsrv_docallback(struct nfsclient *clp, int procnum, if (!error) { if ((nd->nd_flag & ND_NFSV41) != 0) { KASSERT(sep != NULL, ("sep NULL")); - error = newnfs_request(nd, NULL, clp, &clp->lc_req, - NULL, NULL, cred, clp->lc_program, - clp->lc_req.nr_vers, NULL, 1, NULL, - &sep->sess_cbsess); + if (sep->sess_cbsess.nfsess_xprt != NULL) + error = newnfs_request(nd, NULL, clp, + &clp->lc_req, NULL, NULL, cred, + clp->lc_program, clp->lc_req.nr_vers, NULL, + 1, NULL, &sep->sess_cbsess); + else { + /* + * This should probably never occur, but if a + * client somehow does an RPC without a + * SequenceID Op that causes a callback just + * after the nfsd threads have been terminated + * and restared we could conceivably get here + * without a backchannel xprt. + */ + printf("nfsrv_docallback: no xprt\n"); + error = ECONNREFUSED; + } nfsrv_freesession(sep, NULL); } else error = newnfs_request(nd, NULL, clp, &clp->lc_req, @@ -5784,14 +5797,16 @@ nfsrv_checksequence(struct nfsrv_descript *nd, uint32_t sequenceid, * 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 +6065,29 @@ nfsv4_getcbsession(struct nfsclient *clp, struct nfsdsession **sepp) 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); + } + } + } +} + |