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