lint
[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 *
0bd503ad 20 * @(#)nfs_syscalls.c 7.4 (Berkeley) %G%
a2907882
KM
21 */
22
23#include "param.h"
24#include "systm.h"
25#include "user.h"
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"
38#include "nfsv2.h"
39#include "nfs.h"
40
41/* Global defs. */
42extern u_long nfs_prog, nfs_vers;
43extern int (*nfsrv_procs[NFS_NPROCS])();
9238aa59 44extern struct buf nfs_bqueue;
ffe6f482
KM
45extern int nfs_asyncdaemons;
46extern struct proc *nfs_iodwant[MAX_ASYNCDAEMON];
a2907882
KM
47struct file *getsock();
48
49/*
50 * NFS server system calls
51 * getfh() lives here too, but maybe should move to kern/vfs_syscalls.c
52 */
53#define RETURN(value) { u.u_error = (value); return; }
54
55/*
56 * Get file handle system call
57 */
58getfh()
59{
60 register struct a {
61 char *fname;
62 fhandle_t *fhp;
63 } *uap = (struct a *)u.u_ap;
64 register struct nameidata *ndp = &u.u_nd;
65 register struct vnode *vp;
66 fhandle_t fh;
67 int error;
68
69 /*
70 * Must be super user
71 */
72 if (error = suser(u.u_cred, &u.u_acflag))
73 RETURN (error);
74 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW;
75 ndp->ni_segflg = UIO_USERSPACE;
76 ndp->ni_dirp = uap->fname;
77 if (error = namei(ndp))
78 RETURN (error);
79 vp = ndp->ni_vp;
80 bzero((caddr_t)&fh, sizeof(fh));
81 fh.fh_fsid = vp->v_mount->m_fsid;
82 error = VFS_VPTOFH(vp, &fh.fh_fid);
83 vput(vp);
84 if (error)
85 RETURN (error);
86 error = copyout((caddr_t)&fh, (caddr_t)uap->fhp, sizeof (fh));
87 RETURN (error);
88}
89
90/*
91 * Mark a mount point in the filesystem exported
92 */
93exportfs()
94{
95 register struct a {
96 char *fname;
97 int rootuid;
98 int exflags;
99 } *uap = (struct a *)u.u_ap;
100 register struct nameidata *ndp = &u.u_nd;
101 register struct vnode *vp;
102 register struct mount *mp;
103 int error;
104
105 /*
106 * Must be super user
107 */
108 if (error = suser(u.u_cred, &u.u_acflag))
109 RETURN (error);
110 ndp->ni_nameiop = LOOKUP | LOCKLEAF | FOLLOW; /* Or NOFOLLOW ?? */
111 ndp->ni_segflg = UIO_USERSPACE;
112 ndp->ni_dirp = uap->fname;
113 if (error = namei(ndp))
114 RETURN (error);
115 vp = ndp->ni_vp;
116 if (vp->v_type != VDIR) {
117 vput(vp);
118 RETURN (ENOENT);
119 }
120 mp = vp->v_mount;
121
122 /*
123 * If the filesystem has already been exported, just relax
124 * security as required.
125 * Otherwise export it with the given security
126 */
127 if (mp->m_flag & M_EXPORTED) {
128 if (uap->rootuid == 0)
129 mp->m_exroot = 0;
130 if ((uap->exflags & M_EXRDONLY) == 0)
131 mp->m_flag &= ~M_EXRDONLY;
132 } else {
133 mp->m_exroot = uap->rootuid;
134 if (uap->exflags & M_EXRDONLY)
135 mp->m_flag |= M_EXRDONLY;
136 mp->m_flag |= M_EXPORTED;
137 }
138 vput(vp);
139 RETURN (0);
140}
141
142/*
143 * Nfs server psuedo system call for the nfsd's
144 * Never returns unless it fails or gets killed
145 */
146nfssvc()
147{
148 register struct a {
149 int s;
150 } *uap = (struct a *)u.u_ap;
151 register struct mbuf *m;
152 register int siz;
153 register struct ucred *cr;
154 struct file *fp;
155 struct mbuf *mreq, *mrep, *nam, *md;
156 struct socket *so;
157 caddr_t dpos;
0bd503ad 158 int procid;
a2907882
KM
159 u_long retxid;
160 int error;
161
162 /*
163 * Must be super user
164 */
165 if (error = suser(u.u_cred, &u.u_acflag))
166 RETURN (error);
167 fp = getsock(uap->s);
168 if (fp == 0)
169 return;
170 so = (struct socket *)fp->f_data;
171 cr = u.u_cred = crcopy(u.u_cred); /* Copy it so others don't see changes */
172 /*
173 * Just loop arround doin our stuff until SIGKILL
174 */
175 for (;;) {
176 if (error = nfs_getreq(so, nfs_prog, nfs_vers, NFS_NPROCS-1,
0bd503ad 177 &nam, &mrep, &md, &dpos, &retxid, &procid, cr)) {
a2907882
KM
178 m_freem(nam);
179 continue;
180 }
0bd503ad 181 if (error = (*(nfsrv_procs[procid]))(mrep, md, dpos,
a2907882
KM
182 cr, retxid, &mreq)) {
183 m_freem(nam);
184 nfsstats.srv_errs++;
185 continue;
186 } else
0bd503ad 187 nfsstats.srvrpccnt[procid]++;
a2907882
KM
188 m = mreq;
189 siz = 0;
190 while (m) {
191 siz += m->m_len;
192 m = m->m_next;
193 }
194 if (siz <= 0 || siz > 9216) {
195 printf("mbuf siz=%d\n",siz);
196 panic("Bad nfs svc reply");
197 }
198 error = nfs_udpsend(so, nam, mreq, 0, siz);
199 m_freem(nam);
200 }
201}
9238aa59 202
9238aa59
RM
203/*
204 * Nfs pseudo system call for asynchronous i/o daemons.
205 * These babies just pretend to be disk interrupt service routines
ffe6f482 206 * for client nfs. They are mainly here for read ahead/write behind.
9238aa59
RM
207 * Never returns unless it fails or gets killed
208 */
209async_daemon()
210{
211 register struct buf *bp, *dp;
212 int error;
ffe6f482 213 int myiod;
9238aa59
RM
214
215 /*
216 * Must be super user
217 */
218 if (error = suser(u.u_cred, &u.u_acflag))
219 RETURN (error);
ffe6f482
KM
220 /*
221 * Assign my position or return error if too many already running
222 */
223 if (nfs_asyncdaemons > MAX_ASYNCDAEMON)
224 RETURN (EBUSY);
225 myiod = nfs_asyncdaemons++;
9238aa59
RM
226 dp = &nfs_bqueue;
227 /*
ffe6f482 228 * Just loop around doin our stuff until SIGKILL
9238aa59
RM
229 */
230 for (;;) {
231 while (dp->b_actf == NULL) {
ffe6f482
KM
232 nfs_iodwant[myiod] = u.u_procp;
233 sleep((caddr_t)&nfs_iodwant[myiod], PZERO+1);
9238aa59
RM
234 }
235 /* Take one off the end of the list */
236 bp = dp->b_actl;
237 if (bp->b_actl == dp) {
238 dp->b_actf = dp->b_actl = (struct buf *)0;
239 } else {
240 dp->b_actl = bp->b_actl;
241 bp->b_actl->b_actf = dp;
242 }
243 (void) nfs_doio(bp);
244 }
245}