backport to buster
[hcoop/debian/openafs.git] / src / afs / OBSD / osi_vfsops.c
CommitLineData
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/*
10copyright 2002
11the regents of the university of michigan
12all rights reserved
13
14permission is granted to use, copy, create derivative works
15and redistribute this software and such derivative works
16for any purpose, so long as the name of the university of
17michigan is not used in any advertising or publicity
18pertaining to the use or distribution of this software
19without specific, written prior authorization. if the
20above copyright notice or any other identification of the
21university of michigan is included in any copy of any
22portion of this software, then the disclaimer below must
23also be included.
24
25this software is provided as is, without representation
26from the university of michigan as to its fitness for any
27purpose, and without warranty by the university of
28michigan of any kind, either express or implied, including
29without limitation the implied warranties of
30merchantability and fitness for a particular purpose. the
31regents of the university of michigan shall not be liable
32for any damages, including special, indirect, incidental, or
33consequential damages, with respect to any claim arising
34out of or in connection with the use of the software, even
35if it has been or is hereafter advised of the possibility of
36such damages.
37*/
38
39/*
40Copyright 1995 Massachusetts Institute of Technology. All Rights
41Reserved.
42
43You are hereby granted a worldwide, irrevocable, paid-up, right and
44license to use, execute, display, modify, copy and distribute MIT's
45Modifications, provided that (i) you abide by the terms and conditions
46of the OpenAFS License Agreement, and (ii) you do not use the name
47of MIT in any advertising or publicity without the prior written consent
48of MIT. MIT disclaims all liability for your use of MIT's
49Modifications. MIT's Modifications are provided "AS IS" WITHOUT
50WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,
51ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
52NONINFRINGEMENT.
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 */
109extern void insmntque(struct vnode *, struct mount *);
110
111extern int sys_lkmnosys(), afs_xioctl(), Afs_xsetgroups();
112
113static int lkmid = -1;
114static int afs_badcall(struct proc *p, void *xx, register_t * yy);
115static struct sysent old_sysent;
116
117struct osi_vfs *afs_globalVFS;
118struct vcache *afs_globalVp;
119
120int afs_quotactl();
121int afs_fhtovp();
122int afs_vptofh();
123int afsinit();
124int afs_start();
125int afs_mount();
126int afs_unmount();
127int afs_root();
128int afs_statfs();
129int afs_sync();
130int afs_vget();
131int afs_sysctl();
132int afs_checkexp();
133
134struct 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
150int
151afs_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
171int
172afs_quotactl()
173{
174 return EOPNOTSUPP;
175}
176
177int
178afs_sysctl()
179{
180 return EOPNOTSUPP;
181}
182
183int
184afs_checkexp()
185{
186 return EOPNOTSUPP;
187}
188
189int
190afs_fhtovp(mp, fhp, vpp)
191 struct mount *mp;
192 struct fid *fhp;
193 struct vnode **vpp;
194{
195
196 return (EINVAL);
197}
198
199int
200afs_vptofh(vp, fhp)
201 struct vnode *vp;
202 struct fid *fhp;
203{
204
205 return (EINVAL);
206}
207
208int
209afs_start(mp, flags, p)
210 struct mount *mp;
211 int flags;
212 struct proc *p;
213{
214 return (0); /* nothing to do. ? */
215}
216
217int
218afs_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
265int
266afs_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
311static int
312afs_badcall(struct proc *p, void *xx, register_t * yy)
313{
314 return ENOSYS;
315}
316
317#if defined(AFS_OBSD49_ENV)
318extern struct vops afs_vops;
319#endif
320
321void
322afs_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
335int
336afs_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
372int
373afs_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
385int
386afs_sync(struct osi_vfs *afsp)
387{
388 AFS_STATCNT(afs_sync);
389 return 0;
390}
391
392int
393afs_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
411extern struct vfsops afs_vfsops;
412extern struct vnodeopv_desc afs_vnodeop_opv_desc;
413
414static struct vfsconf afs_vfsconf = {
415 &afs_vfsops,
416 "afs",
417 0,
418 0,
419 0,
420 NULL,
421 NULL,
422};
423
424MOD_VFS("afs", 0, &afs_vfsconf);
425
426static char afsgenmem[] = "afsgenmem";
427static char afsfidmem[] = "afsfidmem";
428static char afsbhdrmem[] = "afsbhdrmem";
429static char afsbfrmem[] = "afsbfrmem";
430
431int
432afsinit()
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
446int
447afs_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
468int
469afs_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
492int
493libafs_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}