922b1d591a9ba51950d6278739f8cae10c0bb631
[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
104 #if 0
105 /* from /usr/src/sys/kern/vfs_subr.c */
106 extern void insmntque(struct vnode *, struct mount *);
107 #endif
108 extern int sys_lkmnosys(), afs3_syscall(), afs_xioctl(), Afs_xsetgroups();
109
110 static int lkmid = -1;
111 static int afs_badcall(struct lwp *, void *, register_t *);
112
113 #if 0
114 int
115 newcall(l, v, retval)
116         struct lwp *l;
117         void *v;
118         int *retval;
119 {
120         struct afs_sysargs *uap = v;
121
122         printf("kmod: newcall: %ld %ld %ld %ld\n",
123                SCARG(uap, syscall), SCARG(uap, parm1),
124                SCARG(uap, parm2), SCARG(uap, parm3));
125         return(0);
126 }
127 #endif
128
129 struct sysent afs_sysent = { 6,
130                              sizeof(struct afs_sysargs),
131                              0,
132                              afs3_syscall};
133
134 static struct sysent old_sysent;
135
136 struct osi_vfs *afs_globalVFS;
137 struct vcache *afs_globalVp;
138 fsid_t afs_dynamic_fsid;
139
140 int afs_mount(struct mount *, const char *, void *,
141               struct nameidata *, struct lwp *);
142 int afs_start(struct mount *, int, struct lwp *);
143 int afs_unmount(struct mount *, int, struct lwp *);
144 int afs_root(struct mount *, struct vnode **);
145 int afs_quotactl(struct mount *, int, uid_t, void *, struct lwp *);
146 int afs_statvfs(struct mount *, struct statvfs *, struct lwp *);
147 int afs_sync(struct mount *, int, kauth_cred_t, struct lwp *);
148 int afs_vget(struct mount *, ino_t, struct vnode **);
149 void afs_init(void);
150 void afs_reinit(void);
151 void afs_done(void);
152
153 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
154 static const struct vnodeopv_desc *afs_vnodeopv_descs[] = {
155         &afs_vnodeop_opv_desc,
156         NULL,
157 };
158
159 struct vfsops afs_vfsops = {
160     AFS_MOUNT_AFS,
161     afs_mount,
162     afs_start,
163     afs_unmount,
164     afs_root,
165     afs_quotactl,
166     afs_statvfs,
167     afs_sync,
168     afs_vget,
169     (void *) eopnotsupp,        /* vfs_fhtovp */
170     (void *) eopnotsupp,        /* vfs_vptofh */
171     afs_init,
172     afs_reinit,
173     afs_done,
174     (int (*) (void)) eopnotsupp, /* mountroot */
175     (int (*)(struct mount *, struct vnode *, struct timespec *)) eopnotsupp,
176     vfs_stdextattrctl,
177     afs_vnodeopv_descs,
178     0,                  /* vfs_refcount */
179     { NULL, NULL },
180 };
181
182 VFS_ATTACH(afs_vfsops);
183
184 int
185 afs_nbsd_lookupname(char *fnamep, enum uio_seg segflg, int followlink,
186                     struct vnode **compvpp)
187 {
188     struct nameidata nd;
189     int niflag;
190     int error;
191
192     afs_warn("afs_nbsd_lookupname enter (%s)\n", fnamep);
193
194     /*
195      * Lookup pathname "fnamep", returning leaf in *compvpp.  segflg says
196      * whether the pathname is user or system space.
197      */
198     /* XXX LOCKLEAF ? */
199     niflag = followlink ? FOLLOW : NOFOLLOW;
200     NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc());
201     if ((error = namei(&nd)))
202         return error;
203     *compvpp = nd.ni_vp;
204     return error;
205 }
206
207 int
208 afs_quotactl(struct mount *mp, int cmd, uid_t uid,
209     void *arg, struct lwp *l)
210 {
211     return EOPNOTSUPP;
212 }
213
214 int
215 afs_sysctl()
216 {
217     return EOPNOTSUPP;
218 }
219
220 int
221 afs_start(struct mount *mp, int flags, struct lwp *l)
222 {
223     return (0); /* nothing to do? */
224 }
225
226 void afs_done(void)
227 {
228     return; /* nothing to do? */
229 }
230
231 int
232 afs_mount(struct mount *mp, const char *path, void *data,
233           struct nameidata *ndp, struct lwp *l)
234 {
235     /* ndp contains the mounted-from device.  Just ignore it.
236      * we also don't care about our proc struct. */
237     u_int size;
238
239     AFS_STATCNT(afs_mount);
240
241     afs_warn("afs_mount enter\n");
242
243     if (mp->mnt_flag & MNT_UPDATE)
244         return EINVAL;
245
246     if (afs_globalVFS) {
247         /* Don't allow remounts */
248         return EBUSY;
249     }
250
251     AFS_GLOCK();
252     /* initialize the vcache entries before we start using them */
253
254     /* XXX find a better place for this if possible  */
255     init_vcache_entries();
256     afs_globalVFS = mp;
257     mp->mnt_stat.f_bsize = 8192;
258     mp->mnt_stat.f_frsize = 8192;
259     mp->mnt_stat.f_iosize = 8192;
260 #if 0
261     mp->osi_vfs_fsid.val[0] = AFS_VFSMAGIC;     /* magic */
262     mp->osi_vfs_fsid.val[1] = (int)AFS_VFSFSID;
263 #else
264     vfs_getnewfsid(mp);
265     afs_dynamic_fsid = mp->mnt_stat.f_fsidx;
266 #endif
267     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1,
268                     &size);
269     bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
270     bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
271     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
272     /* null terminated string "AFS" will fit, just leave it be. */
273     strcpy(mp->mnt_stat.f_fstypename, AFS_MOUNT_AFS);
274     AFS_GUNLOCK();
275     (void)afs_statvfs(mp, &mp->mnt_stat, l);
276
277     afs_warn("afs_mount exit\n");
278
279     return 0;
280 }
281
282 int
283 afs_unmount(struct mount *mp, int mntflags, struct lwp *l)
284 {
285     extern int sys_ioctl(), sys_setgroups();
286
287     AFS_STATCNT(afs_unmount);
288     give_up_cbs();
289     if (afs_globalVFS == NULL) {
290         printf("afs already unmounted\n");
291         return 0;
292     }
293     if (afs_globalVp)
294         vrele(AFSTOV(afs_globalVp));
295     afs_globalVp = NULL;
296
297     vflush(mp, NULLVP, 0);      /* don't support forced */
298     mp->mnt_data = NULL;
299     AFS_GLOCK();
300     afs_globalVFS = 0;
301     afs_cold_shutdown = 1;
302     afs_shutdown();             /* XXX */
303     AFS_GUNLOCK();
304
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 lwp *l, void *xx, register_t * yy)
313 {
314     return ENOSYS;
315 }
316
317 int
318 afs_root(struct mount *mp, struct vnode **vpp)
319 {
320     struct vrequest treq;
321     struct vcache *tvp;
322     int code, glocked;
323
324     AFS_STATCNT(afs_root);
325
326     glocked = ISAFS_GLOCK();
327     afs_warn("afs_root enter, glocked==%d\n", glocked);
328
329     AFS_GLOCK();
330
331     afs_warn("glocked\n");
332
333     if (!(code = afs_InitReq(&treq, osi_curcred()))
334         && !(code = afs_CheckInit())) {
335
336         afs_warn("afs_root: initReq && CheckInit: code==%d\n", code);
337
338         tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
339         afs_warn("afs_root: GetVCache: tvp==%lx\n", tvp);
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                 VREF(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     afs_warn("afs_root: gunlocked\n");
360
361     if (!code) {
362         if (!VOP_ISLOCKED(*vpp))
363             vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); /* return it locked */
364     }
365
366     afs_warn("afs_root exit\n");
367
368     return code;
369 }
370
371 int
372 afs_statvfs(struct mount *mp, struct statvfs *abp, struct lwp *l)
373 {
374     AFS_STATCNT(afs_statfs);
375
376     afs_warn("afs_statvfs enter\n");
377
378     /* thank you, NetBSD */
379     copy_statvfs_info(abp, mp);
380
381     /* not actually sure which we really must set, but
382      * pretty sure of the right values (and in 40, none touched by
383      * the above convenience function) */
384     abp->f_bsize = mp->osi_vfs_bsize;
385     abp->f_frsize = mp->osi_vfs_bsize;
386     abp->f_iosize = mp->osi_vfs_bsize;
387
388     /*
389      * Fake a high number below to satisfy programs that use the ustat (for
390      * * AIX), or statfs (for the rest) call to make sure that there's
391      * enough * space in the device partition before storing something there
392      * (like * ed(1))
393      */
394     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
395         abp->f_ffree = 9000000;
396
397     return (0);
398 }
399
400 int
401 afs_sync(struct mount *mp, int waitfor, kauth_cred_t cred, struct lwp *l)
402 {
403     AFS_STATCNT(afs_sync);
404     /* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
405     store_dirty_vcaches();
406     return 0;
407 }
408
409 int
410 afs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
411 {
412     return (EOPNOTSUPP);
413 }
414
415 void
416 afs_init()
417 {
418     osi_Init();
419     return;
420 }
421
422 void
423 afs_reinit(void)
424 {
425     return;
426 }
427
428 /* LKM */
429
430 /*
431  * declare the filesystem
432  */
433 MOD_VFS("afs", -1, &afs_vfsops);
434
435 #if 0
436 static char afsgenmem[] = "afsgenmem";
437 static char afsfidmem[] = "afsfidmem";
438 static char afsbhdrmem[] = "afsbhdrmem";
439 static char afsbfrmem[] = "afsbfrmem";
440 #endif
441
442 int
443 afs_vfs_load(struct lkm_table *lkmtp, int cmd)
444 {
445 #if 0
446     extern char *memname[];
447
448     if (memname[M_AFSGENERIC] == NULL)
449         memname[M_AFSGENERIC] = afsgenmem;
450     if (memname[M_AFSFID] == NULL)
451         memname[M_AFSFID] = afsfidmem;
452     if (memname[M_AFSBUFHDR] == NULL)
453         memname[M_AFSBUFHDR] = afsbhdrmem;
454     if (memname[M_AFSBUFFER] == NULL)
455         memname[M_AFSBUFFER] = afsbfrmem;
456 #endif
457     lkmid = lkmtp->id;
458
459     if (sysent[AFS_SYSCALL].sy_call != sys_nosys) {
460         printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
461                AFS_SYSCALL);
462         /* return EEXIST; */
463     }
464
465     old_sysent = sysent[AFS_SYSCALL];
466     sysent[AFS_SYSCALL] = afs_sysent;
467
468     printf("OpenAFS lkm loaded\n");
469
470     return (0);
471 }
472
473 int
474 afs_vfs_unload(struct lkm_table *lktmp, int cmd)
475 {
476 #if 0
477     extern char *memname[];
478 #endif
479
480     if (afs_globalVp)
481         return EBUSY;
482 #if 0
483     if (memname[M_AFSGENERIC] == afsgenmem)
484         memname[M_AFSGENERIC] = NULL;
485     if (memname[M_AFSFID] == afsfidmem)
486         memname[M_AFSFID] = NULL;
487     if (memname[M_AFSBUFHDR] == afsbhdrmem)
488         memname[M_AFSBUFHDR] = NULL;
489     if (memname[M_AFSBUFFER] == afsbfrmem)
490         memname[M_AFSBUFFER] = NULL;
491 #endif
492
493     if (sysent[AFS_SYSCALL].sy_call != afs_sysent.sy_call) {
494         printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
495                AFS_SYSCALL);
496         return EEXIST;
497     }
498
499     sysent[AFS_SYSCALL] = old_sysent;
500     printf("OpenAFS unloaded\n");
501
502     return (0);
503 }
504
505 int
506 libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
507 {
508     if (cmd == LKM_E_LOAD) {
509         if (sysent[AFS_SYSCALL].sy_call == afs3_syscall
510             || sysent[AFS_SYSCALL].sy_call == afs_badcall) {
511             printf("AFS already loaded\n");
512             return EINVAL;
513         }
514     }
515     DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc);
516 }