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