7 #include <afs/sysincludes.h> /* Standard vendor system headers */
8 #include <afsincludes.h> /* Afs-based standard headers */
9 #include <afs/afs_stats.h> /* statistics */
10 #include <sys/malloc.h>
11 #include <sys/namei.h>
14 int afs_vop_lookup(struct vop_lookup_args *);
15 int afs_vop_create(struct vop_create_args *);
16 int afs_vop_mknod(struct vop_mknod_args *);
17 int afs_vop_open(struct vop_open_args *);
18 int afs_vop_close(struct vop_close_args *);
19 int afs_vop_access(struct vop_access_args *);
20 int afs_vop_getattr(struct vop_getattr_args *);
21 int afs_vop_setattr(struct vop_setattr_args *);
22 int afs_vop_read(struct vop_read_args *);
23 int afs_vop_write(struct vop_write_args *);
24 int afs_vop_pagein(struct vop_pagein_args *);
25 int afs_vop_pageout(struct vop_pageout_args *);
26 int afs_vop_ioctl(struct vop_ioctl_args *);
27 int afs_vop_select(struct vop_select_args *);
28 int afs_vop_mmap(struct vop_mmap_args *);
29 int afs_vop_fsync(struct vop_fsync_args *);
30 int afs_vop_seek(struct vop_seek_args *);
31 int afs_vop_remove(struct vop_remove_args *);
32 int afs_vop_link(struct vop_link_args *);
33 int afs_vop_rename(struct vop_rename_args *);
34 int afs_vop_mkdir(struct vop_mkdir_args *);
35 int afs_vop_rmdir(struct vop_rmdir_args *);
36 int afs_vop_symlink(struct vop_symlink_args *);
37 int afs_vop_readdir(struct vop_readdir_args *);
38 int afs_vop_readlink(struct vop_readlink_args *);
39 extern int ufs_abortop(struct vop_abortop_args *);
40 int afs_vop_inactive(struct vop_inactive_args *);
41 int afs_vop_reclaim(struct vop_reclaim_args *);
42 int afs_vop_lock(struct vop_lock_args *);
43 int afs_vop_unlock(struct vop_unlock_args *);
44 int afs_vop_bmap(struct vop_bmap_args *);
45 int afs_vop_strategy(struct vop_strategy_args *);
46 int afs_vop_print(struct vop_print_args *);
47 int afs_vop_islocked(struct vop_islocked_args *);
48 int afs_vop_pathconf(struct vop_pathconf_args *);
49 int afs_vop_advlock(struct vop_advlock_args *);
50 int afs_vop_truncate(struct vop_truncate_args *);
51 int afs_vop_update(struct vop_update_args *);
52 int afs_vop_blktooff __P((struct vop_blktooff_args *));
53 int afs_vop_offtoblk __P((struct vop_offtoblk_args *));
54 int afs_vop_cmap __P((struct vop_cmap_args *));
57 #define afs_vop_opnotsupp \
58 ((int (*) __P((struct vop_reallocblks_args *)))eopnotsupp)
59 #define afs_vop_valloc afs_vop_opnotsupp
60 #define afs_vop_vfree afs_vop_opnotsupp
61 #define afs_vop_blkatoff afs_vop_opnotsupp
62 #define afs_vop_reallocblks afs_vop_opnotsupp
64 /* Global vfs data structures for AFS. */
65 int (**afs_vnodeop_p) ();
66 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
67 {&vop_default_desc, vn_default_error},
68 {&vop_lookup_desc, afs_vop_lookup}, /* lookup */
69 {&vop_create_desc, afs_vop_create}, /* create */
70 {&vop_mknod_desc, afs_vop_mknod}, /* mknod */
71 {&vop_open_desc, afs_vop_open}, /* open */
72 {&vop_close_desc, afs_vop_close}, /* close */
73 {&vop_access_desc, afs_vop_access}, /* access */
74 {&vop_getattr_desc, afs_vop_getattr}, /* getattr */
75 {&vop_setattr_desc, afs_vop_setattr}, /* setattr */
76 {&vop_read_desc, afs_vop_read}, /* read */
77 {&vop_write_desc, afs_vop_write}, /* write */
78 {&vop_pagein_desc, afs_vop_pagein}, /* read */
79 {&vop_pageout_desc, afs_vop_pageout}, /* write */
80 {&vop_ioctl_desc, afs_vop_ioctl}, /* XXX ioctl */
81 {&vop_select_desc, afs_vop_select}, /* select */
82 {&vop_mmap_desc, afs_vop_mmap}, /* mmap */
83 {&vop_fsync_desc, afs_vop_fsync}, /* fsync */
84 {&vop_seek_desc, afs_vop_seek}, /* seek */
85 {&vop_remove_desc, afs_vop_remove}, /* remove */
86 {&vop_link_desc, afs_vop_link}, /* link */
87 {&vop_rename_desc, afs_vop_rename}, /* rename */
88 {&vop_mkdir_desc, afs_vop_mkdir}, /* mkdir */
89 {&vop_rmdir_desc, afs_vop_rmdir}, /* rmdir */
90 {&vop_symlink_desc, afs_vop_symlink}, /* symlink */
91 {&vop_readdir_desc, afs_vop_readdir}, /* readdir */
92 {&vop_readlink_desc, afs_vop_readlink}, /* readlink */
93 /* Yes, we use the ufs_abortop call. It just releases the namei
95 {&vop_abortop_desc, ufs_abortop}, /* abortop */
96 {&vop_inactive_desc, afs_vop_inactive}, /* inactive */
97 {&vop_reclaim_desc, afs_vop_reclaim}, /* reclaim */
98 {&vop_lock_desc, afs_vop_lock}, /* lock */
99 {&vop_unlock_desc, afs_vop_unlock}, /* unlock */
100 {&vop_bmap_desc, afs_vop_bmap}, /* bmap */
101 {&vop_strategy_desc, afs_vop_strategy}, /* strategy */
102 {&vop_print_desc, afs_vop_print}, /* print */
103 {&vop_islocked_desc, afs_vop_islocked}, /* islocked */
104 {&vop_pathconf_desc, afs_vop_pathconf}, /* pathconf */
105 {&vop_advlock_desc, afs_vop_advlock}, /* advlock */
106 {&vop_blkatoff_desc, afs_vop_blkatoff}, /* blkatoff */
107 {&vop_valloc_desc, afs_vop_valloc}, /* valloc */
108 {&vop_reallocblks_desc, afs_vop_reallocblks}, /* reallocblks */
109 {&vop_vfree_desc, afs_vop_vfree}, /* vfree */
110 {&vop_truncate_desc, afs_vop_truncate}, /* truncate */
111 {&vop_update_desc, afs_vop_update}, /* update */
112 {&vop_blktooff_desc, afs_vop_blktooff}, /* blktooff */
113 {&vop_offtoblk_desc, afs_vop_offtoblk}, /* offtoblk */
114 {&vop_cmap_desc, afs_vop_cmap}, /* cmap */
115 {&vop_bwrite_desc, vn_bwrite},
116 {(struct vnodeop_desc *)NULL, (int (*)())NULL}
118 struct vnodeopv_desc afs_vnodeop_opv_desc =
119 { &afs_vnodeop_p, afs_vnodeop_entries };
122 struct componentname *cnp = ap->a_cnp; \
124 MALLOC(name, char *, cnp->cn_namelen+1, M_TEMP, M_WAITOK); \
125 memcpy(name, cnp->cn_nameptr, cnp->cn_namelen); \
126 name[cnp->cn_namelen] = '\0'
128 #define DROPNAME() FREE(name, M_TEMP)
134 struct vop_lookup_args /* {
135 * struct vnodeop_desc * a_desc;
136 * struct vnode *a_dvp;
137 * struct vnode **a_vpp;
138 * struct componentname *a_cnp;
143 struct vnode *vp, *dvp;
144 register int flags = ap->a_cnp->cn_flags;
145 int lockparent; /* 1 => lockparent flag is set */
146 int wantparent; /* 1 => wantparent or lockparent flag */
150 lockparent = flags & LOCKPARENT;
151 wantparent = flags & (LOCKPARENT | WANTPARENT);
153 if (ap->a_dvp->v_type != VDIR) {
159 if (flags & ISDOTDOT)
160 VOP_UNLOCK(dvp, 0, p);
162 error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
165 if (flags & ISDOTDOT)
166 VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
167 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
168 && (flags & ISLASTCN) && error == ENOENT)
170 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
171 cnp->cn_flags |= SAVENAME;
176 vp = AFSTOV(vcp); /* always get a node if no error */
177 vp->v_vfsp = dvp->v_vfsp;
179 /* The parent directory comes in locked. We unlock it on return
180 * unless the caller wants it left locked.
181 * we also always return the vnode locked. */
183 if (flags & ISDOTDOT) {
184 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
185 /* always return the child locked */
186 if (lockparent && (flags & ISLASTCN)
187 && (error = vn_lock(dvp, LK_EXCLUSIVE, p))) {
192 } else if (vp == dvp) {
193 /* they're the same; afs_lookup() already ref'ed the leaf.
194 * It came in locked, so we don't need to ref OR lock it */
196 if (!lockparent || !(flags & ISLASTCN))
197 VOP_UNLOCK(dvp, 0, p); /* done with parent. */
198 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
199 /* always return the child locked */
203 if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)
204 || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
205 cnp->cn_flags |= SAVENAME;
213 struct vop_create_args /* {
214 * struct vnode *a_dvp;
215 * struct vnode **a_vpp;
216 * struct componentname *a_cnp;
217 * struct vattr *a_vap;
222 register struct vnode *dvp = ap->a_dvp;
227 /* vnode layer handles excl/nonexcl */
230 afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
234 VOP_ABORTOP(dvp, cnp);
241 *ap->a_vpp = AFSTOV(vcp);
242 (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
243 vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
244 if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp))
245 ubc_info_init(*ap->a_vpp);
249 if ((cnp->cn_flags & SAVESTART) == 0)
250 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
258 struct vop_mknod_args /* {
259 * struct vnode *a_dvp;
260 * struct vnode **a_vpp;
261 * struct componentname *a_cnp;
262 * struct vattr *a_vap;
265 FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
272 struct vop_open_args /* {
273 * struct vnode *a_vp;
275 * struct ucred *a_cred;
280 struct vcache *vc = VTOAFS(ap->a_vp);
282 error = afs_open(&vc, ap->a_mode, ap->a_cred);
284 if (AFSTOV(vc) != ap->a_vp)
285 panic("AFS open changed vnode!");
287 afs_BozonLock(&vc->pvnLock, vc);
288 osi_FlushPages(vc, ap->a_cred);
289 afs_BozonUnlock(&vc->pvnLock, vc);
296 struct vop_close_args /* {
297 * struct vnode *a_vp;
299 * struct ucred *a_cred;
304 struct vcache *avc = ap->a_vp;
307 code = afs_close(avc, ap->a_fflag, ap->a_cred, ap->a_p);
309 code = afs_close(avc, ap->a_fflag, &afs_osi_cred, ap->a_p);
310 afs_BozonLock(&avc->pvnLock, avc);
311 osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
312 afs_BozonUnlock(&avc->pvnLock, avc);
314 #ifdef AFS_DARWIN14_ENV
315 if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) {
317 if (ap->a_vp->v_ubcinfo->ui_refcount < 2) {
318 printf("afs: Imminent ui_refcount panic\n");
320 printf("afs: WARNING: ui_refcount panic averted\n");
330 struct vop_access_args /* {
331 * struct vnode *a_vp;
333 * struct ucred *a_cred;
339 code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
346 struct vop_getattr_args /* {
347 * struct vnode *a_vp;
348 * struct vattr *a_vap;
349 * struct ucred *a_cred;
355 code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
362 struct vop_setattr_args /* {
363 * struct vnode *a_vp;
364 * struct vattr *a_vap;
365 * struct ucred *a_cred;
371 code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
378 struct vop_read_args /* {
379 * struct vnode *a_vp;
382 * struct ucred *a_cred;
386 struct vcache *avc = VTOAFS(ap->a_vp);
388 afs_BozonLock(&avc->pvnLock, avc);
389 osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
390 code = afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
391 afs_BozonUnlock(&avc->pvnLock, avc);
398 struct vop_pagein_args /* {
399 * struct vnode *a_vp;
401 * vm_offset_t a_pl_offset;
404 * struct ucred *a_cred;
408 register struct vnode *vp = ap->a_vp;
410 size_t size = ap->a_size;
411 off_t f_offset = ap->a_f_offset;
412 vm_offset_t pl_offset = ap->a_pl_offset;
413 int flags = ap->a_flags;
418 struct uio *uio = &auio;
419 int nocommit = flags & UPL_NOCOMMIT;
422 struct vcache *tvc = VTOAFS(vp);
424 if (UBCINVALID(vp)) {
426 panic("afs_vop_pagein: invalid vp");
427 #endif /* DIAGNOSTIC */
431 UBCINFOCHECK("afs_vop_pagein", vp);
432 if (pl == (upl_t) NULL) {
433 panic("afs_vop_pagein: no upl");
436 cred = ubc_getcred(vp);
442 kernel_upl_abort_range(pl, pl_offset, size,
443 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
448 kernel_upl_abort_range(pl, pl_offset, size,
449 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
452 if (f_offset & PAGE_MASK)
453 panic("afs_vop_pagein: offset not page aligned");
455 auio.uio_iov = &aiov;
457 auio.uio_offset = f_offset;
458 auio.uio_segflg = UIO_SYSSPACE;
459 auio.uio_rw = UIO_READ;
460 auio.uio_procp = NULL;
461 kernel_upl_map(kernel_map, pl, &ioaddr);
463 auio.uio_resid = aiov.iov_len = size;
464 aiov.iov_base = (caddr_t) ioaddr;
466 afs_BozonLock(&tvc->pvnLock, tvc);
467 osi_FlushPages(tvc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
468 code = afs_read(tvc, uio, cred, 0, 0, 0);
470 ObtainWriteLock(&tvc->lock, 2);
471 tvc->states |= CMAPPED;
472 ReleaseWriteLock(&tvc->lock);
474 afs_BozonUnlock(&tvc->pvnLock, tvc);
477 /* Zero out rest of last page if there wasn't enough data in the file */
478 if (code == 0 && auio.uio_resid > 0)
479 memset(aiov.iov_base, 0, auio.uio_resid);
481 kernel_upl_unmap(kernel_map, pl);
484 kernel_upl_abort_range(pl, pl_offset, size,
485 UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
487 kernel_upl_commit_range(pl, pl_offset, size,
488 UPL_COMMIT_CLEAR_DIRTY |
489 UPL_COMMIT_FREE_ON_EMPTY,
490 UPL_GET_INTERNAL_PAGE_LIST(pl),
498 struct vop_write_args /* {
499 * struct vnode *a_vp;
502 * struct ucred *a_cred;
506 struct vcache *avc = VTOAFS(ap->a_vp);
509 afs_BozonLock(&avc->pvnLock, avc);
510 osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
511 if (UBCINFOEXISTS(ap->a_vp))
512 ubc_clean(ap->a_vp, 1);
513 if (UBCINFOEXISTS(ap->a_vp))
514 osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset,
515 ap->a_uio->uio_resid);
517 afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
518 afs_BozonUnlock(&avc->pvnLock, avc);
525 struct vop_pageout_args /* {
526 * struct vnode *a_vp;
528 * vm_offset_t a_pl_offset,
531 * struct ucred *a_cred,
535 register struct vnode *vp = ap->a_vp;
537 size_t size = ap->a_size;
538 off_t f_offset = ap->a_f_offset;
539 vm_offset_t pl_offset = ap->a_pl_offset;
540 int flags = ap->a_flags;
545 struct uio *uio = &auio;
546 int nocommit = flags & UPL_NOCOMMIT;
549 struct vcache *tvc = VTOAFS(vp);
551 if (UBCINVALID(vp)) {
553 panic("afs_vop_pageout: invalid vp");
554 #endif /* DIAGNOSTIC */
558 UBCINFOCHECK("afs_vop_pageout", vp);
559 if (pl == (upl_t) NULL) {
560 panic("afs_vop_pageout: no upl");
566 int biosize = DEV_BSIZE;
568 lbn = f_offset / DEV_BSIZE;
570 for (iosize = size; iosize > 0; iosize -= biosize, lbn++) {
573 if (bp = incore(vp, lbn)) {
574 if (ISSET(bp->b_flags, B_BUSY))
575 panic("nfs_pageout: found BUSY buffer incore\n");
578 SET(bp->b_flags, (B_BUSY | B_INVAL));
585 cred = ubc_getcred(vp);
591 kernel_upl_abort_range(pl, pl_offset, size,
592 UPL_ABORT_FREE_ON_EMPTY);
595 if (flags & (IO_APPEND | IO_SYNC))
596 panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
599 kernel_upl_abort_range(pl, pl_offset, size,
600 UPL_ABORT_FREE_ON_EMPTY);
603 if (f_offset >= tvc->m.Length) {
605 kernel_upl_abort_range(pl, pl_offset, size,
606 UPL_ABORT_FREE_ON_EMPTY);
610 if (f_offset & PAGE_MASK)
611 panic("afs_vop_pageout: offset not page aligned");
613 auio.uio_iov = &aiov;
615 auio.uio_offset = f_offset;
616 auio.uio_segflg = UIO_SYSSPACE;
617 auio.uio_rw = UIO_WRITE;
618 auio.uio_procp = NULL;
619 kernel_upl_map(kernel_map, pl, &ioaddr);
621 auio.uio_resid = aiov.iov_len = size;
622 aiov.iov_base = (caddr_t) ioaddr;
626 * check for partial page and clear the
627 * contents past end of the file before
628 * releasing it in the VM page cache
630 if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
631 size_t io = tvc->m.Length - f_offset;
633 memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
639 afs_BozonLock(&tvc->pvnLock, tvc);
640 osi_FlushPages(tvc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */
641 ObtainWriteLock(&tvc->lock, 1);
643 ReleaseWriteLock(&tvc->lock);
645 code = afs_write(tvc, uio, flags, cred, 0);
647 ObtainWriteLock(&tvc->lock, 1);
648 afs_FakeClose(tvc, cred);
649 ReleaseWriteLock(&tvc->lock);
650 afs_BozonUnlock(&tvc->pvnLock, tvc);
652 kernel_upl_unmap(kernel_map, pl);
655 kernel_upl_abort_range(pl, pl_offset, size,
656 UPL_ABORT_FREE_ON_EMPTY);
658 kernel_upl_commit_range(pl, pl_offset, size,
659 UPL_COMMIT_CLEAR_DIRTY |
660 UPL_COMMIT_FREE_ON_EMPTY,
661 UPL_GET_INTERNAL_PAGE_LIST(pl),
670 struct vop_ioctl_args /* {
671 * struct vnode *a_vp;
675 * struct ucred *a_cred;
679 struct vcache *tvc = VTOAFS(ap->a_vp);
680 struct afs_ioctl data;
683 /* in case we ever get in here... */
685 AFS_STATCNT(afs_ioctl);
686 if (((ap->a_command >> 8) & 0xff) == 'V') {
687 /* This is a VICEIOCTL call */
689 error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
690 ap->a_command, ap->a_data);
694 /* No-op call; just return. */
702 struct vop_select_args /* {
703 * struct vnode *a_vp;
706 * struct ucred *a_cred;
711 * We should really check to see if I/O is possible.
719 * NB Currently unsupported.
724 struct vop_mmap_args /* {
725 * struct vnode *a_vp;
727 * struct ucred *a_cred;
736 struct vop_fsync_args /* {
737 * struct vnode *a_vp;
738 * struct ucred *a_cred;
743 int wait = ap->a_waitfor == MNT_WAIT;
745 register struct vnode *vp = ap->a_vp;
748 /*vflushbuf(vp, wait); */
750 error = afs_fsync(VTOAFS(vp), ap->a_cred);
752 error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
759 struct vop_seek_args /* {
760 * struct vnode *a_vp;
763 * struct ucred *a_cred;
766 if (ap->a_newoff > ULONG_MAX) /* AFS doesn't support 64-bit offsets */
773 struct vop_remove_args /* {
774 * struct vnode *a_dvp;
775 * struct vnode *a_vp;
776 * struct componentname *a_cnp;
780 register struct vnode *vp = ap->a_vp;
781 register struct vnode *dvp = ap->a_dvp;
785 error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
788 if (!error && UBCINFOEXISTS(vp)) {
789 #ifdef AFS_DARWIN14_ENV
790 (void)ubc_uncache(vp);
792 int wasmapped = ubc_issetflags(vp, UI_WASMAPPED);
793 int hasobjref = ubc_issetflags(vp, UI_HASOBJREF);
795 (void)ubc_uncache(vp);
798 /* WARNING vp may not be valid after this */
807 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
814 struct vop_link_args /* {
815 * struct vnode *a_vp;
816 * struct vnode *a_tdvp;
817 * struct componentname *a_cnp;
821 register struct vnode *dvp = ap->a_tdvp;
822 register struct vnode *vp = ap->a_vp;
827 if (vp->v_type == VDIR) {
828 VOP_ABORTOP(vp, cnp);
832 if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
833 VOP_ABORTOP(dvp, cnp);
837 error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
839 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
841 VOP_UNLOCK(vp, 0, p);
850 struct vop_rename_args /* {
851 * struct vnode *a_fdvp;
852 * struct vnode *a_fvp;
853 * struct componentname *a_fcnp;
854 * struct vnode *a_tdvp;
855 * struct vnode *a_tvp;
856 * struct componentname *a_tcnp;
860 struct componentname *fcnp = ap->a_fcnp;
862 struct componentname *tcnp = ap->a_tcnp;
864 struct vnode *tvp = ap->a_tvp;
865 register struct vnode *tdvp = ap->a_tdvp;
866 struct vnode *fvp = ap->a_fvp;
867 register struct vnode *fdvp = ap->a_fdvp;
868 struct proc *p = fcnp->cn_proc;
871 * if fvp == tvp, we're just removing one name of a pair of
872 * directory entries for the same element. convert call into rename.
873 ( (pinched from NetBSD 1.0's ufs_rename())
876 if (fvp->v_type == VDIR) {
879 VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
886 VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
892 /* Release destination completely. */
893 VOP_ABORTOP(tdvp, tcnp);
900 fcnp->cn_flags &= ~MODMASK;
901 fcnp->cn_flags |= LOCKPARENT | LOCKLEAF;
902 if ((fcnp->cn_flags & SAVESTART) == 0)
903 panic("afs_rename: lost from startdir");
904 fcnp->cn_nameiop = DELETE;
905 (void)relookup(fdvp, &fvp, fcnp);
906 return (VOP_REMOVE(fdvp, fvp, fcnp));
908 if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
911 MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
912 memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
913 fname[fcnp->cn_namelen] = '\0';
914 MALLOC(tname, char *, tcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
915 memcpy(tname, tcnp->cn_nameptr, tcnp->cn_namelen);
916 tname[tcnp->cn_namelen] = '\0';
920 /* XXX use "from" or "to" creds? NFS uses "to" creds */
922 afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
925 VOP_UNLOCK(fvp, 0, p);
929 goto abortit; /* XXX */
943 struct vop_mkdir_args /* {
944 * struct vnode *a_dvp;
945 * struct vnode **a_vpp;
946 * struct componentname *a_cnp;
947 * struct vattr *a_vap;
950 register struct vnode *dvp = ap->a_dvp;
951 register struct vattr *vap = ap->a_vap;
959 if ((cnp->cn_flags & HASBUF) == 0)
960 panic("afs_vop_mkdir: no name");
963 error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
966 VOP_ABORTOP(dvp, cnp);
972 *ap->a_vpp = AFSTOV(vcp);
973 (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
974 vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
978 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
985 struct vop_rmdir_args /* {
986 * struct vnode *a_dvp;
987 * struct vnode *a_vp;
988 * struct componentname *a_cnp;
992 register struct vnode *vp = ap->a_vp;
993 register struct vnode *dvp = ap->a_dvp;
999 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1005 error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
1015 struct vop_symlink_args /* {
1016 * struct vnode *a_dvp;
1017 * struct vnode **a_vpp;
1018 * struct componentname *a_cnp;
1019 * struct vattr *a_vap;
1023 register struct vnode *dvp = ap->a_dvp;
1025 /* NFS ignores a_vpp; so do we. */
1030 afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
1033 FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
1040 struct vop_readdir_args /* {
1041 * struct vnode *a_vp;
1042 * struct uio *a_uio;
1043 * struct ucred *a_cred;
1045 * u_long *a_cookies;
1051 /* printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
1053 off = ap->a_uio->uio_offset;
1056 afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
1058 if (!error && ap->a_ncookies != NULL) {
1059 struct uio *uio = ap->a_uio;
1060 const struct dirent *dp, *dp_start, *dp_end;
1062 u_long *cookies, *cookiep;
1064 if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
1065 panic("afs_readdir: burned cookies");
1066 dp = (const struct dirent *)
1067 ((const char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
1069 dp_end = (const struct dirent *)uio->uio_iov->iov_base;
1070 for (dp_start = dp, ncookies = 0; dp < dp_end;
1071 dp = (const struct dirent *)((const char *)dp + dp->d_reclen))
1074 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
1076 for (dp = dp_start, cookiep = cookies; dp < dp_end;
1077 dp = (const struct dirent *)((const char *)dp + dp->d_reclen)) {
1078 off += dp->d_reclen;
1081 *ap->a_cookies = cookies;
1082 *ap->a_ncookies = ncookies;
1089 afs_vop_readlink(ap)
1090 struct vop_readlink_args /* {
1091 * struct vnode *a_vp;
1092 * struct uio *a_uio;
1093 * struct ucred *a_cred;
1097 /* printf("readlink %x\n", ap->a_vp);*/
1099 error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
1104 extern int prtactive;
1107 afs_vop_inactive(ap)
1108 struct vop_inactive_args /* {
1109 * struct vnode *a_vp;
1113 register struct vnode *vp = ap->a_vp;
1115 if (prtactive && vp->v_usecount != 0)
1116 vprint("afs_vop_inactive(): pushing active", vp);
1119 afs_InactiveVCache(VTOAFS(vp), 0); /* decrs ref counts */
1121 VOP_UNLOCK(vp, 0, ap->a_p);
1127 struct vop_reclaim_args /* {
1128 * struct vnode *a_vp;
1133 register struct vnode *vp = ap->a_vp;
1135 cache_purge(vp); /* just in case... */
1139 error = afs_FlushVCache(VTOAFS(vp), &sl); /* tosses our stuff from vnode */
1142 if (!error && vp->v_data)
1143 panic("afs_reclaim: vnode not cleaned");
1146 if (vp->v_usecount == 2) {
1147 vprint("reclaim count==2", vp);
1148 } else if (vp->v_usecount == 1) {
1149 vprint("reclaim count==1", vp);
1151 vprint("reclaim bad count", vp);
1159 struct vop_lock_args /* {
1160 * struct vnode *a_vp;
1163 register struct vnode *vp = ap->a_vp;
1164 register struct vcache *avc = VTOAFS(vp);
1166 if (vp->v_tag == VT_NON)
1168 return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
1173 struct vop_unlock_args /* {
1174 * struct vnode *a_vp;
1177 struct vnode *vp = ap->a_vp;
1178 struct vcache *avc = VTOAFS(vp);
1180 (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
1187 struct vop_bmap_args /* {
1188 * struct vnode *a_vp;
1190 * struct vnode **a_vpp;
1199 *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
1202 *ap->a_vpp = ap->a_vp;
1204 if (ap->a_runp != NULL)
1207 if (ap->a_runb != NULL)
1215 afs_vop_strategy(ap)
1216 struct vop_strategy_args /* {
1222 error = afs_ustrategy(ap->a_bp);
1229 struct vop_print_args /* {
1230 * struct vnode *a_vp;
1233 register struct vnode *vp = ap->a_vp;
1234 register struct vcache *vc = VTOAFS(ap->a_vp);
1236 printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
1237 vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
1238 vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
1239 printf("\n states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
1240 (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
1241 (s & CMAPPED) ? " mapped" : "",
1242 (s & CVFlushed) ? " flush in progress" : "");
1243 if (UBCISVALID(vp)) {
1245 if (UBCINFOEXISTS(vp)) {
1247 #ifdef AFS_DARWIN14_ENV
1248 printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
1249 ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
1250 ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
1252 printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
1255 printf("does not exist");
1262 afs_vop_islocked(ap)
1263 struct vop_islocked_args /* {
1264 * struct vnode *a_vp;
1267 struct vcache *vc = VTOAFS(ap->a_vp);
1268 return lockstatus(&vc->rwlock);
1272 * Return POSIX pathconf information applicable to ufs filesystems.
1274 afs_vop_pathconf(ap)
1275 struct vop_pathconf_args /* {
1276 * struct vnode *a_vp;
1281 AFS_STATCNT(afs_cntl);
1282 switch (ap->a_name) {
1284 *ap->a_retval = LINK_MAX;
1287 *ap->a_retval = NAME_MAX;
1290 *ap->a_retval = PATH_MAX;
1292 case _PC_CHOWN_RESTRICTED:
1308 * Advisory record locking support (fcntl() POSIX style)
1312 struct vop_advlock_args /* {
1313 * struct vnode *a_vp;
1316 * struct flock *a_fl;
1321 struct proc *p = current_proc();
1324 cr = *p->p_cred->pc_ucred;
1328 afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr, (int)ap->a_id);
1334 afs_vop_truncate(ap)
1335 struct vop_truncate_args /* {
1336 * struct vnode *a_vp;
1339 * struct ucred *a_cred;
1343 printf("stray afs_vop_truncate\n");
1349 struct vop_update_args /* {
1350 * struct vnode *a_vp;
1351 * struct timeval *a_access;
1352 * struct timeval *a_modify;
1356 printf("stray afs_vop_update\n");
1361 afs_vop_blktooff(ap)
1362 struct vop_blktooff_args /* {
1363 * struct vnode *a_vp;
1368 *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
1373 afs_vop_offtoblk(ap)
1374 struct vop_offtoblk_args /* {
1375 * struct vnode *a_vp;
1377 * daddr_t *a_lblkno;
1380 *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
1387 struct vop_cmap_args /* {
1388 * struct vnode *a_vp;
1396 *ap->a_bpn = (daddr_t) (ap->a_foffset / DEV_BSIZE);
1397 *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));