nfs_nfsiod.c revision 1817
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94 37 * $Id$ 38 */ 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/kernel.h> 43#include <sys/file.h> 44#include <sys/stat.h> 45#include <sys/vnode.h> 46#include <sys/mount.h> 47#include <sys/proc.h> 48#include <sys/uio.h> 49#include <sys/malloc.h> 50#include <sys/buf.h> 51#include <sys/mbuf.h> 52#include <sys/socket.h> 53#include <sys/socketvar.h> 54#include <sys/domain.h> 55#include <sys/protosw.h> 56#include <sys/namei.h> 57#include <sys/syslog.h> 58 59#include <netinet/in.h> 60#include <netinet/tcp.h> 61#ifdef ISO 62#include <netiso/iso.h> 63#endif 64#include <nfs/rpcv2.h> 65#include <nfs/nfsv2.h> 66#include <nfs/nfs.h> 67#include <nfs/nfsrvcache.h> 68#include <nfs/nfsmount.h> 69#include <nfs/nfsnode.h> 70#include <nfs/nqnfs.h> 71#include <nfs/nfsrtt.h> 72 73void nfsrv_zapsock __P((struct nfssvc_sock *)); 74 75/* Global defs. */ 76extern u_long nfs_prog, nfs_vers; 77extern int (*nfsrv_procs[NFS_NPROCS])(); 78extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 79extern int nfs_numasync; 80extern time_t nqnfsstarttime; 81extern struct nfsrv_req nsrvq_head; 82extern struct nfsd nfsd_head; 83extern int nqsrv_writeslack; 84extern int nfsrtton; 85struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock; 86int nuidhash_max = NFS_MAXUIDHASH; 87static int nfs_numnfsd = 0; 88int nfsd_waiting = 0; 89static int notstarted = 1; 90static int modify_flag = 0; 91static struct nfsdrt nfsdrt; 92void nfsrv_cleancache(), nfsrv_rcv(), nfsrv_wakenfsd(), nfs_sndunlock(); 93static void nfsd_rt(); 94void nfsrv_slpderef(), nfsrv_init(); 95 96#define TRUE 1 97#define FALSE 0 98 99static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; 100/* 101 * NFS server system calls 102 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c 103 */ 104 105/* 106 * Get file handle system call 107 */ 108struct getfh_args { 109 char *fname; 110 fhandle_t *fhp; 111}; 112int 113getfh(p, uap, retval) 114 struct proc *p; 115 register struct getfh_args *uap; 116 int *retval; 117{ 118 register struct vnode *vp; 119 fhandle_t fh; 120 int error; 121 struct nameidata nd; 122 123 /* 124 * Must be super user 125 */ 126 if (error = suser(p->p_ucred, &p->p_acflag)) 127 return (error); 128 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 129 if (error = namei(&nd)) 130 return (error); 131 vp = nd.ni_vp; 132 bzero((caddr_t)&fh, sizeof(fh)); 133 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 134 error = VFS_VPTOFH(vp, &fh.fh_fid); 135 vput(vp); 136 if (error) 137 return (error); 138 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); 139 return (error); 140} 141 142static struct nfssvc_sock nfssvc_sockhead; 143 144/* 145 * Nfs server psuedo system call for the nfsd's 146 * Based on the flag value it either: 147 * - adds a socket to the selection list 148 * - remains in the kernel as an nfsd 149 * - remains in the kernel as an nfsiod 150 */ 151struct nfssvc_args { 152 int flag; 153 caddr_t argp; 154}; 155int 156nfssvc(p, uap, retval) 157 struct proc *p; 158 register struct nfssvc_args *uap; 159 int *retval; 160{ 161 struct nameidata nd; 162 struct file *fp; 163 struct mbuf *nam; 164 struct nfsd_args nfsdarg; 165 struct nfsd_srvargs nfsd_srvargs, *nsd = &nfsd_srvargs; 166 struct nfsd_cargs ncd; 167 struct nfsd *nfsd; 168 struct nfssvc_sock *slp; 169 struct nfsuid *nuidp, **nuh; 170 struct nfsmount *nmp; 171 int error; 172 173 /* 174 * Must be super user 175 */ 176 if (error = suser(p->p_ucred, &p->p_acflag)) 177 return (error); 178 while (nfssvc_sockhead.ns_flag & SLP_INIT) { 179 nfssvc_sockhead.ns_flag |= SLP_WANTINIT; 180 (void) tsleep((caddr_t)&nfssvc_sockhead, PSOCK, "nfsd init", 0); 181 } 182 if (uap->flag & NFSSVC_BIOD) 183 error = nfssvc_iod(p); 184 else if (uap->flag & NFSSVC_MNTD) { 185 if (error = copyin(uap->argp, (caddr_t)&ncd, sizeof (ncd))) 186 return (error); 187 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 188 ncd.ncd_dirp, p); 189 if (error = namei(&nd)) 190 return (error); 191 if ((nd.ni_vp->v_flag & VROOT) == 0) 192 error = EINVAL; 193 nmp = VFSTONFS(nd.ni_vp->v_mount); 194 vput(nd.ni_vp); 195 if (error) 196 return (error); 197 if ((nmp->nm_flag & NFSMNT_MNTD) && 198 (uap->flag & NFSSVC_GOTAUTH) == 0) 199 return (0); 200 nmp->nm_flag |= NFSMNT_MNTD; 201 error = nqnfs_clientd(nmp, p->p_ucred, &ncd, uap->flag, 202 uap->argp, p); 203 } else if (uap->flag & NFSSVC_ADDSOCK) { 204 if (error = copyin(uap->argp, (caddr_t)&nfsdarg, 205 sizeof(nfsdarg))) 206 return (error); 207 if (error = getsock(p->p_fd, nfsdarg.sock, &fp)) 208 return (error); 209 /* 210 * Get the client address for connected sockets. 211 */ 212 if (nfsdarg.name == NULL || nfsdarg.namelen == 0) 213 nam = (struct mbuf *)0; 214 else if (error = sockargs(&nam, nfsdarg.name, nfsdarg.namelen, 215 MT_SONAME)) 216 return (error); 217 error = nfssvc_addsock(fp, nam); 218 } else { 219 if (error = copyin(uap->argp, (caddr_t)nsd, sizeof (*nsd))) 220 return (error); 221 if ((uap->flag & NFSSVC_AUTHIN) && (nfsd = nsd->nsd_nfsd) && 222 (nfsd->nd_slp->ns_flag & SLP_VALID)) { 223 slp = nfsd->nd_slp; 224 225 /* 226 * First check to see if another nfsd has already 227 * added this credential. 228 */ 229 nuidp = slp->ns_uidh[NUIDHASH(nsd->nsd_uid)]; 230 while (nuidp) { 231 if (nuidp->nu_uid == nsd->nsd_uid) 232 break; 233 nuidp = nuidp->nu_hnext; 234 } 235 if (!nuidp) { 236 /* 237 * Nope, so we will. 238 */ 239 if (slp->ns_numuids < nuidhash_max) { 240 slp->ns_numuids++; 241 nuidp = (struct nfsuid *) 242 malloc(sizeof (struct nfsuid), M_NFSUID, 243 M_WAITOK); 244 } else 245 nuidp = (struct nfsuid *)0; 246 if ((slp->ns_flag & SLP_VALID) == 0) { 247 if (nuidp) 248 free((caddr_t)nuidp, M_NFSUID); 249 } else { 250 if (nuidp == (struct nfsuid *)0) { 251 nuidp = slp->ns_lruprev; 252 remque(nuidp); 253 if (nuidp->nu_hprev) 254 nuidp->nu_hprev->nu_hnext = 255 nuidp->nu_hnext; 256 if (nuidp->nu_hnext) 257 nuidp->nu_hnext->nu_hprev = 258 nuidp->nu_hprev; 259 } 260 nuidp->nu_cr = nsd->nsd_cr; 261 if (nuidp->nu_cr.cr_ngroups > NGROUPS) 262 nuidp->nu_cr.cr_ngroups = NGROUPS; 263 nuidp->nu_cr.cr_ref = 1; 264 nuidp->nu_uid = nsd->nsd_uid; 265 insque(nuidp, (struct nfsuid *)slp); 266 nuh = &slp->ns_uidh[NUIDHASH(nsd->nsd_uid)]; 267 if (nuidp->nu_hnext = *nuh) 268 nuidp->nu_hnext->nu_hprev = nuidp; 269 nuidp->nu_hprev = (struct nfsuid *)0; 270 *nuh = nuidp; 271 } 272 } 273 } 274 if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd)) 275 nfsd->nd_flag |= NFSD_AUTHFAIL; 276 error = nfssvc_nfsd(nsd, uap->argp, p); 277 } 278 if (error == EINTR || error == ERESTART) 279 error = 0; 280 return (error); 281} 282 283/* 284 * Adds a socket to the list for servicing by nfsds. 285 */ 286int 287nfssvc_addsock(fp, mynam) 288 struct file *fp; 289 struct mbuf *mynam; 290{ 291 register struct mbuf *m; 292 register int siz; 293 register struct nfssvc_sock *slp; 294 register struct socket *so; 295 struct nfssvc_sock *tslp; 296 int error, s; 297 298 so = (struct socket *)fp->f_data; 299 tslp = (struct nfssvc_sock *)0; 300 /* 301 * Add it to the list, as required. 302 */ 303 if (so->so_proto->pr_protocol == IPPROTO_UDP) { 304 tslp = nfs_udpsock; 305 if (tslp->ns_flag & SLP_VALID) { 306 m_freem(mynam); 307 return (EPERM); 308 } 309#ifdef ISO 310 } else if (so->so_proto->pr_protocol == ISOPROTO_CLTP) { 311 tslp = nfs_cltpsock; 312 if (tslp->ns_flag & SLP_VALID) { 313 m_freem(mynam); 314 return (EPERM); 315 } 316#endif /* ISO */ 317 } 318 if (so->so_type == SOCK_STREAM) 319 siz = NFS_MAXPACKET + sizeof (u_long); 320 else 321 siz = NFS_MAXPACKET; 322 if (error = soreserve(so, siz, siz)) { 323 m_freem(mynam); 324 return (error); 325 } 326 327 /* 328 * Set protocol specific options { for now TCP only } and 329 * reserve some space. For datagram sockets, this can get called 330 * repeatedly for the same socket, but that isn't harmful. 331 */ 332 if (so->so_type == SOCK_STREAM) { 333 MGET(m, M_WAIT, MT_SOOPTS); 334 *mtod(m, int *) = 1; 335 m->m_len = sizeof(int); 336 sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); 337 } 338 if (so->so_proto->pr_domain->dom_family == AF_INET && 339 so->so_proto->pr_protocol == IPPROTO_TCP) { 340 MGET(m, M_WAIT, MT_SOOPTS); 341 *mtod(m, int *) = 1; 342 m->m_len = sizeof(int); 343 sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); 344 } 345 so->so_rcv.sb_flags &= ~SB_NOINTR; 346 so->so_rcv.sb_timeo = 0; 347 so->so_snd.sb_flags &= ~SB_NOINTR; 348 so->so_snd.sb_timeo = 0; 349 if (tslp) 350 slp = tslp; 351 else { 352 slp = (struct nfssvc_sock *) 353 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 354 bzero((caddr_t)slp, sizeof (struct nfssvc_sock)); 355 slp->ns_prev = nfssvc_sockhead.ns_prev; 356 slp->ns_prev->ns_next = slp; 357 slp->ns_next = &nfssvc_sockhead; 358 nfssvc_sockhead.ns_prev = slp; 359 slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp; 360 } 361 slp->ns_so = so; 362 slp->ns_nam = mynam; 363 fp->f_count++; 364 slp->ns_fp = fp; 365 s = splnet(); 366 so->so_upcallarg = (caddr_t)slp; 367 so->so_upcall = nfsrv_rcv; 368 slp->ns_flag = (SLP_VALID | SLP_NEEDQ); 369 nfsrv_wakenfsd(slp); 370 splx(s); 371 return (0); 372} 373 374/* 375 * Called by nfssvc() for nfsds. Just loops around servicing rpc requests 376 * until it is killed by a signal. 377 */ 378int 379nfssvc_nfsd(nsd, argp, p) 380 struct nfsd_srvargs *nsd; 381 caddr_t argp; 382 struct proc *p; 383{ 384 register struct mbuf *m, *nam2; 385 register int siz; 386 register struct nfssvc_sock *slp; 387 register struct socket *so; 388 register int *solockp; 389 struct nfsd *nd = nsd->nsd_nfsd; 390 struct mbuf *mreq, *nam; 391 struct timeval starttime; 392 struct nfsuid *uidp; 393 int error = 0, cacherep, s; 394 int sotype; 395 396 s = splnet(); 397 if (nd == (struct nfsd *)0) { 398 nsd->nsd_nfsd = nd = (struct nfsd *) 399 malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK); 400 bzero((caddr_t)nd, sizeof (struct nfsd)); 401 nd->nd_procp = p; 402 nd->nd_cr.cr_ref = 1; 403 insque(nd, &nfsd_head); 404 nd->nd_nqlflag = NQL_NOVAL; 405 nfs_numnfsd++; 406 } 407 /* 408 * Loop getting rpc requests until SIGKILL. 409 */ 410 for (;;) { 411 if ((nd->nd_flag & NFSD_REQINPROG) == 0) { 412 while (nd->nd_slp == (struct nfssvc_sock *)0 && 413 (nfsd_head.nd_flag & NFSD_CHECKSLP) == 0) { 414 nd->nd_flag |= NFSD_WAITING; 415 nfsd_waiting++; 416 error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0); 417 nfsd_waiting--; 418 if (error) 419 goto done; 420 } 421 if (nd->nd_slp == (struct nfssvc_sock *)0 && 422 (nfsd_head.nd_flag & NFSD_CHECKSLP)) { 423 slp = nfssvc_sockhead.ns_next; 424 while (slp != &nfssvc_sockhead) { 425 if ((slp->ns_flag & (SLP_VALID | SLP_DOREC)) 426 == (SLP_VALID | SLP_DOREC)) { 427 slp->ns_flag &= ~SLP_DOREC; 428 slp->ns_sref++; 429 nd->nd_slp = slp; 430 break; 431 } 432 slp = slp->ns_next; 433 } 434 if (slp == &nfssvc_sockhead) 435 nfsd_head.nd_flag &= ~NFSD_CHECKSLP; 436 } 437 if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0) 438 continue; 439 if (slp->ns_flag & SLP_VALID) { 440 if (slp->ns_flag & SLP_DISCONN) 441 nfsrv_zapsock(slp); 442 else if (slp->ns_flag & SLP_NEEDQ) { 443 slp->ns_flag &= ~SLP_NEEDQ; 444 (void) nfs_sndlock(&slp->ns_solock, 445 (struct nfsreq *)0); 446 nfsrv_rcv(slp->ns_so, (caddr_t)slp, 447 M_WAIT); 448 nfs_sndunlock(&slp->ns_solock); 449 } 450 error = nfsrv_dorec(slp, nd); 451 nd->nd_flag |= NFSD_REQINPROG; 452 } 453 } else { 454 error = 0; 455 slp = nd->nd_slp; 456 } 457 if (error || (slp->ns_flag & SLP_VALID) == 0) { 458 nd->nd_slp = (struct nfssvc_sock *)0; 459 nd->nd_flag &= ~NFSD_REQINPROG; 460 nfsrv_slpderef(slp); 461 continue; 462 } 463 splx(s); 464 so = slp->ns_so; 465 sotype = so->so_type; 466 starttime = time; 467 if (so->so_proto->pr_flags & PR_CONNREQUIRED) 468 solockp = &slp->ns_solock; 469 else 470 solockp = (int *)0; 471 /* 472 * nam == nam2 for connectionless protocols such as UDP 473 * nam2 == NULL for connection based protocols to disable 474 * recent request caching. 475 */ 476 if (nam2 = nd->nd_nam) { 477 nam = nam2; 478 cacherep = RC_CHECKIT; 479 } else { 480 nam = slp->ns_nam; 481 cacherep = RC_DOIT; 482 } 483 484 /* 485 * Check to see if authorization is needed. 486 */ 487 if (nd->nd_flag & NFSD_NEEDAUTH) { 488 static int logauth = 0; 489 490 nd->nd_flag &= ~NFSD_NEEDAUTH; 491 /* 492 * Check for a mapping already installed. 493 */ 494 uidp = slp->ns_uidh[NUIDHASH(nd->nd_cr.cr_uid)]; 495 while (uidp) { 496 if (uidp->nu_uid == nd->nd_cr.cr_uid) 497 break; 498 uidp = uidp->nu_hnext; 499 } 500 if (!uidp) { 501 nsd->nsd_uid = nd->nd_cr.cr_uid; 502 if (nam2 && logauth++ == 0) 503 log(LOG_WARNING, "Kerberized NFS using UDP\n"); 504 nsd->nsd_haddr = 505 mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; 506 nsd->nsd_authlen = nd->nd_authlen; 507 if (copyout(nd->nd_authstr, nsd->nsd_authstr, 508 nd->nd_authlen) == 0 && 509 copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0) 510 return (ENEEDAUTH); 511 cacherep = RC_DROPIT; 512 } 513 } 514 if (cacherep == RC_CHECKIT) 515 cacherep = nfsrv_getcache(nam2, nd, &mreq); 516 517 /* 518 * Check for just starting up for NQNFS and send 519 * fake "try again later" replies to the NQNFS clients. 520 */ 521 if (notstarted && nqnfsstarttime <= time.tv_sec) { 522 if (modify_flag) { 523 nqnfsstarttime = time.tv_sec + nqsrv_writeslack; 524 modify_flag = 0; 525 } else 526 notstarted = 0; 527 } 528 if (notstarted) { 529 if (nd->nd_nqlflag == NQL_NOVAL) 530 cacherep = RC_DROPIT; 531 else if (nd->nd_procnum != NFSPROC_WRITE) { 532 nd->nd_procnum = NFSPROC_NOOP; 533 nd->nd_repstat = NQNFS_TRYLATER; 534 cacherep = RC_DOIT; 535 } else 536 modify_flag = 1; 537 } else if (nd->nd_flag & NFSD_AUTHFAIL) { 538 nd->nd_flag &= ~NFSD_AUTHFAIL; 539 nd->nd_procnum = NFSPROC_NOOP; 540 nd->nd_repstat = NQNFS_AUTHERR; 541 cacherep = RC_DOIT; 542 } 543 544 switch (cacherep) { 545 case RC_DOIT: 546 error = (*(nfsrv_procs[nd->nd_procnum]))(nd, 547 nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr, 548 nam, &mreq); 549 if (nd->nd_cr.cr_ref != 1) { 550 printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref); 551 panic("nfssvc cref"); 552 } 553 if (error) { 554 if (nd->nd_procnum != NQNFSPROC_VACATED) 555 nfsstats.srv_errs++; 556 if (nam2) { 557 nfsrv_updatecache(nam2, nd, FALSE, mreq); 558 m_freem(nam2); 559 } 560 break; 561 } 562 nfsstats.srvrpccnt[nd->nd_procnum]++; 563 if (nam2) 564 nfsrv_updatecache(nam2, nd, TRUE, mreq); 565 nd->nd_mrep = (struct mbuf *)0; 566 case RC_REPLY: 567 m = mreq; 568 siz = 0; 569 while (m) { 570 siz += m->m_len; 571 m = m->m_next; 572 } 573 if (siz <= 0 || siz > NFS_MAXPACKET) { 574 printf("mbuf siz=%d\n",siz); 575 panic("Bad nfs svc reply"); 576 } 577 m = mreq; 578 m->m_pkthdr.len = siz; 579 m->m_pkthdr.rcvif = (struct ifnet *)0; 580 /* 581 * For stream protocols, prepend a Sun RPC 582 * Record Mark. 583 */ 584 if (sotype == SOCK_STREAM) { 585 M_PREPEND(m, NFSX_UNSIGNED, M_WAIT); 586 *mtod(m, u_long *) = htonl(0x80000000 | siz); 587 } 588 if (solockp) 589 (void) nfs_sndlock(solockp, (struct nfsreq *)0); 590 if (slp->ns_flag & SLP_VALID) 591 error = nfs_send(so, nam2, m, (struct nfsreq *)0); 592 else { 593 error = EPIPE; 594 m_freem(m); 595 } 596 if (nfsrtton) 597 nfsd_rt(&starttime, sotype, nd, nam, cacherep); 598 if (nam2) 599 MFREE(nam2, m); 600 if (nd->nd_mrep) 601 m_freem(nd->nd_mrep); 602 if (error == EPIPE) 603 nfsrv_zapsock(slp); 604 if (solockp) 605 nfs_sndunlock(solockp); 606 if (error == EINTR || error == ERESTART) { 607 nfsrv_slpderef(slp); 608 s = splnet(); 609 goto done; 610 } 611 break; 612 case RC_DROPIT: 613 if (nfsrtton) 614 nfsd_rt(&starttime, sotype, nd, nam, cacherep); 615 m_freem(nd->nd_mrep); 616 m_freem(nam2); 617 break; 618 }; 619 s = splnet(); 620 if (nfsrv_dorec(slp, nd)) { 621 nd->nd_flag &= ~NFSD_REQINPROG; 622 nd->nd_slp = (struct nfssvc_sock *)0; 623 nfsrv_slpderef(slp); 624 } 625 } 626done: 627 remque(nd); 628 splx(s); 629 free((caddr_t)nd, M_NFSD); 630 nsd->nsd_nfsd = (struct nfsd *)0; 631 if (--nfs_numnfsd == 0) 632 nfsrv_init(TRUE); /* Reinitialize everything */ 633 return (error); 634} 635 636/* 637 * Asynchronous I/O daemons for client nfs. 638 * They do read-ahead and write-behind operations on the block I/O cache. 639 * Never returns unless it fails or gets killed. 640 */ 641int 642nfssvc_iod(p) 643 struct proc *p; 644{ 645 register struct buf *bp; 646 register int i, myiod; 647 int error = 0; 648 649 /* 650 * Assign my position or return error if too many already running 651 */ 652 myiod = -1; 653 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 654 if (nfs_asyncdaemon[i] == 0) { 655 nfs_asyncdaemon[i]++; 656 myiod = i; 657 break; 658 } 659 if (myiod == -1) 660 return (EBUSY); 661 nfs_numasync++; 662 /* 663 * Just loop around doin our stuff until SIGKILL 664 */ 665 for (;;) { 666 while (nfs_bufq.tqh_first == NULL && error == 0) { 667 nfs_iodwant[myiod] = p; 668 error = tsleep((caddr_t)&nfs_iodwant[myiod], 669 PWAIT | PCATCH, "nfsidl", 0); 670 } 671 while ((bp = nfs_bufq.tqh_first) != NULL) { 672 /* Take one off the front of the list */ 673 TAILQ_REMOVE(&nfs_bufq, bp, b_freelist); 674 if (bp->b_flags & B_READ) 675 (void) nfs_doio(bp, bp->b_rcred, (struct proc *)0); 676 else 677 (void) nfs_doio(bp, bp->b_wcred, (struct proc *)0); 678 } 679 if (error) { 680 nfs_asyncdaemon[myiod] = 0; 681 nfs_numasync--; 682 return (error); 683 } 684 } 685} 686 687/* 688 * Shut down a socket associated with an nfssvc_sock structure. 689 * Should be called with the send lock set, if required. 690 * The trick here is to increment the sref at the start, so that the nfsds 691 * will stop using it and clear ns_flag at the end so that it will not be 692 * reassigned during cleanup. 693 */ 694void 695nfsrv_zapsock(slp) 696 register struct nfssvc_sock *slp; 697{ 698 register struct nfsuid *nuidp, *onuidp; 699 register int i; 700 struct socket *so; 701 struct file *fp; 702 struct mbuf *m; 703 704 slp->ns_flag &= ~SLP_ALLFLAGS; 705 if (fp = slp->ns_fp) { 706 slp->ns_fp = (struct file *)0; 707 so = slp->ns_so; 708 so->so_upcall = NULL; 709 soshutdown(so, 2); 710 closef(fp, (struct proc *)0); 711 if (slp->ns_nam) 712 MFREE(slp->ns_nam, m); 713 m_freem(slp->ns_raw); 714 m_freem(slp->ns_rec); 715 nuidp = slp->ns_lrunext; 716 while (nuidp != (struct nfsuid *)slp) { 717 onuidp = nuidp; 718 nuidp = nuidp->nu_lrunext; 719 free((caddr_t)onuidp, M_NFSUID); 720 } 721 slp->ns_lrunext = slp->ns_lruprev = (struct nfsuid *)slp; 722 for (i = 0; i < NUIDHASHSIZ; i++) 723 slp->ns_uidh[i] = (struct nfsuid *)0; 724 } 725} 726 727/* 728 * Get an authorization string for the uid by having the mount_nfs sitting 729 * on this mount point porpous out of the kernel and do it. 730 */ 731int 732nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len) 733 register struct nfsmount *nmp; 734 struct nfsreq *rep; 735 struct ucred *cred; 736 int *auth_type; 737 char **auth_str; 738 int *auth_len; 739{ 740 int error = 0; 741 742 while ((nmp->nm_flag & NFSMNT_WAITAUTH) == 0) { 743 nmp->nm_flag |= NFSMNT_WANTAUTH; 744 (void) tsleep((caddr_t)&nmp->nm_authtype, PSOCK, 745 "nfsauth1", 2 * hz); 746 if (error = nfs_sigintr(nmp, rep, rep->r_procp)) { 747 nmp->nm_flag &= ~NFSMNT_WANTAUTH; 748 return (error); 749 } 750 } 751 nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH); 752 nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK); 753 nmp->nm_authuid = cred->cr_uid; 754 wakeup((caddr_t)&nmp->nm_authstr); 755 756 /* 757 * And wait for mount_nfs to do its stuff. 758 */ 759 while ((nmp->nm_flag & NFSMNT_HASAUTH) == 0 && error == 0) { 760 (void) tsleep((caddr_t)&nmp->nm_authlen, PSOCK, 761 "nfsauth2", 2 * hz); 762 error = nfs_sigintr(nmp, rep, rep->r_procp); 763 } 764 if (nmp->nm_flag & NFSMNT_AUTHERR) { 765 nmp->nm_flag &= ~NFSMNT_AUTHERR; 766 error = EAUTH; 767 } 768 if (error) 769 free((caddr_t)*auth_str, M_TEMP); 770 else { 771 *auth_type = nmp->nm_authtype; 772 *auth_len = nmp->nm_authlen; 773 } 774 nmp->nm_flag &= ~NFSMNT_HASAUTH; 775 nmp->nm_flag |= NFSMNT_WAITAUTH; 776 if (nmp->nm_flag & NFSMNT_WANTAUTH) { 777 nmp->nm_flag &= ~NFSMNT_WANTAUTH; 778 wakeup((caddr_t)&nmp->nm_authtype); 779 } 780 return (error); 781} 782 783/* 784 * Derefence a server socket structure. If it has no more references and 785 * is no longer valid, you can throw it away. 786 */ 787void 788nfsrv_slpderef(slp) 789 register struct nfssvc_sock *slp; 790{ 791 if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) { 792 slp->ns_prev->ns_next = slp->ns_next; 793 slp->ns_next->ns_prev = slp->ns_prev; 794 free((caddr_t)slp, M_NFSSVC); 795 } 796} 797 798/* 799 * Initialize the data structures for the server. 800 * Handshake with any new nfsds starting up to avoid any chance of 801 * corruption. 802 */ 803void 804nfsrv_init(terminating) 805 int terminating; 806{ 807 register struct nfssvc_sock *slp; 808 struct nfssvc_sock *oslp; 809 810 if (nfssvc_sockhead.ns_flag & SLP_INIT) 811 panic("nfsd init"); 812 nfssvc_sockhead.ns_flag |= SLP_INIT; 813 if (terminating) { 814 slp = nfssvc_sockhead.ns_next; 815 while (slp != &nfssvc_sockhead) { 816 if (slp->ns_flag & SLP_VALID) 817 nfsrv_zapsock(slp); 818 slp->ns_next->ns_prev = slp->ns_prev; 819 slp->ns_prev->ns_next = slp->ns_next; 820 oslp = slp; 821 slp = slp->ns_next; 822 free((caddr_t)oslp, M_NFSSVC); 823 } 824 nfsrv_cleancache(); /* And clear out server cache */ 825 } 826 nfs_udpsock = (struct nfssvc_sock *) 827 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 828 bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock)); 829 nfs_cltpsock = (struct nfssvc_sock *) 830 malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK); 831 bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock)); 832 nfssvc_sockhead.ns_next = nfs_udpsock; 833 nfs_udpsock->ns_next = nfs_cltpsock; 834 nfs_cltpsock->ns_next = &nfssvc_sockhead; 835 nfssvc_sockhead.ns_prev = nfs_cltpsock; 836 nfs_cltpsock->ns_prev = nfs_udpsock; 837 nfs_udpsock->ns_prev = &nfssvc_sockhead; 838 nfs_udpsock->ns_lrunext = nfs_udpsock->ns_lruprev = 839 (struct nfsuid *)nfs_udpsock; 840 nfs_cltpsock->ns_lrunext = nfs_cltpsock->ns_lruprev = 841 (struct nfsuid *)nfs_cltpsock; 842 nfsd_head.nd_next = nfsd_head.nd_prev = &nfsd_head; 843 nfsd_head.nd_flag = 0; 844 nfssvc_sockhead.ns_flag &= ~SLP_INIT; 845 if (nfssvc_sockhead.ns_flag & SLP_WANTINIT) { 846 nfssvc_sockhead.ns_flag &= ~SLP_WANTINIT; 847 wakeup((caddr_t)&nfssvc_sockhead); 848 } 849} 850 851/* 852 * Add entries to the server monitor log. 853 */ 854static void 855nfsd_rt(startp, sotype, nd, nam, cacherep) 856 struct timeval *startp; 857 int sotype; 858 register struct nfsd *nd; 859 struct mbuf *nam; 860 int cacherep; 861{ 862 register struct drt *rt; 863 864 rt = &nfsdrt.drt[nfsdrt.pos]; 865 if (cacherep == RC_DOIT) 866 rt->flag = 0; 867 else if (cacherep == RC_REPLY) 868 rt->flag = DRT_CACHEREPLY; 869 else 870 rt->flag = DRT_CACHEDROP; 871 if (sotype == SOCK_STREAM) 872 rt->flag |= DRT_TCP; 873 if (nd->nd_nqlflag != NQL_NOVAL) 874 rt->flag |= DRT_NQNFS; 875 rt->proc = nd->nd_procnum; 876 if (mtod(nam, struct sockaddr *)->sa_family == AF_INET) 877 rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr; 878 else 879 rt->ipadr = INADDR_ANY; 880 rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) + 881 (time.tv_usec - startp->tv_usec); 882 rt->tstamp = time; 883 nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ; 884} 885