Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * OpenBSD specific assistance routines & VFS ops | |
3 | * Original NetBSD version for Transarc afs by John Kohl <jtk@MIT.EDU> | |
4 | * OpenBSD version by Jim Rees <rees@umich.edu> | |
5 | * | |
6 | * $Id$ | |
7 | */ | |
8 | ||
9 | /* | |
10 | copyright 2002 | |
11 | the regents of the university of michigan | |
12 | all rights reserved | |
13 | ||
14 | permission is granted to use, copy, create derivative works | |
15 | and redistribute this software and such derivative works | |
16 | for any purpose, so long as the name of the university of | |
17 | michigan is not used in any advertising or publicity | |
18 | pertaining to the use or distribution of this software | |
19 | without specific, written prior authorization. if the | |
20 | above copyright notice or any other identification of the | |
21 | university of michigan is included in any copy of any | |
22 | portion of this software, then the disclaimer below must | |
23 | also be included. | |
24 | ||
25 | this software is provided as is, without representation | |
26 | from the university of michigan as to its fitness for any | |
27 | purpose, and without warranty by the university of | |
28 | michigan of any kind, either express or implied, including | |
29 | without limitation the implied warranties of | |
30 | merchantability and fitness for a particular purpose. the | |
31 | regents of the university of michigan shall not be liable | |
32 | for any damages, including special, indirect, incidental, or | |
33 | consequential damages, with respect to any claim arising | |
34 | out of or in connection with the use of the software, even | |
35 | if it has been or is hereafter advised of the possibility of | |
36 | such damages. | |
37 | */ | |
38 | ||
39 | /* | |
40 | Copyright 1995 Massachusetts Institute of Technology. All Rights | |
41 | Reserved. | |
42 | ||
43 | You are hereby granted a worldwide, irrevocable, paid-up, right and | |
44 | license to use, execute, display, modify, copy and distribute MIT's | |
45 | Modifications, provided that (i) you abide by the terms and conditions | |
46 | of the OpenAFS License Agreement, and (ii) you do not use the name | |
47 | of MIT in any advertising or publicity without the prior written consent | |
48 | of MIT. MIT disclaims all liability for your use of MIT's | |
49 | Modifications. MIT's Modifications are provided "AS IS" WITHOUT | |
50 | WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, | |
51 | ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR | |
52 | NONINFRINGEMENT. | |
53 | */ | |
54 | ||
55 | /* | |
56 | * Some code cribbed from ffs_vfsops and other NetBSD sources, which | |
57 | * are marked: | |
58 | */ | |
59 | /* | |
60 | * Copyright (c) 1989, 1991, 1993, 1994 | |
61 | * The Regents of the University of California. All rights reserved. | |
62 | * | |
63 | * Redistribution and use in source and binary forms, with or without | |
64 | * modification, are permitted provided that the following conditions | |
65 | * are met: | |
66 | * 1. Redistributions of source code must retain the above copyright | |
67 | * notice, this list of conditions and the following disclaimer. | |
68 | * 2. Redistributions in binary form must reproduce the above copyright | |
69 | * notice, this list of conditions and the following disclaimer in the | |
70 | * documentation and/or other materials provided with the distribution. | |
71 | * 3. All advertising materials mentioning features or use of this software | |
72 | * must display the following acknowledgement: | |
73 | * This product includes software developed by the University of | |
74 | * California, Berkeley and its contributors. | |
75 | * 4. Neither the name of the University nor the names of its contributors | |
76 | * may be used to endorse or promote products derived from this software | |
77 | * without specific prior written permission. | |
78 | * | |
79 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
80 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
81 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
82 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
83 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
84 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
85 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
86 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
87 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
88 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
89 | * SUCH DAMAGE. | |
90 | * | |
91 | */ | |
92 | ||
93 | #include <afsconfig.h> | |
94 | #include "afs/param.h" | |
95 | ||
96 | ||
97 | #include "afs/sysincludes.h" /* Standard vendor system headers */ | |
98 | #include "afs/afsincludes.h" /* Afs-based standard headers */ | |
99 | #include "afs/afs_stats.h" /* statistics */ | |
100 | ||
101 | #include <sys/conf.h> | |
102 | #include <sys/exec.h> | |
103 | #include <sys/lkm.h> | |
104 | #include <sys/namei.h> | |
105 | #include <sys/syscall.h> | |
106 | #include <sys/syscallargs.h> | |
107 | ||
108 | /* from /usr/src/sys/kern/vfs_subr.c */ | |
109 | extern void insmntque(struct vnode *, struct mount *); | |
110 | ||
111 | extern int sys_lkmnosys(), afs_xioctl(), Afs_xsetgroups(); | |
112 | ||
113 | static int lkmid = -1; | |
114 | static int afs_badcall(struct proc *p, void *xx, register_t * yy); | |
115 | static struct sysent old_sysent; | |
116 | ||
117 | struct osi_vfs *afs_globalVFS; | |
118 | struct vcache *afs_globalVp; | |
119 | ||
120 | int afs_quotactl(); | |
121 | int afs_fhtovp(); | |
122 | int afs_vptofh(); | |
123 | int afsinit(); | |
124 | int afs_start(); | |
125 | int afs_mount(); | |
126 | int afs_unmount(); | |
127 | int afs_root(); | |
128 | int afs_statfs(); | |
129 | int afs_sync(); | |
130 | int afs_vget(); | |
131 | int afs_sysctl(); | |
132 | int afs_checkexp(); | |
133 | ||
134 | struct vfsops afs_vfsops = { | |
135 | afs_mount, | |
136 | afs_start, | |
137 | afs_unmount, | |
138 | afs_root, | |
139 | afs_quotactl, | |
140 | afs_statfs, | |
141 | afs_sync, | |
142 | afs_vget, | |
143 | afs_fhtovp, | |
144 | afs_vptofh, | |
145 | afsinit, | |
146 | afs_sysctl, | |
147 | afs_checkexp, | |
148 | }; | |
149 | ||
150 | int | |
151 | afs_obsd_lookupname(char *fnamep, enum uio_seg segflg, int followlink, | |
152 | struct vnode **compvpp) | |
153 | { | |
154 | struct nameidata nd; | |
155 | int niflag; | |
156 | int error; | |
157 | ||
158 | /* | |
159 | * Lookup pathname "fnamep", returning leaf in *compvpp. segflg says | |
160 | * whether the pathname is user or system space. | |
161 | */ | |
162 | /* XXX LOCKLEAF ? */ | |
163 | niflag = followlink ? FOLLOW : NOFOLLOW; | |
164 | NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc()); | |
165 | if ((error = namei(&nd))) | |
166 | return error; | |
167 | *compvpp = nd.ni_vp; | |
168 | return error; | |
169 | } | |
170 | ||
171 | int | |
172 | afs_quotactl() | |
173 | { | |
174 | return EOPNOTSUPP; | |
175 | } | |
176 | ||
177 | int | |
178 | afs_sysctl() | |
179 | { | |
180 | return EOPNOTSUPP; | |
181 | } | |
182 | ||
183 | int | |
184 | afs_checkexp() | |
185 | { | |
186 | return EOPNOTSUPP; | |
187 | } | |
188 | ||
189 | int | |
190 | afs_fhtovp(mp, fhp, vpp) | |
191 | struct mount *mp; | |
192 | struct fid *fhp; | |
193 | struct vnode **vpp; | |
194 | { | |
195 | ||
196 | return (EINVAL); | |
197 | } | |
198 | ||
199 | int | |
200 | afs_vptofh(vp, fhp) | |
201 | struct vnode *vp; | |
202 | struct fid *fhp; | |
203 | { | |
204 | ||
205 | return (EINVAL); | |
206 | } | |
207 | ||
208 | int | |
209 | afs_start(mp, flags, p) | |
210 | struct mount *mp; | |
211 | int flags; | |
212 | struct proc *p; | |
213 | { | |
214 | return (0); /* nothing to do. ? */ | |
215 | } | |
216 | ||
217 | int | |
218 | afs_mount(mp, path, data, ndp, p) | |
219 | struct mount *mp; | |
220 | char *path; | |
221 | caddr_t data; | |
222 | struct nameidata *ndp; | |
223 | struct proc *p; | |
224 | { | |
225 | /* ndp contains the mounted-from device. Just ignore it. | |
226 | * we also don't care about our proc struct. */ | |
227 | int size; | |
228 | ||
229 | if (mp->mnt_flag & MNT_UPDATE) | |
230 | return EINVAL; | |
231 | ||
232 | if (afs_globalVFS) { | |
233 | /* Don't allow remounts */ | |
234 | return EBUSY; | |
235 | } | |
236 | ||
237 | AFS_STATCNT(afs_mount); | |
238 | AFS_GLOCK(); | |
239 | ||
240 | /* initialize the vcache entries before we start using them */ | |
241 | ||
242 | /* XXX find a better place for this if possible */ | |
243 | afs_globalVFS = mp; | |
244 | mp->osi_vfs_bsize = 8192; | |
245 | mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC; /* magic */ | |
246 | mp->osi_vfs_fsid.val[1] = (int)AFS_VFSFSID; | |
247 | ||
248 | #if defined(AFS_OBSD53_ENV) | |
249 | bzero(mp->mnt_stat.f_mntonname, MNAMELEN); | |
250 | strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN); | |
251 | #else | |
252 | (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); | |
253 | bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size); | |
254 | #endif | |
255 | bzero(mp->mnt_stat.f_mntfromname, MNAMELEN); | |
256 | strcpy(mp->mnt_stat.f_mntfromname, "AFS"); | |
257 | /* null terminated string "AFS" will fit, just leave it be. */ | |
258 | strcpy(mp->mnt_stat.f_fstypename, MOUNT_AFS); | |
259 | AFS_GUNLOCK(); | |
260 | (void)afs_statfs(mp, &mp->mnt_stat); | |
261 | ||
262 | return 0; | |
263 | } | |
264 | ||
265 | int | |
266 | afs_unmount(afsp, flags, p) | |
267 | struct mount *afsp; | |
268 | int flags; | |
269 | struct proc *p; | |
270 | { | |
271 | extern int sys_ioctl(), sys_setgroups(); | |
272 | ||
273 | struct vnode *vp; | |
274 | ||
275 | for (vp = LIST_FIRST(&afsp->mnt_vnodelist); vp != NULL; | |
276 | vp = LIST_NEXT(vp, v_mntvnodes)) { | |
277 | if (vp->v_usecount) return EBUSY; | |
278 | } | |
279 | ||
280 | AFS_STATCNT(afs_unmount); | |
281 | if (afs_globalVFS == NULL) { | |
282 | printf("afs already unmounted\n"); | |
283 | return 0; | |
284 | } | |
285 | if (afs_globalVp) | |
286 | vrele(AFSTOV(afs_globalVp)); | |
287 | afs_globalVp = NULL; | |
288 | ||
289 | vflush(afsp, NULLVP, 0); /* don't support forced */ | |
290 | afsp->mnt_data = NULL; | |
291 | AFS_GLOCK(); | |
292 | afs_globalVFS = 0; | |
293 | afs_cold_shutdown = 1; | |
294 | afs_shutdown(); /* XXX */ | |
295 | AFS_GUNLOCK(); | |
296 | ||
297 | /* give up syscall entries for ioctl & setgroups, which we've stolen */ | |
298 | sysent[SYS_ioctl].sy_call = sys_ioctl; | |
299 | sysent[SYS_setgroups].sy_call = sys_setgroups; | |
300 | ||
301 | /* give up the stolen syscall entry */ | |
302 | sysent[AFS_SYSCALL].sy_narg = 0; | |
303 | sysent[AFS_SYSCALL].sy_argsize = 0; | |
304 | sysent[AFS_SYSCALL].sy_call = afs_badcall; | |
305 | printf | |
306 | ("AFS unmounted--use `/sbin/modunload -i %d' to unload before restarting AFS\n", | |
307 | lkmid); | |
308 | return 0; | |
309 | } | |
310 | ||
311 | static int | |
312 | afs_badcall(struct proc *p, void *xx, register_t * yy) | |
313 | { | |
314 | return ENOSYS; | |
315 | } | |
316 | ||
317 | #if defined(AFS_OBSD49_ENV) | |
318 | extern struct vops afs_vops; | |
319 | #endif | |
320 | ||
321 | void | |
322 | afs_obsd_getnewvnode(struct vcache *tvc) | |
323 | { | |
324 | #if defined(AFS_OBSD49_ENV) | |
325 | while (getnewvnode(VT_AFS, afs_globalVFS, &afs_vops, &tvc->v)) { | |
326 | #else | |
327 | while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) { | |
328 | #endif | |
329 | /* no vnodes available, force an alloc (limits be damned)! */ | |
330 | desiredvnodes++; | |
331 | } | |
332 | tvc->v->v_data = (void *)tvc; | |
333 | } | |
334 | ||
335 | int | |
336 | afs_root(struct mount *mp, struct vnode **vpp) | |
337 | { | |
338 | struct vrequest treq; | |
339 | struct vcache *tvp; | |
340 | int code; | |
341 | ||
342 | AFS_STATCNT(afs_root); | |
343 | ||
344 | AFS_GLOCK(); | |
345 | if (!(code = afs_InitReq(&treq, osi_curcred())) | |
346 | && !(code = afs_CheckInit())) { | |
347 | tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL); | |
348 | if (tvp) { | |
349 | /* There is really no reason to over-hold this bugger--it's held | |
350 | * by the root filesystem reference. */ | |
351 | if (afs_globalVp != tvp) { | |
352 | #ifdef AFS_DONT_OVERHOLD_GLOBALVP | |
353 | if (afs_globalVp) | |
354 | AFS_RELE(AFSTOV(afs_globalVp)); | |
355 | #endif | |
356 | afs_globalVp = tvp; | |
357 | vref(AFSTOV(afs_globalVp)); | |
358 | } | |
359 | AFSTOV(tvp)->v_flag |= VROOT; | |
360 | afs_globalVFS = mp; | |
361 | *vpp = AFSTOV(tvp); | |
362 | } else | |
363 | code = EIO; | |
364 | } | |
365 | AFS_GUNLOCK(); | |
366 | ||
367 | if (!code) | |
368 | vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curproc); /* return it locked */ | |
369 | return code; | |
370 | } | |
371 | ||
372 | int | |
373 | afs_statfs(struct osi_vfs *afsp, struct statfs *abp) | |
374 | { | |
375 | AFS_STATCNT(afs_statfs); | |
376 | abp->f_bsize = afsp->osi_vfs_bsize; | |
377 | ||
378 | abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files = | |
379 | abp->f_ffree = AFS_VFS_FAKEFREE; | |
380 | abp->f_fsid.val[0] = AFS_VFSMAGIC; /* magic */ | |
381 | abp->f_fsid.val[1] = (int)AFS_VFSFSID; | |
382 | return 0; | |
383 | } | |
384 | ||
385 | int | |
386 | afs_sync(struct osi_vfs *afsp) | |
387 | { | |
388 | AFS_STATCNT(afs_sync); | |
389 | return 0; | |
390 | } | |
391 | ||
392 | int | |
393 | afs_vget(vp, lfl) | |
394 | struct vnode *vp; | |
395 | int lfl; | |
396 | { | |
397 | int error; | |
398 | ||
399 | if (vp->v_usecount < 0) { | |
400 | vprint("bad usecount", vp); | |
401 | panic("afs_vget"); | |
402 | } | |
403 | error = vget(vp, lfl, curproc); | |
404 | if (!error && vp->v_usecount == 1) { | |
405 | /* vget() took it off the freelist; put it on our mount queue */ | |
406 | insmntque(vp, afs_globalVFS); | |
407 | } | |
408 | return error; | |
409 | } | |
410 | ||
411 | extern struct vfsops afs_vfsops; | |
412 | extern struct vnodeopv_desc afs_vnodeop_opv_desc; | |
413 | ||
414 | static struct vfsconf afs_vfsconf = { | |
415 | &afs_vfsops, | |
416 | "afs", | |
417 | 0, | |
418 | 0, | |
419 | 0, | |
420 | NULL, | |
421 | NULL, | |
422 | }; | |
423 | ||
424 | MOD_VFS("afs", 0, &afs_vfsconf); | |
425 | ||
426 | static char afsgenmem[] = "afsgenmem"; | |
427 | static char afsfidmem[] = "afsfidmem"; | |
428 | static char afsbhdrmem[] = "afsbhdrmem"; | |
429 | static char afsbfrmem[] = "afsbfrmem"; | |
430 | ||
431 | int | |
432 | afsinit() | |
433 | { | |
434 | old_sysent = sysent[AFS_SYSCALL]; | |
435 | ||
436 | sysent[AFS_SYSCALL].sy_call = afs3_syscall; | |
437 | sysent[AFS_SYSCALL].sy_narg = 6; | |
438 | sysent[AFS_SYSCALL].sy_argsize = 6 * sizeof(long); | |
439 | sysent[SYS_ioctl].sy_call = afs_xioctl; | |
440 | sysent[SYS_setgroups].sy_call = Afs_xsetgroups; | |
441 | osi_Init(); | |
442 | ||
443 | return 0; | |
444 | } | |
445 | ||
446 | int | |
447 | afs_vfs_load(struct lkm_table *lkmtp, int cmd) | |
448 | { | |
449 | extern char *memname[]; | |
450 | ||
451 | #if ! defined(AFS_OBSD49_ENV) | |
452 | vfs_opv_init_explicit(&afs_vnodeop_opv_desc); | |
453 | vfs_opv_init_default(&afs_vnodeop_opv_desc); | |
454 | #endif | |
455 | if (memname[M_AFSGENERIC] == NULL) | |
456 | memname[M_AFSGENERIC] = afsgenmem; | |
457 | if (memname[M_AFSFID] == NULL) | |
458 | memname[M_AFSFID] = afsfidmem; | |
459 | if (memname[M_AFSBUFHDR] == NULL) | |
460 | memname[M_AFSBUFHDR] = afsbhdrmem; | |
461 | if (memname[M_AFSBUFFER] == NULL) | |
462 | memname[M_AFSBUFFER] = afsbfrmem; | |
463 | lkmid = lkmtp->id; | |
464 | printf("OpenAFS ($Revision$) lkm loaded\n"); | |
465 | return 0; | |
466 | } | |
467 | ||
468 | int | |
469 | afs_vfs_unload(struct lkm_table *lktmp, int cmd) | |
470 | { | |
471 | extern char *memname[]; | |
472 | ||
473 | if (afs_globalVp) | |
474 | return EBUSY; | |
475 | if (sysent[SYS_ioctl].sy_call != sys_ioctl) | |
476 | return EBUSY; | |
477 | ||
478 | if (memname[M_AFSGENERIC] == afsgenmem) | |
479 | memname[M_AFSGENERIC] = NULL; | |
480 | if (memname[M_AFSFID] == afsfidmem) | |
481 | memname[M_AFSFID] = NULL; | |
482 | if (memname[M_AFSBUFHDR] == afsbhdrmem) | |
483 | memname[M_AFSBUFHDR] = NULL; | |
484 | if (memname[M_AFSBUFFER] == afsbfrmem) | |
485 | memname[M_AFSBUFFER] = NULL; | |
486 | ||
487 | sysent[AFS_SYSCALL] = old_sysent; | |
488 | printf("OpenAFS unloaded\n"); | |
489 | return 0; | |
490 | } | |
491 | ||
492 | int | |
493 | libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver) | |
494 | { | |
495 | if (cmd == LKM_E_LOAD) { | |
496 | if (sysent[AFS_SYSCALL].sy_call == afs3_syscall | |
497 | || sysent[AFS_SYSCALL].sy_call == afs_badcall) { | |
498 | printf("AFS already loaded\n"); | |
499 | return EINVAL; | |
500 | } | |
501 | } | |
502 | DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc); | |
503 | } |