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