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