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