nfs_nfsdkrpc.c revision 192780
1191783Srmacklem/*- 2191783Srmacklem * Copyright (c) 1989, 1993 3191783Srmacklem * The Regents of the University of California. All rights reserved. 4191783Srmacklem * 5191783Srmacklem * This code is derived from software contributed to Berkeley by 6191783Srmacklem * Rick Macklem at The University of Guelph. 7191783Srmacklem * 8191783Srmacklem * Redistribution and use in source and binary forms, with or without 9191783Srmacklem * modification, are permitted provided that the following conditions 10191783Srmacklem * are met: 11191783Srmacklem * 1. Redistributions of source code must retain the above copyright 12191783Srmacklem * notice, this list of conditions and the following disclaimer. 13191783Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 14191783Srmacklem * notice, this list of conditions and the following disclaimer in the 15191783Srmacklem * documentation and/or other materials provided with the distribution. 16191783Srmacklem * 4. Neither the name of the University nor the names of its contributors 17191783Srmacklem * may be used to endorse or promote products derived from this software 18191783Srmacklem * without specific prior written permission. 19191783Srmacklem * 20191783Srmacklem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21191783Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22191783Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23191783Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24191783Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25191783Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26191783Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27191783Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28191783Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29191783Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30191783Srmacklem * SUCH DAMAGE. 31191783Srmacklem * 32191783Srmacklem */ 33191783Srmacklem 34191783Srmacklem#include <sys/cdefs.h> 35191783Srmacklem__FBSDID("$FreeBSD: head/sys/fs/nfsserver/nfs_nfsdkrpc.c 192780 2009-05-26 01:09:33Z rmacklem $"); 36191783Srmacklem 37191783Srmacklem#include "opt_inet6.h" 38191783Srmacklem#include "opt_kgssapi.h" 39191783Srmacklem 40191783Srmacklem#include <fs/nfs/nfsport.h> 41191783Srmacklem 42191783Srmacklem#include <rpc/rpc.h> 43191783Srmacklem#include <rpc/rpcsec_gss.h> 44191783Srmacklem 45191783SrmacklemNFSDLOCKMUTEX; 46191783Srmacklem 47191783Srmacklem/* 48191783Srmacklem * Mapping of old NFS Version 2 RPC numbers to generic numbers. 49191783Srmacklem */ 50191783Srmacklemstatic int newnfs_nfsv3_procid[NFS_V3NPROCS] = { 51191783Srmacklem NFSPROC_NULL, 52191783Srmacklem NFSPROC_GETATTR, 53191783Srmacklem NFSPROC_SETATTR, 54191783Srmacklem NFSPROC_NOOP, 55191783Srmacklem NFSPROC_LOOKUP, 56191783Srmacklem NFSPROC_READLINK, 57191783Srmacklem NFSPROC_READ, 58191783Srmacklem NFSPROC_NOOP, 59191783Srmacklem NFSPROC_WRITE, 60191783Srmacklem NFSPROC_CREATE, 61191783Srmacklem NFSPROC_REMOVE, 62191783Srmacklem NFSPROC_RENAME, 63191783Srmacklem NFSPROC_LINK, 64191783Srmacklem NFSPROC_SYMLINK, 65191783Srmacklem NFSPROC_MKDIR, 66191783Srmacklem NFSPROC_RMDIR, 67191783Srmacklem NFSPROC_READDIR, 68191783Srmacklem NFSPROC_FSSTAT, 69191783Srmacklem NFSPROC_NOOP, 70191783Srmacklem NFSPROC_NOOP, 71191783Srmacklem NFSPROC_NOOP, 72191783Srmacklem NFSPROC_NOOP, 73191783Srmacklem}; 74191783Srmacklem 75191783Srmacklem 76191783SrmacklemSYSCTL_DECL(_vfs_newnfs); 77191783Srmacklem 78191783SrmacklemSVCPOOL *nfsrvd_pool; 79191783Srmacklem 80191783Srmacklemstatic int nfs_privport = 0; 81191783SrmacklemSYSCTL_INT(_vfs_newnfs, OID_AUTO, nfs_privport, CTLFLAG_RW, 82191783Srmacklem &nfs_privport, 0, 83191783Srmacklem "Only allow clients using a privileged port for NFSv2 and 3"); 84191783Srmacklem 85191783Srmacklemstatic int nfs_proc(struct nfsrv_descript *, u_int32_t, struct socket *, 86191783Srmacklem u_int64_t, struct nfsrvcache **); 87191783Srmacklem 88191783Srmacklemextern u_long sb_max_adj; 89191783Srmacklemextern int newnfs_numnfsd; 90191783Srmacklem 91191783Srmacklem/* 92191783Srmacklem * NFS server system calls 93191783Srmacklem */ 94191783Srmacklem 95191783Srmacklemstatic void 96191783Srmacklemnfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) 97191783Srmacklem{ 98191783Srmacklem struct nfsrv_descript nd; 99191783Srmacklem struct nfsrvcache *rp = NULL; 100192121Srmacklem int cacherep, credflavor; 101191783Srmacklem 102191783Srmacklem memset(&nd, 0, sizeof(nd)); 103191783Srmacklem if (rqst->rq_vers == NFS_VER2) { 104191783Srmacklem if (rqst->rq_proc > NFSV2PROC_STATFS) { 105191783Srmacklem svcerr_noproc(rqst); 106191783Srmacklem svc_freereq(rqst); 107191783Srmacklem return; 108191783Srmacklem } 109191783Srmacklem nd.nd_procnum = newnfs_nfsv3_procid[rqst->rq_proc]; 110191783Srmacklem nd.nd_flag = ND_NFSV2; 111191783Srmacklem } else if (rqst->rq_vers == NFS_VER3) { 112191783Srmacklem if (rqst->rq_proc >= NFS_V3NPROCS) { 113191783Srmacklem svcerr_noproc(rqst); 114191783Srmacklem svc_freereq(rqst); 115191783Srmacklem return; 116191783Srmacklem } 117191783Srmacklem nd.nd_procnum = rqst->rq_proc; 118191783Srmacklem nd.nd_flag = ND_NFSV3; 119191783Srmacklem } else { 120191783Srmacklem if (rqst->rq_proc != NFSPROC_NULL && 121191783Srmacklem rqst->rq_proc != NFSV4PROC_COMPOUND) { 122191783Srmacklem svcerr_noproc(rqst); 123191783Srmacklem svc_freereq(rqst); 124191783Srmacklem return; 125191783Srmacklem } 126191783Srmacklem nd.nd_procnum = rqst->rq_proc; 127191783Srmacklem nd.nd_flag = ND_NFSV4; 128191783Srmacklem } 129191783Srmacklem 130191783Srmacklem /* 131191783Srmacklem * Note: we want rq_addr, not svc_getrpccaller for nd_nam2 - 132191783Srmacklem * NFS_SRVMAXDATA uses a NULL value for nd_nam2 to detect TCP 133191783Srmacklem * mounts. 134191783Srmacklem */ 135191783Srmacklem nd.nd_mrep = rqst->rq_args; 136191783Srmacklem rqst->rq_args = NULL; 137191783Srmacklem newnfs_realign(&nd.nd_mrep); 138191783Srmacklem nd.nd_md = nd.nd_mrep; 139191783Srmacklem nd.nd_dpos = mtod(nd.nd_md, caddr_t); 140191783Srmacklem nd.nd_nam = svc_getrpccaller(rqst); 141191783Srmacklem nd.nd_nam2 = rqst->rq_addr; 142191783Srmacklem nd.nd_mreq = NULL; 143191783Srmacklem nd.nd_cred = NULL; 144191783Srmacklem 145191783Srmacklem if (nfs_privport && (nd.nd_flag & ND_NFSV4) == 0) { 146191783Srmacklem /* Check if source port is privileged */ 147191783Srmacklem u_short port; 148191783Srmacklem struct sockaddr *nam = nd.nd_nam; 149191783Srmacklem struct sockaddr_in *sin; 150191783Srmacklem 151191783Srmacklem sin = (struct sockaddr_in *)nam; 152191783Srmacklem /* 153191783Srmacklem * INET/INET6 - same code: 154191783Srmacklem * sin_port and sin6_port are at same offset 155191783Srmacklem */ 156191783Srmacklem port = ntohs(sin->sin_port); 157191783Srmacklem if (port >= IPPORT_RESERVED && 158191783Srmacklem nd.nd_procnum != NFSPROC_NULL) { 159191783Srmacklem#ifdef INET6 160191783Srmacklem char b6[INET6_ADDRSTRLEN]; 161191783Srmacklem#if defined(KLD_MODULE) 162191783Srmacklem /* Do not use ip6_sprintf: the nfs module should work without INET6. */ 163191783Srmacklem#define ip6_sprintf(buf, a) \ 164191783Srmacklem (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \ 165191783Srmacklem (a)->s6_addr16[0], (a)->s6_addr16[1], \ 166191783Srmacklem (a)->s6_addr16[2], (a)->s6_addr16[3], \ 167191783Srmacklem (a)->s6_addr16[4], (a)->s6_addr16[5], \ 168191783Srmacklem (a)->s6_addr16[6], (a)->s6_addr16[7]), \ 169191783Srmacklem (buf)) 170191783Srmacklem#endif 171191783Srmacklem#endif 172191783Srmacklem printf("NFS request from unprivileged port (%s:%d)\n", 173191783Srmacklem#ifdef INET6 174191783Srmacklem sin->sin_family == AF_INET6 ? 175191783Srmacklem ip6_sprintf(b6, &satosin6(sin)->sin6_addr) : 176191783Srmacklem#if defined(KLD_MODULE) 177191783Srmacklem#undef ip6_sprintf 178191783Srmacklem#endif 179191783Srmacklem#endif 180191783Srmacklem inet_ntoa(sin->sin_addr), port); 181191783Srmacklem svcerr_weakauth(rqst); 182191783Srmacklem svc_freereq(rqst); 183191783Srmacklem m_freem(nd.nd_mrep); 184191783Srmacklem return; 185191783Srmacklem } 186191783Srmacklem } 187191783Srmacklem 188191783Srmacklem if (nd.nd_procnum != NFSPROC_NULL) { 189192121Srmacklem if (!svc_getcred(rqst, &nd.nd_cred, &credflavor)) { 190191783Srmacklem svcerr_weakauth(rqst); 191191783Srmacklem svc_freereq(rqst); 192191783Srmacklem m_freem(nd.nd_mrep); 193191783Srmacklem return; 194191783Srmacklem } 195192121Srmacklem 196192121Srmacklem /* Set the flag based on credflavor */ 197192121Srmacklem if (credflavor == RPCSEC_GSS_KRB5) { 198192121Srmacklem nd.nd_flag |= ND_GSS; 199192121Srmacklem } else if (credflavor == RPCSEC_GSS_KRB5I) { 200192121Srmacklem nd.nd_flag |= (ND_GSS | ND_GSSINTEGRITY); 201192121Srmacklem } else if (credflavor == RPCSEC_GSS_KRB5P) { 202192121Srmacklem nd.nd_flag |= (ND_GSS | ND_GSSPRIVACY); 203192121Srmacklem } else if (credflavor != AUTH_SYS) { 204192121Srmacklem svcerr_weakauth(rqst); 205192121Srmacklem svc_freereq(rqst); 206192121Srmacklem m_freem(nd.nd_mrep); 207192121Srmacklem return; 208192121Srmacklem } 209192121Srmacklem 210191783Srmacklem#ifdef MAC 211191783Srmacklem mac_cred_associate_nfsd(nd.nd_cred); 212191783Srmacklem#endif 213192780Srmacklem if ((nd.nd_flag & ND_NFSV4) != 0) { 214191783Srmacklem nd.nd_repstat = nfsvno_v4rootexport(&nd); 215192780Srmacklem if (nd.nd_repstat != 0) { 216192780Srmacklem svcerr_weakauth(rqst); 217192780Srmacklem svc_freereq(rqst); 218192780Srmacklem m_freem(nd.nd_mrep); 219192780Srmacklem return; 220192780Srmacklem } 221192780Srmacklem } 222191783Srmacklem 223191783Srmacklem cacherep = nfs_proc(&nd, rqst->rq_xid, xprt->xp_socket, 224191783Srmacklem xprt->xp_sockref, &rp); 225191783Srmacklem } else { 226191783Srmacklem NFSMGET(nd.nd_mreq); 227191783Srmacklem nd.nd_mreq->m_len = 0; 228191783Srmacklem cacherep = RC_REPLY; 229191783Srmacklem } 230191783Srmacklem if (nd.nd_mrep != NULL) 231191783Srmacklem m_freem(nd.nd_mrep); 232191783Srmacklem 233191783Srmacklem if (nd.nd_cred != NULL) 234191783Srmacklem crfree(nd.nd_cred); 235191783Srmacklem 236191783Srmacklem if (cacherep == RC_DROPIT) { 237191783Srmacklem if (nd.nd_mreq != NULL) 238191783Srmacklem m_freem(nd.nd_mreq); 239191783Srmacklem svc_freereq(rqst); 240191783Srmacklem return; 241191783Srmacklem } 242191783Srmacklem 243191783Srmacklem if (nd.nd_mreq == NULL) { 244191783Srmacklem svcerr_decode(rqst); 245191783Srmacklem svc_freereq(rqst); 246191783Srmacklem return; 247191783Srmacklem } 248191783Srmacklem 249191783Srmacklem if (nd.nd_repstat & NFSERR_AUTHERR) { 250191783Srmacklem svcerr_auth(rqst, nd.nd_repstat & ~NFSERR_AUTHERR); 251191783Srmacklem if (nd.nd_mreq != NULL) 252191783Srmacklem m_freem(nd.nd_mreq); 253191783Srmacklem } else if (!svc_sendreply_mbuf(rqst, nd.nd_mreq)) { 254191783Srmacklem svcerr_systemerr(rqst); 255191783Srmacklem } 256191783Srmacklem if (rp != NULL) 257191783Srmacklem nfsrvd_sentcache(rp, xprt->xp_socket, 0); 258191783Srmacklem svc_freereq(rqst); 259191783Srmacklem} 260191783Srmacklem 261191783Srmacklem/* 262191783Srmacklem * Check the cache and, optionally, do the RPC. 263191783Srmacklem * Return the appropriate cache response. 264191783Srmacklem */ 265191783Srmacklemstatic int 266191783Srmacklemnfs_proc(struct nfsrv_descript *nd, u_int32_t xid, struct socket *so, 267191783Srmacklem u_int64_t sockref, struct nfsrvcache **rpp) 268191783Srmacklem{ 269191783Srmacklem struct thread *td = curthread; 270191783Srmacklem int cacherep = RC_DOIT, isdgram; 271191783Srmacklem 272191783Srmacklem *rpp = NULL; 273191783Srmacklem if (nd->nd_nam2 == NULL) { 274191783Srmacklem nd->nd_flag |= ND_STREAMSOCK; 275191783Srmacklem isdgram = 0; 276191783Srmacklem } else { 277191783Srmacklem isdgram = 1; 278191783Srmacklem } 279191783Srmacklem NFSGETTIME(&nd->nd_starttime); 280191783Srmacklem 281191783Srmacklem /* 282192780Srmacklem * Two cases: 283191783Srmacklem * 1 - For NFSv2 over UDP, if we are near our malloc/mget 284191783Srmacklem * limit, just drop the request. There is no 285191783Srmacklem * NFSERR_RESOURCE or NFSERR_DELAY for NFSv2 and the 286191783Srmacklem * client will timeout/retry over UDP in a little while. 287192780Srmacklem * 2 - nd_repstat == 0 && nd_mreq == NULL, which 288191783Srmacklem * means a normal nfs rpc, so check the cache 289191783Srmacklem */ 290191783Srmacklem if ((nd->nd_flag & ND_NFSV2) && nd->nd_nam2 != NULL && 291191783Srmacklem nfsrv_mallocmget_limit()) { 292191783Srmacklem cacherep = RC_DROPIT; 293191783Srmacklem } else { 294191783Srmacklem /* 295191783Srmacklem * For NFSv3, play it safe and assume that the client is 296191783Srmacklem * doing retries on the same TCP connection. 297191783Srmacklem */ 298191783Srmacklem if ((nd->nd_flag & (ND_NFSV4 | ND_STREAMSOCK)) == 299191783Srmacklem ND_STREAMSOCK) 300191783Srmacklem nd->nd_flag |= ND_SAMETCPCONN; 301191783Srmacklem nd->nd_retxid = xid; 302191783Srmacklem nd->nd_tcpconntime = NFSD_MONOSEC; 303191783Srmacklem nd->nd_sockref = sockref; 304191783Srmacklem cacherep = nfsrvd_getcache(nd, so); 305191783Srmacklem } 306191783Srmacklem 307191783Srmacklem /* 308191783Srmacklem * Handle the request. There are three cases. 309191783Srmacklem * RC_DOIT - do the RPC 310191783Srmacklem * RC_REPLY - return the reply already created 311191783Srmacklem * RC_DROPIT - just throw the request away 312191783Srmacklem */ 313191783Srmacklem if (cacherep == RC_DOIT) { 314191783Srmacklem nfsrvd_dorpc(nd, isdgram, td); 315191783Srmacklem if (nd->nd_repstat == NFSERR_DONTREPLY) 316191783Srmacklem cacherep = RC_DROPIT; 317191783Srmacklem else 318191783Srmacklem cacherep = RC_REPLY; 319191783Srmacklem *rpp = nfsrvd_updatecache(nd, so); 320191783Srmacklem } 321191783Srmacklem return (cacherep); 322191783Srmacklem} 323191783Srmacklem 324191783Srmacklem/* 325191783Srmacklem * Adds a socket to the list for servicing by nfsds. 326191783Srmacklem */ 327191783Srmacklemint 328191783Srmacklemnfsrvd_addsock(struct file *fp) 329191783Srmacklem{ 330191783Srmacklem int siz; 331191783Srmacklem struct socket *so; 332191783Srmacklem int error; 333191783Srmacklem SVCXPRT *xprt; 334191783Srmacklem static u_int64_t sockref = 0; 335191783Srmacklem 336191783Srmacklem so = fp->f_data; 337191783Srmacklem 338191783Srmacklem siz = sb_max_adj; 339191783Srmacklem error = soreserve(so, siz, siz); 340191783Srmacklem if (error) { 341191783Srmacklem return (error); 342191783Srmacklem } 343191783Srmacklem 344191783Srmacklem /* 345191783Srmacklem * Steal the socket from userland so that it doesn't close 346191783Srmacklem * unexpectedly. 347191783Srmacklem */ 348191783Srmacklem if (so->so_type == SOCK_DGRAM) 349191783Srmacklem xprt = svc_dg_create(nfsrvd_pool, so, 0, 0); 350191783Srmacklem else 351191783Srmacklem xprt = svc_vc_create(nfsrvd_pool, so, 0, 0); 352191783Srmacklem if (xprt) { 353191783Srmacklem fp->f_ops = &badfileops; 354191783Srmacklem fp->f_data = NULL; 355191783Srmacklem xprt->xp_sockref = ++sockref; 356191783Srmacklem svc_reg(xprt, NFS_PROG, NFS_VER2, nfssvc_program, NULL); 357191783Srmacklem svc_reg(xprt, NFS_PROG, NFS_VER3, nfssvc_program, NULL); 358191783Srmacklem svc_reg(xprt, NFS_PROG, NFS_VER4, nfssvc_program, NULL); 359191783Srmacklem } 360191783Srmacklem 361191783Srmacklem return (0); 362191783Srmacklem} 363191783Srmacklem 364191783Srmacklem/* 365191783Srmacklem * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 366191783Srmacklem * until it is killed by a signal. 367191783Srmacklem */ 368191783Srmacklemint 369191783Srmacklemnfsrvd_nfsd(struct thread *td, struct nfsd_nfsd_args *args) 370191783Srmacklem{ 371191783Srmacklem#ifdef KGSSAPI 372192017Srmacklem char principal[MAXHOSTNAMELEN + 5]; 373191783Srmacklem int error; 374191783Srmacklem bool_t ret2, ret3, ret4; 375191783Srmacklem#endif 376191783Srmacklem 377191783Srmacklem#ifdef KGSSAPI 378192017Srmacklem error = copyinstr(args->principal, principal, sizeof (principal), 379192017Srmacklem NULL); 380192017Srmacklem if (error) 381192017Srmacklem return (error); 382191783Srmacklem#endif 383191783Srmacklem 384191783Srmacklem /* 385191783Srmacklem * Only the first nfsd actually does any work. The RPC code 386191783Srmacklem * adds threads to it as needed. Any extra processes offered 387191783Srmacklem * by nfsd just exit. If nfsd is new enough, it will call us 388191783Srmacklem * once with a structure that specifies how many threads to 389191783Srmacklem * use. 390191783Srmacklem */ 391191783Srmacklem NFSD_LOCK(); 392191783Srmacklem if (newnfs_numnfsd == 0) { 393191783Srmacklem newnfs_numnfsd++; 394191783Srmacklem 395191783Srmacklem NFSD_UNLOCK(); 396191783Srmacklem 397191783Srmacklem#ifdef KGSSAPI 398192017Srmacklem /* An empty string implies AUTH_SYS only. */ 399192017Srmacklem if (principal[0] != '\0') { 400192017Srmacklem ret2 = rpc_gss_set_svc_name(principal, "kerberosv5", 401192017Srmacklem GSS_C_INDEFINITE, NFS_PROG, NFS_VER2); 402192017Srmacklem ret3 = rpc_gss_set_svc_name(principal, "kerberosv5", 403192017Srmacklem GSS_C_INDEFINITE, NFS_PROG, NFS_VER3); 404192017Srmacklem ret4 = rpc_gss_set_svc_name(principal, "kerberosv5", 405192017Srmacklem GSS_C_INDEFINITE, NFS_PROG, NFS_VER4); 406191783Srmacklem 407192017Srmacklem if (!ret2 || !ret3 || !ret4) { 408192017Srmacklem NFSD_LOCK(); 409192017Srmacklem newnfs_numnfsd--; 410192017Srmacklem nfsrvd_init(1); 411192017Srmacklem NFSD_UNLOCK(); 412192017Srmacklem return (EAUTH); 413192017Srmacklem } 414191783Srmacklem } 415191783Srmacklem#endif 416191783Srmacklem 417192017Srmacklem nfsrvd_pool->sp_minthreads = args->minthreads; 418192017Srmacklem nfsrvd_pool->sp_maxthreads = args->maxthreads; 419191783Srmacklem 420191783Srmacklem svc_run(nfsrvd_pool); 421191783Srmacklem 422191783Srmacklem#ifdef KGSSAPI 423192017Srmacklem if (principal[0] != '\0') { 424192017Srmacklem rpc_gss_clear_svc_name(NFS_PROG, NFS_VER2); 425192017Srmacklem rpc_gss_clear_svc_name(NFS_PROG, NFS_VER3); 426192017Srmacklem rpc_gss_clear_svc_name(NFS_PROG, NFS_VER4); 427192017Srmacklem } 428191783Srmacklem#endif 429191783Srmacklem 430191783Srmacklem NFSD_LOCK(); 431191783Srmacklem newnfs_numnfsd--; 432191783Srmacklem nfsrvd_init(1); 433191783Srmacklem } 434191783Srmacklem NFSD_UNLOCK(); 435191783Srmacklem 436191783Srmacklem return (0); 437191783Srmacklem} 438191783Srmacklem 439191783Srmacklem/* 440191783Srmacklem * Initialize the data structures for the server. 441191783Srmacklem * Handshake with any new nfsds starting up to avoid any chance of 442191783Srmacklem * corruption. 443191783Srmacklem */ 444191783Srmacklemvoid 445191783Srmacklemnfsrvd_init(int terminating) 446191783Srmacklem{ 447191783Srmacklem 448191783Srmacklem NFSD_LOCK_ASSERT(); 449191783Srmacklem 450191783Srmacklem if (terminating) { 451191783Srmacklem NFSD_UNLOCK(); 452191783Srmacklem svcpool_destroy(nfsrvd_pool); 453191783Srmacklem nfsrvd_pool = NULL; 454191783Srmacklem NFSD_LOCK(); 455191783Srmacklem } 456191783Srmacklem 457191783Srmacklem NFSD_UNLOCK(); 458191783Srmacklem 459191783Srmacklem nfsrvd_pool = svcpool_create("nfsd", SYSCTL_STATIC_CHILDREN(_vfs_newnfs)); 460191783Srmacklem nfsrvd_pool->sp_rcache = NULL; 461191783Srmacklem nfsrvd_pool->sp_assign = NULL; 462191783Srmacklem nfsrvd_pool->sp_done = NULL; 463191783Srmacklem 464191783Srmacklem NFSD_LOCK(); 465191783Srmacklem} 466191783Srmacklem 467