|
|
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.