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