Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / afs / NBSD / osi_vfsops.c
CommitLineData
805e021f
CE
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/*
11copyright 2002
12the regents of the university of michigan
13all rights reserved
14
15permission is granted to use, copy, create derivative works
16and redistribute this software and such derivative works
17for any purpose, so long as the name of the university of
18michigan is not used in any advertising or publicity
19pertaining to the use or distribution of this software
20without specific, written prior authorization. if the
21above copyright notice or any other identification of the
22university of michigan is included in any copy of any
23portion of this software, then the disclaimer below must
24also be included.
25
26this software is provided as is, without representation
27from the university of michigan as to its fitness for any
28purpose, and without warranty by the university of
29michigan of any kind, either express or implied, including
30without limitation the implied warranties of
31merchantability and fitness for a particular purpose. the
32regents of the university of michigan shall not be liable
33for any damages, including special, indirect, incidental, or
34consequential damages, with respect to any claim arising
35out of or in connection with the use of the software, even
36if it has been or is hereafter advised of the possibility of
37such damages.
38*/
39
40/*
41Copyright 1995 Massachusetts Institute of Technology. All Rights
42Reserved.
43
44You are hereby granted a worldwide, irrevocable, paid-up, right and
45license to use, execute, display, modify, copy and distribute MIT's
46Modifications, provided that (i) you abide by the terms and conditions
47of the OpenAFS License Agreement, and (ii) you do not use the name
48of MIT in any advertising or publicity without the prior written consent
49of MIT. MIT disclaims all liability for your use of MIT's
50Modifications. MIT's Modifications are provided "AS IS" WITHOUT
51WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,
52ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
53NONINFRINGEMENT.
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
108VFS_PROTOS(afs);
109
110#ifndef AFS_NBSD60_ENV
111extern int sys_lkmnosys(struct lwp *, const void *, register_t *);
112extern int afs3_syscall(struct lwp *, const void *, register_t *);
113extern int afs_xioctl(struct lwp *, const void *, register_t *);
114extern int Afs_xsetgroups(struct lwp *, const void *, register_t *);
115static int afs_badcall(struct lwp *, const void *, register_t *);
116
117static int lkmid = -1;
118
119struct sysent afs_sysent = { 6,
120 sizeof(struct afs_sysargs),
121 0,
122 afs3_syscall};
123
124static struct sysent old_sysent;
125static struct sysent old_setgroups;
126#endif
127
128struct osi_vfs *afs_globalVFS;
129struct vcache *afs_globalVp;
130fsid_t afs_dynamic_fsid;
131
132int afs_mount(struct mount *, const char *, void *, size_t *);
133int afs_start(struct mount *, int);
134int afs_unmount(struct mount *, int);
135int afs_root(struct mount *, struct vnode **);
136int afs_statvfs(struct mount *, struct statvfs *);
137int afs_sync(struct mount *, int, kauth_cred_t);
138void afs_init(void);
139void afs_reinit(void);
140void afs_done(void);
141
142extern struct vnodeopv_desc afs_vnodeop_opv_desc;
143static const struct vnodeopv_desc *afs_vnodeopv_descs[] = {
144 &afs_vnodeop_opv_desc,
145 NULL,
146};
147
148struct vfsops afs_vfsops = {
149 AFS_MOUNT_AFS,
150#ifdef AFS_NBSD50_ENV
151 0, /* vfs_min_mount_data */
152#endif
153 afs_mount,
154 afs_start,
155 afs_unmount,
156 afs_root,
157 (void *) eopnotsupp, /* vfs_quotactl */
158 afs_statvfs,
159 afs_sync,
160 (void *) eopnotsupp, /* vfs_vget */
161 (void *) eopnotsupp, /* vfs_fhtovp */
162 (void *) eopnotsupp, /* vfs_vptofh */
163 afs_init,
164 afs_reinit,
165 afs_done,
166 (void *) eopnotsupp, /* vfs_mountroot */
167 (void *) eopnotsupp, /* vfs_snapshot */
168 vfs_stdextattrctl,
169#ifdef AFS_NBSD50_ENV
170 (void *) eopnotsupp, /* vfs_suspendctl */
171 genfs_renamelock_enter, /* vfs_renamelock_enter */
172 genfs_renamelock_exit, /* vfs_renamelock_exit */
173 (void *) eopnotsupp, /* vfs_fsync */
174#endif
175 afs_vnodeopv_descs,
176 0, /* vfs_refcount */
177 { NULL, NULL },
178};
179
180int
181afs_nbsd_lookupname(const char *fnamep, enum uio_seg segflg, int followlink,
182 struct vnode **compvpp)
183{
184 struct nameidata nd;
185 int niflag;
186 int error;
187
188 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
189 afs_warn("afs_nbsd_lookupname enter (%s)\n", fnamep);
190 }
191
192 /*
193 * Lookup pathname "fnamep", returning leaf in *compvpp. segflg says
194 * whether the pathname is user or system space.
195 */
196 /* XXX LOCKLEAF ? */
197 niflag = followlink ? FOLLOW : NOFOLLOW;
198 /*
199 * NBSD50 seems to have stopped caring about the curproc of things.
200 * mattjsm
201 */
202#if defined(AFS_NBSD60_ENV)
203 struct pathbuf *ipb = NULL;
204 ipb = pathbuf_create(fnamep);
205 NDINIT(&nd, LOOKUP, niflag, ipb);
206#elif defined(AFS_NBSD50_ENV)
207 NDINIT(&nd, LOOKUP, niflag, segflg, fnamep);
208#else
209 NDINIT(&nd, LOOKUP, niflag, segflg, fnamep, osi_curproc());
210#endif
211 if ((error = namei(&nd))) {
212 goto out;
213 }
214 *compvpp = nd.ni_vp;
215out:
216#if defined(AFS_NBSD60_ENV)
217 pathbuf_destroy(ipb);
218#endif
219 return error;
220}
221
222int
223afs_start(struct mount *mp, int flags)
224{
225 return (0); /* nothing to do? */
226}
227
228void afs_done(void)
229{
230 return; /* nothing to do? */
231}
232
233int
234afs_mount(struct mount *mp, const char *path, void *data,
235 size_t *dlen)
236{
237 /* ndp contains the mounted-from device. Just ignore it.
238 * we also don't care about our proc struct. */
239 size_t size;
240
241 AFS_STATCNT(afs_mount);
242
243 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
244 afs_warn("afs_mount enter\n");
245 }
246
247 if (mp->mnt_flag & MNT_UPDATE)
248 return EINVAL;
249
250 if (afs_globalVFS != NULL) {
251 /* Don't allow remounts */
252 return EBUSY;
253 }
254
255 AFS_GLOCK();
256#ifdef AFS_DISCON_ENV
257 /* initialize the vcache entries before we start using them */
258
259 /* XXX find a better place for this if possible */
260 init_vcache_entries();
261#endif
262 afs_globalVFS = mp;
263 mp->mnt_stat.f_bsize = 8192;
264 mp->mnt_stat.f_frsize = 8192;
265 mp->mnt_stat.f_iosize = 8192;
266 mp->mnt_fs_bshift = DEV_BSHIFT;
267 mp->mnt_dev_bshift = DEV_BSHIFT;
268 vfs_getnewfsid(mp);
269 afs_dynamic_fsid = mp->mnt_stat.f_fsidx;
270 (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1,
271 &size);
272 memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
273 memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
274 strcpy(mp->mnt_stat.f_mntfromname, "AFS");
275 /* null terminated string "AFS" will fit, just leave it be. */
276 strcpy(mp->mnt_stat.f_fstypename, AFS_MOUNT_AFS);
277 AFS_GUNLOCK();
278 (void)afs_statvfs(mp, &mp->mnt_stat);
279
280 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
281 afs_warn("afs_mount exit\n");
282 }
283
284 return 0;
285}
286
287int
288afs_unmount(struct mount *mp, int mntflags)
289{
290 AFS_STATCNT(afs_unmount);
291#ifdef AFS_DISCON_ENV
292 give_up_cbs();
293#endif
294 if (afs_globalVFS == NULL) {
295 printf("afs already unmounted\n");
296 return 0;
297 }
298 if (afs_globalVp)
299 vrele(AFSTOV(afs_globalVp));
300 afs_globalVp = NULL;
301
302 vflush(mp, NULLVP, 0); /* don't support forced */
303 AFS_GLOCK();
304 afs_globalVFS = NULL;
305 afs_cold_shutdown = 1;
306 afs_shutdown(); /* XXX */
307 AFS_GUNLOCK();
308
309 mp->mnt_data = NULL;
310
311 printf("AFS unmounted.\n");
312 return 0;
313}
314
315#ifndef AFS_NBSD60_ENV
316static int
317afs_badcall(struct lwp *l, const void *xx, register_t *yy)
318{
319 return ENOSYS;
320}
321#endif
322
323int
324afs_root(struct mount *mp, struct vnode **vpp)
325{
326 struct vrequest treq;
327 struct vcache *tvp;
328 struct vcache *gvp;
329 int code;
330
331 AFS_STATCNT(afs_root);
332
333 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
334 int glocked = ISAFS_GLOCK();
335 afs_warn("afs_root enter, glocked==%d\n", glocked);
336 }
337
338 AFS_GLOCK();
339
340 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
341 afs_warn("afs_root: glocked\n");
342 }
343
344 tvp = NULL;
345tryagain:
346 if (afs_globalVp && (afs_globalVp->f.states & CStatd)) {
347 tvp = afs_globalVp;
348 code = 0;
349 } else {
350 if (afs_globalVp) {
351 gvp = afs_globalVp;
352 afs_globalVp = NULL;
353 afs_PutVCache(gvp);
354 }
355
356 if (!(code = afs_InitReq(&treq, osi_curcred()))
357 && !(code = afs_CheckInit())) {
358 tvp = afs_GetVCache(&afs_rootFid, &treq, NULL, NULL);
359
360 if (tvp) {
361 if (afs_globalVp) {
362
363 afs_PutVCache(tvp);
364 tvp = NULL;
365 goto tryagain;
366 }
367 afs_globalVp = tvp;
368 } else
369 code = EIO;
370 }
371 }
372 if (tvp) {
373 struct vnode *vp = AFSTOV(tvp);
374 AFS_GUNLOCK();
375 vref(vp);
376 if (code != 0) {
377 vrele(vp);
378 return code;
379 }
380 if (!VOP_ISLOCKED(*vpp))
381 code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
382 AFS_GLOCK();
383 if (!afs_globalVp || !(afs_globalVp->f.states & CStatd) ||
384 tvp != afs_globalVp) {
385 vput(vp);
386 afs_PutVCache(tvp);
387 tvp = NULL;
388 goto tryagain;
389 }
390 if (code != 0)
391 goto tryagain;
392 vp->v_vflag |= VV_ROOT;
393 if (afs_globalVFS != mp)
394 afs_globalVFS = mp;
395 *vpp = vp;
396 }
397 AFS_GUNLOCK();
398
399 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
400 afs_warn("afs_root exit\n");
401 }
402
403 return code;
404}
405
406int
407afs_statvfs(struct mount *mp, struct statvfs *abp)
408{
409 AFS_STATCNT(afs_statfs);
410
411 if ((afs_debug & AFSDEB_VNLAYER) != 0) {
412 afs_warn("afs_statvfs enter\n");
413 }
414
415 /* thank you, NetBSD */
416 copy_statvfs_info(abp, mp);
417
418 /* not actually sure which we really must set, but
419 * pretty sure of the right values (and in 40, none touched by
420 * the above convenience function) */
421 abp->f_bsize = mp->osi_vfs_bsize;
422 abp->f_frsize = mp->osi_vfs_bsize;
423 abp->f_iosize = mp->osi_vfs_bsize;
424
425 abp->f_blocks = abp->f_bfree = abp->f_bavail = abp->f_files =
426 abp->f_ffree = AFS_VFS_FAKEFREE;
427
428 return (0);
429}
430
431int
432afs_sync(struct mount *mp, int waitfor, kauth_cred_t cred)
433{
434 AFS_STATCNT(afs_sync);
435#if defined(AFS_DISCON_ENV)
436 /* Can't do this in OpenBSD 2.7, it faults when called from apm_suspend() */
437 store_dirty_vcaches();
438#endif
439 return 0;
440}
441
442void
443afs_init(void)
444{
445 osi_Init();
446 return;
447}
448
449void
450afs_reinit(void)
451{
452 return;
453}
454
455#ifndef AFS_NBSD60_ENV
456/* LKM */
457
458/*
459 * declare the filesystem
460 */
461MOD_VFS("afs", -1, &afs_vfsops);
462
463static int
464afs_vfs_load(struct lkm_table *lkmtp, int cmd)
465{
466 lkmid = lkmtp->id;
467 if (sysent[AFS_SYSCALL].sy_call != sys_lkmnosys) {
468 printf("LKM afs_vfs_load(): AFS3 syscall %d already used\n",
469 AFS_SYSCALL);
470 /* return EEXIST; */
471 }
472
473 old_sysent = sysent[AFS_SYSCALL];
474 sysent[AFS_SYSCALL] = afs_sysent;
475 old_setgroups = sysent[SYS_setgroups];
476 sysent[SYS_setgroups].sy_call = Afs_xsetgroups;
477#if NOTYET
478 old_ioctl = sysent[SYS_ioctl];
479 sysent[SYS_ioctl].sy_call = afs_xioctl;
480#endif
481
482 aprint_verbose("OpenAFS loaded\n");
483
484 return (0);
485}
486
487static int
488afs_vfs_unload(struct lkm_table *lktmp, int cmd)
489{
490 if (afs_globalVp)
491 return EBUSY;
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 sysent[SYS_setgroups] = old_setgroups;
501#if NOTYET
502 sysent[SYS_ioctl] = old_ioctl;
503#endif
504 printf("OpenAFS unloaded\n");
505
506 return (0);
507}
508
509int libafs_lkmentry(struct lkm_table *, int, int);
510
511int
512libafs_lkmentry(struct lkm_table *lkmtp, int cmd, int ver)
513{
514 if (cmd == LKM_E_LOAD) {
515 if (sysent[AFS_SYSCALL].sy_call == afs3_syscall
516 || sysent[AFS_SYSCALL].sy_call == afs_badcall) {
517 printf("AFS already loaded\n");
518 return EINVAL;
519 }
520 }
521
522 DISPATCH(lkmtp, cmd, ver, afs_vfs_load, afs_vfs_unload, lkm_nofunc);
523}
524#endif