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