|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * 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 is only permitted until one year after the first shipment ! 9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 10: * binary forms are permitted provided that: (1) source distributions retain ! 11: * this entire copyright notice and comment, and (2) distributions including ! 12: * binaries display the following acknowledgement: This product includes ! 13: * software developed by the University of California, Berkeley and its ! 14: * contributors'' in the documentation or other materials provided with the ! 15: * distribution and in all advertising materials mentioning features or use ! 16: * of this software. Neither the name of the University nor the names of ! 17: * its contributors may be used to endorse or promote products derived from ! 18: * this software without specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: * ! 23: * @(#)nfs_syscalls.c 7.18 (Berkeley) 6/28/90 ! 24: */ ! 25: ! 26: #include "param.h" ! 27: #include "systm.h" ! 28: #include "user.h" ! 29: #include "kernel.h" ! 30: #include "file.h" ! 31: #include "stat.h" ! 32: #include "vnode.h" ! 33: #include "mount.h" ! 34: #include "proc.h" ! 35: #include "uio.h" ! 36: #include "malloc.h" ! 37: #include "buf.h" ! 38: #include "mbuf.h" ! 39: #include "socket.h" ! 40: #include "socketvar.h" ! 41: #include "domain.h" ! 42: #include "protosw.h" ! 43: #include "../netinet/in.h" ! 44: #include "../netinet/tcp.h" ! 45: #include "nfsv2.h" ! 46: #include "nfs.h" ! 47: #include "nfsrvcache.h" ! 48: ! 49: /* Global defs. */ ! 50: extern u_long nfs_prog, nfs_vers; ! 51: extern int (*nfsrv_procs[NFS_NPROCS])(); ! 52: extern struct buf nfs_bqueue; ! 53: extern int nfs_asyncdaemons; ! 54: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; ! 55: extern int nfs_tcpnodelay; ! 56: struct file *getsock(); ! 57: ! 58: #define TRUE 1 ! 59: #define FALSE 0 ! 60: ! 61: /* ! 62: * NFS server system calls ! 63: * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c ! 64: */ ! 65: ! 66: /* ! 67: * Get file handle system call ! 68: */ ! 69: /* ARGSUSED */ ! 70: getfh(p, uap, retval) ! 71: struct proc *p; ! 72: register struct args { ! 73: char *fname; ! 74: fhandle_t *fhp; ! 75: } *uap; ! 76: int *retval; ! 77: { ! 78: register struct nameidata *ndp = &u.u_nd; ! 79: register struct vnode *vp; ! 80: fhandle_t fh; ! 81: int error; ! 82: ! 83: /* ! 84: * Must be super user ! 85: */ ! 86: if (error = suser(ndp->ni_cred, &u.u_acflag)) ! 87: return (error); ! 88: ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; ! 89: ndp->ni_segflg = UIO_USERSPACE; ! 90: ndp->ni_dirp = uap->fname; ! 91: if (error = namei(ndp)) ! 92: return (error); ! 93: vp = ndp->ni_vp; ! 94: bzero((caddr_t)&fh, sizeof(fh)); ! 95: fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; ! 96: error = VFS_VPTOFH(vp, &fh.fh_fid); ! 97: vput(vp); ! 98: if (error) ! 99: return (error); ! 100: error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); ! 101: return (error); ! 102: } ! 103: ! 104: /* ! 105: * Nfs server psuedo system call for the nfsd's ! 106: * Never returns unless it fails or gets killed ! 107: */ ! 108: /* ARGSUSED */ ! 109: nfssvc(p, uap, retval) ! 110: struct proc *p; ! 111: register struct args { ! 112: int s; ! 113: caddr_t mskval; ! 114: int msklen; ! 115: caddr_t mtchval; ! 116: int mtchlen; ! 117: } *uap; ! 118: int *retval; ! 119: { ! 120: register struct mbuf *m; ! 121: register int siz; ! 122: register struct ucred *cr; ! 123: struct file *fp; ! 124: struct mbuf *mreq, *mrep, *nam, *md; ! 125: struct mbuf msk, mtch; ! 126: struct socket *so; ! 127: caddr_t dpos; ! 128: int procid, repstat, error, cacherep; ! 129: u_long retxid; ! 130: ! 131: /* ! 132: * Must be super user ! 133: */ ! 134: if (error = suser(u.u_cred, &u.u_acflag)) ! 135: goto bad; ! 136: fp = getsock(uap->s); ! 137: if (fp == 0) ! 138: return; ! 139: so = (struct socket *)fp->f_data; ! 140: if (sosendallatonce(so)) ! 141: siz = NFS_MAXPACKET; ! 142: else ! 143: siz = NFS_MAXPACKET + sizeof(u_long); ! 144: if (error = soreserve(so, siz, siz)) ! 145: goto bad; ! 146: if (error = sockargs(&nam, uap->mskval, uap->msklen, MT_SONAME)) ! 147: goto bad; ! 148: bcopy((caddr_t)nam, (caddr_t)&msk, sizeof (struct mbuf)); ! 149: msk.m_data = msk.m_dat; ! 150: m_freem(nam); ! 151: if (error = sockargs(&nam, uap->mtchval, uap->mtchlen, MT_SONAME)) ! 152: goto bad; ! 153: bcopy((caddr_t)nam, (caddr_t)&mtch, sizeof (struct mbuf)); ! 154: mtch.m_data = mtch.m_dat; ! 155: m_freem(nam); ! 156: ! 157: /* Copy the cred so others don't see changes */ ! 158: cr = u.u_cred = crcopy(u.u_cred); ! 159: ! 160: /* ! 161: * Set protocol specific options { for now TCP only } and ! 162: * reserve some space. For datagram sockets, this can get called ! 163: * repeatedly for the same socket, but that isn't harmful. ! 164: */ ! 165: if (so->so_proto->pr_flags & PR_CONNREQUIRED) { ! 166: MGET(m, M_WAIT, MT_SOOPTS); ! 167: *mtod(m, int *) = 1; ! 168: m->m_len = sizeof(int); ! 169: sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); ! 170: } ! 171: if (so->so_proto->pr_domain->dom_family == AF_INET && ! 172: so->so_proto->pr_protocol == IPPROTO_TCP && ! 173: nfs_tcpnodelay) { ! 174: MGET(m, M_WAIT, MT_SOOPTS); ! 175: *mtod(m, int *) = 1; ! 176: m->m_len = sizeof(int); ! 177: sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); ! 178: } ! 179: so->so_rcv.sb_flags &= ~SB_NOINTR; ! 180: so->so_rcv.sb_timeo = 0; ! 181: so->so_snd.sb_flags &= ~SB_NOINTR; ! 182: so->so_snd.sb_timeo = 0; ! 183: ! 184: /* ! 185: * Just loop around doin our stuff until SIGKILL ! 186: */ ! 187: for (;;) { ! 188: if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1, ! 189: &nam, &mrep, &md, &dpos, &retxid, &procid, cr, ! 190: &msk, &mtch)) { ! 191: if (nam) ! 192: m_freem(nam); ! 193: if (error == EPIPE || error == EINTR || ! 194: error == ERESTART) { ! 195: error = 0; ! 196: goto bad; ! 197: } ! 198: so->so_error = 0; ! 199: continue; ! 200: } ! 201: ! 202: if (nam) ! 203: cacherep = nfsrv_getcache(nam, retxid, procid, &mreq); ! 204: else ! 205: cacherep = RC_DOIT; ! 206: switch (cacherep) { ! 207: case RC_DOIT: ! 208: if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos, ! 209: cr, retxid, &mreq, &repstat)) { ! 210: nfsstats.srv_errs++; ! 211: if (nam) { ! 212: nfsrv_updatecache(nam, retxid, procid, ! 213: FALSE, repstat, mreq); ! 214: m_freem(nam); ! 215: } ! 216: break; ! 217: } ! 218: nfsstats.srvrpccnt[procid]++; ! 219: if (nam) ! 220: nfsrv_updatecache(nam, retxid, procid, TRUE, ! 221: repstat, mreq); ! 222: mrep = (struct mbuf *)0; ! 223: case RC_REPLY: ! 224: m = mreq; ! 225: siz = 0; ! 226: while (m) { ! 227: siz += m->m_len; ! 228: m = m->m_next; ! 229: } ! 230: if (siz <= 0 || siz > NFS_MAXPACKET) { ! 231: printf("mbuf siz=%d\n",siz); ! 232: panic("Bad nfs svc reply"); ! 233: } ! 234: mreq->m_pkthdr.len = siz; ! 235: mreq->m_pkthdr.rcvif = (struct ifnet *)0; ! 236: /* ! 237: * For non-atomic protocols, prepend a Sun RPC ! 238: * Record Mark. ! 239: */ ! 240: if (!sosendallatonce(so)) { ! 241: M_PREPEND(mreq, sizeof(u_long), M_WAIT); ! 242: *mtod(mreq, u_long *) = htonl(0x80000000 | siz); ! 243: } ! 244: error = nfs_send(so, nam, mreq, (struct nfsreq *)0); ! 245: if (nam) ! 246: m_freem(nam); ! 247: if (mrep) ! 248: m_freem(mrep); ! 249: if (error) { ! 250: if (error == EPIPE || error == EINTR || ! 251: error == ERESTART) ! 252: goto bad; ! 253: so->so_error = 0; ! 254: } ! 255: break; ! 256: case RC_DROPIT: ! 257: m_freem(mrep); ! 258: m_freem(nam); ! 259: break; ! 260: }; ! 261: } ! 262: bad: ! 263: return (error); ! 264: } ! 265: ! 266: /* ! 267: * Nfs pseudo system call for asynchronous i/o daemons. ! 268: * These babies just pretend to be disk interrupt service routines ! 269: * for client nfs. They are mainly here for read ahead/write behind. ! 270: * Never returns unless it fails or gets killed ! 271: */ ! 272: /* ARGSUSED */ ! 273: async_daemon(p, uap, retval) ! 274: struct proc *p; ! 275: struct args *uap; ! 276: int *retval; ! 277: { ! 278: register struct buf *bp, *dp; ! 279: int error; ! 280: int myiod; ! 281: ! 282: /* ! 283: * Must be super user ! 284: */ ! 285: if (error = suser(u.u_cred, &u.u_acflag)) ! 286: return (error); ! 287: /* ! 288: * Assign my position or return error if too many already running ! 289: */ ! 290: if (nfs_asyncdaemons > NFS_MAXASYNCDAEMON) ! 291: return (EBUSY); ! 292: myiod = nfs_asyncdaemons++; ! 293: dp = &nfs_bqueue; ! 294: /* ! 295: * Just loop around doin our stuff until SIGKILL ! 296: */ ! 297: for (;;) { ! 298: while (dp->b_actf == NULL) { ! 299: nfs_iodwant[myiod] = p; ! 300: if (error = tsleep((caddr_t)&nfs_iodwant[myiod], ! 301: PWAIT | PCATCH, "nfsidl", 0)) ! 302: return (error); ! 303: } ! 304: /* Take one off the end of the list */ ! 305: bp = dp->b_actl; ! 306: if (bp->b_actl == dp) { ! 307: dp->b_actf = dp->b_actl = (struct buf *)0; ! 308: } else { ! 309: dp->b_actl = bp->b_actl; ! 310: bp->b_actl->b_actf = dp; ! 311: } ! 312: (void) nfs_doio(bp); ! 313: } ! 314: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.