macos: fix race in afs_root
[openafs.git] / src / afs / DARWIN / osi_vnodeops.c
index 5413cf6..1d8a163 100644 (file)
@@ -4,8 +4,6 @@
 #include <afsconfig.h>
 #include <afs/param.h>
 
-RCSID
-    ("$Header$");
 
 #include <afs/sysincludes.h>   /* Standard vendor system headers */
 #include <afsincludes.h>       /* Afs-based standard headers */
@@ -13,54 +11,79 @@ RCSID
 #include <sys/malloc.h>
 #include <sys/namei.h>
 #include <sys/ubc.h>
-#if defined(AFS_DARWIN70_ENV)
 #include <vfs/vfs_support.h>
-#endif /* defined(AFS_DARWIN70_ENV) */
-
-int afs_vop_lookup(struct vop_lookup_args *);
-int afs_vop_create(struct vop_create_args *);
-int afs_vop_mknod(struct vop_mknod_args *);
-int afs_vop_open(struct vop_open_args *);
-int afs_vop_close(struct vop_close_args *);
-int afs_vop_access(struct vop_access_args *);
-int afs_vop_getattr(struct vop_getattr_args *);
-int afs_vop_setattr(struct vop_setattr_args *);
-int afs_vop_read(struct vop_read_args *);
-int afs_vop_write(struct vop_write_args *);
-int afs_vop_pagein(struct vop_pagein_args *);
-int afs_vop_pageout(struct vop_pageout_args *);
-int afs_vop_ioctl(struct vop_ioctl_args *);
-int afs_vop_select(struct vop_select_args *);
-int afs_vop_mmap(struct vop_mmap_args *);
-int afs_vop_fsync(struct vop_fsync_args *);
-int afs_vop_seek(struct vop_seek_args *);
-int afs_vop_remove(struct vop_remove_args *);
-int afs_vop_link(struct vop_link_args *);
-int afs_vop_rename(struct vop_rename_args *);
-int afs_vop_mkdir(struct vop_mkdir_args *);
-int afs_vop_rmdir(struct vop_rmdir_args *);
-int afs_vop_symlink(struct vop_symlink_args *);
-int afs_vop_readdir(struct vop_readdir_args *);
-int afs_vop_readlink(struct vop_readlink_args *);
-#if !defined(AFS_DARWIN70_ENV)
-extern int ufs_abortop(struct vop_abortop_args *);
-#endif /* !defined(AFS_DARWIN70_ENV) */
-int afs_vop_inactive(struct vop_inactive_args *);
-int afs_vop_reclaim(struct vop_reclaim_args *);
-int afs_vop_lock(struct vop_lock_args *);
-int afs_vop_unlock(struct vop_unlock_args *);
-int afs_vop_bmap(struct vop_bmap_args *);
-int afs_vop_strategy(struct vop_strategy_args *);
-int afs_vop_print(struct vop_print_args *);
-int afs_vop_islocked(struct vop_islocked_args *);
-int afs_vop_pathconf(struct vop_pathconf_args *);
-int afs_vop_advlock(struct vop_advlock_args *);
-int afs_vop_truncate(struct vop_truncate_args *);
-int afs_vop_update(struct vop_update_args *);
-int afs_vop_blktooff __P((struct vop_blktooff_args *));
-int afs_vop_offtoblk __P((struct vop_offtoblk_args *));
-int afs_vop_cmap __P((struct vop_cmap_args *));
+#ifdef AFS_DARWIN80_ENV
+#include <sys/vnode_if.h>
+#include <sys/kauth.h>
+#endif
+
+#ifdef AFS_DARWIN80_ENV
+#define VOPPREF(x) &vnop_ ## x
+#define VOPPROT(x) vnop_ ## x
+#define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
+  ubc_upl_abort_range((pl), (offset), (size), (flags))
+#define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
+  ubc_upl_commit_range((pl), (offset), (size), (flags))
+#define OSI_UPL_MAP(upl, offset) ubc_upl_map((upl), (offset))
+#define OSI_UPL_UNMAP(upl) ubc_upl_unmap((upl))
+#define VOP_ABORTOP(x, y)
+#else
+#define VOPPREF(x) &vop_ ## x
+#define VOPPROT(x) vop_ ## x
+#define OSI_UPL_ABORT_RANGE(pl, offset, size, flags) \
+  kernel_upl_abort_range((pl), (offset), (size), (flags))
+#define OSI_UPL_COMMIT_RANGE(pl, offset, size, flags) \
+  kernel_upl_commit_range((pl), (offset), (size), (flags), \
+                          UPL_GET_INTERNAL_PAGE_LIST((pl)),\
+                                    MAX_UPL_TRANSFER)
+#define OSI_UPL_MAP(upl, offset) kernel_upl_map(kernel_map, (upl), (offset))
+#define OSI_UPL_UNMAP(upl) kernel_upl_unmap(kernel_map, (upl))
+#endif
 
+extern char afs_zeros[AFS_ZEROS];
+
+int afs_vop_lookup(struct VOPPROT(lookup_args) *);
+int afs_vop_create(struct VOPPROT(create_args) *);
+int afs_vop_mknod(struct VOPPROT(mknod_args) *);
+int afs_vop_open(struct VOPPROT(open_args) *);
+int afs_vop_close(struct VOPPROT(close_args) *);
+int afs_vop_access(struct VOPPROT(access_args) *);
+int afs_vop_getattr(struct VOPPROT(getattr_args) *);
+int afs_vop_setattr(struct VOPPROT(setattr_args) *);
+int afs_vop_read(struct VOPPROT(read_args) *);
+int afs_vop_write(struct VOPPROT(write_args) *);
+int afs_vop_pagein(struct VOPPROT(pagein_args) *);
+int afs_vop_pageout(struct VOPPROT(pageout_args) *);
+int afs_vop_ioctl(struct VOPPROT(ioctl_args) *);
+int afs_vop_select(struct VOPPROT(select_args) *);
+int afs_vop_mmap(struct VOPPROT(mmap_args) *);
+int afs_vop_fsync(struct VOPPROT(fsync_args) *);
+int afs_vop_remove(struct VOPPROT(remove_args) *);
+int afs_vop_link(struct VOPPROT(link_args) *);
+int afs_vop_rename(struct VOPPROT(rename_args) *);
+int afs_vop_mkdir(struct VOPPROT(mkdir_args) *);
+int afs_vop_rmdir(struct VOPPROT(rmdir_args) *);
+int afs_vop_symlink(struct VOPPROT(symlink_args) *);
+int afs_vop_readdir(struct VOPPROT(readdir_args) *);
+int afs_vop_readlink(struct VOPPROT(readlink_args) *);
+int afs_vop_inactive(struct VOPPROT(inactive_args) *);
+int afs_vop_reclaim(struct VOPPROT(reclaim_args) *);
+int afs_vop_strategy(struct VOPPROT(strategy_args) *);
+int afs_vop_pathconf(struct VOPPROT(pathconf_args) *);
+int afs_vop_advlock(struct VOPPROT(advlock_args) *);
+int afs_vop_blktooff __P((struct VOPPROT(blktooff_args) *));
+int afs_vop_offtoblk __P((struct VOPPROT(offtoblk_args) *));
+#ifndef AFS_DARWIN80_ENV
+int afs_vop_truncate(struct VOPPROT(truncate_args) *);
+int afs_vop_update(struct VOPPROT(update_args) *);
+int afs_vop_lock(struct VOPPROT(lock_args) *);
+int afs_vop_unlock(struct VOPPROT(unlock_args) *);
+int afs_vop_bmap(struct VOPPROT(bmap_args) *);
+int afs_vop_seek(struct VOPPROT(seek_args) *);
+int afs_vop_cmap __P((struct VOPPROT(cmap_args) *));
+int afs_vop_print(struct VOPPROT(print_args) *);
+int afs_vop_islocked(struct VOPPROT(islocked_args) *);
+#endif
 
 #define afs_vop_opnotsupp \
        ((int (*) __P((struct  vop_reallocblks_args *)))eopnotsupp)
@@ -71,65 +94,120 @@ int afs_vop_cmap __P((struct vop_cmap_args *));
 
 /* Global vfs data structures for AFS. */
 int (**afs_vnodeop_p) ();
+
+#define VOPFUNC int (*)(void *)
+
 struct vnodeopv_entry_desc afs_vnodeop_entries[] = {
-    {&vop_default_desc, vn_default_error},
-    {&vop_lookup_desc, afs_vop_lookup},        /* lookup */
-    {&vop_create_desc, afs_vop_create},        /* create */
-    {&vop_mknod_desc, afs_vop_mknod},  /* mknod */
-    {&vop_open_desc, afs_vop_open},    /* open */
-    {&vop_close_desc, afs_vop_close},  /* close */
-    {&vop_access_desc, afs_vop_access},        /* access */
-    {&vop_getattr_desc, afs_vop_getattr},      /* getattr */
-    {&vop_setattr_desc, afs_vop_setattr},      /* setattr */
-    {&vop_read_desc, afs_vop_read},    /* read */
-    {&vop_write_desc, afs_vop_write},  /* write */
-    {&vop_pagein_desc, afs_vop_pagein},        /* read */
-    {&vop_pageout_desc, afs_vop_pageout},      /* write */
-    {&vop_ioctl_desc, afs_vop_ioctl},  /* XXX ioctl */
-    {&vop_select_desc, afs_vop_select},        /* select */
-    {&vop_mmap_desc, afs_vop_mmap},    /* mmap */
-    {&vop_fsync_desc, afs_vop_fsync},  /* fsync */
-    {&vop_seek_desc, afs_vop_seek},    /* seek */
-    {&vop_remove_desc, afs_vop_remove},        /* remove */
-    {&vop_link_desc, afs_vop_link},    /* link */
-    {&vop_rename_desc, afs_vop_rename},        /* rename */
-    {&vop_mkdir_desc, afs_vop_mkdir},  /* mkdir */
-    {&vop_rmdir_desc, afs_vop_rmdir},  /* rmdir */
-    {&vop_symlink_desc, afs_vop_symlink},      /* symlink */
-    {&vop_readdir_desc, afs_vop_readdir},      /* readdir */
-    {&vop_readlink_desc, afs_vop_readlink},    /* readlink */
-#if defined(AFS_DARWIN70_ENV)
-    { &vop_abortop_desc, nop_abortop },             /* abortop */
-#else /* ! defined(AFS_DARWIN70_ENV) */
-    /* Yes, we use the ufs_abortop call.  It just releases the namei
-     * buffer stuff */
-    {&vop_abortop_desc, ufs_abortop},  /* abortop */
-#endif /* defined(AFS_DARWIN70_ENV) */
-    {&vop_inactive_desc, afs_vop_inactive},    /* inactive */
-    {&vop_reclaim_desc, afs_vop_reclaim},      /* reclaim */
-    {&vop_lock_desc, afs_vop_lock},    /* lock */
-    {&vop_unlock_desc, afs_vop_unlock},        /* unlock */
-    {&vop_bmap_desc, afs_vop_bmap},    /* bmap */
-    {&vop_strategy_desc, afs_vop_strategy},    /* strategy */
-    {&vop_print_desc, afs_vop_print},  /* print */
-    {&vop_islocked_desc, afs_vop_islocked},    /* islocked */
-    {&vop_pathconf_desc, afs_vop_pathconf},    /* pathconf */
-    {&vop_advlock_desc, afs_vop_advlock},      /* advlock */
-    {&vop_blkatoff_desc, afs_vop_blkatoff},    /* blkatoff */
-    {&vop_valloc_desc, afs_vop_valloc},        /* valloc */
-    {&vop_reallocblks_desc, afs_vop_reallocblks},      /* reallocblks */
-    {&vop_vfree_desc, afs_vop_vfree},  /* vfree */
-    {&vop_truncate_desc, afs_vop_truncate},    /* truncate */
-    {&vop_update_desc, afs_vop_update},        /* update */
-    {&vop_blktooff_desc, afs_vop_blktooff},    /* blktooff */
-    {&vop_offtoblk_desc, afs_vop_offtoblk},    /* offtoblk */
-    {&vop_cmap_desc, afs_vop_cmap},    /* cmap */
-    {&vop_bwrite_desc, vn_bwrite},
-    {(struct vnodeop_desc *)NULL, (int (*)())NULL}
+    {VOPPREF(default_desc), (VOPFUNC)vn_default_error},
+    {VOPPREF(lookup_desc), (VOPFUNC)afs_vop_lookup},   /* lookup */
+    {VOPPREF(create_desc), (VOPFUNC)afs_vop_create},   /* create */
+    {VOPPREF(mknod_desc), (VOPFUNC)afs_vop_mknod},     /* mknod */
+    {VOPPREF(open_desc), (VOPFUNC)afs_vop_open},       /* open */
+    {VOPPREF(close_desc), (VOPFUNC)afs_vop_close},     /* close */
+    {VOPPREF(access_desc), (VOPFUNC)afs_vop_access},   /* access */
+    {VOPPREF(getattr_desc), (VOPFUNC)afs_vop_getattr}, /* getattr */
+    {VOPPREF(setattr_desc), (VOPFUNC)afs_vop_setattr}, /* setattr */
+    {VOPPREF(read_desc), (VOPFUNC)afs_vop_read},       /* read */
+    {VOPPREF(write_desc), (VOPFUNC)afs_vop_write},     /* write */
+    {VOPPREF(pagein_desc), (VOPFUNC)afs_vop_pagein},   /* read */
+    {VOPPREF(pageout_desc), (VOPFUNC)afs_vop_pageout}, /* write */
+    {VOPPREF(ioctl_desc), (VOPFUNC)afs_vop_ioctl},     /* XXX ioctl */
+    {VOPPREF(select_desc), (VOPFUNC)afs_vop_select},   /* select */
+    {VOPPREF(mmap_desc), (VOPFUNC)afs_vop_mmap},       /* mmap */
+    {VOPPREF(fsync_desc), (VOPFUNC)afs_vop_fsync},     /* fsync */
+#ifndef AFS_DARWIN80_ENV
+    {VOPPREF(seek_desc), (VOPFUNC)afs_vop_seek},       /* seek */
+#endif
+    {VOPPREF(remove_desc), (VOPFUNC)afs_vop_remove},   /* remove */
+    {VOPPREF(link_desc), (VOPFUNC)afs_vop_link},       /* link */
+    {VOPPREF(rename_desc), (VOPFUNC)afs_vop_rename},   /* rename */
+    {VOPPREF(mkdir_desc), (VOPFUNC)afs_vop_mkdir},     /* mkdir */
+    {VOPPREF(rmdir_desc), (VOPFUNC)afs_vop_rmdir},     /* rmdir */
+    {VOPPREF(symlink_desc), (VOPFUNC)afs_vop_symlink}, /* symlink */
+    {VOPPREF(readdir_desc), (VOPFUNC)afs_vop_readdir}, /* readdir */
+    {VOPPREF(readlink_desc), (VOPFUNC)afs_vop_readlink},       /* readlink */
+#ifndef AFS_DARWIN80_ENV
+    {VOPPREF(abortop_desc), (VOPFUNC)nop_abortop },             /* abortop */
+#endif
+    {VOPPREF(inactive_desc), (VOPFUNC)afs_vop_inactive},       /* inactive */
+    {VOPPREF(reclaim_desc), (VOPFUNC)afs_vop_reclaim}, /* reclaim */
+#ifndef AFS_DARWIN80_ENV
+    {VOPPREF(lock_desc), (VOPFUNC)afs_vop_lock},       /* lock */
+    {VOPPREF(unlock_desc), (VOPFUNC)afs_vop_unlock},   /* unlock */
+    {VOPPREF(bmap_desc), (VOPFUNC)afs_vop_bmap},       /* bmap */
+#endif
+#ifdef AFS_DARWIN80_ENV
+    {VOPPREF(strategy_desc), (VOPFUNC)err_strategy},   /* strategy */
+#else
+    {VOPPREF(strategy_desc), (VOPFUNC)afs_vop_strategy},       /* strategy */
+#endif
+#ifndef AFS_DARWIN80_ENV
+    {VOPPREF(print_desc), (VOPFUNC)afs_vop_print},     /* print */
+    {VOPPREF(islocked_desc), (VOPFUNC)afs_vop_islocked},       /* islocked */
+#endif
+    {VOPPREF(pathconf_desc), (VOPFUNC)afs_vop_pathconf},       /* pathconf */
+    {VOPPREF(advlock_desc), (VOPFUNC)afs_vop_advlock}, /* advlock */
+#ifndef AFS_DARWIN80_ENV
+    {VOPPREF(blkatoff_desc), (VOPFUNC)afs_vop_blkatoff},       /* blkatoff */
+    {VOPPREF(valloc_desc), (VOPFUNC)afs_vop_valloc},   /* valloc */
+    {VOPPREF(reallocblks_desc), (VOPFUNC)afs_vop_reallocblks}, /* reallocblks */
+    {VOPPREF(vfree_desc), (VOPFUNC)afs_vop_vfree},     /* vfree */
+    {VOPPREF(update_desc), (VOPFUNC)afs_vop_update},   /* update */
+    {VOPPREF(cmap_desc), (VOPFUNC)afs_vop_cmap},       /* cmap */
+    {VOPPREF(truncate_desc), (VOPFUNC)afs_vop_truncate},       /* truncate */
+#endif
+    {VOPPREF(blktooff_desc), (VOPFUNC)afs_vop_blktooff},       /* blktooff */
+    {VOPPREF(offtoblk_desc), (VOPFUNC)afs_vop_offtoblk},       /* offtoblk */
+    {VOPPREF(bwrite_desc), (VOPFUNC)vn_bwrite},
+    {(struct vnodeop_desc *)NULL, (void (*)())NULL}
 };
 struct vnodeopv_desc afs_vnodeop_opv_desc =
     { &afs_vnodeop_p, afs_vnodeop_entries };
 
+#ifdef AFS_DARWIN80_ENV
+/* vfs structures for incompletely initialized vnodes */
+int (**afs_dead_vnodeop_p) ();
+
+struct vnodeopv_entry_desc afs_dead_vnodeop_entries[] = {
+    {VOPPREF(default_desc), (VOPFUNC)vn_default_error},
+    {VOPPREF(lookup_desc), (VOPFUNC)vn_default_error}, /* lookup */
+    {VOPPREF(create_desc), (VOPFUNC)err_create},       /* create */
+    {VOPPREF(mknod_desc), (VOPFUNC)err_mknod}, /* mknod */
+    {VOPPREF(open_desc), (VOPFUNC)err_open},   /* open */
+    {VOPPREF(close_desc), (VOPFUNC)err_close}, /* close */
+    {VOPPREF(access_desc), (VOPFUNC)err_access},       /* access */
+    {VOPPREF(getattr_desc), (VOPFUNC)err_getattr},     /* getattr */
+    {VOPPREF(setattr_desc), (VOPFUNC)err_setattr},     /* setattr */
+    {VOPPREF(read_desc), (VOPFUNC)err_read},   /* read */
+    {VOPPREF(write_desc), (VOPFUNC)err_write}, /* write */
+    {VOPPREF(pagein_desc), (VOPFUNC)err_pagein},       /* read */
+    {VOPPREF(pageout_desc), (VOPFUNC)err_pageout},     /* write */
+    {VOPPREF(ioctl_desc), (VOPFUNC)err_ioctl}, /* XXX ioctl */
+    {VOPPREF(select_desc), (VOPFUNC)nop_select},       /* select */
+    {VOPPREF(mmap_desc), (VOPFUNC)err_mmap},   /* mmap */
+    {VOPPREF(fsync_desc), (VOPFUNC)err_fsync}, /* fsync */
+    {VOPPREF(remove_desc), (VOPFUNC)err_remove},       /* remove */
+    {VOPPREF(link_desc), (VOPFUNC)err_link},   /* link */
+    {VOPPREF(rename_desc), (VOPFUNC)err_rename},       /* rename */
+    {VOPPREF(mkdir_desc), (VOPFUNC)err_mkdir}, /* mkdir */
+    {VOPPREF(rmdir_desc), (VOPFUNC)err_rmdir}, /* rmdir */
+    {VOPPREF(symlink_desc), (VOPFUNC)err_symlink},     /* symlink */
+    {VOPPREF(readdir_desc), (VOPFUNC)err_readdir},     /* readdir */
+    {VOPPREF(readlink_desc), (VOPFUNC)err_readlink},   /* readlink */
+    {VOPPREF(inactive_desc), (VOPFUNC)afs_vop_inactive},       /* inactive */
+    {VOPPREF(reclaim_desc), (VOPFUNC)afs_vop_reclaim}, /* reclaim */
+    {VOPPREF(strategy_desc), (VOPFUNC)err_strategy},   /* strategy */
+    {VOPPREF(pathconf_desc), (VOPFUNC)err_pathconf},   /* pathconf */
+    {VOPPREF(advlock_desc), (VOPFUNC)err_advlock},     /* advlock */
+    {VOPPREF(blktooff_desc), (VOPFUNC)err_blktooff},   /* blktooff */
+    {VOPPREF(offtoblk_desc), (VOPFUNC)err_offtoblk},   /* offtoblk */
+    {VOPPREF(bwrite_desc), (VOPFUNC)err_bwrite},
+    {(struct vnodeop_desc *)NULL, (void (*)())NULL}
+};
+struct vnodeopv_desc afs_dead_vnodeop_opv_desc =
+    { &afs_dead_vnodeop_p, afs_dead_vnodeop_entries };
+#endif
+
 #define GETNAME()       \
     struct componentname *cnp = ap->a_cnp; \
     char *name; \
@@ -139,11 +217,61 @@ struct vnodeopv_desc afs_vnodeop_opv_desc =
 
 #define DROPNAME() FREE(name, M_TEMP)
 
+void 
+darwin_vn_hold(struct vnode *vp)
+{
+    int haveGlock=ISAFS_GLOCK(); 
+    struct vcache *tvc = VTOAFS(vp);
 
+#ifndef AFS_DARWIN80_ENV
+    tvc->f.states |= CUBCinit;
+#endif
+#ifdef AFS_DARWIN80_ENV
+    osi_Assert((tvc->f.states & CVInit) == 0);
+    if (tvc->f.states & CDeadVnode)
+       osi_Assert(!vnode_isinuse(vp, 1));
+#endif
+    if (haveGlock) AFS_GUNLOCK(); 
+
+#ifdef AFS_DARWIN80_ENV
+       if (vnode_get(vp)) {
+           /* being terminated. kernel won't give us a ref. Now what? our
+              callers don't expect us to fail */
+           if (haveGlock) AFS_GLOCK(); 
+           return;
+        }
+       if (vnode_ref(vp)) {
+           vnode_put(vp);
+           if (haveGlock) AFS_GLOCK(); 
+           return;
+       }
+       vnode_put(vp);
+#else
+    /* vget needed for 0 ref'd vnode in GetVCache to not panic in vref.
+       vref needed for multiref'd vnode in vnop_remove not to deadlock
+       ourselves during vop_inactive, except we also need to not reinst
+       the ubc... so we just call VREF there now anyway. */
+
+    if (VREFCOUNT_GT(tvc, 0))
+       VREF(((struct vnode *)(vp))); 
+     else 
+       afs_vget(afs_globalVFS, 0, (vp));
+#endif
+
+#ifndef AFS_DARWIN80_ENV
+    if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp)) {
+       ubc_info_init(vp); 
+    }
+#endif
 
+    if (haveGlock) AFS_GLOCK(); 
+#ifndef AFS_DARWIN80_ENV
+    tvc->f.states &= ~CUBCinit;
+#endif
+}
 int
 afs_vop_lookup(ap)
-     struct vop_lookup_args    /* {
+     struct VOPPROT(lookup_args)/* {
                                 * struct vnodeop_desc * a_desc;
                                 * struct vnode *a_dvp;
                                 * struct vnode **a_vpp;
@@ -153,51 +281,81 @@ afs_vop_lookup(ap)
     int error;
     struct vcache *vcp;
     struct vnode *vp, *dvp;
-    register int flags = ap->a_cnp->cn_flags;
+    int flags = ap->a_cnp->cn_flags;
     int lockparent;            /* 1 => lockparent flag is set */
     int wantparent;            /* 1 => wantparent or lockparent flag */
     struct proc *p;
+#ifdef AFS_DARWIN80_ENV
+    vcp = VTOAFS(ap->a_dvp);
+    /*
+     * ._ file attribute mirroring touches this.
+     * we can't flag the vcache as there is none, so fail here.
+     * needed for fsevents support.
+     */
+    if (ap->a_context == afs_osi_ctxtp)
+       return ENOENT;
+    if (vcp->mvstat != 1) {
+       error = cache_lookup(ap->a_dvp, ap->a_vpp, ap->a_cnp);
+       if (error == -1) 
+           return 0;
+       if (error == ENOENT) 
+           return error;
+    }
+#endif
+
     GETNAME();
-    p = cnp->cn_proc;
+    p = vop_cn_proc;
+
     lockparent = flags & LOCKPARENT;
     wantparent = flags & (LOCKPARENT | WANTPARENT);
 
-    if (ap->a_dvp->v_type != VDIR) {
+    if (!vnode_isdir(ap->a_dvp)) {
        *ap->a_vpp = 0;
        DROPNAME();
        return ENOTDIR;
     }
     dvp = ap->a_dvp;
+#ifndef AFS_DARWIN80_ENV
     if (flags & ISDOTDOT)
        VOP_UNLOCK(dvp, 0, p);
+#endif
     AFS_GLOCK();
-    error = afs_lookup(VTOAFS(dvp), name, &vcp, cnp->cn_cred);
+    error = afs_lookup(VTOAFS(dvp), name, &vcp, vop_cn_cred);
     AFS_GUNLOCK();
     if (error) {
+#ifndef AFS_DARWIN80_ENV
        if (flags & ISDOTDOT)
            VOP_LOCK(dvp, LK_EXCLUSIVE | LK_RETRY, p);
+#endif
        if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME)
            && (flags & ISLASTCN) && error == ENOENT)
            error = EJUSTRETURN;
+#ifndef AFS_DARWIN80_ENV
        if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
            cnp->cn_flags |= SAVENAME;
+#endif
        DROPNAME();
        *ap->a_vpp = 0;
        return (error);
     }
+#ifdef AFS_DARWIN80_ENV
+    if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0))) {
+       DROPNAME();
+       *ap->a_vpp = 0;
+       return error;
+    }
+#endif
     vp = AFSTOV(vcp);          /* always get a node if no error */
+#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
     vp->v_vfsp = dvp->v_vfsp;
 
     if (UBCINFOMISSING(vp) ||
        UBCINFORECLAIMED(vp)) {
-#ifdef AFS_DARWIN14_ENV
-       if (UBCINFORECLAIMED(vp) && ISSET(vp->v_flag, (VXLOCK|VORECLAIM))) {
-           DROPNAME();
-           return (ENXIO);
-       } else 
-#endif
            ubc_info_init(vp);
     }
+#endif
+
+#ifndef AFS_DARWIN80_ENV
     /* The parent directory comes in locked.  We unlock it on return
      * unless the caller wants it left locked.
      * we also always return the vnode locked. */
@@ -220,11 +378,14 @@ afs_vop_lookup(ap)
        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
        /* always return the child locked */
     }
+#endif
     *ap->a_vpp = vp;
 
+#ifndef AFS_DARWIN80_ENV
     if ((cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)
         || (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))))
        cnp->cn_flags |= SAVENAME;
+#endif
 
     DROPNAME();
     return error;
@@ -232,7 +393,7 @@ afs_vop_lookup(ap)
 
 int
 afs_vop_create(ap)
-     struct vop_create_args    /* {
+     struct VOPPROT(create_args)       /* {
                                 * struct vnode *a_dvp;
                                 * struct vnode **a_vpp;
                                 * struct componentname *a_cnp;
@@ -241,66 +402,75 @@ afs_vop_create(ap)
 {
     int error = 0;
     struct vcache *vcp;
-    register struct vnode *dvp = ap->a_dvp;
+    struct vnode *dvp = ap->a_dvp;
     struct proc *p;
     GETNAME();
-    p = cnp->cn_proc;
+    p = vop_cn_proc;
 
     /* vnode layer handles excl/nonexcl */
     AFS_GLOCK();
     error =
        afs_create(VTOAFS(dvp), name, ap->a_vap, NONEXCL, ap->a_vap->va_mode,
-                  &vcp, cnp->cn_cred);
+                  &vcp, vop_cn_cred);
     AFS_GUNLOCK();
     if (error) {
+#ifndef AFS_DARWIN80_ENV
        VOP_ABORTOP(dvp, cnp);
        vput(dvp);
+#endif
        DROPNAME();
        return (error);
     }
 
     if (vcp) {
+#ifdef AFS_DARWIN80_ENV
+      if ((error=afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0))) {
+           DROPNAME();
+           *ap->a_vpp=0;
+           return error;
+        }
+#endif
        *ap->a_vpp = AFSTOV(vcp);
+#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
        (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
        vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
        if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp)) {
-#ifdef AFS_DARWIN14_ENV
-           if (UBCINFORECLAIMED(*ap->a_vpp) && ISSET((*ap->a_vpp)->v_flag, 
-                                                     (VXLOCK|VORECLAIM))) {
-               vput(dvp);
-               DROPNAME();
-               return (ENXIO);
-           } else 
-#endif
-               ubc_info_init(*ap->a_vpp);
+           vcp->f.states |= CUBCinit;
+           ubc_info_init(*ap->a_vpp);
+           vcp->f.states &= ~CUBCinit;
        }
+#endif
     } else
        *ap->a_vpp = 0;
 
+#ifndef AFS_DARWIN80_ENV
     if ((cnp->cn_flags & SAVESTART) == 0)
        FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
     vput(dvp);
+#endif
     DROPNAME();
     return error;
 }
 
 int
 afs_vop_mknod(ap)
-     struct vop_mknod_args     /* {
+     struct VOPPROT(mknod_args)        /* {
                                 * struct vnode *a_dvp;
                                 * struct vnode **a_vpp;
                                 * struct componentname *a_cnp;
                                 * struct vattr *a_vap;
                                 * } */ *ap;
 {
+#ifndef AFS_DARWIN80_ENV
     FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
     vput(ap->a_dvp);
+#endif
     return (ENODEV);
 }
 
 int
 afs_vop_open(ap)
-     struct vop_open_args      /* {
+     struct VOPPROT(open_args) /* {
                                 * struct vnode *a_vp;
                                 * int  a_mode;
                                 * struct ucred *a_cred;
@@ -310,7 +480,7 @@ afs_vop_open(ap)
     int error;
     struct vnode *vp = ap->a_vp;
     struct vcache *vc = VTOAFS(vp);
-#ifdef AFS_DARWIN14_ENV
+#if !defined(AFS_DARWIN80_ENV)
     int didhold = 0;
     /*----------------------------------------------------------------
      * osi_VM_TryReclaim() removes the ubcinfo of a vnode, but that vnode
@@ -324,27 +494,25 @@ afs_vop_open(ap)
     if (vp->v_type == VREG && !(vp->v_flag & VSYSTEM)
       && vp->v_ubcinfo->ui_refcount < 2)
        didhold = ubc_hold(vp);
-#endif /* AFS_DARWIN14_ENV */
+#endif /* !AFS_DARWIN80_ENV */
     AFS_GLOCK();
-    error = afs_open(&vc, ap->a_mode, ap->a_cred);
+    error = afs_open(&vc, ap->a_mode, vop_cred);
 #ifdef DIAGNOSTIC
     if (AFSTOV(vc) != vp)
        panic("AFS open changed vnode!");
 #endif
-    afs_BozonLock(&vc->pvnLock, vc);
-    osi_FlushPages(vc, ap->a_cred);
-    afs_BozonUnlock(&vc->pvnLock, vc);
+    osi_FlushPages(vc, vop_cred);
     AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
+#if !defined(AFS_DARWIN80_ENV)
     if (error && didhold)
        ubc_rele(vp);
-#endif /* AFS_DARWIN14_ENV */
+#endif /* !AFS_DARWIN80_ENV */
     return error;
 }
 
 int
 afs_vop_close(ap)
-     struct vop_close_args     /* {
+     struct VOPPROT(close_args)        /* {
                                 * struct vnode *a_vp;
                                 * int  a_fflag;
                                 * struct ucred *a_cred;
@@ -352,44 +520,150 @@ afs_vop_close(ap)
                                 * } */ *ap;
 {
     int code;
-    struct vcache *avc = ap->a_vp;
+    struct vnode *vp = ap->a_vp;
+    struct vcache *avc = VTOAFS(vp);
+    /* allows faking FSE_CONTENT_MODIFIED */
+    if (afs_osi_ctxtp == ap->a_context)
+       return 0;
     AFS_GLOCK();
-    if (ap->a_cred)
-       code = afs_close(avc, ap->a_fflag, ap->a_cred, ap->a_p);
+    if (vop_cred)
+       code = afs_close(avc, ap->a_fflag, vop_cred);
     else
-       code = afs_close(avc, ap->a_fflag, &afs_osi_cred, ap->a_p);
-    afs_BozonLock(&avc->pvnLock, avc);
-    osi_FlushPages(avc, ap->a_cred);   /* hold bozon lock, but not basic vnode lock */
-    afs_BozonUnlock(&avc->pvnLock, avc);
+       code = afs_close(avc, ap->a_fflag, &afs_osi_cred);
+    osi_FlushPages(avc, vop_cred);     /* hold bozon lock, but not basic vnode lock */
+    /* This is legit; it just forces the fstrace event to happen */
+    code = afs_CheckCode(code, NULL, 60);
     AFS_GUNLOCK();
-#ifdef AFS_DARWIN14_ENV
-    if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) {
-       ubc_hold(ap->a_vp);
-       if (ap->a_vp->v_ubcinfo->ui_refcount < 2) {
-           printf("afs: Imminent ui_refcount panic\n");
-       } else {
-           printf("afs: WARNING: ui_refcount panic averted\n");
-       }
+
+    return code;
+}
+
+#ifdef AFS_DARWIN80_ENV
+extern int afs_fakestat_enable;
+
+int
+afs_vop_access(ap)
+     struct VOPPROT(access_args)        /* {
+                                 * struct vnode *a_vp;
+                                 * int  a_action;
+                                 * vfs_context_t a_context;
+                                 * } */ *ap;
+{
+    int code;
+    struct vrequest treq;
+    struct afs_fakestat_state fakestate;
+    struct vcache * tvc = VTOAFS(ap->a_vp);
+    int bits=0;
+    int cmb = CHECK_MODE_BITS;
+#ifdef AFS_DARWIN80_ENV
+    /*
+     * needed for fsevents. ._ file attribute mirroring touches this.
+     * we can't flag the vcache, as there is none, so fail here.
+     */
+    if (ap->a_context == afs_osi_ctxtp)
+       return ENOENT;
+#endif
+    AFS_GLOCK();
+    afs_InitFakeStat(&fakestate);
+    if ((code = afs_InitReq(&treq, vop_cred)))
+        goto out2;
+
+    code = afs_TryEvalFakeStat(&tvc, &fakestate, &treq);
+    if (code) {
+        code = afs_CheckCode(code, &treq, 55);
+        goto out;
     }
-    if (UBCINFOMISSING(ap->a_vp) ||
-       UBCINFORECLAIMED(ap->a_vp)) {
-       if (UBCINFORECLAIMED(ap->a_vp) && ISSET(ap->a_vp->v_flag, 
-                                               (VXLOCK|VORECLAIM))) {
-           printf("no ubc for %x in close, reclaim set\n", ap->a_vp);
-           return (ENXIO);
-       } else {
-           printf("no ubc for %x in close, put back\n", ap->a_vp);
-           ubc_info_init(ap->a_vp);
-       }
+
+    code = afs_VerifyVCache(tvc, &treq);
+    if (code) {
+        code = afs_CheckCode(code, &treq, 56);
+        goto out;
     }
+    if (afs_fakestat_enable && tvc->mvstat && !(tvc->f.states & CStatd)) {
+        code = 0;
+        goto out;
+    }
+    if (vnode_isdir(ap->a_vp)) {
+       if (ap->a_action & KAUTH_VNODE_LIST_DIRECTORY)
+          bits |= PRSFS_LOOKUP;
+       if (ap->a_action & KAUTH_VNODE_ADD_FILE)
+          bits |= PRSFS_INSERT;
+       if (ap->a_action & KAUTH_VNODE_SEARCH)
+          bits |= PRSFS_LOOKUP;
+       if (ap->a_action & KAUTH_VNODE_DELETE)
+          bits |= PRSFS_DELETE;
+       if (ap->a_action & KAUTH_VNODE_ADD_SUBDIRECTORY)
+          bits |= PRSFS_INSERT;
+       if (ap->a_action & KAUTH_VNODE_DELETE_CHILD)
+          bits |= PRSFS_DELETE;
+#if 0 /* I'd argue this should be enforced on the parent. But that's ugly */
+       if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
+          bits |= PRSFS_LOOKUP;
+       if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
+          bits |= PRSFS_LOOKUP;
 #endif
-
+    } else {
+       if (ap->a_action & KAUTH_VNODE_READ_DATA)
+          bits |= PRSFS_READ;
+       if (ap->a_action & KAUTH_VNODE_WRITE_DATA)
+          bits |= PRSFS_WRITE;
+       if (ap->a_action & KAUTH_VNODE_EXECUTE)
+          bits |= PRSFS_READ; /* and mode bits.... */
+       if (ap->a_action & KAUTH_VNODE_READ_ATTRIBUTES)
+          bits |= PRSFS_LOOKUP;
+       if (ap->a_action & KAUTH_VNODE_READ_SECURITY) /* mode bits/gid, not afs acl */
+          bits |= PRSFS_LOOKUP;
+       if ((ap->a_action & ((1 << 25) - 1)) == KAUTH_VNODE_EXECUTE)
+          /* if only exec, don't check for read mode bit */
+          /* high bits of ap->a_action are not for 'generic rights bits', and
+             so should not be checked (KAUTH_VNODE_ACCESS is often present
+             and needs to be masked off) */
+         cmb |= CMB_ALLOW_EXEC_AS_READ;
+    }
+    if (ap->a_action & KAUTH_VNODE_WRITE_ATTRIBUTES)
+       bits |= PRSFS_WRITE;
+#if 0 /* no extended attributes */
+    if (ap->a_action & KAUTH_VNODE_READ_EXTATTRIBUTES)
+       bits |= PRSFS_READ;
+    if (ap->a_action & KAUTH_VNODE_WRITE_EXTATTRIBUTES)
+       bits |= PRSFS_WRITE;
+#endif
+    if (ap->a_action & KAUTH_VNODE_WRITE_SECURITY)
+       bits |= PRSFS_WRITE;
+    /* we can't check for KAUTH_VNODE_TAKE_OWNERSHIP, so we always permit it */
+    
+    code = afs_AccessOK(tvc, bits, &treq, cmb);
+    /*
+     * Special cased dropbox handling:
+     * cp on 10.4 behaves badly, looping on EACCES
+     * Finder may reopen the file. Let it.
+     */
+    if (code == 0 && ((bits &~(PRSFS_READ|PRSFS_WRITE)) == 0))
+       code = afs_AccessOK(tvc, PRSFS_ADMINISTER|PRSFS_INSERT|bits, &treq, cmb);
+    /* Finder also treats dropboxes as insert+delete. fake it out. */
+    if (code == 0 && (bits == (PRSFS_INSERT|PRSFS_DELETE)))
+       code = afs_AccessOK(tvc, PRSFS_INSERT, &treq, cmb);
+
+    if (code == 1 && vnode_vtype(ap->a_vp) == VREG &&
+        ap->a_action & KAUTH_VNODE_EXECUTE &&
+        (tvc->f.m.Mode & 0100) != 0100) {
+        code = 0;
+    }
+    if (code) {
+        code= 0;               /* if access is ok */
+    } else {
+           code = afs_CheckCode(EACCES, &treq, 57);        /* failure code */
+    }
+out:
+     afs_PutFakeStat(&fakestate);
+out2:
+    AFS_GUNLOCK();
     return code;
 }
-
+#else
 int
 afs_vop_access(ap)
-     struct vop_access_args    /* {
+     struct VOPPROT(access_args)       /* {
                                 * struct vnode *a_vp;
                                 * int  a_mode;
                                 * struct ucred *a_cred;
@@ -398,14 +672,15 @@ afs_vop_access(ap)
 {
     int code;
     AFS_GLOCK();
-    code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, ap->a_cred);
+    code = afs_access(VTOAFS(ap->a_vp), ap->a_mode, vop_cred);
     AFS_GUNLOCK();
     return code;
 }
+#endif
 
 int
 afs_vop_getattr(ap)
-     struct vop_getattr_args   /* {
+     struct VOPPROT(getattr_args)      /* {
                                 * struct vnode *a_vp;
                                 * struct vattr *a_vap;
                                 * struct ucred *a_cred;
@@ -413,31 +688,109 @@ afs_vop_getattr(ap)
                                 * } */ *ap;
 {
     int code;
-    AFS_GLOCK();
-    code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
-    AFS_GUNLOCK();
+
+#ifdef AFS_DARWIN80_ENV
+    /* CEvent excludes the fsevent. our context excludes the ._ */
+    if ((VTOAFS(ap->a_vp)->f.states & CEvent) ||
+       (ap->a_context == afs_osi_ctxtp)){
+       struct vcache *avc = VTOAFS(ap->a_vp);
+       int isglock = ISAFS_GLOCK();
+
+       /* this is needed because of how and when we re-enter */
+       if (!isglock)
+         AFS_GLOCK();
+       /* do minimal work to return fake result for fsevents */
+       if (afs_fakestat_enable && VTOAFS(ap->a_vp)->mvstat == 1) {
+           struct afs_fakestat_state fakestat;
+           struct vrequest treq;
+
+           code = afs_InitReq(&treq, vop_cred);
+           if (code) {
+               if (!isglock)
+                   AFS_GUNLOCK();
+               return code;
+           }
+           afs_InitFakeStat(&fakestat);
+           /* expects GLOCK */
+           code = afs_TryEvalFakeStat(&avc, &fakestat, &treq);
+           if (code) {
+               if (!isglock)
+                   AFS_GUNLOCK();
+               afs_PutFakeStat(&fakestat);
+               return code;
+           }
+       }
+       code = afs_CopyOutAttrs(avc, ap->a_vap);
+       if (!isglock)
+           AFS_GUNLOCK();
+       if (0 && !code) {
+           /* tweak things so finder will recheck */
+           (ap->a_vap)->va_gid = ((ap->a_vap)->va_gid == 1) ? 2 : 1;
+           (ap->a_vap)->va_mode &= ~(VSGID);
+       }
+    } else
+#endif
+    {
+       AFS_GLOCK();
+       code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, vop_cred);
+       /* This is legit; it just forces the fstrace event to happen */
+       code = afs_CheckCode(code, NULL, 58);
+       AFS_GUNLOCK();
+    }
+#ifdef AFS_DARWIN80_ENV
+    VATTR_SET_SUPPORTED(ap->a_vap, va_type);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_mode);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_uid);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_gid);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_fsid);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_fileid);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_nlink);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_data_size);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_access_time);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_modify_time);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_change_time);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_gen);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_flags);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_iosize);
+    VATTR_SET_SUPPORTED(ap->a_vap, va_total_alloc);
+#endif
     return code;
 }
 
 int
 afs_vop_setattr(ap)
-     struct vop_setattr_args   /* {
+     struct VOPPROT(setattr_args)      /* {
                                 * struct vnode *a_vp;
                                 * struct vattr *a_vap;
                                 * struct ucred *a_cred;
                                 * struct proc *a_p;
                                 * } */ *ap;
 {
-    int code;
+    int code, pass = 0;
+    struct vcache *avc = VTOAFS(ap->a_vp);
+#ifdef AFS_DARWIN80_ENV
+    /* fsevents tries to set attributes. drop it. */
+    if (ap->a_context == afs_osi_ctxtp)
+       return 0;
+#endif
     AFS_GLOCK();
-    code = afs_setattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred);
+retry:
+    code = afs_setattr(avc, ap->a_vap, vop_cred);
+    /* This is legit; it just forces the fstrace event to happen */
+    code = afs_CheckCode(code, NULL, 59);
+    if (!pass && code == EINVAL && (VATTR_IS_ACTIVE(ap->a_vap, va_mode) &&
+                                   (vType(avc) == VLNK))) {
+       VATTR_CLEAR_ACTIVE(ap->a_vap, va_mode);
+       pass++;
+       goto retry;
+    }
     AFS_GUNLOCK();
     return code;
 }
 
 int
 afs_vop_read(ap)
-     struct vop_read_args      /* {
+     struct VOPPROT(read_args) /* {
                                 * struct vnode *a_vp;
                                 * struct uio *a_uio;
                                 * int a_ioflag;
@@ -445,19 +798,28 @@ afs_vop_read(ap)
                                 * } */ *ap;
 {
     int code;
-    struct vcache *avc = VTOAFS(ap->a_vp);
+    struct vnode *vp = ap->a_vp;
+    struct vcache *avc = VTOAFS(vp);
+
+    if (vnode_isdir(ap->a_vp)) 
+       return EISDIR;
+#ifdef AFS_DARWIN80_ENV
+    ubc_msync_range(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio), AFS_UIO_OFFSET(ap->a_uio) + AFS_UIO_RESID(ap->a_uio), UBC_PUSHDIRTY);
+#else
+    if (UBCINFOEXISTS(ap->a_vp)) {
+       ubc_clean(ap->a_vp, 0);
+    }
+#endif
     AFS_GLOCK();
-    afs_BozonLock(&avc->pvnLock, avc);
-    osi_FlushPages(avc, ap->a_cred);   /* hold bozon lock, but not basic vnode lock */
-    code = afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0);
-    afs_BozonUnlock(&avc->pvnLock, avc);
+    osi_FlushPages(avc, vop_cred);     /* hold bozon lock, but not basic vnode lock */
+    code = afs_read(avc, ap->a_uio, vop_cred, 0);
     AFS_GUNLOCK();
     return code;
 }
 
 int
 afs_vop_pagein(ap)
-     struct vop_pagein_args    /* {
+     struct VOPPROT(pagein_args)       /* {
                                 * struct vnode *a_vp;
                                 * upl_t a_pl;
                                 * vm_offset_t a_pl_offset;
@@ -467,7 +829,7 @@ afs_vop_pagein(ap)
                                 * int a_flags;
                                 * } */ *ap;
 {
-    register struct vnode *vp = ap->a_vp;
+    struct vnode *vp = ap->a_vp;
     upl_t pl = ap->a_pl;
     size_t size = ap->a_size;
     off_t f_offset = ap->a_f_offset;
@@ -475,14 +837,18 @@ afs_vop_pagein(ap)
     int flags = ap->a_flags;
     struct ucred *cred;
     vm_offset_t ioaddr;
+#ifdef AFS_DARWIN80_ENV
+    struct uio *uio;
+#else
     struct uio auio;
     struct iovec aiov;
     struct uio *uio = &auio;
+#endif
     int nocommit = flags & UPL_NOCOMMIT;
 
     int code;
     struct vcache *tvc = VTOAFS(vp);
-
+#ifndef AFS_DARWIN80_ENV
     if (UBCINVALID(vp)) {
 #if DIAGNOSTIC
        panic("afs_vop_pagein: invalid vp");
@@ -491,73 +857,84 @@ afs_vop_pagein(ap)
     }
 
     UBCINFOCHECK("afs_vop_pagein", vp);
+#endif
     if (pl == (upl_t) NULL) {
        panic("afs_vop_pagein: no upl");
     }
 
     cred = ubc_getcred(vp);
     if (cred == NOCRED)
-       cred = ap->a_cred;
+       cred = vop_cred;
 
     if (size == 0) {
        if (!nocommit)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
        return (0);
     }
     if (f_offset < 0) {
        if (!nocommit)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
        return (EINVAL);
     }
     if (f_offset & PAGE_MASK)
        panic("afs_vop_pagein: offset not page aligned");
 
+    OSI_UPL_MAP(pl, &ioaddr);
+    ioaddr += pl_offset;
+#ifdef AFS_DARWIN80_ENV
+    uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
+    uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
+#else
     auio.uio_iov = &aiov;
     auio.uio_iovcnt = 1;
     auio.uio_offset = f_offset;
     auio.uio_segflg = UIO_SYSSPACE;
     auio.uio_rw = UIO_READ;
     auio.uio_procp = NULL;
-    kernel_upl_map(kernel_map, pl, &ioaddr);
-    ioaddr += pl_offset;
     auio.uio_resid = aiov.iov_len = size;
     aiov.iov_base = (caddr_t) ioaddr;
+#endif
     AFS_GLOCK();
-    afs_BozonLock(&tvc->pvnLock, tvc);
-    osi_FlushPages(tvc, ap->a_cred);   /* hold bozon lock, but not basic vnode lock */
-    code = afs_read(tvc, uio, cred, 0, 0, 0);
+    osi_FlushPages(tvc, vop_cred);     /* hold bozon lock, but not basic vnode lock */
+    code = afs_read(tvc, uio, cred, 0);
     if (code == 0) {
        ObtainWriteLock(&tvc->lock, 2);
-       tvc->states |= CMAPPED;
+       tvc->f.states |= CMAPPED;
        ReleaseWriteLock(&tvc->lock);
     }
-    afs_BozonUnlock(&tvc->pvnLock, tvc);
     AFS_GUNLOCK();
 
     /* Zero out rest of last page if there wasn't enough data in the file */
-    if (code == 0 && auio.uio_resid > 0)
+    if (code == 0 && AFS_UIO_RESID(uio) > 0) {
+#ifdef AFS_DARWIN80_ENV
+       memset(((caddr_t)ioaddr) + (size - AFS_UIO_RESID(uio)), 0,
+               AFS_UIO_RESID(uio));
+#else
        memset(aiov.iov_base, 0, auio.uio_resid);
+#endif
+    }
 
-    kernel_upl_unmap(kernel_map, pl);
+    OSI_UPL_UNMAP(pl);
     if (!nocommit) {
        if (code)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_ERROR | UPL_ABORT_FREE_ON_EMPTY);
        else
-           kernel_upl_commit_range(pl, pl_offset, size,
+           OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
                                    UPL_COMMIT_CLEAR_DIRTY |
-                                   UPL_COMMIT_FREE_ON_EMPTY,
-                                   UPL_GET_INTERNAL_PAGE_LIST(pl),
-                                   MAX_UPL_TRANSFER);
+                                   UPL_COMMIT_FREE_ON_EMPTY);
     }
+#ifdef AFS_DARWIN80_ENV
+    uio_free(uio);
+#endif
     return code;
 }
 
 int
 afs_vop_write(ap)
-     struct vop_write_args     /* {
+     struct VOPPROT(write_args)        /* {
                                 * struct vnode *a_vp;
                                 * struct uio *a_uio;
                                 * int a_ioflag;
@@ -567,24 +944,27 @@ afs_vop_write(ap)
     int code;
     struct vcache *avc = VTOAFS(ap->a_vp);
     void *object;
-    AFS_GLOCK();
-    afs_BozonLock(&avc->pvnLock, avc);
-    osi_FlushPages(avc, ap->a_cred);   /* hold bozon lock, but not basic vnode lock */
-    if (UBCINFOEXISTS(ap->a_vp))
+#ifdef AFS_DARWIN80_ENV
+    ubc_msync_range(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio), AFS_UIO_OFFSET(ap->a_uio) + AFS_UIO_RESID(ap->a_uio), UBC_INVALIDATE);
+#else
+    if (UBCINFOEXISTS(ap->a_vp)) {
        ubc_clean(ap->a_vp, 1);
+    }
     if (UBCINFOEXISTS(ap->a_vp))
-       osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset,
-                        ap->a_uio->uio_resid);
+       osi_VM_NukePages(ap->a_vp, AFS_UIO_OFFSET(ap->a_uio),
+                        AFS_UIO_RESID(ap->a_uio));
+#endif
+    AFS_GLOCK();
+    osi_FlushPages(avc, vop_cred);     /* hold bozon lock, but not basic vnode lock */
     code =
-       afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, ap->a_cred, 0);
-    afs_BozonUnlock(&avc->pvnLock, avc);
+       afs_write(VTOAFS(ap->a_vp), ap->a_uio, ap->a_ioflag, vop_cred, 0);
     AFS_GUNLOCK();
     return code;
 }
 
 int
 afs_vop_pageout(ap)
-     struct vop_pageout_args   /* {
+     struct VOPPROT(pageout_args)      /* {
                                 * struct vnode *a_vp;
                                 * upl_t   a_pl,
                                 * vm_offset_t   a_pl_offset,
@@ -594,7 +974,7 @@ afs_vop_pageout(ap)
                                 * int           a_flags
                                 * } */ *ap;
 {
-    register struct vnode *vp = ap->a_vp;
+    struct vnode *vp = ap->a_vp;
     upl_t pl = ap->a_pl;
     size_t size = ap->a_size;
     off_t f_offset = ap->a_f_offset;
@@ -602,15 +982,19 @@ afs_vop_pageout(ap)
     int flags = ap->a_flags;
     struct ucred *cred;
     vm_offset_t ioaddr;
+#ifdef AFS_DARWIN80_ENV
+    struct uio *uio;
+#else
     struct uio auio;
     struct iovec aiov;
     struct uio *uio = &auio;
+#endif
     int nocommit = flags & UPL_NOCOMMIT;
     int iosize;
 
     int code;
     struct vcache *tvc = VTOAFS(vp);
-
+#ifndef AFS_DARWIN80_ENV
     if (UBCINVALID(vp)) {
 #if DIAGNOSTIC
        panic("afs_vop_pageout: invalid vp");
@@ -619,10 +1003,14 @@ afs_vop_pageout(ap)
     }
 
     UBCINFOCHECK("afs_vop_pageout", vp);
+#endif
     if (pl == (upl_t) NULL) {
        panic("afs_vop_pageout: no upl");
     }
-#if 1
+#if !defined(AFS_DARWIN80_ENV) /* XXX nfs now uses it's own bufs (struct nfsbuf)
+                                  maybe the generic
+                                  layer doesn't have them anymore? In any case,
+                                  we can't just copy code from nfs... */
     {
        int lbn, s;
        struct buf *bp;
@@ -647,11 +1035,11 @@ afs_vop_pageout(ap)
 #endif
     cred = ubc_getcred(vp);
     if (cred == NOCRED)
-       cred = ap->a_cred;
+       cred = vop_cred;
 
     if (size == 0) {
        if (!nocommit)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_FREE_ON_EMPTY);
        return (0);
     }
@@ -659,13 +1047,13 @@ afs_vop_pageout(ap)
        panic("nfs_pageout: (IO_APPEND | IO_SYNC)");
     if (f_offset < 0) {
        if (!nocommit)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_FREE_ON_EMPTY);
        return (EINVAL);
     }
-    if (f_offset >= tvc->m.Length) {
+    if (f_offset >= tvc->f.m.Length) {
        if (!nocommit)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_FREE_ON_EMPTY);
        return (EINVAL);
     }
@@ -675,45 +1063,47 @@ afs_vop_pageout(ap)
 
     /* size will always be a multiple of PAGE_SIZE */
     /* pageout isn't supposed to extend files */
-    if (f_offset + size > tvc->m.Length) 
-        iosize = tvc->m.Length - f_offset;
+    if (f_offset + size > tvc->f.m.Length) 
+        iosize = tvc->f.m.Length - f_offset;
     else
         iosize = size;
 
     if (size > (iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK && !nocommit)  {
             int iosize_rnd=(iosize + (PAGE_SIZE - 1)) & ~PAGE_MASK;
-           kernel_upl_abort_range(pl, pl_offset + iosize_rnd,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset + iosize_rnd,
                                    size - iosize_rnd,
                                   UPL_ABORT_FREE_ON_EMPTY);
     }
+    OSI_UPL_MAP(pl, &ioaddr);
+    ioaddr += pl_offset;
+#ifdef AFS_DARWIN80_ENV
+    uio = uio_create(1, f_offset, UIO_SYSSPACE32, UIO_READ);
+    uio_addiov(uio, CAST_USER_ADDR_T(ioaddr), size);
+#else
     auio.uio_iov = &aiov;
     auio.uio_iovcnt = 1;
     auio.uio_offset = f_offset;
     auio.uio_segflg = UIO_SYSSPACE;
     auio.uio_rw = UIO_WRITE;
     auio.uio_procp = NULL;
-    kernel_upl_map(kernel_map, pl, &ioaddr);
-    ioaddr += pl_offset;
     auio.uio_resid = aiov.iov_len = iosize;
     aiov.iov_base = (caddr_t) ioaddr;
-#if 1                          /* USV [ */
+#endif
     {
-       /* 
+       /* USV?
         * check for partial page and clear the
         * contents past end of the file before
         * releasing it in the VM page cache
         */
-       if ((f_offset < tvc->m.Length) && (f_offset + size) > tvc->m.Length) {
-           size_t io = tvc->m.Length - f_offset;
+       if ((f_offset < tvc->f.m.Length) && (f_offset + size) > tvc->f.m.Length) {
+           size_t io = tvc->f.m.Length - f_offset;
 
            memset((caddr_t) (ioaddr + pl_offset + io), 0, size - io);
        }
     }
-#endif /* ] USV */
 
     AFS_GLOCK();
-    afs_BozonLock(&tvc->pvnLock, tvc);
-    osi_FlushPages(tvc, ap->a_cred);   /* hold bozon lock, but not basic vnode lock */
+    osi_FlushPages(tvc, vop_cred);     /* hold bozon lock, but not basic vnode lock */
     ObtainWriteLock(&tvc->lock, 1);
     afs_FakeOpen(tvc);
     ReleaseWriteLock(&tvc->lock);
@@ -723,27 +1113,27 @@ afs_vop_pageout(ap)
     ObtainWriteLock(&tvc->lock, 1);
     afs_FakeClose(tvc, cred);
     ReleaseWriteLock(&tvc->lock);
-    afs_BozonUnlock(&tvc->pvnLock, tvc);
     AFS_GUNLOCK();
-    kernel_upl_unmap(kernel_map, pl);
+    OSI_UPL_UNMAP(pl);
     if (!nocommit) {
        if (code)
-           kernel_upl_abort_range(pl, pl_offset, size,
+           OSI_UPL_ABORT_RANGE(pl, pl_offset, size,
                                   UPL_ABORT_FREE_ON_EMPTY);
        else
-           kernel_upl_commit_range(pl, pl_offset, size,
+           OSI_UPL_COMMIT_RANGE(pl, pl_offset, size,
                                    UPL_COMMIT_CLEAR_DIRTY |
-                                   UPL_COMMIT_FREE_ON_EMPTY,
-                                   UPL_GET_INTERNAL_PAGE_LIST(pl),
-                                   MAX_UPL_TRANSFER);
+                                   UPL_COMMIT_FREE_ON_EMPTY);
     }
 
+#ifdef AFS_DARWIN80_ENV
+    uio_free(uio);
+#endif
     return code;
 }
 
 int
 afs_vop_ioctl(ap)
-     struct vop_ioctl_args     /* {
+     struct VOPPROT(ioctl_args)        /* {
                                 * struct vnode *a_vp;
                                 * int  a_command;
                                 * caddr_t  a_data;
@@ -762,8 +1152,7 @@ afs_vop_ioctl(ap)
     if (((ap->a_command >> 8) & 0xff) == 'V') {
        /* This is a VICEIOCTL call */
        AFS_GLOCK();
-       error = HandleIoctl(tvc, (struct file *)0 /*Not used */ ,
-                           ap->a_command, ap->a_data);
+       error = HandleIoctl(tvc, ap->a_command, ap->a_data);
        AFS_GUNLOCK();
        return (error);
     } else {
@@ -775,7 +1164,7 @@ afs_vop_ioctl(ap)
 /* ARGSUSED */
 int
 afs_vop_select(ap)
-     struct vop_select_args    /* {
+     struct VOPPROT(select_args)       /* {
                                 * struct vnode *a_vp;
                                 * int  a_which;
                                 * int  a_fflags;
@@ -797,7 +1186,7 @@ afs_vop_select(ap)
 /* ARGSUSED */
 int
 afs_vop_mmap(ap)
-     struct vop_mmap_args      /* {
+     struct VOPPROT(mmap_args) /* {
                                 * struct vnode *a_vp;
                                 * int  a_fflags;
                                 * struct ucred *a_cred;
@@ -809,7 +1198,7 @@ afs_vop_mmap(ap)
 
 int
 afs_vop_fsync(ap)
-     struct vop_fsync_args     /* {
+     struct VOPPROT(fsync_args)        /* {
                                 * struct vnode *a_vp;
                                 * struct ucred *a_cred;
                                 * int a_waitfor;
@@ -818,21 +1207,27 @@ afs_vop_fsync(ap)
 {
     int wait = ap->a_waitfor == MNT_WAIT;
     int error;
-    register struct vnode *vp = ap->a_vp;
+    struct vnode *vp = ap->a_vp;
+    int haveGlock = ISAFS_GLOCK();
 
-    AFS_GLOCK();
-    /*vflushbuf(vp, wait); */
-    if (ap->a_cred)
-       error = afs_fsync(VTOAFS(vp), ap->a_cred);
+    /* in order to recycle faked vnodes for bulkstat */
+    if (VTOAFS(vp) == NULL)
+       return ENOTSUP;
+
+    /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */
+    if (!haveGlock) AFS_GLOCK();
+    if (vop_cred)
+       error = afs_fsync(VTOAFS(vp), vop_cred);
     else
        error = afs_fsync(VTOAFS(vp), &afs_osi_cred);
-    AFS_GUNLOCK();
+    if (!haveGlock) AFS_GUNLOCK();
     return error;
 }
 
+#ifndef AFS_DARWIN80_ENV
 int
 afs_vop_seek(ap)
-     struct vop_seek_args      /* {
+     struct VOPPROT(seek_args) /* {
                                 * struct vnode *a_vp;
                                 * off_t  a_oldoff;
                                 * off_t  a_newoff;
@@ -843,88 +1238,120 @@ afs_vop_seek(ap)
        return EINVAL;
     return (0);
 }
+#endif
 
 int
 afs_vop_remove(ap)
-     struct vop_remove_args    /* {
+     struct VOPPROT(remove_args)       /* {
                                 * struct vnode *a_dvp;
                                 * struct vnode *a_vp;
                                 * struct componentname *a_cnp;
                                 * } */ *ap;
 {
     int error = 0;
-    register struct vnode *vp = ap->a_vp;
-    register struct vnode *dvp = ap->a_dvp;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
+
+#ifdef AFS_DARWIN80_ENV
+    if (ap->a_flags & VNODE_REMOVE_NODELETEBUSY) {
+            /* Caller requested Carbon delete semantics */
+            if (vnode_isinuse(vp, 0)) {
+                    return EBUSY;
+            }
+    }
+#endif
 
     GETNAME();
     AFS_GLOCK();
-    error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred);
+    error = afs_remove(VTOAFS(dvp), name, vop_cn_cred);
+    error = afs_CheckCode(error, NULL, 61);
     AFS_GUNLOCK();
     cache_purge(vp);
-    if (!error && UBCINFOEXISTS(vp)) {
-#ifdef AFS_DARWIN14_ENV
-       /* If crashes continue in ubc_hold, comment this out */
-       /* (void)ubc_uncache(vp);*/
+    if (!error) {
+#ifdef AFS_DARWIN80_ENV
+       struct vcache *tvc = VTOAFS(vp);
+       
+       if (!(tvc->f.states & CUnlinked)) {
+            ubc_setsize(vp, (off_t)0);
+            vnode_recycle(vp);
+       }
 #else
-       int wasmapped = ubc_issetflags(vp, UI_WASMAPPED);
-       int hasobjref = ubc_issetflags(vp, UI_HASOBJREF);
-       if (wasmapped)
-           (void)ubc_uncache(vp);
-       if (hasobjref)
-           ubc_release(vp);
-       /* WARNING vp may not be valid after this */
+        /* necessary so we don't deadlock ourselves in vclean */
+        VOP_UNLOCK(vp, 0, cnp->cn_proc);
+
+       /* If crashes continue in ubc_hold, comment this out */
+        (void)ubc_uncache(vp);
 #endif
+    } else {
+       /* should check for PRSFS_INSERT and not PRSFS_DELETE, but the
+          goal here is to deal with Finder's unhappiness with resource
+          forks that have no resources in a dropbox setting */
+       if (name[0] == '.' && name[1] == '_' && error == EACCES) 
+           error = 0;
     }
+
+#ifndef AFS_DARWIN80_ENV
+    vput(dvp);
     if (dvp == vp)
        vrele(vp);
     else
        vput(vp);
-    vput(dvp);
+#endif
 
+#ifndef AFS_DARWIN80_ENV
     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#endif
     DROPNAME();
     return error;
 }
 
 int
 afs_vop_link(ap)
-     struct vop_link_args      /* {
+     struct VOPPROT(link_args) /* {
                                 * struct vnode *a_vp;
                                 * struct vnode *a_tdvp;
                                 * struct componentname *a_cnp;
                                 * } */ *ap;
 {
     int error = 0;
-    register struct vnode *dvp = ap->a_tdvp;
-    register struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_tdvp;
+    struct vnode *vp = ap->a_vp;
     struct proc *p;
 
     GETNAME();
-    p = cnp->cn_proc;
-    if (vp->v_type == VDIR) {
+    p = vop_cn_proc;
+    if (vnode_isdir(vp)) {
        VOP_ABORTOP(vp, cnp);
        error = EISDIR;
        goto out;
     }
+#ifndef AFS_DARWIN80_ENV
     if (error = vn_lock(vp, LK_EXCLUSIVE, p)) {
        VOP_ABORTOP(dvp, cnp);
        goto out;
     }
+#endif
     AFS_GLOCK();
-    error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, cnp->cn_cred);
+    error = afs_link(VTOAFS(vp), VTOAFS(dvp), name, vop_cn_cred);
     AFS_GUNLOCK();
+#ifndef AFS_DARWIN80_ENV
     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#endif
+#ifndef AFS_DARWIN80_ENV
     if (dvp != vp)
        VOP_UNLOCK(vp, 0, p);
+#endif
   out:
+#ifndef AFS_DARWIN80_ENV
     vput(dvp);
+#endif
     DROPNAME();
     return error;
 }
 
 int
 afs_vop_rename(ap)
-     struct vop_rename_args    /* {
+     struct VOPPROT(rename_args)       /* {
                                 * struct vnode *a_fdvp;
                                 * struct vnode *a_fvp;
                                 * struct componentname *a_fcnp;
@@ -939,19 +1366,29 @@ afs_vop_rename(ap)
     struct componentname *tcnp = ap->a_tcnp;
     char *tname;
     struct vnode *tvp = ap->a_tvp;
-    register struct vnode *tdvp = ap->a_tdvp;
+    struct vnode *tdvp = ap->a_tdvp;
     struct vnode *fvp = ap->a_fvp;
-    register struct vnode *fdvp = ap->a_fdvp;
-    struct proc *p = fcnp->cn_proc;
+    struct vnode *fdvp = ap->a_fdvp;
+    struct proc *p; 
 
-       /* Check for cross-device rename.
-        * For AFS, this means anything not in AFS-space
-        */
-       if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
-               (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
-                       error = EXDEV;
-                       goto abortit;
-       }
+    p = cn_proc(fcnp);
+
+#ifdef AFS_DARWIN80_ENV
+    /*
+     * generic code tests for v_mount equality, so we don't have to, but we
+     * don't get the multiple-mount "benefits" of the old behavior
+     * the generic code doesn't do this, so we really should, but all the
+     * vrele's are wrong...
+     */
+#else
+    /* Check for cross-device rename.
+     * For AFS, this means anything not in AFS-space
+     */
+    if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) ||
+       (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) {
+       error = EXDEV;
+       goto abortit;
+    }
 
     /*
      * if fvp == tvp, we're just removing one name of a pair of
@@ -959,7 +1396,7 @@ afs_vop_rename(ap)
      ( (pinched from NetBSD 1.0's ufs_rename())
      */
     if (fvp == tvp) {
-       if (fvp->v_type == VDIR) {
+       if (vnode_isdir(fvp)) {
            error = EINVAL;
          abortit:
            VOP_ABORTOP(tdvp, tcnp);    /* XXX, why not in NFS? */
@@ -979,7 +1416,6 @@ afs_vop_rename(ap)
        VOP_ABORTOP(tdvp, tcnp);
        vput(tdvp);
        vput(tvp);
-
        /* Delete source. */
        vrele(fdvp);
        vrele(fvp);
@@ -996,8 +1432,8 @@ afs_vop_rename(ap)
         if (fvp == NULL) {
            return (ENOENT);
         }
-        
         error=VOP_REMOVE(fdvp, fvp, fcnp);
+        
         if (fdvp == fvp)
             vrele(fdvp);
         else
@@ -1007,6 +1443,7 @@ afs_vop_rename(ap)
     }
     if (error = vn_lock(fvp, LK_EXCLUSIVE, p))
        goto abortit;
+#endif
 
     MALLOC(fname, char *, fcnp->cn_namelen + 1, M_TEMP, M_WAITOK);
     memcpy(fname, fcnp->cn_nameptr, fcnp->cn_namelen);
@@ -1019,12 +1456,11 @@ afs_vop_rename(ap)
     AFS_GLOCK();
     /* XXX use "from" or "to" creds? NFS uses "to" creds */
     error =
-       afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, tcnp->cn_cred);
-    AFS_GUNLOCK();
+       afs_rename(VTOAFS(fdvp), fname, VTOAFS(tdvp), tname, cn_cred(tcnp));
 
+#if !defined(AFS_DARWIN80_ENV) 
+    AFS_GUNLOCK();
     VOP_UNLOCK(fvp, 0, p);
-    FREE(fname, M_TEMP);
-    FREE(tname, M_TEMP);
     if (error)
        goto abortit;           /* XXX */
     if (tdvp == tvp)
@@ -1035,84 +1471,182 @@ afs_vop_rename(ap)
        vput(tvp);
     vrele(fdvp);
     vrele(fvp);
+#else
+    if (error == EXDEV) {
+        struct brequest *tb;
+        struct afs_uspc_param mvReq;
+        struct vcache *tvc;
+        struct vcache *fvc = VTOAFS(fdvp);
+        int code = 0;
+        struct afs_fakestat_state fakestate;
+        int fakestatdone = 0;
+
+       tvc = VTOAFS(tdvp);
+
+        /* unrewritten mount point? */
+        if (tvc->mvstat == 1) {
+            if (tvc->mvid && (tvc->f.states & CMValid)) {
+                struct vrequest treq;
+
+                afs_InitFakeStat(&fakestate);
+                code = afs_InitReq(&treq, vop_cred);
+                if (!code) {
+                    fakestatdone = 1;
+                    code = afs_EvalFakeStat(&tvc, &fakestate, &treq);
+                } else
+                    afs_PutFakeStat(&fakestate);
+            }
+        }
+
+        if (!code) {
+           /* at some point in the future we should allow other types */
+           mvReq.reqtype = AFS_USPC_UMV;
+            mvReq.req.umv.id = afs_cr_uid(cn_cred(tcnp));
+            mvReq.req.umv.idtype = IDTYPE_UID;
+            mvReq.req.umv.sCell = fvc->f.fid.Cell;
+            mvReq.req.umv.sVolume = fvc->f.fid.Fid.Volume;
+            mvReq.req.umv.sVnode = fvc->f.fid.Fid.Vnode;
+            mvReq.req.umv.sUnique = fvc->f.fid.Fid.Unique;
+            mvReq.req.umv.dCell = tvc->f.fid.Cell;
+            mvReq.req.umv.dVolume = tvc->f.fid.Fid.Volume;
+            mvReq.req.umv.dVnode = tvc->f.fid.Fid.Vnode;
+            mvReq.req.umv.dUnique = tvc->f.fid.Fid.Unique;
+
+           /*
+            * su %d -c mv /afs/.:mount/%d:%d:%d:%d/%s
+            * /afs/.:mount/%d:%d:%d:%d/%s where:
+            * mvReq.req.umv.id, fvc->f.fid.Cell, fvc->f.fid.Fid.Volume,
+            * fvc->f.fid.Fid.Vnode, fvc->f.fid.Fid.Unique, fname,
+            * tvc->f.fid.Cell, tvc->f.fid.Fid.Volume, tvc->f.fid.Fid.Vnode,
+            * tvc->f.fid.Fid.Unique, tname
+            */
+
+            tb = afs_BQueue(BOP_MOVE, NULL, 0, 1, cn_cred(tcnp),
+                            0L, 0L, &mvReq, fname, tname);
+           /* wait to collect result */
+            while ((tb->flags & BUVALID) == 0) {
+                tb->flags |= BUWAIT;
+                afs_osi_Sleep(tb);
+            }
+            /* if we succeeded, clear the error. otherwise, EXDEV */
+            if (mvReq.retval == 0)
+                error = 0;
+
+            afs_BRelease(tb);
+        }
+
+        if (fakestatdone)
+            afs_PutFakeStat(&fakestate);
+    }
+    AFS_GUNLOCK();
+
+    cache_purge(fdvp);
+    cache_purge(fvp);
+    cache_purge(tdvp);
+    if (tvp) {
+       cache_purge(tvp);
+       if (!error) {
+           vnode_recycle(tvp);
+       }
+    }
+    if (!error)
+       cache_enter(tdvp, fvp, tcnp);
+#endif
+    FREE(fname, M_TEMP);
+    FREE(tname, M_TEMP);
     return error;
 }
 
 int
 afs_vop_mkdir(ap)
-     struct vop_mkdir_args     /* {
+     struct VOPPROT(mkdir_args)        /* {
                                 * struct vnode *a_dvp;
                                 * struct vnode **a_vpp;
                                 * struct componentname *a_cnp;
                                 * struct vattr *a_vap;
                                 * } */ *ap;
 {
-    register struct vnode *dvp = ap->a_dvp;
-    register struct vattr *vap = ap->a_vap;
+    struct vnode *dvp = ap->a_dvp;
+    struct vattr *vap = ap->a_vap;
     int error = 0;
     struct vcache *vcp;
     struct proc *p;
 
     GETNAME();
-    p = cnp->cn_proc;
-#ifdef DIAGNOSTIC
+    p = vop_cn_proc;
+#if defined(DIAGNOSTIC) && !defined(AFS_DARWIN80_ENV)
     if ((cnp->cn_flags & HASBUF) == 0)
        panic("afs_vop_mkdir: no name");
 #endif
     AFS_GLOCK();
-    error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, cnp->cn_cred);
+    error = afs_mkdir(VTOAFS(dvp), name, vap, &vcp, vop_cn_cred);
     AFS_GUNLOCK();
     if (error) {
+#ifndef AFS_DARWIN80_ENV
        VOP_ABORTOP(dvp, cnp);
        vput(dvp);
+#endif
        DROPNAME();
        return (error);
     }
     if (vcp) {
+#ifdef AFS_DARWIN80_ENV
+       afs_darwin_finalizevnode(vcp, ap->a_dvp, ap->a_cnp, 0, 0);
+#endif
        *ap->a_vpp = AFSTOV(vcp);
+#ifndef AFS_DARWIN80_ENV /* XXX needed for multi-mount thing, but can't have it yet */
        (*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
        vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p);
+#endif
     } else
        *ap->a_vpp = 0;
     DROPNAME();
+#ifndef AFS_DARWIN80_ENV
     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
     vput(dvp);
+#endif
     return error;
 }
 
 int
 afs_vop_rmdir(ap)
-     struct vop_rmdir_args     /* {
+     struct VOPPROT(rmdir_args)        /* {
                                 * struct vnode *a_dvp;
                                 * struct vnode *a_vp;
                                 * struct componentname *a_cnp;
                                 * } */ *ap;
 {
     int error = 0;
-    register struct vnode *vp = ap->a_vp;
-    register struct vnode *dvp = ap->a_dvp;
+    struct vnode *vp = ap->a_vp;
+    struct vnode *dvp = ap->a_dvp;
 
     GETNAME();
     if (dvp == vp) {
+#ifndef AFS_DARWIN80_ENV
        vrele(dvp);
        vput(vp);
        FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
+#endif
        DROPNAME();
        return (EINVAL);
     }
 
     AFS_GLOCK();
-    error = afs_rmdir(VTOAFS(dvp), name, cnp->cn_cred);
+    error = afs_rmdir(VTOAFS(dvp), name, vop_cn_cred);
     AFS_GUNLOCK();
     DROPNAME();
+    cache_purge(dvp);
+    cache_purge(vp);
+#ifndef AFS_DARWIN80_ENV
     vput(dvp);
     vput(vp);
+#endif
     return error;
 }
 
 int
 afs_vop_symlink(ap)
-     struct vop_symlink_args   /* {
+     struct VOPPROT(symlink_args)      /* {
                                 * struct vnode *a_dvp;
                                 * struct vnode **a_vpp;
                                 * struct componentname *a_cnp;
@@ -1120,24 +1654,26 @@ afs_vop_symlink(ap)
                                 * char *a_target;
                                 * } */ *ap;
 {
-    register struct vnode *dvp = ap->a_dvp;
+    struct vnode *dvp = ap->a_dvp;
     int error = 0;
     /* NFS ignores a_vpp; so do we. */
 
     GETNAME();
     AFS_GLOCK();
     error =
-       afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, cnp->cn_cred);
+       afs_symlink(VTOAFS(dvp), name, ap->a_vap, ap->a_target, vop_cn_cred);
     AFS_GUNLOCK();
     DROPNAME();
+#ifndef AFS_DARWIN80_ENV
     FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
     vput(dvp);
+#endif
     return error;
 }
 
 int
 afs_vop_readdir(ap)
-     struct vop_readdir_args   /* {
+     struct VOPPROT(readdir_args)      /* {
                                 * struct vnode *a_vp;
                                 * struct uio *a_uio;
                                 * struct ucred *a_cred;
@@ -1150,11 +1686,18 @@ afs_vop_readdir(ap)
     off_t off;
 /*    printf("readdir %x cookies %x ncookies %d\n", ap->a_vp, ap->a_cookies,
           ap->a_ncookies); */
-    off = ap->a_uio->uio_offset;
+#ifdef AFS_DARWIN80_ENV
+    /* too much work for now */
+    /* should only break nfs exports */
+    if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
+         return (EINVAL);
+#endif
+    off = AFS_UIO_OFFSET(ap->a_uio);
     AFS_GLOCK();
     error =
-       afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred, ap->a_eofflag);
+       afs_readdir(VTOAFS(ap->a_vp), ap->a_uio, vop_cred, ap->a_eofflag);
     AFS_GUNLOCK();
+#ifndef AFS_DARWIN80_ENV
     if (!error && ap->a_ncookies != NULL) {
        struct uio *uio = ap->a_uio;
        const struct dirent *dp, *dp_start, *dp_end;
@@ -1181,13 +1724,14 @@ afs_vop_readdir(ap)
        *ap->a_cookies = cookies;
        *ap->a_ncookies = ncookies;
     }
+#endif
 
     return error;
 }
 
 int
 afs_vop_readlink(ap)
-     struct vop_readlink_args  /* {
+     struct VOPPROT(readlink_args)     /* {
                                 * struct vnode *a_vp;
                                 * struct uio *a_uio;
                                 * struct ucred *a_cred;
@@ -1196,7 +1740,7 @@ afs_vop_readlink(ap)
     int error;
 /*    printf("readlink %x\n", ap->a_vp);*/
     AFS_GLOCK();
-    error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, ap->a_cred);
+    error = afs_readlink(VTOAFS(ap->a_vp), ap->a_uio, vop_cred);
     AFS_GUNLOCK();
     return error;
 }
@@ -1205,174 +1749,96 @@ extern int prtactive;
 
 int
 afs_vop_inactive(ap)
-     struct vop_inactive_args  /* {
+     struct VOPPROT(inactive_args)     /* {
                                 * struct vnode *a_vp;
                                 * struct proc *a_p;
                                 * } */ *ap;
 {
-    register struct vnode *vp = ap->a_vp;
-
+    struct vnode *vp = ap->a_vp;
+    struct vcache *tvc = VTOAFS(vp);
+#ifndef AFS_DARWIN80_ENV
     if (prtactive && vp->v_usecount != 0)
        vprint("afs_vop_inactive(): pushing active", vp);
-
-    AFS_GLOCK();
-    afs_InactiveVCache(VTOAFS(vp), 0); /* decrs ref counts */
-    AFS_GUNLOCK();
+#endif
+    if (tvc) {
+#ifdef AFS_DARWIN80_ENV
+        int unlinked = tvc->f.states & CUnlinked;
+#endif
+       AFS_GLOCK();
+       afs_InactiveVCache(tvc, 0);     /* decrs ref counts */
+       AFS_GUNLOCK();
+#ifdef AFS_DARWIN80_ENV
+       if (unlinked) {
+           vnode_recycle(vp);
+           cache_purge(vp);
+       }
+#endif
+    }
+#ifndef AFS_DARWIN80_ENV
     VOP_UNLOCK(vp, 0, ap->a_p);
+#endif
     return 0;
 }
 
 int
 afs_vop_reclaim(ap)
-     struct vop_reclaim_args   /* {
+     struct VOPPROT(reclaim_args)      /* {
                                 * struct vnode *a_vp;
                                 * } */ *ap;
 {
-    int error;
-    int sl;
-    register struct vnode *vp = ap->a_vp;
+    int error = 0;
+    int sl, writelocked;
+    struct vnode *vp = ap->a_vp;
+    struct vcache *tvc = VTOAFS(vp);
 
+    osi_Assert(!ISAFS_GLOCK());
     cache_purge(vp);           /* just in case... */
-
-#if 0
-    AFS_GLOCK();
-    error = afs_FlushVCache(VTOAFS(vp), &sl);  /* tosses our stuff from vnode */
-    AFS_GUNLOCK();
-    ubc_unlink(vp);
-    if (!error && vp->v_data)
-       panic("afs_reclaim: vnode not cleaned");
-    return error;
+    if (tvc) {
+       AFS_GLOCK();
+       writelocked = (0 == NBObtainWriteLock(&afs_xvcache, 335));
+       if (!writelocked) {
+          ObtainWriteLock(&afs_xvreclaim, 176);
+#ifdef AFS_DARWIN80_ENV
+          vnode_clearfsnode(AFSTOV(tvc));
+          vnode_removefsref(AFSTOV(tvc));
 #else
-    if (vp->v_usecount == 2) {
-       vprint("reclaim count==2", vp);
-    } else if (vp->v_usecount == 1) {
-       vprint("reclaim count==1", vp);
-    } else
-       vprint("reclaim bad count", vp);
-
-    return 0;
+          tvc->v->v_data = NULL;  /* remove from vnode */
 #endif
-}
-
-int
-afs_vop_lock(ap)
-     struct vop_lock_args      /* {
-                                * struct vnode *a_vp;
-                                * } */ *ap;
-{
-    register struct vnode *vp = ap->a_vp;
-    register struct vcache *avc = VTOAFS(vp);
-
-    if (vp->v_tag == VT_NON)
-       return (ENOENT);
-    return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
-}
-
-int
-afs_vop_unlock(ap)
-     struct vop_unlock_args    /* {
-                                * struct vnode *a_vp;
-                                * } */ *ap;
-{
-    struct vnode *vp = ap->a_vp;
-    struct vcache *avc = VTOAFS(vp);
-    return (lockmgr
-           (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
-            ap->a_p));
-
-}
-
-int
-afs_vop_bmap(ap)
-     struct vop_bmap_args      /* {
-                                * struct vnode *a_vp;
-                                * daddr_t  a_bn;
-                                * struct vnode **a_vpp;
-                                * daddr_t *a_bnp;
-                                * int *a_runp;
-                                * int *a_runb;
-                                * } */ *ap;
-{
-    struct vcache *vcp;
-    int error;
-    if (ap->a_bnp) {
-       *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
-    }
-    if (ap->a_vpp) {
-       *ap->a_vpp = ap->a_vp;
-    }
-    if (ap->a_runp != NULL)
-       *ap->a_runp = 0;
-#ifdef notyet
-    if (ap->a_runb != NULL)
-       *ap->a_runb = 0;
+          AFSTOV(tvc) = NULL;             /* also drop the ptr to vnode */
+          tvc->f.states |= CVInit; /* also CDeadVnode? */
+          tvc->nextfree = ReclaimedVCList;
+          ReclaimedVCList = tvc;
+          ReleaseWriteLock(&afs_xvreclaim);
+       } else {
+          error = afs_FlushVCache(tvc, &sl);   /* toss our stuff from vnode */
+          if (tvc->f.states & (CVInit
+#ifdef AFS_DARWIN80_ENV
+                             | CDeadVnode
 #endif
-
-    return 0;
-}
-
-int
-afs_vop_strategy(ap)
-     struct vop_strategy_args  /* {
-                                * struct buf *a_bp;
-                                * } */ *ap;
-{
-    int error;
-    AFS_GLOCK();
-    error = afs_ustrategy(ap->a_bp);
-    AFS_GUNLOCK();
-    return error;
-}
-
-int
-afs_vop_print(ap)
-     struct vop_print_args     /* {
-                                * struct vnode *a_vp;
-                                * } */ *ap;
-{
-    register struct vnode *vp = ap->a_vp;
-    register struct vcache *vc = VTOAFS(ap->a_vp);
-    int s = vc->states;
-    printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
-          vc->fid.Cell, vc->fid.Fid.Volume, vc->fid.Fid.Vnode,
-          vc->fid.Fid.Unique, vc->opens, vc->execsOrWriters);
-    printf("\n  states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
-          (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
-          (s & CMAPPED) ? " mapped" : "",
-          (s & CVFlushed) ? " flush in progress" : "");
-    if (UBCISVALID(vp)) {
-       printf("\n  UBC: ");
-       if (UBCINFOEXISTS(vp)) {
-           printf("exists, ");
-#ifdef AFS_DARWIN14_ENV
-           printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
-                  ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
-                  ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
-#else
-           printf("holdcnt %d", vp->v_ubcinfo->ui_holdcnt);
+                  )) {
+              tvc->f.states &= ~(CVInit
+#ifdef AFS_DARWIN80_ENV
+                               | CDeadVnode
 #endif
-       } else
-           printf("does not exist");
+                  );
+              afs_osi_Wakeup(&tvc->f.states);
+          }
+          if (!error && vnode_fsnode(vp))
+              panic("afs_reclaim: vnode not cleaned");
+          if (!error && (tvc->v != NULL)) 
+              panic("afs_reclaim: vcache not cleaned");
+          ReleaseWriteLock(&afs_xvcache);
+       }
+       AFS_GUNLOCK();
     }
-    printf("\n");
-    return 0;
-}
-
-int
-afs_vop_islocked(ap)
-     struct vop_islocked_args  /* {
-                                * struct vnode *a_vp;
-                                * } */ *ap;
-{
-    struct vcache *vc = VTOAFS(ap->a_vp);
-    return lockstatus(&vc->rwlock);
+    return error;
 }
 
 /*
  * Return POSIX pathconf information applicable to ufs filesystems.
  */
 afs_vop_pathconf(ap)
-     struct vop_pathconf_args  /* {
+     struct VOPPROT(pathconf_args)     /* {
                                 * struct vnode *a_vp;
                                 * int a_name;
                                 * int *a_retval;
@@ -1398,7 +1864,6 @@ afs_vop_pathconf(ap)
     case _PC_PIPE_BUF:
        return EINVAL;
        break;
-#if defined(AFS_DARWIN70_ENV)
     case _PC_NAME_CHARS_MAX:
         *ap->a_retval = NAME_MAX;
        break;
@@ -1408,7 +1873,6 @@ afs_vop_pathconf(ap)
     case _PC_CASE_PRESERVING:
         *ap->a_retval = 1;
        break;
-#endif /* defined(AFS_DARWIN70_ENV) */
     default:
        return EINVAL;
     }
@@ -1420,7 +1884,7 @@ afs_vop_pathconf(ap)
  */
 int
 afs_vop_advlock(ap)
-     struct vop_advlock_args   /* {
+     struct VOPPROT(advlock_args)      /* {
                                 * struct vnode *a_vp;
                                 * caddr_t  a_id;
                                 * int  a_op;
@@ -1429,21 +1893,103 @@ afs_vop_advlock(ap)
                                 * } */ *ap;
 {
     int error;
+    struct ucred *tcr;
+    int clid;
+    int op;
+#ifdef AFS_DARWIN80_ENV
+    proc_t p;
+    tcr=vop_cred;
+#else
     struct proc *p = current_proc();
     struct ucred cr;
     pcred_readlock(p);
     cr = *p->p_cred->pc_ucred;
     pcred_unlock(p);
+    tcr=&cr;
+#endif
+    if (ap->a_flags & F_POSIX) {
+#ifdef AFS_DARWIN80_ENV
+       p = (proc_t) ap->a_id;
+       clid = proc_pid(p);
+#else
+       p = (struct proc *) ap->a_id;
+       clid = p->p_pid;
+#endif
+    } else {
+       clid = (int)ap->a_id;
+    }
+    if (ap->a_op == F_UNLCK) {
+       op = F_SETLK;
+    } else if (ap->a_op == F_SETLK && ap->a_flags & F_WAIT) {
+       op = F_SETLKW;
+    } else {
+       op = ap->a_op;
+    }
     AFS_GLOCK();
-    error =
-       afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, ap->a_op, &cr, (int)ap->a_id);
+    error = afs_lockctl(VTOAFS(ap->a_vp), ap->a_fl, op, tcr, clid);
     AFS_GUNLOCK();
     return error;
 }
 
 int
+afs_vop_blktooff(ap)
+     struct VOPPROT(blktooff_args)     /* {
+                                * struct vnode *a_vp;
+                                * daddr_t a_lblkno;
+                                * off_t *a_offset;    
+                                * } */ *ap;
+{
+    *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
+    return 0;
+}
+
+int
+afs_vop_offtoblk(ap)
+     struct VOPPROT(offtoblk_args)     /* {
+                                * struct vnode *a_vp;
+                                * off_t a_offset;    
+                                * daddr_t *a_lblkno;
+                                * } */ *ap;
+{
+    *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
+
+    return (0);
+}
+
+#ifndef AFS_DARWIN80_ENV
+int
+afs_vop_lock(ap)
+     struct VOPPROT(lock_args) /* {
+                                * struct vnode *a_vp;
+                                * } */ *ap;
+{
+    struct vnode *vp = ap->a_vp;
+    struct vcache *avc = VTOAFS(vp);
+
+    if (vp->v_tag == VT_NON)
+       return (ENOENT);
+
+    return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p));
+}
+
+int
+afs_vop_unlock(ap)
+     struct VOPPROT(unlock_args)       /* {
+                                * struct vnode *a_vp;
+                                * } */ *ap;
+{
+    struct vnode *vp = ap->a_vp;
+    struct vcache *avc = VTOAFS(vp);
+
+    return (lockmgr
+           (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock,
+            ap->a_p));
+
+}
+
+int
 afs_vop_truncate(ap)
-     struct vop_truncate_args  /* {
+     struct VOPPROT(truncate_args)     /* {
                                 * struct vnode *a_vp;
                                 * off_t a_length;
                                 * int a_flags;
@@ -1451,51 +1997,107 @@ afs_vop_truncate(ap)
                                 * struct proc *a_p;
                                 * } */ *ap;
 {
-    printf("stray afs_vop_truncate\n");
-    return EOPNOTSUPP;
+    /* printf("stray afs_vop_truncate\n"); */
+    return ENOTSUP;
 }
 
 int
 afs_vop_update(ap)
-     struct vop_update_args    /* {
+     struct VOPPROT(update_args)       /* {
                                 * struct vnode *a_vp;
                                 * struct timeval *a_access;
                                 * struct timeval *a_modify;
                                 * int a_waitfor;
                                 * } */ *ap;
 {
-    printf("stray afs_vop_update\n");
-    return EOPNOTSUPP;
+    /* printf("stray afs_vop_update\n"); */
+    return ENOTSUP;
 }
 
 int
-afs_vop_blktooff(ap)
-     struct vop_blktooff_args  /* {
+afs_vop_bmap(ap)
+     struct VOPPROT(bmap_args) /* {
                                 * struct vnode *a_vp;
-                                * daddr_t a_lblkno;
-                                * off_t *a_offset;    
+                                * daddr_t  a_bn;
+                                * struct vnode **a_vpp;
+                                * daddr_t *a_bnp;
+                                * int *a_runp;
+                                * int *a_runb;
                                 * } */ *ap;
 {
-    *ap->a_offset = (off_t) (ap->a_lblkno * DEV_BSIZE);
+    int error;
+    if (ap->a_bnp) {
+       *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE);
+    }
+    if (ap->a_vpp) {
+       *ap->a_vpp = ap->a_vp;
+    }
+    if (ap->a_runp != NULL)
+       *ap->a_runp = 0;
+#ifdef notyet
+    if (ap->a_runb != NULL)
+       *ap->a_runb = 0;
+#endif
+
     return 0;
 }
 
 int
-afs_vop_offtoblk(ap)
-     struct vop_offtoblk_args  /* {
+afs_vop_strategy(ap)
+     struct VOPPROT(strategy_args)     /* {
+                                * struct buf *a_bp;
+                                * } */ *ap;
+{
+    int error;
+    AFS_GLOCK();
+    error = afs_ustrategy(ap->a_bp);
+    AFS_GUNLOCK();
+    return error;
+}
+
+int
+afs_vop_print(ap)
+     struct VOPPROT(print_args)        /* {
                                 * struct vnode *a_vp;
-                                * off_t a_offset;    
-                                * daddr_t *a_lblkno;
                                 * } */ *ap;
 {
-    *ap->a_lblkno = (daddr_t) (ap->a_offset / DEV_BSIZE);
+    struct vnode *vp = ap->a_vp;
+    struct vcache *vc = VTOAFS(ap->a_vp);
+    int s = vc->f.states;
+    printf("tag %d, fid: %ld.%x.%x.%x, opens %d, writers %d", vp->v_tag,
+          vc->f.fid.Cell, vc->f.fid.Fid.Volume, vc->f.fid.Fid.Vnode,
+          vc->f.fid.Fid.Unique, vc->opens, vc->execsOrWriters);
+    printf("\n  states%s%s%s%s%s", (s & CStatd) ? " statd" : "",
+          (s & CRO) ? " readonly" : "", (s & CDirty) ? " dirty" : "",
+          (s & CMAPPED) ? " mapped" : "",
+          (s & CVFlushed) ? " flush in progress" : "");
+    if (UBCISVALID(vp)) {
+       printf("\n  UBC: ");
+       if (UBCINFOEXISTS(vp)) {
+           printf("exists, ");
+           printf("refs %d%s%s", vp->v_ubcinfo->ui_refcount,
+                  ubc_issetflags(vp, UI_HASOBJREF) ? " HASOBJREF" : "",
+                  ubc_issetflags(vp, UI_WASMAPPED) ? " WASMAPPED" : "");
+       } else
+           printf("does not exist");
+    }
+    printf("\n");
+    return 0;
+}
 
-    return (0);
+int
+afs_vop_islocked(ap)
+     struct VOPPROT(islocked_args)     /* {
+                                * struct vnode *a_vp;
+                                * } */ *ap;
+{
+    struct vcache *vc = VTOAFS(ap->a_vp);
+    return lockstatus(&vc->rwlock);
 }
 
 int
 afs_vop_cmap(ap)
-     struct vop_cmap_args      /* {
+     struct VOPPROT(cmap_args) /* {
                                 * struct vnode *a_vp;
                                 * off_t a_foffset;    
                                 * size_t a_size;
@@ -1508,3 +2110,143 @@ afs_vop_cmap(ap)
     *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset));
     return 0;
 }
+#endif
+
+int
+afs_darwin_getnewvnode(struct vcache *avc)
+{
+#ifdef AFS_DARWIN80_ENV
+    vnode_t vp;
+    int error, dead;
+    struct vnode_fsparam par;
+
+    memset(&par, 0, sizeof(struct vnode_fsparam));
+    par.vnfs_vtype = VNON;
+    par.vnfs_vops = afs_dead_vnodeop_p;
+    par.vnfs_flags = VNFS_NOCACHE|VNFS_CANTCACHE;
+    par.vnfs_mp = afs_globalVFS;
+    par.vnfs_fsnode = avc;
+
+    error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &vp);
+    if (!error) {
+      vnode_addfsref(vp);
+      vnode_ref(vp);
+      avc->v = vp;
+      vnode_recycle(vp); /* terminate as soon as iocount drops */
+      avc->f.states |= CDeadVnode;
+    }
+    return error;
+#else
+    while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &avc->v)) {
+        /* no vnodes available, force an alloc (limits be damned)! */
+       printf("failed to get vnode\n");
+    }
+    avc->v->v_data = (void *)avc;
+    return 0;
+#endif
+}
+#ifdef AFS_DARWIN80_ENV
+/* if this fails, then tvc has been unrefed and may have been freed. 
+   Don't touch! */
+int
+afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp,
+                        struct componentname *cnp, int isroot, int locked)
+{
+    vnode_t ovp;
+    vnode_t nvp;
+    int error;
+    struct vnode_fsparam par;
+
+    if (!locked) {
+       AFS_GLOCK();
+       ObtainWriteLock(&avc->lock,325);
+    }
+    ovp = AFSTOV(avc);
+
+    if (!(avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON) {
+       AFS_GUNLOCK();
+#if 0 /* unsupported */
+        if (dvp && cnp)
+           vnode_update_identity(ovp, dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                                 cnp->cn_hash,
+                                 VNODE_UPDATE_PARENT|VNODE_UPDATE_NAME);
+#endif
+       /* Can end up in reclaim... drop GLOCK */
+       vnode_rele(ovp);
+       AFS_GLOCK();
+       if (!locked) {
+           ReleaseWriteLock(&avc->lock);
+           AFS_GUNLOCK();
+       }
+       return 0;
+    }
+
+    if ((avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON)
+       panic("vcache %p should not be CDeadVnode", avc);
+    AFS_GUNLOCK();
+    memset(&par, 0, sizeof(struct vnode_fsparam));
+    par.vnfs_mp = afs_globalVFS;
+    par.vnfs_vtype = avc->f.m.Type;
+    par.vnfs_vops = afs_vnodeop_p;
+    par.vnfs_filesize = avc->f.m.Length;
+    par.vnfs_fsnode = avc;
+    par.vnfs_dvp = dvp;
+    if (cnp && (cnp->cn_flags & ISDOTDOT) == 0)
+       par.vnfs_cnp = cnp;
+    if (!dvp || !cnp || (cnp->cn_flags & MAKEENTRY) == 0)
+       par.vnfs_flags = VNFS_NOCACHE;
+    if (isroot)
+       par.vnfs_markroot = 1;
+    error = vnode_create(VNCREATE_FLAVOR, VCREATESIZE, &par, &nvp);
+    if (!error) {
+       vnode_addfsref(nvp);
+       if ((avc->f.states & CDeadVnode) && vnode_vtype(ovp) != VNON)
+           printf("vcache %p should not be CDeadVnode", avc);
+       if (avc->v == ovp) {
+           if (!(avc->f.states & CVInit)) {
+               vnode_clearfsnode(ovp);
+               vnode_removefsref(ovp);
+           }
+           /* we're discarding on a fixup. mark for recycle */
+           if (!(avc->f.states & CDeadVnode))
+               vnode_recycle(ovp);
+       }
+       avc->v = nvp;
+       avc->f.states &=~ CDeadVnode;
+       /* If we were carrying an extra ref for dirty, hold/push it. */
+       if (avc->f.ddirty_flags) {
+           vnode_get(nvp);
+           vnode_ref(nvp);
+       }
+       /* If we were carrying an extra ref for shadow, hold/push it. */
+       if (avc->f.shadow.vnode) {
+           vnode_get(nvp);
+           vnode_ref(nvp);
+       }
+    }
+    /* Drop any extra dirty ref on the old vnode */
+    if (avc->f.ddirty_flags) {
+       vnode_put(ovp);
+       vnode_rele(ovp);
+    }
+    /* Drop any extra shadow ref on the old vnode */
+    if (avc->f.shadow.vnode) {
+       vnode_put(ovp);
+       vnode_rele(ovp);
+    }
+    /* If it's ref'd still, unmark stat'd to force new lookup */
+    if ((vnode_vtype(ovp) != avc->f.m.Type) && VREFCOUNT_GT(avc, 1))
+       avc->f.states &= ~CStatd;
+
+    vnode_put(ovp);
+    vnode_rele(ovp);
+    AFS_GLOCK();
+    if (!locked)
+       ReleaseWriteLock(&avc->lock);
+    if (!error)
+       afs_osi_Wakeup(&avc->f.states);
+    if (!locked)
+       AFS_GUNLOCK();
+    return error;
+}
+#endif