afs: Zero uninitialized uio structs
[openafs.git] / src / afs / OBSD / osi_vnodeops.c
1 /*
2  * OpenBSD specific vnodeops + other misc interface glue
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 your 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  * A bunch of code cribbed from NetBSD ufs_vnops.c, ffs_vnops.c, and
57  * nfs_vnops.c which carry this copyright:
58  */
59 /*
60  * Copyright (c) 1982, 1986, 1989, 1993
61  *      The Regents of the University of California.  All rights reserved.
62  * (c) UNIX System Laboratories, Inc.
63  * All or some portions of this file are derived from material licensed
64  * to the University of California by American Telephone and Telegraph
65  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
66  * the permission of UNIX System Laboratories, Inc.
67  *
68  * Redistribution and use in source and binary forms, with or without
69  * modification, are permitted provided that the following conditions
70  * are met:
71  * 1. Redistributions of source code must retain the above copyright
72  *    notice, this list of conditions and the following disclaimer.
73  * 2. Redistributions in binary form must reproduce the above copyright
74  *    notice, this list of conditions and the following disclaimer in the
75  *    documentation and/or other materials provided with the distribution.
76  * 3. All advertising materials mentioning features or use of this software
77  *    must display the following acknowledgement:
78  *      This product includes software developed by the University of
79  *      California, Berkeley and its contributors.
80  * 4. Neither the name of the University nor the names of its contributors
81  *    may be used to endorse or promote products derived from this software
82  *    without specific prior written permission.
83  *
84  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
85  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
87  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
88  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
90  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94  * SUCH DAMAGE.
95  *
96  */
97
98 #include <afsconfig.h>
99 #include "afs/param.h"
100
101
102 #include "afs/sysincludes.h"    /* Standard vendor system headers */
103 #include "afs/afsincludes.h"    /* Afs-based standard headers */
104 #include "afs/afs_stats.h"      /* statistics */
105
106 #include <sys/malloc.h>
107 #include <sys/namei.h>
108 #ifdef AFS_OBSD36_ENV
109 #include <sys/pool.h>
110 #endif
111
112 #include "afs/afs_cbqueue.h"
113 #include "afs/nfsclient.h"
114 #include "afs/afs_osidnlc.h"
115
116 #define M_AFSNODE (M_TEMP-1)    /* XXX */
117
118 int afs_obsd_lookup(void *);
119 int afs_obsd_create(void *);
120 int afs_obsd_mknod(void *);
121 int afs_obsd_open(void *);
122 int afs_obsd_close(void *);
123 int afs_obsd_access(void *);
124 int afs_obsd_getattr(void *);
125 int afs_obsd_setattr(void *);
126 int afs_obsd_read(void *);
127 int afs_obsd_write(void *);
128 int afs_obsd_ioctl(void *);
129 int afs_obsd_select(void *);
130 int afs_obsd_fsync(void *);
131 int afs_obsd_remove(void *);
132 int afs_obsd_link(void *);
133 int afs_obsd_rename(void *);
134 int afs_obsd_mkdir(void *);
135 int afs_obsd_rmdir(void *);
136 int afs_obsd_symlink(void *);
137 int afs_obsd_readdir(void *);
138 int afs_obsd_readlink(void *);
139 int afs_obsd_inactive(void *);
140 int afs_obsd_reclaim(void *);
141 int afs_obsd_lock(void *);
142 int afs_obsd_unlock(void *);
143 int afs_obsd_bmap(void *);
144 int afs_obsd_strategy(void *);
145 int afs_obsd_print(void *);
146 int afs_obsd_islocked(void *);
147 int afs_obsd_pathconf(void *);
148 int afs_obsd_advlock(void *);
149
150 #define afs_obsd_opnotsupp \
151         ((int (*) __P((void *)))eopnotsupp)
152 #define afs_obsd_reallocblks afs_obsd_opnotsupp
153
154 #if defined(AFS_OBSD49_ENV)
155
156 struct vops afs_vops = {
157         .vop_lookup     = afs_obsd_lookup,
158         .vop_create     = afs_obsd_create,
159         .vop_mknod      = afs_obsd_mknod,
160         .vop_open       = afs_obsd_open,
161         .vop_close      = afs_obsd_close,
162         .vop_access     = afs_obsd_access,
163         .vop_getattr    = afs_obsd_getattr,
164         .vop_setattr    = afs_obsd_setattr,
165         .vop_read       = afs_obsd_read,
166         .vop_write      = afs_obsd_write,
167         .vop_ioctl      = afs_obsd_ioctl,
168         .vop_poll       = afs_obsd_select,
169         .vop_fsync      = afs_obsd_fsync,
170         .vop_remove     = afs_obsd_remove,
171         .vop_link       = afs_obsd_link,
172         .vop_rename     = afs_obsd_rename,
173         .vop_mkdir      = afs_obsd_mkdir,
174         .vop_rmdir      = afs_obsd_rmdir,
175         .vop_symlink    = afs_obsd_symlink,
176         .vop_readdir    = afs_obsd_readdir,
177         .vop_readlink   = afs_obsd_readlink,
178         .vop_abortop    = vop_generic_abortop,
179         .vop_inactive   = afs_obsd_inactive,
180         .vop_reclaim    = afs_obsd_reclaim,
181         .vop_lock       = afs_obsd_lock,
182         .vop_unlock     = afs_obsd_unlock,
183         .vop_bmap       = afs_obsd_bmap,
184         .vop_strategy   = afs_obsd_strategy,
185         .vop_print      = afs_obsd_print,
186         .vop_islocked   = afs_obsd_islocked,
187         .vop_pathconf   = afs_obsd_pathconf,
188         .vop_advlock    = afs_obsd_advlock,
189         .vop_bwrite     = vop_generic_bwrite,
190 };
191
192 #else
193
194 /* Global vfs data structures for AFS. */
195 int (**afs_vnodeop_p) __P((void *));
196 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
197 #ifdef AFS_OBSD44_ENV /* feel free to zero in on this */
198   {&vop_default_desc, eopnotsupp},
199 #else
200     {&vop_default_desc, vn_default_error},
201 #endif
202     {&vop_lookup_desc, afs_obsd_lookup},        /* lookup */
203     {&vop_create_desc, afs_obsd_create},        /* create */
204     {&vop_mknod_desc, afs_obsd_mknod},          /* mknod */
205     {&vop_open_desc, afs_obsd_open},            /* open */
206     {&vop_close_desc, afs_obsd_close},          /* close */
207     {&vop_access_desc, afs_obsd_access},        /* access */
208     {&vop_getattr_desc, afs_obsd_getattr},      /* getattr */
209     {&vop_setattr_desc, afs_obsd_setattr},      /* setattr */
210     {&vop_read_desc, afs_obsd_read},            /* read */
211     {&vop_write_desc, afs_obsd_write},          /* write */
212     {&vop_ioctl_desc, afs_obsd_ioctl},          /* XXX ioctl */
213 #ifdef AFS_OBSD35_ENV
214     {&vop_poll_desc, afs_obsd_select},          /* select */
215 #else
216     {&vop_select_desc, afs_obsd_select},        /* select */
217 #endif
218     {&vop_fsync_desc, afs_obsd_fsync},          /* fsync */
219     {&vop_remove_desc, afs_obsd_remove},        /* remove */
220     {&vop_link_desc, afs_obsd_link},            /* link */
221     {&vop_rename_desc, afs_obsd_rename},        /* rename */
222     {&vop_mkdir_desc, afs_obsd_mkdir},          /* mkdir */
223     {&vop_rmdir_desc, afs_obsd_rmdir},          /* rmdir */
224     {&vop_symlink_desc, afs_obsd_symlink},      /* symlink */
225     {&vop_readdir_desc, afs_obsd_readdir},      /* readdir */
226     {&vop_readlink_desc, afs_obsd_readlink},    /* readlink */
227     {&vop_abortop_desc, vop_generic_abortop},   /* abortop */
228     {&vop_inactive_desc, afs_obsd_inactive},    /* inactive */
229     {&vop_reclaim_desc, afs_obsd_reclaim},      /* reclaim */
230     {&vop_lock_desc, afs_obsd_lock},            /* lock */
231     {&vop_unlock_desc, afs_obsd_unlock},        /* unlock */
232     {&vop_bmap_desc, afs_obsd_bmap},            /* bmap */
233     {&vop_strategy_desc, afs_obsd_strategy},    /* strategy */
234     {&vop_print_desc, afs_obsd_print},          /* print */
235     {&vop_islocked_desc, afs_obsd_islocked},    /* islocked */
236     {&vop_pathconf_desc, afs_obsd_pathconf},    /* pathconf */
237     {&vop_advlock_desc, afs_obsd_advlock},      /* advlock */
238     {&vop_reallocblks_desc, afs_obsd_reallocblks},      /* reallocblks */
239     {&vop_bwrite_desc, vop_generic_bwrite},
240     {NULL, (int (*)__P((void *)))NULL}
241 };
242 struct vnodeopv_desc afs_vnodeop_opv_desc =
243     { &afs_vnodeop_p, afs_vnodeop_entries };
244
245 #endif
246
247 #define GETNAME()       \
248     struct componentname *cnp = ap->a_cnp; \
249     char *name; \
250     BSD_KMALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
251     bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
252     name[cnp->cn_namelen] = '\0'
253
254 #define DROPNAME() BSD_KFREE(name, M_TEMP)
255
256 #ifdef AFS_OBSD36_ENV
257 #define DROPCNP(cnp) pool_put(&namei_pool, (cnp)->cn_pnbuf)
258 #else
259 #define DROPCNP(cnp) FREE((cnp)->cn_pnbuf, M_NAMEI)
260 #endif
261
262 int afs_debug;
263
264 int
265 afs_obsd_lookup(void *v)
266 {
267     struct vop_lookup_args      /* {
268                                  * struct vnodeop_desc * a_desc;
269                                  * struct vnode *a_dvp;
270                                  * struct vnode **a_vpp;
271                                  * struct componentname *a_cnp;
272                                  * } */ *ap = v;
273     int code;
274     struct vcache *vcp;
275     struct vnode *vp, *dvp;
276     int flags = ap->a_cnp->cn_flags;
277     int lockparent;             /* 1 => lockparent flag is set */
278     int wantparent;             /* 1 => wantparent or lockparent flag */
279
280     GETNAME();
281     lockparent = flags & LOCKPARENT;
282     wantparent = flags & (LOCKPARENT | WANTPARENT);
283 #ifdef PDIRUNLOCK
284     cnp->cn_flags &= ~PDIRUNLOCK;
285 #endif
286
287     if (ap->a_dvp->v_type != VDIR) {
288         *ap->a_vpp = NULL;
289         DROPNAME();
290         return ENOTDIR;
291     }
292     dvp = ap->a_dvp;
293     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
294         printf("nbsd_lookup dvp %p flags %x name %s cnt %d\n", dvp, flags,
295                name, dvp->v_usecount);
296     AFS_GLOCK();
297     code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
298     AFS_GUNLOCK();
299     if (code) {
300         if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
301             && (flags & ISLASTCN) && code == ENOENT)
302             code = EJUSTRETURN;
303         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
304             cnp->cn_flags |= SAVENAME;
305         DROPNAME();
306         *ap->a_vpp = NULL;
307         return (code);
308     }
309     vp = AFSTOV(vcp);           /* always get a node if no error */
310
311     /*
312      * The parent directory comes in locked.  We unlock it on return
313      * unless the caller wants it left locked.
314      * we also always return the vnode locked.
315      */
316
317     if (vp == dvp) {
318         /* they're the same; afs_lookup() already ref'ed the leaf.
319          * It came in locked, so we don't need to ref OR lock it */
320         if (afs_debug & AFSDEB_VNLAYER)
321             printf("ref'ed %p as .\n", dvp);
322     } else {
323         if (!lockparent || !(flags & ISLASTCN)) {
324             VOP_UNLOCK(dvp, 0, curproc);        /* done with parent. */
325 #ifdef PDIRUNLOCK
326             cnp->cn_flags |= PDIRUNLOCK;
327 #endif
328         }
329         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);  /* always return the child locked */
330         if (afs_debug & AFSDEB_VNLAYER)
331             printf("locked ret %p from lookup\n", vp);
332     }
333     *ap->a_vpp = vp;
334
335     if (((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN))
336          || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
337         cnp->cn_flags |= SAVENAME;
338
339     DROPNAME();
340     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
341         printf("nbsd_lookup done dvp %p cnt %d\n", dvp, dvp->v_usecount);
342     return code;
343 }
344
345 int
346 afs_obsd_create(void *v)
347 {
348     struct vop_create_args      /* {
349                                  * struct vnode *a_dvp;
350                                  * struct vnode **a_vpp;
351                                  * struct componentname *a_cnp;
352                                  * struct vattr *a_vap;
353                                  * } */ *ap = v;
354     int code = 0;
355     struct vcache *vcp;
356     struct vnode *dvp = ap->a_dvp;
357     GETNAME();
358
359     if (afs_debug & AFSDEB_VNLAYER)
360         printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount);
361
362     /* vnode layer handles excl/nonexcl */
363
364     AFS_GLOCK();
365     code =
366         afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
367                    &vcp, cnp->cn_cred);
368     AFS_GUNLOCK();
369     if (code) {
370         VOP_ABORTOP(dvp, cnp);
371         vput(dvp);
372         DROPNAME();
373         return (code);
374     }
375
376     if (vcp) {
377         *ap->a_vpp = AFSTOV(vcp);
378         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc);
379     } else
380         *ap->a_vpp = 0;
381
382     if ((cnp->cn_flags & SAVESTART) == 0)
383         DROPCNP(cnp);
384     vput(dvp);
385     DROPNAME();
386     if (afs_debug & AFSDEB_VNLAYER)
387         printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
388     return code;
389 }
390
391 int
392 afs_obsd_mknod(void *v)
393 {
394     struct vop_mknod_args       /* {
395                                  * struct vnode *a_dvp;
396                                  * struct vnode **a_vpp;
397                                  * struct componentname *a_cnp;
398                                  * struct vattr *a_vap;
399                                  * } */ *ap = v;
400     DROPCNP(ap->a_cnp);
401     vput(ap->a_dvp);
402     return (ENODEV);
403 }
404
405 int
406 afs_obsd_open(void *v)
407 {
408     struct vop_open_args        /* {
409                                  * struct vnode *a_vp;
410                                  * int  a_mode;
411                                  * struct ucred *a_cred;
412                                  * struct proc *a_p;
413                                  * } */ *ap = v;
414     int code;
415     struct vcache *vc = VTOAFS(ap->a_vp);
416
417     AFS_GLOCK();
418     code = afs_open(&vc, ap->a_mode, ap->a_cred);
419 #ifdef DIAGNOSTIC
420     if (AFSTOV(vc) != ap->a_vp)
421         panic("AFS open changed vnode!");
422 #endif
423     AFS_GUNLOCK();
424     return code;
425 }
426
427 int
428 afs_obsd_close(void *v)
429 {
430     struct vop_close_args       /* {
431                                  * struct vnode *a_vp;
432                                  * int  a_fflag;
433                                  * struct ucred *a_cred;
434                                  * struct proc *a_p;
435                                  * } */ *ap = v;
436     int code;
437
438     AFS_GLOCK();
439     code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred);
440     AFS_GUNLOCK();
441     return code;
442 }
443
444 int
445 afs_obsd_access(void *v)
446 {
447     struct vop_access_args      /* {
448                                  * struct vnode *a_vp;
449                                  * int  a_mode;
450                                  * struct ucred *a_cred;
451                                  * struct proc *a_p;
452                                  * } */ *ap = v;
453     int code;
454
455     AFS_GLOCK();
456     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
457     AFS_GUNLOCK();
458     return code;
459 }
460
461 int
462 afs_obsd_getattr(void *v)
463 {
464     struct vop_getattr_args     /* {
465                                  * struct vnode *a_vp;
466                                  * struct vattr *a_vap;
467                                  * struct ucred *a_cred;
468                                  * struct proc *a_p;
469                                  * } */ *ap = v;
470     int code;
471
472     AFS_GLOCK();
473     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
474     AFS_GUNLOCK();
475     return code;
476 }
477
478 int
479 afs_obsd_setattr(void *v)
480 {
481     struct vop_setattr_args     /* {
482                                  * struct vnode *a_vp;
483                                  * struct vattr *a_vap;
484                                  * struct ucred *a_cred;
485                                  * struct proc *a_p;
486                                  * } */ *ap = v;
487     int code;
488
489     AFS_GLOCK();
490     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
491     AFS_GUNLOCK();
492     return code;
493 }
494
495 int
496 afs_obsd_read(void *v)
497 {
498     struct vop_read_args        /* {
499                                  * struct vnode *a_vp;
500                                  * struct uio *a_uio;
501                                  * int a_ioflag;
502                                  * struct ucred *a_cred;
503                                  * } */ *ap = v;
504     int code;
505
506     AFS_GLOCK();
507     code = afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, 0);
508     AFS_GUNLOCK();
509     return code;
510 }
511
512 int
513 afs_obsd_write(void *v)
514 {
515     struct vop_write_args       /* {
516                                  * struct vnode *a_vp;
517                                  * struct uio *a_uio;
518                                  * int a_ioflag;
519                                  * struct ucred *a_cred;
520                                  * } */ *ap = v;
521     int code;
522
523 #ifdef UVM
524     (void)uvm_vnp_uncache(ap->a_vp);    /* toss stale pages */
525 #else
526     vnode_pager_uncache(ap->a_vp);
527 #endif
528     AFS_GLOCK();
529     code =
530         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
531     AFS_GUNLOCK();
532     return code;
533 }
534
535 int
536 afs_obsd_ioctl(void *v)
537 {
538     struct vop_ioctl_args       /* {
539                                  * struct vnode *a_vp;
540                                  * int  a_command;
541                                  * caddr_t  a_data;
542                                  * int  a_fflag;
543                                  * struct ucred *a_cred;
544                                  * struct proc *a_p;
545                                  * } */ *ap = v;
546     int code;
547
548     /* in case we ever get in here... */
549
550     AFS_STATCNT(afs_ioctl);
551     AFS_GLOCK();
552     if (((ap->a_command >> 8) & 0xff) == 'V')
553         /* This is a VICEIOCTL call */
554         code =
555             HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
556                         (struct afs_ioctl *)ap->a_data);
557     else
558         /* No-op call; just return. */
559         code = ENOTTY;
560     AFS_GUNLOCK();
561     return code;
562 }
563
564 int
565 afs_obsd_select(void *v)
566 {
567     return 1;
568 }
569
570 int
571 afs_obsd_fsync(void *v)
572 {
573     struct vop_fsync_args       /* {
574                                  * struct vnode *a_vp;
575                                  * struct ucred *a_cred;
576                                  * int a_waitfor;
577                                  * struct proc *a_p;
578                                  * } */ *ap = v;
579     int wait = ap->a_waitfor == MNT_WAIT;
580     struct vnode *vp = ap->a_vp;
581     int code;
582
583     AFS_GLOCK();
584     vflushbuf(vp, wait);
585     code = afs_fsync(VTOAFS(vp), ap->a_cred);
586     AFS_GUNLOCK();
587     return code;
588 }
589
590 int
591 afs_obsd_remove(void *v)
592 {
593     struct vop_remove_args      /* {
594                                  * struct vnode *a_dvp;
595                                  * struct vnode *a_vp;
596                                  * struct componentname *a_cnp;
597                                  * } */ *ap = v;
598     int code;
599     struct vnode *vp = ap->a_vp;
600     struct vnode *dvp = ap->a_dvp;
601
602     GETNAME();
603     AFS_GLOCK();
604     code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
605     AFS_GUNLOCK();
606     if (dvp == vp)
607         vrele(vp);
608     else
609         vput(vp);
610     vput(dvp);
611     DROPCNP(cnp);
612     DROPNAME();
613     return code;
614 }
615
616 int
617 afs_obsd_link(void *v)
618 {
619     struct vop_link_args        /* {
620                                  * struct vnode *a_vp;
621                                  * struct vnode *a_tdvp;
622                                  * struct componentname *a_cnp;
623                                  * } */ *ap = v;
624     int code;
625     struct vnode *dvp = ap->a_dvp;
626     struct vnode *vp = ap->a_vp;
627
628     GETNAME();
629     if (dvp->v_mount != vp->v_mount) {
630         VOP_ABORTOP(vp, cnp);
631         code = EXDEV;
632         goto out;
633     }
634     if (vp->v_type == VDIR) {
635         VOP_ABORTOP(vp, cnp);
636         code = EISDIR;
637         goto out;
638     }
639     if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
640         VOP_ABORTOP(dvp, cnp);
641         goto out;
642     }
643
644     AFS_GLOCK();
645     code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
646     AFS_GUNLOCK();
647     DROPCNP(cnp);
648     if (dvp != vp)
649         VOP_UNLOCK(vp, 0, curproc);
650
651   out:
652     vput(dvp);
653     DROPNAME();
654     return code;
655 }
656
657 int
658 afs_obsd_rename(void *v)
659 {
660     struct vop_rename_args      /* {
661                                  * struct vnode *a_fdvp;
662                                  * struct vnode *a_fvp;
663                                  * struct componentname *a_fcnp;
664                                  * struct vnode *a_tdvp;
665                                  * struct vnode *a_tvp;
666                                  * struct componentname *a_tcnp;
667                                  * } */ *ap = v;
668     int code = 0;
669     struct componentname *fcnp = ap->a_fcnp;
670     char *fname;
671     struct componentname *tcnp = ap->a_tcnp;
672     char *tname;
673     struct vnode *tvp = ap->a_tvp;
674     struct vnode *tdvp = ap->a_tdvp;
675     struct vnode *fvp = ap->a_fvp;
676     struct vnode *fdvp = ap->a_fdvp;
677
678     /*
679      * Check for cross-device rename.
680      */
681     if ((fvp->v_mount != tdvp->v_mount)
682         || (tvp && (fvp->v_mount != tvp->v_mount))) {
683         code = EXDEV;
684       abortit:
685         VOP_ABORTOP(tdvp, tcnp);        /* XXX, why not in NFS? */
686         if (tdvp == tvp)
687             vrele(tdvp);
688         else
689             vput(tdvp);
690         if (tvp)
691             vput(tvp);
692         VOP_ABORTOP(fdvp, fcnp);        /* XXX, why not in NFS? */
693         vrele(fdvp);
694         vrele(fvp);
695         return (code);
696     }
697     /*
698      * if fvp == tvp, we're just removing one name of a pair of
699      * directory entries for the same element.  convert call into rename.
700      ( (pinched from NetBSD 1.0's ufs_rename())
701      */
702     if (fvp == tvp) {
703         if (fvp->v_type == VDIR) {
704             code = EINVAL;
705             goto abortit;
706         }
707
708         /* Release destination completely. */
709         VOP_ABORTOP(tdvp, tcnp);
710         vput(tdvp);
711         vput(tvp);
712
713         /* Delete source. */
714         vrele(fdvp);
715         vrele(fvp);
716         fcnp->cn_flags &= ~MODMASK;
717         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
718         if ((fcnp->cn_flags & SAVESTART) == 0)
719             panic("afs_rename: lost from startdir");
720         fcnp->cn_nameiop = DELETE;
721 #if defined(AFS_OBSD49_ENV)
722         (void)vfs_relookup(fdvp, &fvp, fcnp);
723 #else
724         (void)relookup(fdvp, &fvp, fcnp);
725 #endif
726         return (VOP_REMOVE(fdvp, fvp, fcnp));
727     }
728
729     if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curproc)))
730         goto abortit;
731
732     BSD_KMALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
733     bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
734     fname[fcnp->cn_namelen] = '\0';
735     BSD_KMALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
736     bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
737     tname[tcnp->cn_namelen] = '\0';
738
739
740     AFS_GLOCK();
741     /* XXX use "from" or "to" creds? NFS uses "to" creds */
742     code =
743         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
744     AFS_GUNLOCK();
745
746     VOP_UNLOCK(fvp, 0, curproc);
747     BSD_KFREE(fname, M_TEMP);
748     BSD_KFREE(tname, M_TEMP);
749     if (code)
750         goto abortit;           /* XXX */
751     if (tdvp == tvp)
752         vrele(tdvp);
753     else
754         vput(tdvp);
755     if (tvp)
756         vput(tvp);
757     vrele(fdvp);
758     vrele(fvp);
759     return code;
760 }
761
762 int
763 afs_obsd_mkdir(void *v)
764 {
765     struct vop_mkdir_args       /* {
766                                  * struct vnode *a_dvp;
767                                  * struct vnode **a_vpp;
768                                  * struct componentname *a_cnp;
769                                  * struct vattr *a_vap;
770                                  * } */ *ap = v;
771     struct vnode *dvp = ap->a_dvp;
772     struct vattr *vap = ap->a_vap;
773     int code;
774     struct vcache *vcp;
775
776     GETNAME();
777 #ifdef DIAGNOSTIC
778     if ((cnp->cn_flags & HASBUF) == 0)
779         panic("afs_obsd_mkdir: no name");
780 #endif
781     AFS_GLOCK();
782     code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
783     AFS_GUNLOCK();
784     if (code) {
785         VOP_ABORTOP(dvp, cnp);
786         vput(dvp);
787         DROPNAME();
788         return (code);
789     }
790     if (vcp) {
791         *ap->a_vpp = AFSTOV(vcp);
792         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc);
793     } else
794         *ap->a_vpp = 0;
795     DROPCNP(cnp);
796     DROPNAME();
797     vput(dvp);
798     return code;
799 }
800
801 int
802 afs_obsd_rmdir(void *v)
803 {
804     struct vop_rmdir_args       /* {
805                                  * struct vnode *a_dvp;
806                                  * struct vnode *a_vp;
807                                  * struct componentname *a_cnp;
808                                  * } */ *ap = v;
809     int code;
810     struct vnode *vp = ap->a_vp;
811     struct vnode *dvp = ap->a_dvp;
812
813     GETNAME();
814     if (dvp == vp) {
815         vrele(dvp);
816         vput(vp);
817         DROPCNP(cnp);
818         DROPNAME();
819         return (EINVAL);
820     }
821
822     AFS_GLOCK();
823     code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
824     AFS_GUNLOCK();
825     DROPNAME();
826     vput(dvp);
827     vput(vp);
828     return code;
829 }
830
831 int
832 afs_obsd_symlink(void *v)
833 {
834     struct vop_symlink_args     /* {
835                                  * struct vnode *a_dvp;
836                                  * struct vnode **a_vpp;
837                                  * struct componentname *a_cnp;
838                                  * struct vattr *a_vap;
839                                  * char *a_target;
840                                  * } */ *ap = v;
841     struct vnode *dvp = ap->a_dvp;
842     int code;
843     /* NFS ignores a_vpp; so do we. */
844
845     GETNAME();
846     AFS_GLOCK();
847     code =
848         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, NULL,
849                     cnp->cn_cred);
850     AFS_GUNLOCK();
851     DROPCNP(cnp);
852     DROPNAME();
853     vput(dvp);
854     return code;
855 }
856
857 int
858 afs_obsd_readdir(void *v)
859 {
860     struct vop_readdir_args     /* {
861                                  * struct vnode *a_vp;
862                                  * struct uio *a_uio;
863                                  * struct ucred *a_cred;
864                                  * int *a_eofflag;
865                                  * int *a_ncookies;
866                                  * u_long **a_cookies;
867                                  * } */ *ap = v;
868     int code;
869
870     AFS_GLOCK();
871 #ifdef AFS_HAVE_COOKIES
872     printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
873            ap->a_ncookies);
874     code =
875         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag,
876                     ap->a_ncookies, ap->a_cookies);
877 #else
878     code =
879         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
880 #endif
881     AFS_GUNLOCK();
882     return code;
883 }
884
885 int
886 afs_obsd_readlink(void *v)
887 {
888     struct vop_readlink_args    /* {
889                                  * struct vnode *a_vp;
890                                  * struct uio *a_uio;
891                                  * struct ucred *a_cred;
892                                  * } */ *ap = v;
893     int code;
894
895     AFS_GLOCK();
896     code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
897     AFS_GUNLOCK();
898     return code;
899 }
900
901 extern int prtactive;
902
903 int
904 afs_obsd_inactive(void *v)
905 {
906     struct vop_inactive_args    /* {
907                                  * struct vnode *a_vp;
908                                  * } */ *ap = v;
909     struct vnode *vp = ap->a_vp;
910     struct vcache *vc = VTOAFS(vp);
911     int haveGlock = ISAFS_GLOCK();
912
913     AFS_STATCNT(afs_inactive);
914
915     if (prtactive && vp->v_usecount != 0)
916         vprint("afs_obsd_inactive(): pushing active", vp);
917
918     if (!haveGlock)
919         AFS_GLOCK();
920     afs_InactiveVCache(vc, 0);  /* decrs ref counts */
921     if (!haveGlock)
922         AFS_GUNLOCK();
923
924     lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
925     return 0;
926 }
927
928 int
929 afs_obsd_reclaim(void *v)
930 {
931     struct vop_reclaim_args     /* {
932                                  * struct vnode *a_vp;
933                                  * } */ *ap = v;
934     int code, slept;
935     struct vnode *vp = ap->a_vp;
936     struct vcache *avc = VTOAFS(vp);
937     int haveGlock = ISAFS_GLOCK();
938     int haveVlock = CheckLock(&afs_xvcache);
939
940 #if 0
941     printf("reclaim usecount %d\n", vp->v_usecount);
942     /* OK, there are no internal vrefCounts, so there shouldn't
943      * be any more refs here. */
944     vp->v_data = NULL;          /* remove from vnode */
945     avc->v = NULL;              /* also drop the ptr to vnode */
946     return 0;
947 #else
948     if (!haveGlock)
949         AFS_GLOCK();
950     if (!haveVlock)
951         ObtainWriteLock(&afs_xvcache, 901);
952     /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
953     code = afs_FlushVCache(avc, &slept);
954     if (!haveVlock)
955         ReleaseWriteLock(&afs_xvcache);
956     if (!haveGlock)
957         AFS_GUNLOCK();
958     return code;
959 #endif
960 }
961
962 #ifdef AFS_OBSD42_ENV
963 #define VP_INTERLOCK NULL
964 #else
965 #define VP_INTERLOCK (&vp->v_interlock)
966 #endif
967
968 int
969 afs_obsd_lock(void *v)
970 {
971     struct vop_lock_args        /* {
972                                  * struct vnode *a_vp;
973                                  * int a_flags;
974                                  * sturct proc *a_p;
975                                  * } */ *ap = v;
976     struct vnode *vp = ap->a_vp;
977     struct vcache *vc = VTOAFS(vp);
978
979     if (!vc)
980         panic("afs_obsd_lock: null vcache");
981     return afs_osi_lockmgr(&vc->rwlock,
982         (ap->a_flags & LK_RECURSEFAIL) ? ap->a_flags : ap->a_flags | LK_CANRECURSE,
983         VP_INTERLOCK, ap->a_p);
984 }
985
986 int
987 afs_obsd_unlock(void *v)
988 {
989     struct vop_unlock_args      /* {
990                                  * struct vnode *a_vp;
991                                  * int a_flags;
992                                  * struct proc *a_p;
993                                  * } */ *ap = v;
994     struct vnode *vp = ap->a_vp;
995     struct vcache *vc = VTOAFS(vp);
996
997     if (!vc)
998         panic("afs_obsd_unlock: null vcache");
999     return afs_osi_lockmgr(&vc->rwlock, ap->a_flags | LK_RELEASE, VP_INTERLOCK, ap->a_p);
1000 }
1001
1002 int
1003 afs_obsd_bmap(void *v)
1004 {
1005     struct vop_bmap_args        /* {
1006                                  * struct vnode *a_vp;
1007                                  * daddr_t  a_bn;
1008                                  * struct vnode **a_vpp;
1009                                  * daddr_t *a_bnp;
1010                                  * int *a_runp;
1011                                  * } */ *ap = v;
1012     struct vcache *vcp = VTOAFS(ap->a_vp);
1013
1014     AFS_STATCNT(afs_bmap);
1015     if (ap->a_bnp)
1016         *ap->a_bnp = ap->a_bn * btodb(8192);
1017     if (ap->a_vpp)
1018         *ap->a_vpp = (vcp) ? AFSTOV(vcp) : NULL;
1019     return 0;
1020 }
1021
1022 int
1023 afs_obsd_strategy(void *v)
1024 {
1025     struct vop_strategy_args    /* {
1026                                  * struct buf *a_bp;
1027                                  * } */ *ap = v;
1028     struct buf *abp = ap->a_bp;
1029     struct uio tuio;
1030     struct iovec tiovec[1];
1031     struct vcache *tvc = VTOAFS(abp->b_vp);
1032     struct ucred *credp = osi_curcred();
1033     long len = abp->b_bcount;
1034     int code;
1035
1036     memset(&tuio, 0, sizeof(tuio));
1037     memset(&tiovec, 0, sizeof(tiovec));
1038
1039     AFS_STATCNT(afs_strategy);
1040
1041     tuio.afsio_iov = tiovec;
1042     tuio.afsio_iovcnt = 1;
1043     tuio.afsio_seg = AFS_UIOSYS;
1044     tuio.afsio_resid = len;
1045     tiovec[0].iov_base = abp->b_data;
1046     tiovec[0].iov_len = len;
1047
1048     AFS_GLOCK();
1049     if ((abp->b_flags & B_READ) == B_READ) {
1050         code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp);
1051         if (code == 0 && tuio.afsio_resid > 0)
1052             bzero(abp->b_data + len - tuio.afsio_resid, tuio.afsio_resid);
1053     } else
1054         code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
1055     AFS_GUNLOCK();
1056
1057     ReleaseWriteLock(&tvc->lock);
1058     AFS_RELE(AFSTOV(tvc));
1059     return code;
1060 }
1061
1062 int
1063 afs_obsd_print(void *v)
1064 {
1065     struct vop_print_args       /* {
1066                                  * struct vnode *a_vp;
1067                                  * } */ *ap = v;
1068     struct vnode *vp = ap->a_vp;
1069     struct vcache *vc = VTOAFS(ap->a_vp);
1070
1071     printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->f.fid.Cell,
1072            (int)vc->f.fid.Fid.Volume, (int)vc->f.fid.Fid.Vnode,
1073            (int)vc->f.fid.Fid.Unique);
1074     lockmgr_printinfo(&vc->rwlock);
1075     printf("\n");
1076     return 0;
1077 }
1078
1079 int
1080 afs_obsd_islocked(void *v)
1081 {
1082     struct vop_islocked_args    /* {
1083                                  * struct vnode *a_vp;
1084                                  * } */ *ap = v;
1085     return lockstatus(&VTOAFS(ap->a_vp)->rwlock);
1086 }
1087
1088 /*
1089  * Return POSIX pathconf information applicable to ufs filesystems.
1090  */
1091 int
1092 afs_obsd_pathconf(void *v)
1093 {
1094     struct vop_pathconf_args    /* {
1095                                  * struct vnode *a_vp;
1096                                  * int a_name;
1097                                  * int *a_retval;
1098                                  * } */ *ap = v;
1099     AFS_STATCNT(afs_cntl);
1100     switch (ap->a_name) {
1101     case _PC_LINK_MAX:
1102         *ap->a_retval = LINK_MAX;
1103         break;
1104     case _PC_NAME_MAX:
1105         *ap->a_retval = NAME_MAX;
1106         break;
1107     case _PC_PATH_MAX:
1108         *ap->a_retval = PATH_MAX;
1109         break;
1110     case _PC_CHOWN_RESTRICTED:
1111         *ap->a_retval = 1;
1112         break;
1113     case _PC_NO_TRUNC:
1114         *ap->a_retval = 1;
1115         break;
1116     case _PC_PIPE_BUF:
1117         return EINVAL;
1118         break;
1119     default:
1120         return EINVAL;
1121     }
1122     return 0;
1123 }
1124
1125 extern int
1126   afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
1127               afs_ucred_t *acred, pid_t clid);
1128
1129 /*
1130  * Advisory record locking support (fcntl() POSIX style)
1131  */
1132 int
1133 afs_obsd_advlock(void *v)
1134 {
1135     struct vop_advlock_args     /* {
1136                                  * struct vnode *a_vp;
1137                                  * caddr_t  a_id;
1138                                  * int  a_op;
1139                                  * struct flock *a_fl;
1140                                  * int  a_flags;
1141                                  * } */ *ap = v;
1142     int code;
1143
1144     AFS_GLOCK();
1145     code =
1146         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
1147                     (int)ap->a_id);
1148     AFS_GUNLOCK();
1149     return code;
1150 }