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