7a753dfbc914a7a4f78cb7180a1c742a597366c0
[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 RCSID
102     ("$Header$");
103
104 #include "afs/sysincludes.h"    /* Standard vendor system headers */
105 #include "afs/afsincludes.h"    /* Afs-based standard headers */
106 #include "afs/afs_stats.h"      /* statistics */
107
108 #include <sys/malloc.h>
109 #include <sys/namei.h>
110
111 #include "afs/afs_cbqueue.h"
112 #include "afs/nfsclient.h"
113 #include "afs/afs_osidnlc.h"
114
115 #ifdef AFS_DISCON_ENV
116 extern int afs_FlushVS(struct vcache *tvc);
117 #endif
118
119 #define M_AFSNODE (M_TEMP-1)    /* XXX */
120
121 int afs_nbsd_lookup(struct vop_lookup_args *);
122 int afs_nbsd_create(struct vop_create_args *);
123 int afs_nbsd_mknod(struct vop_mknod_args *);
124 int afs_nbsd_open(struct vop_open_args *);
125 int afs_nbsd_close(struct vop_close_args *);
126 int afs_nbsd_access(struct vop_access_args *);
127 int afs_nbsd_getattr(struct vop_getattr_args *);
128 int afs_nbsd_setattr(struct vop_setattr_args *);
129 int afs_nbsd_read(struct vop_read_args *);
130 int afs_nbsd_write(struct vop_write_args *);
131 int afs_nbsd_ioctl(struct vop_ioctl_args *);
132 int afs_nbsd_select(struct vop_select_args *);
133 int afs_nbsd_fsync(struct vop_fsync_args *);
134 int afs_nbsd_remove(struct vop_remove_args *);
135 int afs_nbsd_link(struct vop_link_args *);
136 int afs_nbsd_rename(struct vop_rename_args *);
137 int afs_nbsd_mkdir(struct vop_mkdir_args *);
138 int afs_nbsd_rmdir(struct vop_rmdir_args *);
139 int afs_nbsd_symlink(struct vop_symlink_args *);
140 int afs_nbsd_readdir(struct vop_readdir_args *);
141 int afs_nbsd_readlink(struct vop_readlink_args *);
142 extern int ufs_abortop(struct vop_abortop_args *);
143 int afs_nbsd_inactive(struct vop_inactive_args *);
144 int afs_nbsd_reclaim(struct vop_reclaim_args *);
145 int afs_nbsd_lock(struct vop_lock_args *);
146 int afs_nbsd_unlock(struct vop_unlock_args *);
147 int afs_nbsd_bmap(struct vop_bmap_args *);
148 int afs_nbsd_strategy(struct vop_strategy_args *);
149 int afs_nbsd_print(struct vop_print_args *);
150 int afs_nbsd_islocked(struct vop_islocked_args *);
151 int afs_nbsd_pathconf(struct vop_pathconf_args *);
152 int afs_nbsd_advlock(struct vop_advlock_args *);
153
154 #define afs_nbsd_opnotsupp \
155         ((int (*) __P((struct  vop_reallocblks_args *)))eopnotsupp)
156 #define afs_nbsd_reallocblks afs_nbsd_opnotsupp
157
158 /* Global vfs data structures for AFS. */
159 int (**afs_vnodeop_p) __P((void *));
160 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
161     {&vop_default_desc, vn_default_error},
162     {&vop_lookup_desc, afs_nbsd_lookup},        /* lookup */
163     {&vop_create_desc, afs_nbsd_create},        /* create */
164     {&vop_mknod_desc, afs_nbsd_mknod},  /* mknod */
165     {&vop_open_desc, afs_nbsd_open},    /* open */
166     {&vop_close_desc, afs_nbsd_close},  /* close */
167     {&vop_access_desc, afs_nbsd_access},        /* access */
168     {&vop_getattr_desc, afs_nbsd_getattr},      /* getattr */
169     {&vop_setattr_desc, afs_nbsd_setattr},      /* setattr */
170     {&vop_read_desc, afs_nbsd_read},    /* read */
171     {&vop_write_desc, afs_nbsd_write},  /* write */
172     {&vop_ioctl_desc, afs_nbsd_ioctl},  /* XXX ioctl */
173     {&vop_select_desc, afs_nbsd_select},        /* select */
174     {&vop_fsync_desc, afs_nbsd_fsync},  /* fsync */
175     {&vop_remove_desc, afs_nbsd_remove},        /* remove */
176     {&vop_link_desc, afs_nbsd_link},    /* link */
177     {&vop_rename_desc, afs_nbsd_rename},        /* rename */
178     {&vop_mkdir_desc, afs_nbsd_mkdir},  /* mkdir */
179     {&vop_rmdir_desc, afs_nbsd_rmdir},  /* rmdir */
180     {&vop_symlink_desc, afs_nbsd_symlink},      /* symlink */
181     {&vop_readdir_desc, afs_nbsd_readdir},      /* readdir */
182     {&vop_readlink_desc, afs_nbsd_readlink},    /* readlink */
183     {&vop_abortop_desc, vop_generic_abortop},   /* abortop */
184     {&vop_inactive_desc, afs_nbsd_inactive},    /* inactive */
185     {&vop_reclaim_desc, afs_nbsd_reclaim},      /* reclaim */
186     {&vop_lock_desc, afs_nbsd_lock},    /* lock */
187     {&vop_unlock_desc, afs_nbsd_unlock},        /* unlock */
188     {&vop_bmap_desc, afs_nbsd_bmap},    /* bmap */
189     {&vop_strategy_desc, afs_nbsd_strategy},    /* strategy */
190     {&vop_print_desc, afs_nbsd_print},  /* print */
191     {&vop_islocked_desc, afs_nbsd_islocked},    /* islocked */
192     {&vop_pathconf_desc, afs_nbsd_pathconf},    /* pathconf */
193     {&vop_advlock_desc, afs_nbsd_advlock},      /* advlock */
194     {&vop_reallocblks_desc, afs_nbsd_reallocblks},      /* reallocblks */
195     {&vop_bwrite_desc, vop_generic_bwrite},
196     {(struct vnodeop_desc *)NULL, (int (*)__P((void *)))NULL}
197 };
198 struct vnodeopv_desc afs_vnodeop_opv_desc =
199     { &afs_vnodeop_p, afs_vnodeop_entries };
200
201 #define GETNAME()       \
202     struct componentname *cnp = ap->a_cnp; \
203     char *name; \
204     MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
205     bcopy(cnp->cn_nameptr, name, cnp->cn_namelen); \
206     name[cnp->cn_namelen] = '\0'
207
208 #define DROPNAME() FREE(name, M_TEMP)
209
210 int afs_debug;
211
212 #undef vrele
213 #define vrele afs_nbsd_rele
214 #undef VREF
215 #define VREF afs_nbsd_ref
216
217 #if 0
218 extern int afs_lookup();
219 extern int afs_open();
220 extern int afs_close();
221 extern int HandleIoctl(struct vcache *avc, afs_int32 acom,
222                        struct afs_ioctl *adata);
223 extern int afs_fsync();
224 extern int afs_remove();
225 extern int afs_link();
226 extern int afs_rename();
227 extern int afs_mkdir();
228 extern int afs_rmdir();
229 extern int afs_symlink();
230 extern int afs_readdir();
231 extern int afs_readlink();
232 #endif
233
234 int
235 afs_nbsd_lookup(ap)
236      struct vop_lookup_args     /* {
237                                  * struct vnodeop_desc * a_desc;
238                                  * struct vnode *a_dvp;
239                                  * struct vnode **a_vpp;
240                                  * struct componentname *a_cnp;
241                                  * } */ *ap;
242 {
243     int code;
244     struct vcache *vcp;
245     struct vnode *vp, *dvp;
246     int flags = ap->a_cnp->cn_flags;
247     int lockparent;             /* 1 => lockparent flag is set */
248     int wantparent;             /* 1 => wantparent or lockparent flag */
249
250     GETNAME();
251     lockparent = flags & LOCKPARENT;
252     wantparent = flags & (LOCKPARENT | WANTPARENT);
253 #ifdef PDIRUNLOCK
254     cnp->cn_flags &= ~PDIRUNLOCK;
255 #endif
256
257     if (ap->a_dvp->v_type != VDIR) {
258         *ap->a_vpp = NULL;
259         DROPNAME();
260         return ENOTDIR;
261     }
262     dvp = ap->a_dvp;
263     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
264         printf("nbsd_lookup dvp %p flags %x name %s cnt %d\n", dvp, flags,
265                name, dvp->v_usecount);
266     AFS_GLOCK();
267     code = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
268     AFS_GUNLOCK();
269     if (code) {
270         if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
271             && (flags & ISLASTCN) && code == ENOENT)
272             code = EJUSTRETURN;
273         if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
274             cnp->cn_flags |= SAVENAME;
275         DROPNAME();
276         *ap->a_vpp = NULL;
277         return (code);
278     }
279     vp = AFSTOV(vcp);           /* always get a node if no error */
280
281     /*
282      * The parent directory comes in locked.  We unlock it on return
283      * unless the caller wants it left locked.
284      * we also always return the vnode locked.
285      */
286
287     if (vp == dvp) {
288         /* they're the same; afs_lookup() already ref'ed the leaf.
289          * It came in locked, so we don't need to ref OR lock it */
290         if (afs_debug & AFSDEB_VNLAYER)
291             printf("ref'ed %p as .\n", dvp);
292     } else {
293         if (!lockparent || !(flags & ISLASTCN)) {
294             VOP_UNLOCK(dvp, 0, curproc);        /* done with parent. */
295 #ifdef PDIRUNLOCK
296             cnp->cn_flags |= PDIRUNLOCK;
297 #endif
298         }
299         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc);  /* always return the child locked */
300         if (afs_debug & AFSDEB_VNLAYER)
301             printf("locked ret %p from lookup\n", vp);
302     }
303     *ap->a_vpp = vp;
304
305     if (((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN))
306          || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
307         cnp->cn_flags |= SAVENAME;
308
309     DROPNAME();
310     if (afs_debug & AFSDEB_VNLAYER && !(dvp->v_flag & VROOT))
311         printf("nbsd_lookup done dvp %p cnt %d\n", dvp, dvp->v_usecount);
312     return code;
313 }
314
315 int
316 afs_nbsd_create(ap)
317      struct vop_create_args     /* {
318                                  * struct vnode *a_dvp;
319                                  * struct vnode **a_vpp;
320                                  * struct componentname *a_cnp;
321                                  * struct vattr *a_vap;
322                                  * } */ *ap;
323 {
324     int code = 0;
325     struct vcache *vcp;
326     struct vnode *dvp = ap->a_dvp;
327     GETNAME();
328
329     if (afs_debug & AFSDEB_VNLAYER)
330         printf("nbsd_create dvp %p cnt %d\n", dvp, dvp->v_usecount);
331
332     /* vnode layer handles excl/nonexcl */
333
334     AFS_GLOCK();
335     code =
336         afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
337                    &vcp, cnp->cn_cred);
338     AFS_GUNLOCK();
339     if (code) {
340         VOP_ABORTOP(dvp, cnp);
341         vput(dvp);
342         DROPNAME();
343         return (code);
344     }
345
346     if (vcp) {
347         *ap->a_vpp = AFSTOV(vcp);
348         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc);
349     } else
350         *ap->a_vpp = 0;
351
352     if ((cnp->cn_flags & SAVESTART) == 0)
353         FREE(cnp->cn_pnbuf, M_NAMEI);
354     vput(dvp);
355     DROPNAME();
356     if (afs_debug & AFSDEB_VNLAYER)
357         printf("nbsd_create done dvp %p cnt %d\n", dvp, dvp->v_usecount);
358     return code;
359 }
360
361 int
362 afs_nbsd_mknod(ap)
363      struct vop_mknod_args      /* {
364                                  * struct vnode *a_dvp;
365                                  * struct vnode **a_vpp;
366                                  * struct componentname *a_cnp;
367                                  * struct vattr *a_vap;
368                                  * } */ *ap;
369 {
370     free(ap->a_cnp->cn_pnbuf, M_NAMEI);
371     vput(ap->a_dvp);
372     return (ENODEV);
373 }
374
375 int
376 afs_nbsd_open(ap)
377      struct vop_open_args       /* {
378                                  * struct vnode *a_vp;
379                                  * int  a_mode;
380                                  * struct ucred *a_cred;
381                                  * struct proc *a_p;
382                                  * } */ *ap;
383 {
384     int code;
385     struct vcache *vc = VTOAFS(ap->a_vp);
386
387     AFS_GLOCK();
388     code = afs_open(&vc, ap->a_mode, ap->a_cred);
389 #ifdef DIAGNOSTIC
390     if (AFSTOV(vc) != ap->a_vp)
391         panic("AFS open changed vnode!");
392 #endif
393     AFS_GUNLOCK();
394     return code;
395 }
396
397 int
398 afs_nbsd_close(ap)
399      struct vop_close_args      /* {
400                                  * struct vnode *a_vp;
401                                  * int  a_fflag;
402                                  * struct ucred *a_cred;
403                                  * struct proc *a_p;
404                                  * } */ *ap;
405 {
406     int code;
407
408     AFS_GLOCK();
409     code = afs_close(VTOAFS(ap->a_vp), ap->a_fflag, ap->a_cred, ap->a_p);
410     AFS_GUNLOCK();
411     return code;
412 }
413
414 int
415 afs_nbsd_access(ap)
416      struct vop_access_args     /* {
417                                  * struct vnode *a_vp;
418                                  * int  a_mode;
419                                  * struct ucred *a_cred;
420                                  * struct proc *a_p;
421                                  * } */ *ap;
422 {
423     int code;
424
425     AFS_GLOCK();
426     code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
427     AFS_GUNLOCK();
428     return code;
429 }
430
431 int
432 afs_nbsd_getattr(ap)
433      struct vop_getattr_args    /* {
434                                  * struct vnode *a_vp;
435                                  * struct vattr *a_vap;
436                                  * struct ucred *a_cred;
437                                  * struct proc *a_p;
438                                  * } */ *ap;
439 {
440     int code;
441
442     AFS_GLOCK();
443     code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
444     AFS_GUNLOCK();
445     return code;
446 }
447
448 int
449 afs_nbsd_setattr(ap)
450      struct vop_setattr_args    /* {
451                                  * struct vnode *a_vp;
452                                  * struct vattr *a_vap;
453                                  * struct ucred *a_cred;
454                                  * struct proc *a_p;
455                                  * } */ *ap;
456 {
457     int code;
458
459     AFS_GLOCK();
460     code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
461     AFS_GUNLOCK();
462     return code;
463 }
464
465 int
466 afs_nbsd_read(ap)
467      struct vop_read_args       /* {
468                                  * struct vnode *a_vp;
469                                  * struct uio *a_uio;
470                                  * int a_ioflag;
471                                  * struct ucred *a_cred;
472                                  * } */ *ap;
473 {
474     int code;
475
476     AFS_GLOCK();
477     code =
478         afs_read(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, (daddr_t) 0, NULL,
479                  0);
480     AFS_GUNLOCK();
481     return code;
482 }
483
484 int
485 afs_nbsd_write(ap)
486      struct vop_write_args      /* {
487                                  * struct vnode *a_vp;
488                                  * struct uio *a_uio;
489                                  * int a_ioflag;
490                                  * struct ucred *a_cred;
491                                  * } */ *ap;
492 {
493     int code;
494
495 #ifdef UVM
496     (void)uvm_vnp_uncache(ap->a_vp);    /* toss stale pages */
497 #else
498     vnode_pager_uncache(ap->a_vp);
499 #endif
500     AFS_GLOCK();
501     code =
502         afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
503     AFS_GUNLOCK();
504     return code;
505 }
506
507 int
508 afs_nbsd_ioctl(ap)
509      struct vop_ioctl_args      /* {
510                                  * struct vnode *a_vp;
511                                  * int  a_command;
512                                  * caddr_t  a_data;
513                                  * int  a_fflag;
514                                  * struct ucred *a_cred;
515                                  * struct proc *a_p;
516                                  * } */ *ap;
517 {
518     int code;
519
520     /* in case we ever get in here... */
521
522     AFS_STATCNT(afs_ioctl);
523     AFS_GLOCK();
524     if (((ap->a_command >> 8) & 0xff) == 'V')
525         /* This is a VICEIOCTL call */
526         code =
527             HandleIoctl(VTOAFS(ap->a_vp), ap->a_command,
528                         (struct afs_ioctl *)ap->a_data);
529     else
530         /* No-op call; just return. */
531         code = ENOTTY;
532     AFS_GUNLOCK();
533     return code;
534 }
535
536 /* ARGSUSED */
537 int
538 afs_nbsd_select(ap)
539      struct vop_select_args     /* {
540                                  * struct vnode *a_vp;
541                                  * int  a_which;
542                                  * int  a_fflags;
543                                  * struct ucred *a_cred;
544                                  * struct proc *a_p;
545                                  * } */ *ap;
546 {
547     /*
548      * We should really check to see if I/O is possible.
549      */
550     return (1);
551 }
552
553 int
554 afs_nbsd_fsync(ap)
555      struct vop_fsync_args      /* {
556                                  * struct vnode *a_vp;
557                                  * struct ucred *a_cred;
558                                  * int a_waitfor;
559                                  * struct proc *a_p;
560                                  * } */ *ap;
561 {
562     int wait = ap->a_waitfor == MNT_WAIT;
563     struct vnode *vp = ap->a_vp;
564     int code;
565
566     AFS_GLOCK();
567     vflushbuf(vp, wait);
568     code = afs_fsync(VTOAFS(vp), ap->a_cred);
569     AFS_GUNLOCK();
570     return code;
571 }
572
573 int
574 afs_nbsd_remove(ap)
575      struct vop_remove_args     /* {
576                                  * struct vnode *a_dvp;
577                                  * struct vnode *a_vp;
578                                  * struct componentname *a_cnp;
579                                  * } */ *ap;
580 {
581     int code;
582     struct vnode *vp = ap->a_vp;
583     struct vnode *dvp = ap->a_dvp;
584
585     GETNAME();
586     AFS_GLOCK();
587     code = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
588     AFS_GUNLOCK();
589     if (dvp == vp)
590         vrele(vp);
591     else
592         vput(vp);
593     vput(dvp);
594     FREE(cnp->cn_pnbuf, M_NAMEI);
595     DROPNAME();
596     return code;
597 }
598
599 int
600 afs_nbsd_link(ap)
601      struct vop_link_args       /* {
602                                  * struct vnode *a_vp;
603                                  * struct vnode *a_tdvp;
604                                  * struct componentname *a_cnp;
605                                  * } */ *ap;
606 {
607     int code;
608     struct vnode *dvp = ap->a_dvp;
609     struct vnode *vp = ap->a_vp;
610
611     GETNAME();
612     if (dvp->v_mount != vp->v_mount) {
613         VOP_ABORTOP(vp, cnp);
614         code = EXDEV;
615         goto out;
616     }
617     if (vp->v_type == VDIR) {
618         VOP_ABORTOP(vp, cnp);
619         code = EISDIR;
620         goto out;
621     }
622     if ((code = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc))) {
623         VOP_ABORTOP(dvp, cnp);
624         goto out;
625     }
626
627     AFS_GLOCK();
628     code = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
629     AFS_GUNLOCK();
630     FREE(cnp->cn_pnbuf, M_NAMEI);
631     if (dvp != vp)
632         VOP_UNLOCK(vp, 0, curproc);
633
634   out:
635     vput(dvp);
636     DROPNAME();
637     return code;
638 }
639
640 int
641 afs_nbsd_rename(ap)
642      struct vop_rename_args     /* {
643                                  * struct vnode *a_fdvp;
644                                  * struct vnode *a_fvp;
645                                  * struct componentname *a_fcnp;
646                                  * struct vnode *a_tdvp;
647                                  * struct vnode *a_tvp;
648                                  * struct componentname *a_tcnp;
649                                  * } */ *ap;
650 {
651     int code = 0;
652     struct componentname *fcnp = ap->a_fcnp;
653     char *fname;
654     struct componentname *tcnp = ap->a_tcnp;
655     char *tname;
656     struct vnode *tvp = ap->a_tvp;
657     struct vnode *tdvp = ap->a_tdvp;
658     struct vnode *fvp = ap->a_fvp;
659     struct vnode *fdvp = ap->a_fdvp;
660
661     /*
662      * Check for cross-device rename.
663      */
664     if ((fvp->v_mount != tdvp->v_mount)
665         || (tvp && (fvp->v_mount != tvp->v_mount))) {
666         code = EXDEV;
667       abortit:
668         VOP_ABORTOP(tdvp, tcnp);        /* XXX, why not in NFS? */
669         if (tdvp == tvp)
670             vrele(tdvp);
671         else
672             vput(tdvp);
673         if (tvp)
674             vput(tvp);
675         VOP_ABORTOP(fdvp, fcnp);        /* XXX, why not in NFS? */
676         vrele(fdvp);
677         vrele(fvp);
678         return (code);
679     }
680     /*
681      * if fvp == tvp, we're just removing one name of a pair of
682      * directory entries for the same element.  convert call into rename.
683      ( (pinched from NetBSD 1.0's ufs_rename())
684      */
685     if (fvp == tvp) {
686         if (fvp->v_type == VDIR) {
687             code = EINVAL;
688             goto abortit;
689         }
690
691         /* Release destination completely. */
692         VOP_ABORTOP(tdvp, tcnp);
693         vput(tdvp);
694         vput(tvp);
695
696         /* Delete source. */
697         vrele(fdvp);
698         vrele(fvp);
699         fcnp->cn_flags &= ~MODMASK;
700         fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
701         if ((fcnp->cn_flags & SAVESTART) == 0)
702             panic("afs_rename: lost from startdir");
703         fcnp->cn_nameiop = DELETE;
704         (void)relookup(fdvp, &fvp, fcnp);
705         return (VOP_REMOVE(fdvp, fvp, fcnp));
706     }
707
708     if ((code = vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curproc)))
709         goto abortit;
710
711     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
712     bcopy(fcnp->cn_nameptr, fname, fcnp->cn_namelen);
713     fname[fcnp->cn_namelen] = '\0';
714     MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
715     bcopy(tcnp->cn_nameptr, tname, tcnp->cn_namelen);
716     tname[tcnp->cn_namelen] = '\0';
717
718
719     AFS_GLOCK();
720     /* XXX use "from" or "to" creds? NFS uses "to" creds */
721     code =
722         afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
723     AFS_GUNLOCK();
724
725     VOP_UNLOCK(fvp, 0, curproc);
726     FREE(fname, M_TEMP);
727     FREE(tname, M_TEMP);
728     if (code)
729         goto abortit;           /* XXX */
730     if (tdvp == tvp)
731         vrele(tdvp);
732     else
733         vput(tdvp);
734     if (tvp)
735         vput(tvp);
736     vrele(fdvp);
737     vrele(fvp);
738     return code;
739 }
740
741 int
742 afs_nbsd_mkdir(ap)
743      struct vop_mkdir_args      /* {
744                                  * struct vnode *a_dvp;
745                                  * struct vnode **a_vpp;
746                                  * struct componentname *a_cnp;
747                                  * struct vattr *a_vap;
748                                  * } */ *ap;
749 {
750     struct vnode *dvp = ap->a_dvp;
751     struct vattr *vap = ap->a_vap;
752     int code;
753     struct vcache *vcp;
754
755     GETNAME();
756 #ifdef DIAGNOSTIC
757     if ((cnp->cn_flags & HASBUF) == 0)
758         panic("afs_nbsd_mkdir: no name");
759 #endif
760     AFS_GLOCK();
761     code = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
762     AFS_GUNLOCK();
763     if (code) {
764         VOP_ABORTOP(dvp, cnp);
765         vput(dvp);
766         DROPNAME();
767         return (code);
768     }
769     if (vcp) {
770         *ap->a_vpp = AFSTOV(vcp);
771         vn_lock(AFSTOV(vcp), LK_EXCLUSIVE | LK_RETRY, curproc);
772     } else
773         *ap->a_vpp = 0;
774     DROPNAME();
775     FREE(cnp->cn_pnbuf, M_NAMEI);
776     vput(dvp);
777     return code;
778 }
779
780 int
781 afs_nbsd_rmdir(ap)
782      struct vop_rmdir_args      /* {
783                                  * struct vnode *a_dvp;
784                                  * struct vnode *a_vp;
785                                  * struct componentname *a_cnp;
786                                  * } */ *ap;
787 {
788     int code;
789     struct vnode *vp = ap->a_vp;
790     struct vnode *dvp = ap->a_dvp;
791
792     GETNAME();
793     if (dvp == vp) {
794         vrele(dvp);
795         vput(vp);
796         FREE(cnp->cn_pnbuf, M_NAMEI);
797         DROPNAME();
798         return (EINVAL);
799     }
800
801     AFS_GLOCK();
802     code = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
803     AFS_GUNLOCK();
804     DROPNAME();
805     vput(dvp);
806     vput(vp);
807     return code;
808 }
809
810 int
811 afs_nbsd_symlink(ap)
812      struct vop_symlink_args    /* {
813                                  * struct vnode *a_dvp;
814                                  * struct vnode **a_vpp;
815                                  * struct componentname *a_cnp;
816                                  * struct vattr *a_vap;
817                                  * char *a_target;
818                                  * } */ *ap;
819 {
820     struct vnode *dvp = ap->a_dvp;
821     int code;
822     /* NFS ignores a_vpp; so do we. */
823
824     GETNAME();
825     AFS_GLOCK();
826     code =
827         afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
828     AFS_GUNLOCK();
829     DROPNAME();
830     FREE(cnp->cn_pnbuf, M_NAMEI);
831     vput(dvp);
832     return code;
833 }
834
835 int
836 afs_nbsd_readdir(ap)
837      struct vop_readdir_args    /* {
838                                  * struct vnode *a_vp;
839                                  * struct uio *a_uio;
840                                  * struct ucred *a_cred;
841                                  * int *a_eofflag;
842                                  * int *a_ncookies;
843                                  * u_long **a_cookies;
844                                  * } */ *ap;
845 {
846     int code;
847
848     AFS_GLOCK();
849 #ifdef AFS_HAVE_COOKIES
850     printf("readdir %p cookies %p ncookies %d\n", ap->a_vp, ap->a_cookies,
851            ap->a_ncookies);
852     code =
853         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag,
854                     ap->a_ncookies, ap->a_cookies);
855 #else
856     code =
857         afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
858 #endif
859     AFS_GUNLOCK();
860     return code;
861 }
862
863 int
864 afs_nbsd_readlink(ap)
865      struct vop_readlink_args   /* {
866                                  * struct vnode *a_vp;
867                                  * struct uio *a_uio;
868                                  * struct ucred *a_cred;
869                                  * } */ *ap;
870 {
871     int code;
872
873     AFS_GLOCK();
874     code = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
875     AFS_GUNLOCK();
876     return code;
877 }
878
879 extern int prtactive;
880
881 int
882 afs_nbsd_inactive(ap)
883      struct vop_inactive_args   /* {
884                                  * struct vnode *a_vp;
885                                  * } */ *ap;
886 {
887     struct vnode *vp = ap->a_vp;
888     struct vcache *vc = VTOAFS(vp);
889     int haveGlock = ISAFS_GLOCK();
890
891     AFS_STATCNT(afs_inactive);
892
893     if (prtactive && vp->v_usecount != 0)
894         vprint("afs_nbsd_inactive(): pushing active", vp);
895
896     if (!haveGlock)
897         AFS_GLOCK();
898     afs_InactiveVCache(vc, 0);  /* decrs ref counts */
899     if (!haveGlock)
900         AFS_GUNLOCK();
901
902     lockinit(&vc->rwlock, PINOD, "vcache", 0, 0);
903     return 0;
904 }
905
906 int
907 afs_nbsd_reclaim(ap)
908      struct vop_reclaim_args    /* {
909                                  * struct vnode *a_vp;
910                                  * } */ *ap;
911 {
912     int code, slept;
913     struct vnode *vp = ap->a_vp;
914     struct vcache *avc = VTOAFS(vp);
915     int haveGlock = ISAFS_GLOCK();
916     int haveVlock = CheckLock(&afs_xvcache);
917
918     if (!haveGlock)
919         AFS_GLOCK();
920     if (!haveVlock)
921         ObtainWriteLock(&afs_xvcache, 901);
922 #ifndef AFS_DISCON_ENV
923     code = afs_FlushVCache(avc, &slept);        /* tosses our stuff from vnode */
924 #else
925     /* reclaim the vnode and the in-memory vcache, but keep the on-disk vcache */
926     code = afs_FlushVS(avc);
927 #endif
928     if (!haveVlock)
929         ReleaseWriteLock(&afs_xvcache);
930     if (!haveGlock)
931         AFS_GUNLOCK();
932     return code;
933 }
934
935 int
936 afs_nbsd_lock(ap)
937      struct vop_lock_args       /* {
938                                  * struct vnode *a_vp;
939                                  * int a_flags;
940                                  * sturct proc *a_p;
941                                  * } */ *ap;
942 {
943     struct vnode *vp = ap->a_vp;
944     struct vcache *vc = VTOAFS(vp);
945
946     if (!vc)
947         panic("afs_nbsd_lock: null vcache");
948     return lockmgr(&vc->rwlock, ap->a_flags | LK_CANRECURSE, &vp->v_interlock,
949                    ap->a_p);
950 }
951
952 int
953 afs_nbsd_unlock(ap)
954      struct vop_unlock_args     /* {
955                                  * struct vnode *a_vp;
956                                  * int a_flags;
957                                  * struct proc *a_p;
958                                  * } */ *ap;
959 {
960     struct vnode *vp = ap->a_vp;
961     struct vcache *vc = VTOAFS(vp);
962
963     if (!vc)
964         panic("afs_nbsd_unlock: null vcache");
965     return lockmgr(&vc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
966                    ap->a_p);
967 }
968
969 int
970 afs_nbsd_bmap(ap)
971      struct vop_bmap_args       /* {
972                                  * struct vnode *a_vp;
973                                  * daddr_t  a_bn;
974                                  * struct vnode **a_vpp;
975                                  * daddr_t *a_bnp;
976                                  * int *a_runp;
977                                  * } */ *ap;
978 {
979     struct vcache *vcp = VTOAFS(ap->a_vp);
980
981     AFS_STATCNT(afs_bmap);
982     if (ap->a_bnp)
983         ap->a_bnp = (daddr_t *) (ap->a_bn * (8192 / DEV_BSIZE));
984     if (ap->a_vpp)
985         *ap->a_vpp = (vcp) ? AFSTOV(vcp) : NULL;
986     return 0;
987 }
988
989 int
990 afs_nbsd_strategy(ap)
991      struct vop_strategy_args   /* {
992                                  * struct buf *a_bp;
993                                  * } */ *ap;
994 {
995     struct buf *abp = ap->a_bp;
996     struct uio tuio;
997     struct iovec tiovec[1];
998     struct vcache *tvc = VTOAFS(abp->b_vp);
999     struct ucred *credp = osi_curcred();
1000     long len = abp->b_bcount;
1001     int code;
1002
1003     AFS_STATCNT(afs_strategy);
1004
1005     tuio.afsio_iov = tiovec;
1006     tuio.afsio_iovcnt = 1;
1007     tuio.afsio_seg = AFS_UIOSYS;
1008     tuio.afsio_resid = len;
1009     tiovec[0].iov_base = abp->b_un.b_addr;
1010     tiovec[0].iov_len = len;
1011
1012     AFS_GLOCK();
1013     if ((abp->b_flags & B_READ) == B_READ) {
1014         code = afs_rdwr(tvc, &tuio, UIO_READ, 0, credp);
1015         if (code == 0 && tuio.afsio_resid > 0)
1016             bzero(abp->b_un.b_addr + len - tuio.afsio_resid,
1017                   tuio.afsio_resid);
1018     } else
1019         code = afs_rdwr(tvc, &tuio, UIO_WRITE, 0, credp);
1020     AFS_GUNLOCK();
1021
1022     ReleaseWriteLock(&tvc->lock);
1023     AFS_RELE(AFSTOV(tvc));
1024     return code;
1025 }
1026
1027 int
1028 afs_nbsd_print(ap)
1029      struct vop_print_args      /* {
1030                                  * struct vnode *a_vp;
1031                                  * } */ *ap;
1032 {
1033     struct vnode *vp = ap->a_vp;
1034     struct vcache *vc = VTOAFS(ap->a_vp);
1035
1036     printf("tag %d, fid: %d.%x.%x.%x, ", vp->v_tag, vc->fid.Cell,
1037            (int)vc->fid.Fid.Volume, (int)vc->fid.Fid.Vnode,
1038            (int)vc->fid.Fid.Unique);
1039     lockmgr_printinfo(&vc->rwlock);
1040     printf("\n");
1041     return 0;
1042 }
1043
1044 int
1045 afs_nbsd_islocked(ap)
1046      struct vop_islocked_args   /* {
1047                                  * struct vnode *a_vp;
1048                                  * } */ *ap;
1049 {
1050     return lockstatus(&VTOAFS(ap->a_vp)->rwlock);
1051 }
1052
1053 /*
1054  * Return POSIX pathconf information applicable to ufs filesystems.
1055  */
1056 int
1057 afs_nbsd_pathconf(ap)
1058      struct vop_pathconf_args   /* {
1059                                  * struct vnode *a_vp;
1060                                  * int a_name;
1061                                  * int *a_retval;
1062                                  * } */ *ap;
1063 {
1064     AFS_STATCNT(afs_cntl);
1065     switch (ap->a_name) {
1066     case _PC_LINK_MAX:
1067         *ap->a_retval = LINK_MAX;
1068         break;
1069     case _PC_NAME_MAX:
1070         *ap->a_retval = NAME_MAX;
1071         break;
1072     case _PC_PATH_MAX:
1073         *ap->a_retval = PATH_MAX;
1074         break;
1075     case _PC_CHOWN_RESTRICTED:
1076         *ap->a_retval = 1;
1077         break;
1078     case _PC_NO_TRUNC:
1079         *ap->a_retval = 1;
1080         break;
1081     case _PC_PIPE_BUF:
1082         return EINVAL;
1083         break;
1084     default:
1085         return EINVAL;
1086     }
1087     return 0;
1088 }
1089
1090 extern int
1091   afs_lockctl(struct vcache *avc, struct AFS_FLOCK *af, int acmd,
1092               struct AFS_UCRED *acred, pid_t clid);
1093
1094 /*
1095  * Advisory record locking support (fcntl() POSIX style)
1096  */
1097 int
1098 afs_nbsd_advlock(ap)
1099      struct vop_advlock_args    /* {
1100                                  * struct vnode *a_vp;
1101                                  * caddr_t  a_id;
1102                                  * int  a_op;
1103                                  * struct flock *a_fl;
1104                                  * int  a_flags;
1105                                  * } */ *ap;
1106 {
1107     int code;
1108
1109     AFS_GLOCK();
1110     code =
1111         afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, osi_curcred(),
1112                     (int)ap->a_id);
1113     AFS_GUNLOCK();
1114     return code;
1115 }