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