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