Updates to the Cache Manager to include NetBSD5 support
[openafs.git] / src / afs / NBSD / 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  * Reported to NetBSD 4.0 by Matt Benjamin (matt@linuxbox.com)
6  *
7  * $Id: osi_vfsops.c,v 1.20 2005/03/08 21:58:04 shadow Exp $
8  */
9
10 /*
11 copyright 2002
12 the regents of the university of michigan
13 all rights reserved
14
15 permission is granted to use, copy, create derivative works
16 and redistribute this software and such derivative works
17 for any purpose, so long as the name of the university of
18 michigan is not used in any advertising or publicity
19 pertaining to the use or distribution of this software
20 without specific, written prior authorization.  if the
21 above copyright notice or any other identification of the
22 university of michigan is included in any copy of any
23 portion of this software, then the disclaimer below must
24 also be included.
25
26 this software is provided as is, without representation
27 from the university of michigan as to its fitness for any
28 purpose, and without warranty by the university of
29 michigan of any kind, either express or implied, including
30 without limitation the implied warranties of
31 merchantability and fitness for a particular purpose. the
32 regents of the university of michigan shall not be liable
33 for any damages, including special, indirect, incidental, or
34 consequential damages, with respect to any claim arising
35 out of or in connection with the use of the software, even
36 if it has been or is hereafter advised of the possibility of
37 such damages.
38 */
39
40 /*
41 Copyright 1995 Massachusetts Institute of Technology.  All Rights
42 Reserved.
43
44 You are hereby granted a worldwide, irrevocable, paid-up, right and
45 license to use, execute, display, modify, copy and distribute MIT's
46 Modifications, provided that (i) you abide by the terms and conditions
47 of the OpenAFS License Agreement, and (ii) you do not use the name
48 of MIT in any advertising or publicity without the prior written consent
49 of MIT.  MIT disclaims all liability for your use of MIT's
50 Modifications.  MIT's Modifications are provided "AS IS" WITHOUT
51 WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,
52 ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
53 NONINFRINGEMENT.
54 */
55
56 /*
57  * Some code cribbed from ffs_vfsops and other NetBSD sources, which
58  * are marked:
59  */
60 /*
61  * Copyright (c) 1989, 1991, 1993, 1994
62  *      The Regents of the University of California.  All rights reserved.
63  *
64  * Redistribution and use in source and binary forms, with or without
65  * modification, are permitted provided that the following conditions
66  * are met:
67  * 1. Redistributions of source code must retain the above copyright
68  *    notice, this list of conditions and the following disclaimer.
69  * 2. Redistributions in binary form must reproduce the above copyright
70  *    notice, this list of conditions and the following disclaimer in the
71  *    documentation and/or other materials provided with the distribution.
72  * 3. All advertising materials mentioning features or use of this software
73  *    must display the following acknowledgement:
74  *      This product includes software developed by the University of
75  *      California, Berkeley and its contributors.
76  * 4. Neither the name of the University nor the names of its contributors
77  *    may be used to endorse or promote products derived from this software
78  *    without specific prior written permission.
79  *
80  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90  * SUCH DAMAGE.
91  *
92  */
93
94 #include <afsconfig.h>
95 #include "afs/param.h"
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/ioctl.h>
102 #include <sys/lkm.h>
103 #include <sys/namei.h>
104
105 extern unsigned long long afs_debug;
106
107 #if 0
108 /* from /usr/src/sys/kern/vfs_subr.c */
109 extern void insmntque(struct vnode *, struct mount *);
110 #endif
111 extern int sys_lkmnosys(), afs3_syscall(), afs_xioctl(), Afs_xsetgroups();
112
113 static int lkmid = -1;
114 static int afs_badcall(struct lwp *, void *, register_t *);
115
116 #if 0
117 int
118 newcall(l, v, retval)
119         struct lwp *l;
120         void *v;
121         int *retval;
122 {
123         struct afs_sysargs *uap = v;
124
125         printf("kmod: newcall: %ld %ld %ld %ld\n",
126                SCARG(uap, syscall), SCARG(uap, parm1),
127                SCARG(uap, parm2), SCARG(uap, parm3));
128         return(0);
129 }
130 #endif
131
132 struct sysent afs_sysent = { 6,
133                              sizeof(struct afs_sysargs),
134                              0,
135                              afs3_syscall};
136
137 static struct sysent old_sysent;
138
139 struct osi_vfs *afs_globalVFS;
140 struct vcache *afs_globalVp;
141 fsid_t afs_dynamic_fsid;
142
143 int afs_mount(struct mount *, const char *, void *,
144               struct nameidata *, struct lwp *);
145 int afs_start(struct mount *, int, struct lwp *);
146 int afs_unmount(struct mount *, int, struct lwp *);
147 int afs_root(struct mount *, struct vnode **);
148 int afs_quotactl(struct mount *, int, uid_t, void *, struct lwp *);
149 int afs_statvfs(struct mount *, struct statvfs *, struct lwp *);
150 int afs_sync(struct mount *, int, kauth_cred_t, struct lwp *);
151 int afs_vget(struct mount *, ino_t, struct vnode **);
152 void afs_init(void);
153 void afs_reinit(void);
154 void afs_done(void);
155
156 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
157 static const struct vnodeopv_desc *afs_vnodeopv_descs[] = {
158         &afs_vnodeop_opv_desc,
159         NULL,
160 };
161
162 struct vfsops afs_vfsops = {
163     AFS_MOUNT_AFS,
164 #ifdef AFS_NBSD50_ENV
165         0,                                              /* vfs_min_mount_data */
166 #endif
167     afs_mount,
168     afs_start,
169     afs_unmount,
170     afs_root,
171     afs_quotactl,
172     afs_statvfs,
173     afs_sync,
174     afs_vget,
175     (void *) eopnotsupp,        /* vfs_fhtovp */
176     (void *) eopnotsupp,        /* vfs_vptofh */
177     afs_init,
178     afs_reinit,
179     afs_done,
180     (int (*) (void)) eopnotsupp, /* mountroot */
181     (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp, /* vfs_snapshot */
182     vfs_stdextattrctl,
183 #ifdef AFS_NBSD50_ENV
184         (int (*)(struct mount *, int)) eopnotsupp,      /* vfs_suspendctl */
185         (int (*)(struct mount *)) eopnotsupp,           /* vfs_renamelock_enter */
186         (void *) eopnotsupp,                                            /* vfs_renamelock_exit */
187         (int (*)(struct vnode*, int)) eopnotsupp,       /* vfs_fsync */
188 #endif
189     afs_vnodeopv_descs,
190     0,                  /* vfs_refcount */
191     { NULL, NULL },
192 };
193
194 VFS_ATTACH(afs_vfsops);
195
196 int
197 afs_nbsd_lookupname(char *fnamep, enum uio_seg segflg, int followlink,
198                     struct vnode **compvpp)
199 {
200     struct nameidata nd;
201     int niflag;
202     int error;
203
204     afs_warn("afs_nbsd_lookupname enter (%s)\n", fnamep);
205
206     /*
207      * Lookup pathname "fnamep", returning leaf in *compvpp.  segflg says
208      * whether the pathname is user or system space.
209      */
210     /* XXX LOCKLEAF ? */
211     niflag = followlink ? FOLLOW : NOFOLLOW;
212         /*
213         *       NBSD50 seems to have stopped caring about the curproc of things.
214         *       mattjsm
215         */
216 #ifdef AFS_NBSD50_ENV
217         NDINIT(&nd, LOOKUP, niflag, segflg, fnamep);
218 #else
219     NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc());
220 #endif
221     if ((error = namei(&nd)))
222         return error;
223     *compvpp = nd.ni_vp;
224     return error;
225 }
226
227 int
228 afs_quotactl(struct mount *mp, int cmd, uid_t uid,
229     void *arg, struct lwp *l)
230 {
231     return EOPNOTSUPP;
232 }
233
234 int
235 afs_sysctl()
236 {
237     return EOPNOTSUPP;
238 }
239
240 int
241 afs_start(struct mount *mp, int flags, struct lwp *l)
242 {
243     return (0); /* nothing to do? */
244 }
245
246 void afs_done(void)
247 {
248     return; /* nothing to do? */
249 }
250
251 int
252 afs_mount(struct mount *mp, const char *path, void *data,
253           struct nameidata *ndp, struct lwp *l)
254 {
255     /* ndp contains the mounted-from device.  Just ignore it.
256      * we also don't care about our proc struct. */
257     u_int size;
258
259     AFS_STATCNT(afs_mount);
260
261     afs_warn("afs_mount enter\n");
262
263     if (mp->mnt_flag & MNT_UPDATE)
264         return EINVAL;
265
266     if (afs_globalVFS) {
267         /* Don't allow remounts */
268         return EBUSY;
269     }
270
271     AFS_GLOCK();
272 #ifdef AFS_DISCON_ENV
273     /* initialize the vcache entries before we start using them */
274
275     /* XXX find a better place for this if possible  */
276     init_vcache_entries();
277 #endif
278     afs_globalVFS = mp;
279     mp->mnt_stat.f_bsize = 8192;
280     mp->mnt_stat.f_frsize = 8192;
281     mp->mnt_stat.f_iosize = 8192;
282 #if 0
283     mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC;     /* magic */
284     mp->osi_vfs_fsid.val[1] = (int)AFS_VFSFSID;
285 #else
286     vfs_getnewfsid(mp);
287     afs_dynamic_fsid = mp->mnt_stat.f_fsidx;
288 #endif
289     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1,
290                     &size);
291     bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
292     bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
293     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
294     /* null terminated string "AFS" will fit, just leave it be. */
295     strcpy(mp->mnt_stat.f_fstypename, AFS_MOUNT_AFS);
296     AFS_GUNLOCK();
297     (void)afs_statvfs(mp, &mp->mnt_stat, l);
298
299     afs_warn("afs_mount exit\n");
300
301     return 0;
302 }
303
304 int
305 afs_unmount(struct mount *mp, int mntflags, struct lwp *l)
306 {
307     extern int sys_ioctl(), sys_setgroups();
308
309     AFS_STATCNT(afs_unmount);
310 #ifdef AFS_DISCON_ENV
311     give_up_cbs();
312 #endif
313     if (afs_globalVFS == NULL) {
314         printf("afs already unmounted\n");
315         return 0;
316     }
317     if (afs_globalVp)
318         vrele(AFSTOV(afs_globalVp));
319     afs_globalVp = NULL;
320
321     vflush(mp, NULLVP, 0);      /* don't support forced */
322     mp->mnt_data = NULL;
323     AFS_GLOCK();
324     afs_globalVFS = 0;
325     afs_cold_shutdown = 1;
326     afs_shutdown();             /* XXX */
327     AFS_GUNLOCK();
328
329     printf
330         ("AFS unmounted--use `/sbin/modunload -i %d' to unload before restarting AFS\n",
331          lkmid);
332     return 0;
333 }
334
335 static int
336 afs_badcall(struct lwp *l, void *xx, register_t * yy)
337 {
338     return ENOSYS;
339 }
340
341 int
342 afs_root(struct mount *mp, struct vnode **vpp)
343 {
344     struct vrequest treq;
345     struct vcache *tvp;
346     int code, glocked;
347
348     AFS_STATCNT(afs_root);
349
350     glocked = ISAFS_GLOCK();
351     afs_warn("afs_root enter, glocked==%d\n", glocked);
352
353     AFS_GLOCK();
354
355     afs_warn("glocked\n");
356
357     if (!(code = afs_InitReq(&treq, osi_curcred()))
358         && !(code = afs_CheckInit())) {
359
360         afs_warn("afs_root: initReq && CheckInit: code==%d\n", code);
361
362         tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
363         afs_warn("afs_root: GetVCache: tvp==%lx\n", tvp);
364         if (tvp) {
365             /* There is really no reason to over-hold this bugger--it's held
366              * by the root filesystem reference. */
367             if (afs_globalVp != tvp) {
368 #ifdef AFS_DONT_OVERHOLD_GLOBALVP
369                 if (afs_globalVp)
370                     AFS_RELE(AFSTOV(afs_globalVp));
371 #endif
372                 afs_globalVp = tvp;
373                 VREF(AFSTOV(afs_globalVp));
374             }
375 /* v_flag no longer exists... mattjsm */
376 #ifdef AFS_NBSD50_ENV
377                 AFSTOV(tvp)->v_vflag |= VV_ROOT;
378 #else
379             AFSTOV(tvp)->v_flag |= VROOT;
380 #endif
381             afs_globalVFS = mp;
382             *vpp = AFSTOV(tvp);
383         } else
384             code = ENOENT;
385     }
386     AFS_GUNLOCK();
387
388     afs_warn("afs_root: gunlocked\n");
389
390     if (!code) {
391         if (!VOP_ISLOCKED(*vpp))
392             vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); /* return it locked */
393     }
394
395     afs_warn("afs_root exit\n");
396
397     return code;
398 }
399
400 int
401 afs_statvfs(struct mount *mp, struct statvfs *abp, struct lwp *l)
402 {
403     AFS_STATCNT(afs_statfs);
404
405     afs_warn("afs_statvfs enter\n");
406
407     /* thank you, NetBSD */
408     copy_statvfs_info(abp, mp);
409
410     /* not actually sure which we really must set, but
411      * pretty sure of the right values (and in 40, none touched by
412      * the above convenience function) */
413     abp->f_bsize = mp->osi_vfs_bsize;
414     abp->f_frsize = mp->osi_vfs_bsize;
415     abp->f_iosize = mp->osi_vfs_bsize;
416
417     /*
418      * Fake a high number below to satisfy programs that use the ustat (for
419      * * AIX), or statfs (for the rest) call to make sure that there's
420      * enough * space in the device partition before storing something there
421      * (like * ed(1))
422      */
423     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
424         abp->f_ffree = 9000000;
425
426     return (0);
427 }
428
429 int
430 afs_sync(struct mount *mp, int waitfor, kauth_cred_t cred, struct lwp *l)
431 {
432     AFS_STATCNT(afs_sync);
433 #if defined(AFS_DISCON_ENV)
434     /* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
435     store_dirty_vcaches();
436 #endif
437     return 0;
438 }
439
440 int
441 afs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
442 {
443     return (EOPNOTSUPP);
444 }
445
446 void
447 afs_init()
448 {
449     osi_Init();
450     return;
451 }
452
453 void
454 afs_reinit(void)
455 {
456     return;
457 }
458
459 /* LKM */
460
461 /*
462  * declare the filesystem
463  */
464 MOD_VFS("afs", -1, &afs_vfsops);
465
466 #if 0
467 static char afsgenmem[] = "afsgenmem";
468 static char afsfidmem[] = "afsfidmem";
469 static char afsbhdrmem[] = "afsbhdrmem";
470 static char afsbfrmem[] = "afsbfrmem";
471 #endif
472
473 int
474 afs_vfs_load(struct lkm_table *lkmtp, int cmd)
475 {
476 #if 0
477     extern char *memname[];
478
479     if (memname[M_AFSGENERIC] == NULL)
480         memname[M_AFSGENERIC] = afsgenmem;
481     if (memname[M_AFSFID] == NULL)
482         memname[M_AFSFID] = afsfidmem;
483     if (memname[M_AFSBUFHDR] == NULL)
484         memname[M_AFSBUFHDR] = afsbhdrmem;
485     if (memname[M_AFSBUFFER] == NULL)
486         memname[M_AFSBUFFER] = afsbfrmem;
487 #endif
488         lkmid = lkmtp->id;
489         if (sysent[AFS_SYSCALL].sy_call != sys_nosys) {
490                 printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
491                            AFS_SYSCALL);
492                 /* return EEXIST; */
493     }
494
495     old_sysent = sysent[AFS_SYSCALL];
496     sysent[AFS_SYSCALL] = afs_sysent;
497
498         printf("OpenAFS lkm loaded id: %d\n", lkmid);
499
500     return (0);
501 }
502
503 int
504 afs_vfs_unload(struct lkm_table *lktmp, int cmd)
505 {
506 #if 0
507     extern char *memname[];
508 #endif
509
510     if (afs_globalVp)
511         return EBUSY;
512 #if 0
513     if (memname[M_AFSGENERIC] == afsgenmem)
514         memname[M_AFSGENERIC] = NULL;
515     if (memname[M_AFSFID] == afsfidmem)
516         memname[M_AFSFID] = NULL;
517     if (memname[M_AFSBUFHDR] == afsbhdrmem)
518         memname[M_AFSBUFHDR] = NULL;
519     if (memname[M_AFSBUFFER] == afsbfrmem)
520         memname[M_AFSBUFFER] = NULL;
521 #endif
522
523     if (sysent[AFS_SYSCALL].sy_call != afs_sysent.sy_call) {
524         printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
525                AFS_SYSCALL);
526         return EEXIST;
527     }
528
529     sysent[AFS_SYSCALL] = old_sysent;
530     printf("OpenAFS unloaded\n");
531
532     return (0);
533 }
534
535 int
536 libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
537 {
538     if (cmd == LKM_E_LOAD) {
539         if (sysent[AFS_SYSCALL].sy_call == afs3_syscall
540             || sysent[AFS_SYSCALL].sy_call == afs_badcall) {
541             printf("AFS already loaded\n");
542             return EINVAL;
543         }
544     }
545
546 #if DEBUG
547     afs_debug = AFSDEB_VNLAYER;
548 #endif
549
550     DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc);
551 }