reindent-20030715
[openafs.git] / src / afs / OBSD / osi_vfsops.c
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 RCSID
97     ("$Header$");
98
99 #include "afs/sysincludes.h"    /* Standard vendor system headers */
100 #include "afs/afsincludes.h"    /* Afs-based standard headers */
101 #include "afs/afs_stats.h"      /* statistics */
102
103 #include <sys/conf.h>
104 #include <sys/exec.h>
105 #include <sys/lkm.h>
106 #include <sys/namei.h>
107 #include <sys/syscall.h>
108 #include <sys/syscallargs.h>
109
110 /* from /usr/src/sys/kern/vfs_subr.c */
111 extern void insmntque(struct vnode *, struct mount *);
112
113 extern int sys_lkmnosys(), afs3_syscall(), afs_xioctl(), Afs_xsetgroups();
114
115 static int lkmid = -1;
116 static int afs_badcall(struct proc *p, void *xx, register_t * yy);
117 static struct sysent old_sysent;
118
119 char afs_NetBSD_osname[] = "OpenBSD";
120 struct osi_vfs *afs_globalVFS;
121 struct vcache *afs_globalVp;
122
123 int afs_quotactl();
124 int afs_fhtovp();
125 int afs_vptofh();
126 int afsinit();
127 int afs_start();
128 int afs_mount();
129 int afs_unmount();
130 int afs_root();
131 int afs_statfs();
132 int afs_sync();
133 int afs_vget();
134 int afs_sysctl();
135 int afs_checkexp();
136
137 struct vfsops afs_vfsops = {
138     afs_mount,
139     afs_start,
140     afs_unmount,
141     afs_root,
142     afs_quotactl,
143     afs_statfs,
144     afs_sync,
145     afs_vget,
146     afs_fhtovp,
147     afs_vptofh,
148     afsinit,
149     afs_sysctl,
150     afs_checkexp,
151 };
152
153 int
154 afs_nbsd_lookupname(char *fnamep, enum uio_seg segflg, int followlink,
155                     struct vnode **dirvpp, struct vnode **compvpp)
156 {
157     struct nameidata nd;
158     int niflag;
159     int error;
160
161     /*
162      * Lookup pathname "fnamep", returning parent directory in
163      * *dirvpp (if non-null) and leaf in *compvpp.  segflg says whether the
164      * pathname is user or system space.
165      */
166     /* XXX LOCKLEAF ? */
167     niflag = followlink ? FOLLOW : NOFOLLOW;
168     if (dirvpp)
169         niflag |= WANTPARENT;   /* XXX LOCKPARENT? */
170     NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc());
171     if ((error = namei(&nd)))
172         return error;
173     *compvpp = nd.ni_vp;
174     if (dirvpp)
175         *dirvpp = nd.ni_dvp;
176     return error;
177 }
178
179 int
180 afs_quotactl()
181 {
182     return EOPNOTSUPP;
183 }
184
185 int
186 afs_sysctl()
187 {
188     return EOPNOTSUPP;
189 }
190
191 int
192 afs_checkexp()
193 {
194     return EOPNOTSUPP;
195 }
196
197 int
198 afs_fhtovp(mp, fhp, vpp)
199      struct mount *mp;
200      struct fid *fhp;
201      struct vnode **vpp;
202 {
203
204     return (EINVAL);
205 }
206
207 int
208 afs_vptofh(vp, fhp)
209      struct vnode *vp;
210      struct fid *fhp;
211 {
212
213     return (EINVAL);
214 }
215
216 int
217 afs_start(mp, flags, p)
218      struct mount *mp;
219      int flags;
220      struct proc *p;
221 {
222     return (0);                 /* nothing to do. ? */
223 }
224
225 int
226 afs_mount(mp, path, data, ndp, p)
227      register struct mount *mp;
228      char *path;
229      caddr_t data;
230      struct nameidata *ndp;
231      struct proc *p;
232 {
233     /* ndp contains the mounted-from device.  Just ignore it.
234      * we also don't care about our proc struct. */
235     int size;
236
237     if (mp->mnt_flag & MNT_UPDATE)
238         return EINVAL;
239
240     if (afs_globalVFS) {
241         /* Don't allow remounts */
242         return EBUSY;
243     }
244
245     AFS_STATCNT(afs_mount);
246
247 #ifdef AFS_DISCON_ENV
248     /* initialize the vcache entries before we start using them */
249
250     /* XXX find a better place for this if possible  */
251     init_vcache_entries();
252 #endif
253     afs_globalVFS = mp;
254     mp->osi_vfs_bsize = 8192;
255     mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC;     /* magic */
256     mp->osi_vfs_fsid.val[1] = (int)AFS_VFSFSID;
257
258     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
259     bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
260     bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
261     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
262     /* null terminated string "AFS" will fit, just leave it be. */
263     strcpy(mp->mnt_stat.f_fstypename, MOUNT_AFS);
264     (void)afs_statfs(mp, &mp->mnt_stat);
265
266     return 0;
267 }
268
269 int
270 afs_unmount(afsp, flags, p)
271      struct mount *afsp;
272      int flags;
273      struct proc *p;
274 {
275     extern int sys_ioctl(), sys_setgroups();
276
277     AFS_STATCNT(afs_unmount);
278 #ifdef AFS_DISCON_ENV
279     give_up_cbs();
280 #endif
281     if (!afs_globalVFS) {
282         printf("afs already unmounted\n");
283         return 0;
284     }
285     if (afs_globalVp)
286         AFS_RELE(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 void
318 afs_nbsd_getnewvnode(struct vcache *tvc)
319 {
320     while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
321         /* no vnodes available, force an alloc (limits be damned)! */
322         desiredvnodes++;
323     }
324     tvc->v->v_data = (void *)tvc;
325 }
326
327 int
328 afs_root(struct mount *mp, struct vnode **vpp)
329 {
330     struct vrequest treq;
331     struct vcache *tvp;
332     int code;
333
334     AFS_STATCNT(afs_root);
335
336     AFS_GLOCK();
337     if (!(code = afs_InitReq(&treq, osi_curcred()))
338         && !(code = afs_CheckInit())) {
339         tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
340         if (tvp) {
341             /* There is really no reason to over-hold this bugger--it's held
342              * by the root filesystem reference. */
343             if (afs_globalVp != tvp) {
344 #ifdef AFS_DONT_OVERHOLD_GLOBALVP
345                 if (afs_globalVp)
346                     AFS_RELE(AFSTOV(afs_globalVp));
347 #endif
348                 afs_globalVp = tvp;
349                 AFS_HOLD(AFSTOV(afs_globalVp));
350             }
351             AFSTOV(tvp)->v_flag |= VROOT;
352             afs_globalVFS = mp;
353             *vpp = AFSTOV(tvp);
354         } else
355             code = ENOENT;
356     }
357     AFS_GUNLOCK();
358
359     if (!code)
360         vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curproc);        /* return it locked */
361     return code;
362 }
363
364 int
365 afs_statfs(struct osi_vfs *afsp, struct statfs *abp)
366 {
367     AFS_STATCNT(afs_statfs);
368     abp->f_bsize = afsp->osi_vfs_bsize;
369
370     /*
371      * Fake a high number below to satisfy programs that use the ustat (for
372      * * AIX), or statfs (for the rest) call to make sure that there's
373      * enough * space in the device partition before storing something there
374      * (like * ed(1))
375      */
376     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
377         abp->f_ffree = 9000000;
378     abp->f_fsid.val[0] = AFS_VFSMAGIC;  /* magic */
379     abp->f_fsid.val[1] = (int)AFS_VFSFSID;
380     return 0;
381 }
382
383 int
384 afs_sync(struct osi_vfs *afsp)
385 {
386     AFS_STATCNT(afs_sync);
387 #if defined(AFS_DISCON_ENV) && !defined(AFS_OBSD_ENV)
388     /* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
389     store_dirty_vcaches();
390 #endif
391     return 0;
392 }
393
394 void
395 afs_nbsd_ref(struct vnode *vp)
396 {
397     if (vp->v_usecount == 0) {
398         vprint("holding unheld node", vp);
399         panic("afs_ref");
400     }
401     VREF(vp);
402 }
403
404 void
405 afs_nbsd_rele(struct vnode *vp)
406 {
407     if (vp->v_usecount <= 0) {
408         vprint("rele'ing unheld node", vp);
409         panic("afs_rele");
410     }
411     vrele(vp);
412 }
413
414 int
415 afs_vget(vp, lfl)
416      struct vnode *vp;
417      int lfl;
418 {
419     int error;
420
421     if (vp->v_usecount < 0) {
422         vprint("bad usecount", vp);
423         panic("afs_vget");
424     }
425     error = vget(vp, lfl, curproc);
426     if (!error)
427         insmntque(vp, afs_globalVFS);   /* take off free list */
428     return error;
429 }
430
431 extern struct vfsops afs_vfsops;
432 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
433
434 static struct vfsconf afs_vfsconf = {
435     &afs_vfsops,
436     "afs",
437     0,
438     0,
439     0,
440     NULL,
441     NULL,
442 };
443
444 MOD_VFS("afs", 0, &afs_vfsconf);
445
446 static char afsgenmem[] = "afsgenmem";
447 static char afsfidmem[] = "afsfidmem";
448 static char afsbhdrmem[] = "afsbhdrmem";
449 static char afsbfrmem[] = "afsbfrmem";
450
451 int
452 afsinit()
453 {
454     old_sysent = sysent[AFS_SYSCALL];
455
456     sysent[AFS_SYSCALL].sy_call = afs3_syscall;
457     sysent[AFS_SYSCALL].sy_narg = 6;
458     sysent[AFS_SYSCALL].sy_argsize = 6 * sizeof(long);
459     sysent[54].sy_call = afs_xioctl;
460     sysent[80].sy_call = Afs_xsetgroups;
461     osi_Init();
462
463     return 0;
464 }
465
466 int
467 afs_vfs_load(struct lkm_table *lkmtp, int cmd)
468 {
469     extern char *memname[];
470
471     vfs_opv_init_explicit(&afs_vnodeop_opv_desc);
472     vfs_opv_init_default(&afs_vnodeop_opv_desc);
473     if (memname[M_AFSGENERIC] == NULL)
474         memname[M_AFSGENERIC] = afsgenmem;
475     if (memname[M_AFSFID] == NULL)
476         memname[M_AFSFID] = afsfidmem;
477     if (memname[M_AFSBUFHDR] == NULL)
478         memname[M_AFSBUFHDR] = afsbhdrmem;
479     if (memname[M_AFSBUFFER] == NULL)
480         memname[M_AFSBUFFER] = afsbfrmem;
481     lkmid = lkmtp->id;
482     printf("OpenAFS ($Revision$) lkm loaded\n");
483     return 0;
484 }
485
486 int
487 afs_vfs_unload(struct lkm_table *lktmp, int cmd)
488 {
489     extern char *memname[];
490
491     if (afs_globalVp)
492         return EBUSY;
493     if (sysent[SYS_ioctl].sy_call != sys_ioctl)
494         return EBUSY;
495
496     if (memname[M_AFSGENERIC] == afsgenmem)
497         memname[M_AFSGENERIC] = NULL;
498     if (memname[M_AFSFID] == afsfidmem)
499         memname[M_AFSFID] = NULL;
500     if (memname[M_AFSBUFHDR] == afsbhdrmem)
501         memname[M_AFSBUFHDR] = NULL;
502     if (memname[M_AFSBUFFER] == afsbfrmem)
503         memname[M_AFSBUFFER] = NULL;
504
505     sysent[AFS_SYSCALL] = old_sysent;
506     printf("OpenAFS unloaded\n");
507     return 0;
508 }
509
510 int
511 libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
512 {
513     if (cmd == LKM_E_LOAD) {
514         if (strcmp(ostype, afs_NetBSD_osname)) {
515             printf("This is %s version %s\n", ostype, osrelease);
516             printf("This version of AFS is only for %s\n", afs_NetBSD_osname);
517             return EPROGMISMATCH;
518         }
519         if (sysent[AFS_SYSCALL].sy_call == afs3_syscall
520             || sysent[AFS_SYSCALL].sy_call == afs_badcall) {
521             printf("AFS already loaded\n");
522             return EINVAL;
523         }
524     }
525     DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc);
526 }