Commit | Line | Data |
---|---|---|
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. */ | |
42 | extern u_long nfs_prog, nfs_vers; | |
43 | extern int (*nfsrv_procs[NFS_NPROCS])(); | |
9238aa59 | 44 | extern struct buf nfs_bqueue; |
ffe6f482 KM |
45 | extern int nfs_asyncdaemons; |
46 | extern struct proc *nfs_iodwant[MAX_ASYNCDAEMON]; | |
a2907882 KM |
47 | struct 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 | */ | |
58 | getfh() | |
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 | */ | |
93 | exportfs() | |
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 | */ | |
146 | nfssvc() | |
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 | */ | |
209 | async_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 | } |