venus: Remove dedebug
[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 #ifndef AFS_NBSD60_ENV
103 #include <sys/lkm.h>
104 #endif
105 #include <sys/namei.h>
106 #include <miscfs/genfs/genfs.h>
107
108 VFS_PROTOS(afs);
109
110 #ifndef AFS_NBSD60_ENV
111 extern int sys_lkmnosys(struct lwp *, const void *, register_t *);
112 extern int afs3_syscall(struct lwp *, const void *, register_t *);
113 extern int Afs_xsetgroups(struct lwp *, const void *, register_t *);
114 static int afs_badcall(struct lwp *, const void *, register_t *);
115
116 static int lkmid = -1;
117
118 struct sysent afs_sysent = { 6,
119                              sizeof(struct afs_sysargs),
120                              0,
121                              afs3_syscall};
122
123 static struct sysent old_sysent;
124 static struct sysent old_setgroups;
125 #endif
126
127 struct osi_vfs *afs_globalVFS;
128 struct vcache *afs_globalVp;
129 fsid_t afs_dynamic_fsid;
130
131 int afs_mount(struct mount *, const char *, void *, size_t *);
132 int afs_start(struct mount *, int);
133 int afs_unmount(struct mount *, int);
134 int afs_root(struct mount *, struct vnode **);
135 int afs_statvfs(struct mount *, struct statvfs *);
136 int afs_sync(struct mount *, int, kauth_cred_t);
137 void afs_init(void);
138 void afs_reinit(void);
139 void afs_done(void);
140
141 extern struct vnodeopv_desc afs_vnodeop_opv_desc;
142 static const struct vnodeopv_desc *afs_vnodeopv_descs[] = {
143         &afs_vnodeop_opv_desc,
144         NULL,
145 };
146
147 struct vfsops afs_vfsops = {
148     AFS_MOUNT_STR,
149 #ifdef AFS_NBSD50_ENV
150         0,                                              /* vfs_min_mount_data */
151 #endif
152     afs_mount,
153     afs_start,
154     afs_unmount,
155     afs_root,
156     (void *) eopnotsupp,        /* vfs_quotactl */
157     afs_statvfs,
158     afs_sync,
159     (void *) eopnotsupp,        /* vfs_vget */
160     (void *) eopnotsupp,        /* vfs_fhtovp */
161     (void *) eopnotsupp,        /* vfs_vptofh */
162     afs_init,
163     afs_reinit,
164     afs_done,
165     (void *) eopnotsupp,        /* vfs_mountroot */
166     (void *) eopnotsupp,        /* vfs_snapshot */
167     vfs_stdextattrctl,
168 #ifdef AFS_NBSD50_ENV
169     (void *) eopnotsupp,        /* vfs_suspendctl */
170     genfs_renamelock_enter,     /* vfs_renamelock_enter */
171     genfs_renamelock_exit,      /* vfs_renamelock_exit */
172     (void *) eopnotsupp,        /* vfs_fsync */
173 #endif
174     afs_vnodeopv_descs,
175     0,                          /* vfs_refcount */
176     { NULL, NULL },
177 };
178
179 int
180 afs_nbsd_lookupname(const char *fnamep, enum uio_seg segflg, int followlink,
181                     struct vnode **compvpp)
182 {
183     struct nameidata nd;
184     int niflag;
185     int error;
186
187     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
188         afs_warn("afs_nbsd_lookupname enter (%s)\n", fnamep);
189     }
190
191     /*
192      * Lookup pathname "fnamep", returning leaf in *compvpp.  segflg says
193      * whether the pathname is user or system space.
194      */
195     /* XXX LOCKLEAF ? */
196     niflag = followlink ? FOLLOW : NOFOLLOW;
197         /*
198         *       NBSD50 seems to have stopped caring about the curproc of things.
199         *       mattjsm
200         */
201 #if defined(AFS_NBSD60_ENV)
202     struct pathbuf *ipb = NULL;
203     ipb = pathbuf_create(fnamep);
204     NDINIT(&nd, LOOKUP, niflag, ipb);
205 #elif defined(AFS_NBSD50_ENV)
206     NDINIT(&nd, LOOKUP, niflag, segflg, fnamep);
207 #else
208     NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc());
209 #endif
210     if ((error = namei(&nd))) {
211         goto out;
212     }
213     *compvpp = nd.ni_vp;
214 out:
215 #if defined(AFS_NBSD60_ENV)
216     pathbuf_destroy(ipb);
217 #endif
218     return error;
219 }
220
221 int
222 afs_start(struct mount *mp, int flags)
223 {
224     return (0); /* nothing to do? */
225 }
226
227 void afs_done(void)
228 {
229     return; /* nothing to do? */
230 }
231
232 int
233 afs_mount(struct mount *mp, const char *path, void *data,
234           size_t *dlen)
235 {
236     /* ndp contains the mounted-from device.  Just ignore it.
237      * we also don't care about our proc struct. */
238     size_t size;
239
240     AFS_STATCNT(afs_mount);
241
242     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
243         afs_warn("afs_mount enter\n");
244     }
245
246     if (mp->mnt_flag & MNT_UPDATE)
247         return EINVAL;
248
249     if (afs_globalVFS != NULL) {
250         /* Don't allow remounts */
251         return EBUSY;
252     }
253
254     AFS_GLOCK();
255 #ifdef AFS_DISCON_ENV
256     /* initialize the vcache entries before we start using them */
257
258     /* XXX find a better place for this if possible  */
259     init_vcache_entries();
260 #endif
261     afs_globalVFS = mp;
262     mp->mnt_stat.f_bsize = 8192;
263     mp->mnt_stat.f_frsize = 8192;
264     mp->mnt_stat.f_iosize = 8192;
265     mp->mnt_fs_bshift = DEV_BSHIFT;
266     mp->mnt_dev_bshift = DEV_BSHIFT;
267     vfs_getnewfsid(mp);
268     afs_dynamic_fsid = mp->mnt_stat.f_fsidx;
269     (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1,
270                     &size);
271     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
272     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
273     strcpy(mp->mnt_stat.f_mntfromname, "AFS");
274     /* null terminated string "AFS" will fit, just leave it be. */
275     strcpy(mp->mnt_stat.f_fstypename, AFS_MOUNT_STR);
276     AFS_GUNLOCK();
277     (void)afs_statvfs(mp, &mp->mnt_stat);
278
279     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
280         afs_warn("afs_mount exit\n");
281     }
282
283     return 0;
284 }
285
286 int
287 afs_unmount(struct mount *mp, int mntflags)
288 {
289     AFS_STATCNT(afs_unmount);
290 #ifdef AFS_DISCON_ENV
291     give_up_cbs();
292 #endif
293     if (afs_globalVFS == NULL) {
294         printf("afs already unmounted\n");
295         return 0;
296     }
297     if (afs_globalVp)
298         vrele(AFSTOV(afs_globalVp));
299     afs_globalVp = NULL;
300
301     vflush(mp, NULLVP, 0);      /* don't support forced */
302     AFS_GLOCK();
303     afs_globalVFS = NULL;
304     afs_shutdown(AFS_COLD);
305     AFS_GUNLOCK();
306
307     mp->mnt_data = NULL;
308
309     printf("AFS unmounted.\n");
310     return 0;
311 }
312
313 #ifndef AFS_NBSD60_ENV
314 static int
315 afs_badcall(struct lwp *l, const void *xx, register_t *yy)
316 {
317     return ENOSYS;
318 }
319 #endif
320
321 int
322 afs_root(struct mount *mp, struct vnode **vpp)
323 {
324     struct vrequest treq;
325     struct vcache *tvp;
326     struct vcache *gvp;
327     int code;
328
329     AFS_STATCNT(afs_root);
330
331     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
332         int glocked = ISAFS_GLOCK();
333         afs_warn("afs_root enter, glocked==%d\n", glocked);
334     }
335
336     AFS_GLOCK();
337
338     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
339         afs_warn("afs_root: glocked\n");
340     }
341
342     tvp = NULL;
343 tryagain:
344     if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
345         tvp = afs_globalVp;
346         code = 0;
347     } else {
348         if (afs_globalVp) {
349             gvp = afs_globalVp;
350             afs_globalVp = NULL;
351             afs_PutVCache(gvp);
352         }
353
354         if (!(code = afs_InitReq(&treq, osi_curcred()))
355             && !(code = afs_CheckInit())) {
356             tvp = afs_GetVCache(&afs_rootFid, &treq);
357
358             if (tvp) {
359                 if (afs_globalVp) {
360
361                     afs_PutVCache(tvp);
362                     tvp = NULL;
363                     goto tryagain;
364                 }
365                 afs_globalVp = tvp;
366             } else
367                 code = EIO;
368         }
369     }
370     if (tvp) {
371         struct vnode *vp = AFSTOV(tvp);
372         AFS_GUNLOCK();
373         vref(vp);
374         if (code != 0) {
375                 vrele(vp);
376                 return code;
377         }
378         if (!VOP_ISLOCKED(*vpp))
379             code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
380         AFS_GLOCK();
381         if (!afs_globalVp || !(afs_globalVp->f.states & CStatd) ||
382             tvp != afs_globalVp) {
383             vput(vp);
384             afs_PutVCache(tvp);
385             tvp = NULL;
386             goto tryagain;
387         }
388         if (code != 0)
389             goto tryagain;
390         vp->v_vflag |= VV_ROOT;
391         if (afs_globalVFS != mp)
392             afs_globalVFS = mp;
393         *vpp = vp;
394     }
395     AFS_GUNLOCK();
396
397     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
398         afs_warn("afs_root exit\n");
399     }
400
401     return code;
402 }
403
404 int
405 afs_statvfs(struct mount *mp, struct statvfs *abp)
406 {
407     AFS_STATCNT(afs_statfs);
408
409     if ((afs_debug & AFSDEB_VNLAYER) != 0) {
410         afs_warn("afs_statvfs enter\n");
411     }
412
413     /* thank you, NetBSD */
414     copy_statvfs_info(abp, mp);
415
416     /* not actually sure which we really must set, but
417      * pretty sure of the right values (and in 40, none touched by
418      * the above convenience function) */
419     abp->f_bsize = mp->osi_vfs_bsize;
420     abp->f_frsize = mp->osi_vfs_bsize;
421     abp->f_iosize = mp->osi_vfs_bsize;
422
423     abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
424         abp->f_ffree = AFS_VFS_FAKEFREE;
425
426     return (0);
427 }
428
429 int
430 afs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
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 void
441 afs_init(void)
442 {
443     osi_Init();
444     return;
445 }
446
447 void
448 afs_reinit(void)
449 {
450     return;
451 }
452
453 #ifndef AFS_NBSD60_ENV
454 /* LKM */
455
456 /*
457  * declare the filesystem
458  */
459 MOD_VFS("afs", -1, &afs_vfsops);
460
461 static int
462 afs_vfs_load(struct lkm_table *lkmtp, int cmd)
463 {
464     lkmid = lkmtp->id;
465     if (sysent[AFS_SYSCALL].sy_call != sys_lkmnosys) {
466         printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
467             AFS_SYSCALL);
468         /* return EEXIST; */
469     }
470
471     old_sysent = sysent[AFS_SYSCALL];
472     sysent[AFS_SYSCALL] = afs_sysent;
473     old_setgroups = sysent[SYS_setgroups];
474     sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
475 #if NOTYET
476     old_ioctl = sysent[SYS_ioctl];
477     sysent[SYS_ioctl].sy_call = afs_xioctl;
478 #endif
479
480     aprint_verbose("OpenAFS loaded\n");
481
482     return (0);
483 }
484
485 static int
486 afs_vfs_unload(struct lkm_table *lktmp, int cmd)
487 {
488     if (afs_globalVp)
489         return EBUSY;
490
491     if (sysent[AFS_SYSCALL].sy_call != afs_sysent.sy_call) {
492         printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
493                AFS_SYSCALL);
494         return EEXIST;
495     }
496
497     sysent[AFS_SYSCALL] = old_sysent;
498     sysent[SYS_setgroups] = old_setgroups;
499 #if NOTYET
500     sysent[SYS_ioctl] = old_ioctl;
501 #endif
502     printf("OpenAFS unloaded\n");
503
504     return (0);
505 }
506
507 int libafs_lkmentry(struct lkm_table *, int, int);
508
509 int
510 libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
511 {
512     if (cmd == LKM_E_LOAD) {
513         if (sysent[AFS_SYSCALL].sy_call == afs3_syscall
514             || sysent[AFS_SYSCALL].sy_call == afs_badcall) {
515             printf("AFS already loaded\n");
516             return EINVAL;
517         }
518     }
519
520     DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc);
521 }
522 #endif