|
|
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 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 7.26 (Berkeley) 4/16/91 ! 37: */ ! 38: ! 39: #include "param.h" ! 40: #include "systm.h" ! 41: #include "kernel.h" ! 42: #include "file.h" ! 43: #include "stat.h" ! 44: #include "namei.h" ! 45: #include "vnode.h" ! 46: #include "mount.h" ! 47: #include "proc.h" ! 48: #include "malloc.h" ! 49: #include "buf.h" ! 50: #include "mbuf.h" ! 51: #include "socket.h" ! 52: #include "socketvar.h" ! 53: #include "domain.h" ! 54: #include "protosw.h" ! 55: ! 56: #include "../netinet/in.h" ! 57: #include "../netinet/tcp.h" ! 58: ! 59: #include "nfsv2.h" ! 60: #include "nfs.h" ! 61: #include "nfsrvcache.h" ! 62: ! 63: /* Global defs. */ ! 64: extern u_long nfs_prog, nfs_vers; ! 65: extern int (*nfsrv_procs[NFS_NPROCS])(); ! 66: extern struct buf nfs_bqueue; ! 67: extern int nfs_numasync; ! 68: extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; ! 69: extern int nfs_tcpnodelay; ! 70: struct mbuf *nfs_compress(); ! 71: ! 72: #define TRUE 1 ! 73: #define FALSE 0 ! 74: ! 75: static int nfs_asyncdaemon[NFS_MAXASYNCDAEMON]; ! 76: static int compressreply[NFS_NPROCS] = { ! 77: FALSE, ! 78: TRUE, ! 79: TRUE, ! 80: FALSE, ! 81: TRUE, ! 82: TRUE, ! 83: FALSE, ! 84: FALSE, ! 85: TRUE, ! 86: TRUE, ! 87: TRUE, ! 88: TRUE, ! 89: TRUE, ! 90: TRUE, ! 91: TRUE, ! 92: TRUE, ! 93: TRUE, ! 94: TRUE, ! 95: }; ! 96: /* ! 97: * NFS server system calls ! 98: * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c ! 99: */ ! 100: ! 101: /* ! 102: * Get file handle system call ! 103: */ ! 104: /* ARGSUSED */ ! 105: getfh(p, uap, retval) ! 106: struct proc *p; ! 107: register struct args { ! 108: char *fname; ! 109: fhandle_t *fhp; ! 110: } *uap; ! 111: int *retval; ! 112: { ! 113: register struct nameidata *ndp; ! 114: register struct vnode *vp; ! 115: fhandle_t fh; ! 116: int error; ! 117: struct nameidata nd; ! 118: ! 119: /* ! 120: * Must be super user ! 121: */ ! 122: if (error = suser(p->p_ucred, &p->p_acflag)) ! 123: return (error); ! 124: ndp = &nd; ! 125: ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; ! 126: ndp->ni_segflg = UIO_USERSPACE; ! 127: ndp->ni_dirp = uap->fname; ! 128: if (error = namei(ndp, p)) ! 129: return (error); ! 130: vp = ndp->ni_vp; ! 131: bzero((caddr_t)&fh, sizeof(fh)); ! 132: fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; ! 133: error = VFS_VPTOFH(vp, &fh.fh_fid); ! 134: vput(vp); ! 135: if (error) ! 136: return (error); ! 137: error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh)); ! 138: return (error); ! 139: } ! 140: ! 141: /* ! 142: * Nfs server psuedo system call for the nfsd's ! 143: * Never returns unless it fails or gets killed ! 144: */ ! 145: /* ARGSUSED */ ! 146: nfssvc(p, uap, retval) ! 147: struct proc *p; ! 148: register struct args { ! 149: int s; ! 150: caddr_t mskval; ! 151: int msklen; ! 152: caddr_t mtchval; ! 153: int mtchlen; ! 154: } *uap; ! 155: int *retval; ! 156: { ! 157: register struct mbuf *m; ! 158: register int siz; ! 159: register struct ucred *cr; ! 160: struct file *fp; ! 161: struct mbuf *mreq, *mrep, *nam, *md; ! 162: struct mbuf msk, mtch; ! 163: struct socket *so; ! 164: caddr_t dpos; ! 165: int procid, repstat, error, cacherep, wascomp; ! 166: u_long retxid; ! 167: ! 168: /* ! 169: * Must be super user ! 170: */ ! 171: if (error = suser(p->p_ucred, &p->p_acflag)) ! 172: return (error); ! 173: if (error = getsock(p->p_fd, uap->s, &fp)) ! 174: return (error); ! 175: so = (struct socket *)fp->f_data; ! 176: if (sosendallatonce(so)) ! 177: siz = NFS_MAXPACKET; ! 178: else ! 179: siz = NFS_MAXPACKET + sizeof(u_long); ! 180: if (error = soreserve(so, siz, siz)) ! 181: goto bad; ! 182: if (error = sockargs(&nam, uap->mskval, uap->msklen, MT_SONAME)) ! 183: goto bad; ! 184: bcopy((caddr_t)nam, (caddr_t)&msk, sizeof (struct mbuf)); ! 185: msk.m_data = msk.m_dat; ! 186: m_freem(nam); ! 187: if (error = sockargs(&nam, uap->mtchval, uap->mtchlen, MT_SONAME)) ! 188: goto bad; ! 189: bcopy((caddr_t)nam, (caddr_t)&mtch, sizeof (struct mbuf)); ! 190: mtch.m_data = mtch.m_dat; ! 191: m_freem(nam); ! 192: ! 193: /* Copy the cred so others don't see changes */ ! 194: cr = p->p_ucred = crcopy(p->p_ucred); ! 195: ! 196: /* ! 197: * Set protocol specific options { for now TCP only } and ! 198: * reserve some space. For datagram sockets, this can get called ! 199: * repeatedly for the same socket, but that isn't harmful. ! 200: */ ! 201: if (so->so_proto->pr_flags & PR_CONNREQUIRED) { ! 202: MGET(m, M_WAIT, MT_SOOPTS); ! 203: *mtod(m, int *) = 1; ! 204: m->m_len = sizeof(int); ! 205: sosetopt(so, SOL_SOCKET, SO_KEEPALIVE, m); ! 206: } ! 207: if (so->so_proto->pr_domain->dom_family == AF_INET && ! 208: so->so_proto->pr_protocol == IPPROTO_TCP && ! 209: nfs_tcpnodelay) { ! 210: MGET(m, M_WAIT, MT_SOOPTS); ! 211: *mtod(m, int *) = 1; ! 212: m->m_len = sizeof(int); ! 213: sosetopt(so, IPPROTO_TCP, TCP_NODELAY, m); ! 214: } ! 215: so->so_rcv.sb_flags &= ~SB_NOINTR; ! 216: so->so_rcv.sb_timeo = 0; ! 217: so->so_snd.sb_flags &= ~SB_NOINTR; ! 218: so->so_snd.sb_timeo = 0; ! 219: ! 220: /* ! 221: * Just loop around doin our stuff until SIGKILL ! 222: */ ! 223: for (;;) { ! 224: if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1, ! 225: &nam, &mrep, &md, &dpos, &retxid, &procid, cr, ! 226: &msk, &mtch, &wascomp)) { ! 227: if (nam) ! 228: m_freem(nam); ! 229: if (error == EPIPE || error == EINTR || ! 230: error == ERESTART) { ! 231: error = 0; ! 232: goto bad; ! 233: } ! 234: so->so_error = 0; ! 235: continue; ! 236: } ! 237: ! 238: if (nam) ! 239: cacherep = nfsrv_getcache(nam, retxid, procid, &mreq); ! 240: else ! 241: cacherep = RC_DOIT; ! 242: switch (cacherep) { ! 243: case RC_DOIT: ! 244: if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos, ! 245: cr, retxid, &mreq, &repstat, p)) { ! 246: nfsstats.srv_errs++; ! 247: if (nam) { ! 248: nfsrv_updatecache(nam, retxid, procid, ! 249: FALSE, repstat, mreq); ! 250: m_freem(nam); ! 251: } ! 252: break; ! 253: } ! 254: nfsstats.srvrpccnt[procid]++; ! 255: if (nam) ! 256: nfsrv_updatecache(nam, retxid, procid, TRUE, ! 257: repstat, mreq); ! 258: mrep = (struct mbuf *)0; ! 259: case RC_REPLY: ! 260: m = mreq; ! 261: siz = 0; ! 262: while (m) { ! 263: siz += m->m_len; ! 264: m = m->m_next; ! 265: } ! 266: if (siz <= 0 || siz > NFS_MAXPACKET) { ! 267: printf("mbuf siz=%d\n",siz); ! 268: panic("Bad nfs svc reply"); ! 269: } ! 270: mreq->m_pkthdr.len = siz; ! 271: mreq->m_pkthdr.rcvif = (struct ifnet *)0; ! 272: if (wascomp && compressreply[procid]) { ! 273: mreq = nfs_compress(mreq); ! 274: siz = mreq->m_pkthdr.len; ! 275: } ! 276: /* ! 277: * For non-atomic protocols, prepend a Sun RPC ! 278: * Record Mark. ! 279: */ ! 280: if (!sosendallatonce(so)) { ! 281: M_PREPEND(mreq, sizeof(u_long), M_WAIT); ! 282: *mtod(mreq, u_long *) = htonl(0x80000000 | siz); ! 283: } ! 284: error = nfs_send(so, nam, mreq, (struct nfsreq *)0); ! 285: if (nam) ! 286: m_freem(nam); ! 287: if (mrep) ! 288: m_freem(mrep); ! 289: if (error) { ! 290: if (error == EPIPE || error == EINTR || ! 291: error == ERESTART) ! 292: goto bad; ! 293: so->so_error = 0; ! 294: } ! 295: break; ! 296: case RC_DROPIT: ! 297: m_freem(mrep); ! 298: m_freem(nam); ! 299: break; ! 300: }; ! 301: } ! 302: bad: ! 303: return (error); ! 304: } ! 305: ! 306: /* ! 307: * Nfs pseudo system call for asynchronous i/o daemons. ! 308: * These babies just pretend to be disk interrupt service routines ! 309: * for client nfs. They are mainly here for read ahead/write behind. ! 310: * Never returns unless it fails or gets killed ! 311: */ ! 312: /* ARGSUSED */ ! 313: async_daemon(p, uap, retval) ! 314: struct proc *p; ! 315: struct args *uap; ! 316: int *retval; ! 317: { ! 318: register struct buf *bp, *dp; ! 319: register int i, myiod; ! 320: int error; ! 321: ! 322: /* ! 323: * Must be super user ! 324: */ ! 325: if (error = suser(p->p_ucred, &p->p_acflag)) ! 326: return (error); ! 327: /* ! 328: * Assign my position or return error if too many already running ! 329: */ ! 330: myiod = -1; ! 331: for (i = 0; i < NFS_MAXASYNCDAEMON; i++) ! 332: if (nfs_asyncdaemon[i] == 0) { ! 333: nfs_asyncdaemon[i]++; ! 334: myiod = i; ! 335: break; ! 336: } ! 337: if (myiod == -1) ! 338: return (EBUSY); ! 339: nfs_numasync++; ! 340: dp = &nfs_bqueue; ! 341: /* ! 342: * Just loop around doin our stuff until SIGKILL ! 343: */ ! 344: for (;;) { ! 345: while (dp->b_actf == NULL && error == 0) { ! 346: nfs_iodwant[myiod] = p; ! 347: error = tsleep((caddr_t)&nfs_iodwant[myiod], ! 348: PWAIT | PCATCH, "nfsidl", 0); ! 349: nfs_iodwant[myiod] = (struct proc *)0; ! 350: } ! 351: while (dp->b_actf != NULL) { ! 352: /* Take one off the end of the list */ ! 353: bp = dp->b_actl; ! 354: if (bp->b_actl == dp) { ! 355: dp->b_actf = dp->b_actl = (struct buf *)0; ! 356: } else { ! 357: dp->b_actl = bp->b_actl; ! 358: bp->b_actl->b_actf = dp; ! 359: } ! 360: (void) nfs_doio(bp); ! 361: } ! 362: if (error) { ! 363: nfs_asyncdaemon[myiod] = 0; ! 364: nfs_numasync--; ! 365: return (error); ! 366: } ! 367: } ! 368: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.