83976626c72419a5a14897f64be677367aaaba8a
[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 struct osi_vfs *afs_globalVFS;
120 struct vcache *afs_globalVp;
121
122 int afs_quotactl();
123 int afs_fhtovp();
124 int afs_vptofh();
125 int afsinit();
126 int afs_start();
127 int afs_mount();
128 int afs_unmount();
129 int afs_root();
130 int afs_statfs();
131 int afs_sync();
132 int afs_vget();
133 int afs_sysctl();
134 int afs_checkexp();
135
136 struct vfsops afs_vfsops = {
137     afs_mount,
138     afs_start,
139     afs_unmount,
140     afs_root,
141     afs_quotactl,
142     afs_statfs,
143     afs_sync,
144     afs_vget,
145     afs_fhtovp,
146     afs_vptofh,
147     afsinit,
148     afs_sysctl,
149     afs_checkexp,
150 };
151
152 int
153 afs_nbsd_lookupname(char *fnamep, enum uio_seg segflg, int followlink,
154                     struct vnode **compvpp)
155 {
156     struct nameidata nd;
157     int niflag;
158     int error;
159
160     /*
161      * Lookup pathname "fnamep", returning leaf in *compvpp.  segflg says
162      * whether the pathname is user or system space.
163      */
164     /* XXX LOCKLEAF ? */
165     niflag = followlink ? FOLLOW : NOFOLLOW;
166     NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc());
167     if ((error = namei(&nd)))
168         return error;
169     *compvpp = nd.ni_vp;
170     return error;
171 }
172
173 int
174 afs_quotactl()
175 {
176     return EOPNOTSUPP;
177 }
178
179 int
180 afs_sysctl()
181 {
182     return EOPNOTSUPP;
183 }
184
185 int
186 afs_checkexp()
187 {
188     return EOPNOTSUPP;
189 }
190
191 int
192 afs_fhtovp(mp, fhp, vpp)
193      struct mount *mp;
194      struct fid *fhp;
195      struct vnode **vpp;
196 {
197
198     return (EINVAL);
199 }
200
201 int
202 afs_vptofh(vp, fhp)
203      struct vnode *vp;
204      struct fid *fhp;
205 {
206
207     return (EINVAL);
208 }
209
210 int
211 afs_start(mp, flags, p)
212      struct mount *mp;
213      int flags;
214      struct proc *p;
215 {
216     return (0);                 /* nothing to do. ? */
217 }
218
219 int
220 afs_mount(mp, path, data, ndp, p)
221      register struct mount *mp;
222      char *path;
223      caddr_t data;
224      struct nameidata *ndp;
225      struct proc *p;
226 {
227     /* ndp contains the mounted-from device.  Just ignore it.
228      * we also don't care about our proc struct. */
229     int size;
230
231     if (mp->mnt_flag & MNT_UPDATE)
232         return EINVAL;
233
234     if (afs_globalVFS) {
235         /* Don't allow remounts */
236         return EBUSY;
237     }
238
239     AFS_STATCNT(afs_mount);
240     AFS_GLOCK();
241
242 #ifdef AFS_DISCON_ENV
243     /* initialize the vcache entries before we start using them */
244
245     /* XXX find a better place for this if possible  */
246     init_vcache_entries();
247 #endif
248     afs_globalVFS = mp;
249     mp->osi_vfs_bsize = 8192;
250     mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC;     /* magic */
251     mp->osi_vfs_fsid.val[1] = (int)AFS_VFSFSID;
252
253     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
254     bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
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     AFS_STATCNT(afs_unmount);
274 #ifdef AFS_DISCON_ENV
275     give_up_cbs();
276 #endif
277     if (afs_globalVFS == NULL) {
278         printf("afs already unmounted\n");
279         return 0;
280     }
281     if (afs_globalVp)
282         vrele(AFSTOV(afs_globalVp));
283     afs_globalVp = NULL;
284
285     vflush(afsp, NULLVP, 0);    /* don't support forced */
286     afsp->mnt_data = NULL;
287     AFS_GLOCK();
288     afs_globalVFS = 0;
289     afs_cold_shutdown = 1;
290     afs_shutdown();             /* XXX */
291     AFS_GUNLOCK();
292
293     /* give up syscall entries for ioctl & setgroups, which we've stolen */
294     sysent[SYS_ioctl].sy_call = sys_ioctl;
295     sysent[SYS_setgroups].sy_call = sys_setgroups;
296
297     /* give up the stolen syscall entry */
298     sysent[AFS_SYSCALL].sy_narg = 0;
299     sysent[AFS_SYSCALL].sy_argsize = 0;
300     sysent[AFS_SYSCALL].sy_call = afs_badcall;
301     printf
302         ("AFS unmounted--use `/sbin/modunload -i %d' to unload before restarting AFS\n",
303          lkmid);
304     return 0;
305 }
306
307 static int
308 afs_badcall(struct proc *p, void *xx, register_t * yy)
309 {
310     return ENOSYS;
311 }
312
313 void
314 afs_nbsd_getnewvnode(struct vcache *tvc)
315 {
316     while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) {
317         /* no vnodes available, force an alloc (limits be damned)! */
318         desiredvnodes++;
319     }
320     tvc->v->v_data = (void *)tvc;
321 }
322
323 int
324 afs_root(struct mount *mp, struct vnode **vpp)
325 {
326     struct vrequest treq;
327     struct vcache *tvp;
328     int code;
329
330     AFS_STATCNT(afs_root);
331
332     AFS_GLOCK();
333     if (!(code = afs_InitReq(&treq, osi_curcred()))
334         && !(code = afs_CheckInit())) {
335         tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
336         if (tvp) {
337             /* There is really no reason to over-hold this bugger--it's held
338              * by the root filesystem reference. */
339             if (afs_globalVp != tvp) {
340 #ifdef AFS_DONT_OVERHOLD_GLOBALVP
341                 if (afs_globalVp)
342                     AFS_RELE(AFSTOV(afs_globalVp));
343 #endif
344                 afs_globalVp = tvp;
345                 VREF(AFSTOV(afs_globalVp));
346             }
347             AFSTOV(tvp)->v_flag |= VROOT;
348             afs_globalVFS = mp;
349             *vpp = AFSTOV(tvp);
350         } else
351             code = ENOENT;
352     }
353     AFS_GUNLOCK();
354
355     if (!code)
356         vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY, curproc);        /* return it locked */
357     return code;
358 }
359
360 int
361 afs_statfs(struct osi_vfs *afsp, struct statfs *abp)
362 {
363     AFS_STATCNT(afs_statfs);
364     abp->f_bsize = afsp->osi_vfs_bsize;
365
366     /*
367      * Fake a high number below to satisfy programs that use the ustat (for
368      * * AIX), or statfs (for the rest) call to make sure that there's
369      * enough * space in the device partition before storing something there
370      * (like * ed(1))
371      */
372     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
373         abp->f_ffree = 9000000;
374     abp->f_fsid.val[0] = AFS_VFSMAGIC;  /* magic */
375     abp->f_fsid.val[1] = (int)AFS_VFSFSID;
376     return 0;
377 }
378
379 int
380 afs_sync(struct osi_vfs *afsp)
381 {
382     AFS_STATCNT(afs_sync);
383 #if defined(AFS_DISCON_ENV) && !defined(AFS_OBSD_ENV)
384     /* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
385     store_dirty_vcaches();
386 #endif
387     return 0;
388 }
389
390 int
391 afs_vget(vp, lfl)
392      struct vnode *vp;
393      int lfl;
394 {
395     int error;
396
397     if (vp->v_usecount < 0) {
398         vprint("bad usecount", vp);
399         panic("afs_vget");
400     }
401     error = vget(vp, lfl, curproc);
402     if (!error && vp->v_usecount == 1) {
403         /* vget() took it off the freelist; put it on our mount queue */
404         insmntque(vp, afs_globalVFS);
405     }
406     return error;
407 }
408
409 extern struct vfsops afs_vfsops;
410 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
411
412 static struct vfsconf afs_vfsconf = {
413     &afs_vfsops,
414     "afs",
415     0,
416     0,
417     0,
418     NULL,
419     NULL,
420 };
421
422 MOD_VFS("afs", 0, &afs_vfsconf);
423
424 static char afsgenmem[] = "afsgenmem";
425 static char afsfidmem[] = "afsfidmem";
426 static char afsbhdrmem[] = "afsbhdrmem";
427 static char afsbfrmem[] = "afsbfrmem";
428
429 int
430 afsinit()
431 {
432     old_sysent = sysent[AFS_SYSCALL];
433
434     sysent[AFS_SYSCALL].sy_call = afs3_syscall;
435     sysent[AFS_SYSCALL].sy_narg = 6;
436     sysent[AFS_SYSCALL].sy_argsize = 6 * sizeof(long);
437     sysent[SYS_ioctl].sy_call = afs_xioctl;
438     sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
439     osi_Init();
440
441     return 0;
442 }
443
444 int
445 afs_vfs_load(struct lkm_table *lkmtp, int cmd)
446 {
447     extern char *memname[];
448
449     vfs_opv_init_explicit(&afs_vnodeop_opv_desc);
450     vfs_opv_init_default(&afs_vnodeop_opv_desc);
451     if (memname[M_AFSGENERIC] == NULL)
452         memname[M_AFSGENERIC] = afsgenmem;
453     if (memname[M_AFSFID] == NULL)
454         memname[M_AFSFID] = afsfidmem;
455     if (memname[M_AFSBUFHDR] == NULL)
456         memname[M_AFSBUFHDR] = afsbhdrmem;
457     if (memname[M_AFSBUFFER] == NULL)
458         memname[M_AFSBUFFER] = afsbfrmem;
459     lkmid = lkmtp->id;
460     printf("OpenAFS ($Revision$) lkm loaded\n");
461     return 0;
462 }
463
464 int
465 afs_vfs_unload(struct lkm_table *lktmp, int cmd)
466 {
467     extern char *memname[];
468
469     if (afs_globalVp)
470         return EBUSY;
471     if (sysent[SYS_ioctl].sy_call != sys_ioctl)
472         return EBUSY;
473
474     if (memname[M_AFSGENERIC] == afsgenmem)
475         memname[M_AFSGENERIC] = NULL;
476     if (memname[M_AFSFID] == afsfidmem)
477         memname[M_AFSFID] = NULL;
478     if (memname[M_AFSBUFHDR] == afsbhdrmem)
479         memname[M_AFSBUFHDR] = NULL;
480     if (memname[M_AFSBUFFER] == afsbfrmem)
481         memname[M_AFSBUFFER] = NULL;
482
483     sysent[AFS_SYSCALL] = old_sysent;
484     printf("OpenAFS unloaded\n");
485     return 0;
486 }
487
488 int
489 libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
490 {
491     if (cmd == LKM_E_LOAD) {
492         if (sysent[AFS_SYSCALL].sy_call == afs3_syscall
493             || sysent[AFS_SYSCALL].sy_call == afs_badcall) {
494             printf("AFS already loaded\n");
495             return EINVAL;
496         }
497     }
498     DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc);
499 }