VFS messaging/interfacing work stage 5/99. Start work on the new
[dragonfly.git] / sys / vfs / nfs / nfs_vnops.c
index a15cba7..28ac6a1 100644 (file)
@@ -35,7 +35,7 @@
  *
  *     @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95
  * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $
- * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.18 2004/02/08 05:27:42 hmp Exp $
+ * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.30 2004/09/26 01:24:56 dillon Exp $
  */
 
 
@@ -138,95 +138,83 @@ static int        nfs_bwrite (struct vop_bwrite_args *);
 /*
  * Global vfs data structures for nfs
  */
-vop_t **nfsv2_vnodeop_p;
-static struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
-       { &vop_default_desc,            (vop_t *) vop_defaultop },
-       { &vop_access_desc,             (vop_t *) nfs_access },
-       { &vop_advlock_desc,            (vop_t *) nfs_advlock },
-       { &vop_bmap_desc,               (vop_t *) nfs_bmap },
-       { &vop_bwrite_desc,             (vop_t *) nfs_bwrite },
-       { &vop_close_desc,              (vop_t *) nfs_close },
-       { &vop_create_desc,             (vop_t *) nfs_create },
-       { &vop_fsync_desc,              (vop_t *) nfs_fsync },
-       { &vop_getattr_desc,            (vop_t *) nfs_getattr },
-       { &vop_getpages_desc,           (vop_t *) nfs_getpages },
-       { &vop_putpages_desc,           (vop_t *) nfs_putpages },
-       { &vop_inactive_desc,           (vop_t *) nfs_inactive },
-       { &vop_islocked_desc,           (vop_t *) vop_stdislocked },
-       { &vop_lease_desc,              (vop_t *) vop_null },
-       { &vop_link_desc,               (vop_t *) nfs_link },
-       { &vop_lock_desc,               (vop_t *) vop_sharedlock },
-       { &vop_lookup_desc,             (vop_t *) nfs_lookup },
-       { &vop_mkdir_desc,              (vop_t *) nfs_mkdir },
-       { &vop_mknod_desc,              (vop_t *) nfs_mknod },
-       { &vop_mmap_desc,               (vop_t *) nfs_mmap },
-       { &vop_open_desc,               (vop_t *) nfs_open },
-       { &vop_poll_desc,               (vop_t *) nfs_poll },
-       { &vop_print_desc,              (vop_t *) nfs_print },
-       { &vop_read_desc,               (vop_t *) nfs_read },
-       { &vop_readdir_desc,            (vop_t *) nfs_readdir },
-       { &vop_readlink_desc,           (vop_t *) nfs_readlink },
-       { &vop_reclaim_desc,            (vop_t *) nfs_reclaim },
-       { &vop_remove_desc,             (vop_t *) nfs_remove },
-       { &vop_rename_desc,             (vop_t *) nfs_rename },
-       { &vop_rmdir_desc,              (vop_t *) nfs_rmdir },
-       { &vop_setattr_desc,            (vop_t *) nfs_setattr },
-       { &vop_strategy_desc,           (vop_t *) nfs_strategy },
-       { &vop_symlink_desc,            (vop_t *) nfs_symlink },
-       { &vop_unlock_desc,             (vop_t *) vop_stdunlock },
-       { &vop_write_desc,              (vop_t *) nfs_write },
+struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
+       { &vop_default_desc,            vop_defaultop },
+       { &vop_access_desc,             (void *) nfs_access },
+       { &vop_advlock_desc,            (void *) nfs_advlock },
+       { &vop_bmap_desc,               (void *) nfs_bmap },
+       { &vop_bwrite_desc,             (void *) nfs_bwrite },
+       { &vop_close_desc,              (void *) nfs_close },
+       { &vop_create_desc,             (void *) nfs_create },
+       { &vop_fsync_desc,              (void *) nfs_fsync },
+       { &vop_getattr_desc,            (void *) nfs_getattr },
+       { &vop_getpages_desc,           (void *) nfs_getpages },
+       { &vop_putpages_desc,           (void *) nfs_putpages },
+       { &vop_inactive_desc,           (void *) nfs_inactive },
+       { &vop_islocked_desc,           (void *) vop_stdislocked },
+       { &vop_lease_desc,              vop_null },
+       { &vop_link_desc,               (void *) nfs_link },
+       { &vop_lock_desc,               (void *) vop_stdlock },
+       { &vop_lookup_desc,             (void *) nfs_lookup },
+       { &vop_mkdir_desc,              (void *) nfs_mkdir },
+       { &vop_mknod_desc,              (void *) nfs_mknod },
+       { &vop_mmap_desc,               (void *) nfs_mmap },
+       { &vop_open_desc,               (void *) nfs_open },
+       { &vop_poll_desc,               (void *) nfs_poll },
+       { &vop_print_desc,              (void *) nfs_print },
+       { &vop_read_desc,               (void *) nfs_read },
+       { &vop_readdir_desc,            (void *) nfs_readdir },
+       { &vop_readlink_desc,           (void *) nfs_readlink },
+       { &vop_reclaim_desc,            (void *) nfs_reclaim },
+       { &vop_remove_desc,             (void *) nfs_remove },
+       { &vop_rename_desc,             (void *) nfs_rename },
+       { &vop_rmdir_desc,              (void *) nfs_rmdir },
+       { &vop_setattr_desc,            (void *) nfs_setattr },
+       { &vop_strategy_desc,           (void *) nfs_strategy },
+       { &vop_symlink_desc,            (void *) nfs_symlink },
+       { &vop_unlock_desc,             (void *) vop_stdunlock },
+       { &vop_write_desc,              (void *) nfs_write },
        { NULL, NULL }
 };
-static struct vnodeopv_desc nfsv2_vnodeop_opv_desc =
-       { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries };
-VNODEOP_SET(nfsv2_vnodeop_opv_desc);
 
 /*
  * Special device vnode ops
  */
-vop_t **spec_nfsv2nodeop_p;
-static struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
-       { &vop_default_desc,            (vop_t *) spec_vnoperate },
-       { &vop_access_desc,             (vop_t *) nfsspec_access },
-       { &vop_close_desc,              (vop_t *) nfsspec_close },
-       { &vop_fsync_desc,              (vop_t *) nfs_fsync },
-       { &vop_getattr_desc,            (vop_t *) nfs_getattr },
-       { &vop_inactive_desc,           (vop_t *) nfs_inactive },
-       { &vop_islocked_desc,           (vop_t *) vop_stdislocked },
-       { &vop_lock_desc,               (vop_t *) vop_sharedlock },
-       { &vop_print_desc,              (vop_t *) nfs_print },
-       { &vop_read_desc,               (vop_t *) nfsspec_read },
-       { &vop_reclaim_desc,            (vop_t *) nfs_reclaim },
-       { &vop_setattr_desc,            (vop_t *) nfs_setattr },
-       { &vop_unlock_desc,             (vop_t *) vop_stdunlock },
-       { &vop_write_desc,              (vop_t *) nfsspec_write },
+struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
+       { &vop_default_desc,            (void *) spec_vnoperate },
+       { &vop_access_desc,             (void *) nfsspec_access },
+       { &vop_close_desc,              (void *) nfsspec_close },
+       { &vop_fsync_desc,              (void *) nfs_fsync },
+       { &vop_getattr_desc,            (void *) nfs_getattr },
+       { &vop_inactive_desc,           (void *) nfs_inactive },
+       { &vop_islocked_desc,           (void *) vop_stdislocked },
+       { &vop_lock_desc,               (void *) vop_stdlock },
+       { &vop_print_desc,              (void *) nfs_print },
+       { &vop_read_desc,               (void *) nfsspec_read },
+       { &vop_reclaim_desc,            (void *) nfs_reclaim },
+       { &vop_setattr_desc,            (void *) nfs_setattr },
+       { &vop_unlock_desc,             (void *) vop_stdunlock },
+       { &vop_write_desc,              (void *) nfsspec_write },
        { NULL, NULL }
 };
-static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc =
-       { &spec_nfsv2nodeop_p, nfsv2_specop_entries };
-VNODEOP_SET(spec_nfsv2nodeop_opv_desc);
-
-vop_t **fifo_nfsv2nodeop_p;
-static struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
-       { &vop_default_desc,            (vop_t *) fifo_vnoperate },
-       { &vop_access_desc,             (vop_t *) nfsspec_access },
-       { &vop_close_desc,              (vop_t *) nfsfifo_close },
-       { &vop_fsync_desc,              (vop_t *) nfs_fsync },
-       { &vop_getattr_desc,            (vop_t *) nfs_getattr },
-       { &vop_inactive_desc,           (vop_t *) nfs_inactive },
-       { &vop_islocked_desc,           (vop_t *) vop_stdislocked },
-       { &vop_lock_desc,               (vop_t *) vop_sharedlock },
-       { &vop_print_desc,              (vop_t *) nfs_print },
-       { &vop_read_desc,               (vop_t *) nfsfifo_read },
-       { &vop_reclaim_desc,            (vop_t *) nfs_reclaim },
-       { &vop_setattr_desc,            (vop_t *) nfs_setattr },
-       { &vop_unlock_desc,             (vop_t *) vop_stdunlock },
-       { &vop_write_desc,              (vop_t *) nfsfifo_write },
+
+struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
+       { &vop_default_desc,            (void *) fifo_vnoperate },
+       { &vop_access_desc,             (void *) nfsspec_access },
+       { &vop_close_desc,              (void *) nfsfifo_close },
+       { &vop_fsync_desc,              (void *) nfs_fsync },
+       { &vop_getattr_desc,            (void *) nfs_getattr },
+       { &vop_inactive_desc,           (void *) nfs_inactive },
+       { &vop_islocked_desc,           (void *) vop_stdislocked },
+       { &vop_lock_desc,               (void *) vop_stdlock },
+       { &vop_print_desc,              (void *) nfs_print },
+       { &vop_read_desc,               (void *) nfsfifo_read },
+       { &vop_reclaim_desc,            (void *) nfs_reclaim },
+       { &vop_setattr_desc,            (void *) nfs_setattr },
+       { &vop_unlock_desc,             (void *) vop_stdunlock },
+       { &vop_write_desc,              (void *) nfsfifo_write },
        { NULL, NULL }
 };
-static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc =
-       { &fifo_nfsv2nodeop_p, nfsv2_fifoop_entries };
-VNODEOP_SET(fifo_nfsv2nodeop_opv_desc);
 
 static int     nfs_mknodrpc (struct vnode *dvp, struct vnode **vpp,
                                  struct componentname *cnp,
@@ -260,6 +248,10 @@ static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW, 
           &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
 
+static int     nfsneg_cache_timeout = NFS_MINATTRTIMO;
+SYSCTL_INT(_vfs_nfs, OID_AUTO, neg_cache_timeout, CTLFLAG_RW, 
+          &nfsneg_cache_timeout, 0, "NFS NEGATIVE ACCESS cache timeout");
+
 static int     nfsv3_commit_on_close = 0;
 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW, 
           &nfsv3_commit_on_close, 0, "write+commit on close, else only write");
@@ -276,7 +268,7 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
                         | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
 static int
 nfs3_access_otw(struct vnode *vp, int wmode,
-       struct thread *td, struct ucred *cred)
+               struct thread *td, struct ucred *cred)
 {
        const int v3 = 1;
        u_int32_t *tl;
@@ -313,15 +305,12 @@ nfsmout:
  * For nfs version 2, just return ok. File accesses may fail later.
  * For nfs version 3, use the access rpc to check accessibility. If file modes
  * are changed on the server, accesses might still fail later.
+ *
+ * nfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
+ *           struct thread *a_td)
  */
 static int
-nfs_access(ap)
-       struct vop_access_args /* {
-               struct vnode *a_vp;
-               int  a_mode;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfs_access(struct vop_access_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        int error = 0;
@@ -469,16 +458,13 @@ nfs_access(ap)
  * and that deletion is not in progress.
  * For paged in text files, you will need to flush the page cache
  * if consistency is lost.
+ *
+ * nfs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
+ *         struct thread *a_td)
  */
 /* ARGSUSED */
 static int
-nfs_open(ap)
-       struct vop_open_args /* {
-               struct vnode *a_vp;
-               int  a_mode;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfs_open(struct vop_open_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -573,17 +559,13 @@ nfs_open(ap)
  * for NQNFS         - do nothing now, since 2 is dealt with via leases and
  *                     1 should be dealt with via an fsync() system call for
  *                     cases where write errors are important.
+ *
+ * nfs_close(struct vnodeop_desc *a_desc, struct vnode *a_vp, int a_fflag,
+ *          struct ucred *a_cred, struct thread *a_td)
  */
 /* ARGSUSED */
 static int
-nfs_close(ap)
-       struct vop_close_args /* {
-               struct vnodeop_desc *a_desc;
-               struct vnode *a_vp;
-               int  a_fflag;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfs_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -624,15 +606,12 @@ nfs_close(ap)
 
 /*
  * nfs getattr call from vfs.
+ *
+ * nfs_getattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred,
+ *             struct thread *a_td)
  */
 static int
-nfs_getattr(ap)
-       struct vop_getattr_args /* {
-               struct vnode *a_vp;
-               struct vattr *a_vap;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfs_getattr(struct vop_getattr_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -676,16 +655,13 @@ nfsmout:
 
 /*
  * nfs setattr call.
+ *
+ * nfs_setattr(struct vnodeop_desc *a_desc, struct vnode *a_vp,
+ *             struct vattr *a_vap, struct ucred *a_cred,
+ *             struct thread *a_td)
  */
 static int
-nfs_setattr(ap)
-       struct vop_setattr_args /* {
-               struct vnodeop_desc *a_desc;
-               struct vnode *a_vp;
-               struct vattr *a_vap;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfs_setattr(struct vop_setattr_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -756,10 +732,14 @@ nfs_setattr(ap)
                                return (error);
                            }
                        }
-                       /* np->n_size has already been set to vap->va_size
+                       /* 
+                        * np->n_size has already been set to vap->va_size
                         * in nfs_meta_setsize(). We must set it again since
                         * nfs_loadattrcache() could be called through
                         * nfs_meta_setsize() and could modify np->n_size.
+                        *
+                        * (note that nfs_loadattrcache() will have called
+                        * vnode_pager_setsize() for us in that case).
                         */
                        np->n_vattr.va_size = np->n_size = vap->va_size;
                };
@@ -781,9 +761,10 @@ nfs_setattr(ap)
  */
 static int
 nfs_setattrrpc(struct vnode *vp, struct vattr *vap,
-       struct ucred *cred, struct thread *td)
+              struct ucred *cred, struct thread *td)
 {
        struct nfsv2_sattr *sp;
+       struct nfsnode *np = VTONFS(vp);
        caddr_t cp;
        int32_t t1, t2;
        caddr_t bpos, dpos, cp2;
@@ -819,6 +800,7 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap,
        }
        nfsm_request(vp, NFSPROC_SETATTR, td, cred);
        if (v3) {
+               np->n_modestamp = 0;
                nfsm_wcc_data(vp, wccflag);
        } else
                nfsm_loadattr(vp, (struct vattr *)0);
@@ -828,18 +810,13 @@ nfsmout:
 }
 
 /*
- * nfs lookup call, one step at a time...
- * First look in cache
- * If not found, unlock the directory nfsnode and do the rpc
+ * 'cached' nfs directory lookup
+ *
+ * nfs_lookup(struct vnodeop_desc *a_desc, struct vnode *a_dvp,
+ *           struct vnode **a_vpp, struct componentname *a_cnp)
  */
 static int
-nfs_lookup(ap)
-       struct vop_lookup_args /* {
-               struct vnodeop_desc *a_desc;
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-       } */ *ap;
+nfs_lookup(struct vop_lookup_args *ap)
 {
        struct componentname *cnp = ap->a_cnp;
        struct vnode *dvp = ap->a_dvp;
@@ -859,20 +836,36 @@ nfs_lookup(ap)
        int v3 = NFS_ISV3(dvp);
        struct thread *td = cnp->cn_td;
 
+       /*
+        * Read-only mount check and directory check.
+        */
        *vpp = NULLVP;
        if ((flags & CNP_ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
            (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME))
                return (EROFS);
+
        if (dvp->v_type != VDIR)
                return (ENOTDIR);
+
+       /*
+        * Look it up in the cache.  Note that ENOENT is only returned if we
+        * previously entered a negative hit (see later on).  The additional
+        * nfsneg_cache_timeout check causes previously cached results to
+        * be instantly ignored if the negative caching is turned off.
+        */
        lockparent = flags & CNP_LOCKPARENT;
        wantparent = flags & (CNP_LOCKPARENT|CNP_WANTPARENT);
        nmp = VFSTONFS(dvp->v_mount);
        np = VTONFS(dvp);
-       if ((error = cache_lookup(dvp, NCPNULL, vpp, NCPPNULL, cnp)) && error != ENOENT) {
+       error = cache_lookup(dvp, vpp, cnp);
+       if (error != 0) {
                struct vattr vattr;
                int vpid;
 
+               if (error == ENOENT && nfsneg_cache_timeout) {
+                       *vpp = NULLVP;
+                       return (error);
+               }
                if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) {
                        *vpp = NULLVP;
                        return (error);
@@ -885,17 +878,23 @@ nfs_lookup(ap)
                 * for an explanation of the locking protocol
                 */
                if (dvp == newvp) {
-                       VREF(newvp);
+                       vref(newvp);
                        error = 0;
                } else if (flags & CNP_ISDOTDOT) {
-                       VOP_UNLOCK(dvp, 0, td);
-                       error = vget(newvp, LK_EXCLUSIVE, td);
-                       if (!error && lockparent && (flags & CNP_ISLASTCN))
-                               error = vn_lock(dvp, LK_EXCLUSIVE, td);
+                       VOP_UNLOCK(dvp, NULL, 0, td);
+                       cnp->cn_flags |= CNP_PDIRUNLOCK;
+                       error = vget(newvp, NULL, LK_EXCLUSIVE, td);
+                       if (!error && lockparent && (flags & CNP_ISLASTCN)) {
+                               error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
+                               if (error == 0)
+                                       cnp->cn_flags &= ~CNP_PDIRUNLOCK;
+                       }
                } else {
-                       error = vget(newvp, LK_EXCLUSIVE, td);
-                       if (!lockparent || error || !(flags & CNP_ISLASTCN))
-                               VOP_UNLOCK(dvp, 0, td);
+                       error = vget(newvp, NULL, LK_EXCLUSIVE, td);
+                       if (!lockparent || error || !(flags & CNP_ISLASTCN)) {
+                               VOP_UNLOCK(dvp, NULL, 0, td);
+                               cnp->cn_flags |= CNP_PDIRUNLOCK;
+                       }
                }
                if (!error) {
                        if (vpid == newvp->v_id) {
@@ -910,14 +909,22 @@ nfs_lookup(ap)
                           cache_purge(newvp);
                        }
                        vput(newvp);
-                       if (lockparent && dvp != newvp && (flags & CNP_ISLASTCN))
-                               VOP_UNLOCK(dvp, 0, td);
+                       if (lockparent && dvp != newvp && (flags & CNP_ISLASTCN)) {
+                               VOP_UNLOCK(dvp, NULL, 0, td);
+                               cnp->cn_flags |= CNP_PDIRUNLOCK;
+                       }
                }
-               error = vn_lock(dvp, LK_EXCLUSIVE, td);
+               error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
+               if (error == 0)
+                       cnp->cn_flags &= ~CNP_PDIRUNLOCK;
                *vpp = NULLVP;
                if (error)
                        return (error);
        }
+
+       /*
+        * Cache miss, go the wire.
+        */
        error = 0;
        newvp = NULLVP;
        nfsstats.lookupcache_misses++;
@@ -929,6 +936,24 @@ nfs_lookup(ap)
        nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
        nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_td, cnp->cn_cred);
        if (error) {
+               /*
+                * Cache negatve lookups to reduce NFS traffic, but use
+                * a fast timeout.
+                */
+               if (error == ENOENT &&
+                   (cnp->cn_flags & CNP_MAKEENTRY) && 
+                   cnp->cn_nameiop == NAMEI_LOOKUP &&
+                   nfsneg_cache_timeout) {
+                       int toval = nfsneg_cache_timeout * hz;
+                       if (cnp->cn_flags & CNP_CACHETIMEOUT) {
+                               if (cnp->cn_timeout > toval)
+                                       cnp->cn_timeout = toval;
+                       } else {
+                               cnp->cn_flags |= CNP_CACHETIMEOUT;
+                               cnp->cn_timeout = toval;
+                       }
+                       cache_enter(dvp, NCPNULL, NULL, cnp);
+               }
                nfsm_postop_attr(dvp, attrflag);
                m_freem(mrep);
                goto nfsmout;
@@ -957,26 +982,33 @@ nfs_lookup(ap)
                *vpp = newvp;
                m_freem(mrep);
                cnp->cn_flags |= CNP_SAVENAME;
-               if (!lockparent)
-                       VOP_UNLOCK(dvp, 0, td);
+               if (!lockparent) {
+                       VOP_UNLOCK(dvp, NULL, 0, td);
+                       cnp->cn_flags |= CNP_PDIRUNLOCK;
+               }
                return (0);
        }
 
        if (flags & CNP_ISDOTDOT) {
-               VOP_UNLOCK(dvp, 0, td);
+               VOP_UNLOCK(dvp, NULL, 0, td);
+               cnp->cn_flags |= CNP_PDIRUNLOCK;
                error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
                if (error) {
-                       vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
-                       return (error);
+                       vn_lock(dvp, NULL, LK_EXCLUSIVE | LK_RETRY, td);
+                       cnp->cn_flags &= ~CNP_PDIRUNLOCK;
+                       return (error); /* NOTE: return error from nget */
                }
                newvp = NFSTOV(np);
-               if (lockparent && (flags & CNP_ISLASTCN) &&
-                   (error = vn_lock(dvp, LK_EXCLUSIVE, td))) {
-                       vput(newvp);
-                       return (error);
+               if (lockparent && (flags & CNP_ISLASTCN)) {
+                       error = vn_lock(dvp, NULL, LK_EXCLUSIVE, td);
+                       if (error) {
+                               vput(newvp);
+                               return (error);
+                       }
+                       cnp->cn_flags |= CNP_PDIRUNLOCK;
                }
        } else if (NFS_CMPFH(np, fhp, fhsize)) {
-               VREF(dvp);
+               vref(dvp);
                newvp = dvp;
        } else {
                error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
@@ -984,8 +1016,10 @@ nfs_lookup(ap)
                        m_freem(mrep);
                        return (error);
                }
-               if (!lockparent || !(flags & CNP_ISLASTCN))
-                       VOP_UNLOCK(dvp, 0, td);
+               if (!lockparent || !(flags & CNP_ISLASTCN)) {
+                       VOP_UNLOCK(dvp, NULL, 0, td);
+                       cnp->cn_flags |= CNP_PDIRUNLOCK;
+               }
                newvp = NFSTOV(np);
        }
        if (v3) {
@@ -1010,8 +1044,10 @@ nfsmout:
                }
                if ((cnp->cn_nameiop == NAMEI_CREATE || cnp->cn_nameiop == NAMEI_RENAME) &&
                    (flags & CNP_ISLASTCN) && error == ENOENT) {
-                       if (!lockparent)
-                               VOP_UNLOCK(dvp, 0, td);
+                       if (!lockparent) {
+                               VOP_UNLOCK(dvp, NULL, 0, td);
+                               cnp->cn_flags |= CNP_PDIRUNLOCK;
+                       }
                        if (dvp->v_mount->mnt_flag & MNT_RDONLY)
                                error = EROFS;
                        else
@@ -1026,15 +1062,12 @@ nfsmout:
 /*
  * nfs read call.
  * Just call nfs_bioread() to do the work.
+ *
+ * nfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
+ *         struct ucred *a_cred)
  */
 static int
-nfs_read(ap)
-       struct vop_read_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               struct ucred *a_cred;
-       } */ *ap;
+nfs_read(struct vop_read_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
@@ -1051,14 +1084,11 @@ nfs_read(ap)
 
 /*
  * nfs readlink call
+ *
+ * nfs_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
  */
 static int
-nfs_readlink(ap)
-       struct vop_readlink_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               struct ucred *a_cred;
-       } */ *ap;
+nfs_readlink(struct vop_readlink_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
@@ -1170,10 +1200,7 @@ nfsmout:
  * nfs write call
  */
 int
-nfs_writerpc(vp, uiop, iomode, must_commit)
-       struct vnode *vp;
-       struct uio *uiop;
-       int *iomode, *must_commit;
+nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
 {
        u_int32_t *tl;
        caddr_t cp;
@@ -1284,11 +1311,8 @@ nfsmout:
  * mode set to specify the file type and the size field for rdev.
  */
 static int
-nfs_mknodrpc(dvp, vpp, cnp, vap)
-       struct vnode *dvp;
-       struct vnode **vpp;
-       struct componentname *cnp;
-       struct vattr *vap;
+nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
+            struct vattr *vap)
 {
        struct nfsv2_sattr *sp;
        u_int32_t *tl;
@@ -1372,16 +1396,13 @@ nfsmout:
 /*
  * nfs mknod vop
  * just call nfs_mknodrpc() to do the work.
+ *
+ * nfs_mknod(struct vnode *a_dvp, struct vnode **a_vpp,
+ *          struct componentname *a_cnp, struct vattr *a_vap)
  */
 /* ARGSUSED */
 static int
-nfs_mknod(ap)
-       struct vop_mknod_args /* {
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-               struct vattr *a_vap;
-       } */ *ap;
+nfs_mknod(struct vop_mknod_args *ap)
 {
        return nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
 }
@@ -1389,15 +1410,12 @@ nfs_mknod(ap)
 static u_long create_verf;
 /*
  * nfs file create call
+ *
+ * nfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
+ *           struct componentname *a_cnp, struct vattr *a_vap)
  */
 static int
-nfs_create(ap)
-       struct vop_create_args /* {
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-               struct vattr *a_vap;
-       } */ *ap;
+nfs_create(struct vop_create_args *ap)
 {
        struct vnode *dvp = ap->a_dvp;
        struct vattr *vap = ap->a_vap;
@@ -1438,7 +1456,7 @@ again:
                        nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
 #ifdef INET
                        if (!TAILQ_EMPTY(&in_ifaddrhead))
-                               *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr;
+                               *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr.s_addr;
                        else
 #endif
                                *tl++ = create_verf;
@@ -1527,15 +1545,12 @@ nfsmout:
  *          call nfs_sillyrename() to set it up
  *     else
  *       do the remove rpc
+ *
+ * nfs_remove(struct vnodeop_desc *a_desc, struct vnode *a_dvp,
+ *           struct vnode *a_vp, struct componentname *a_cnp)
  */
 static int
-nfs_remove(ap)
-       struct vop_remove_args /* {
-               struct vnodeop_desc *a_desc;
-               struct vnode * a_dvp;
-               struct vnode * a_vp;
-               struct componentname * a_cnp;
-       } */ *ap;
+nfs_remove(struct vop_remove_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct vnode *dvp = ap->a_dvp;
@@ -1592,7 +1607,6 @@ nfs_remove(ap)
 int
 nfs_removeit(struct sillyrename *sp)
 {
-
        return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen,
                sp->s_cred, NULL));
 }
@@ -1601,12 +1615,8 @@ nfs_removeit(struct sillyrename *sp)
  * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
  */
 static int
-nfs_removerpc(dvp, name, namelen, cred, td)
-       struct vnode *dvp;
-       const char *name;
-       int namelen;
-       struct ucred *cred;
-       struct thread *td;
+nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
+             struct ucred *cred, struct thread *td)
 {
        u_int32_t *tl;
        caddr_t cp;
@@ -1634,17 +1644,13 @@ nfsmout:
 
 /*
  * nfs file rename call
+ *
+ * nfs_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
+ *           struct componentname *a_fcnp, struct vnode *a_tdvp,
+ *           struct vnode *a_tvp, struct componentname *a_tcnp)
  */
 static int
-nfs_rename(ap)
-       struct vop_rename_args  /* {
-               struct vnode *a_fdvp;
-               struct vnode *a_fvp;
-               struct componentname *a_fcnp;
-               struct vnode *a_tdvp;
-               struct vnode *a_tvp;
-               struct componentname *a_tcnp;
-       } */ *ap;
+nfs_rename(struct vop_rename_args *ap)
 {
        struct vnode *fvp = ap->a_fvp;
        struct vnode *tvp = ap->a_tvp;
@@ -1721,10 +1727,8 @@ out:
  * nfs file rename rpc called from nfs_remove() above
  */
 static int
-nfs_renameit(sdvp, scnp, sp)
-       struct vnode *sdvp;
-       struct componentname *scnp;
-       struct sillyrename *sp;
+nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
+            struct sillyrename *sp)
 {
        return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
                sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_td));
@@ -1734,15 +1738,9 @@ nfs_renameit(sdvp, scnp, sp)
  * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
  */
 static int
-nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, td)
-       struct vnode *fdvp;
-       const char *fnameptr;
-       int fnamelen;
-       struct vnode *tdvp;
-       const char *tnameptr;
-       int tnamelen;
-       struct ucred *cred;
-       struct thread *td;
+nfs_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
+             struct vnode *tdvp, const char *tnameptr, int tnamelen,
+             struct ucred *cred, struct thread *td)
 {
        u_int32_t *tl;
        caddr_t cp;
@@ -1778,14 +1776,12 @@ nfsmout:
 
 /*
  * nfs hard link create call
+ *
+ * nfs_link(struct vnode *a_tdvp, struct vnode *a_vp,
+ *         struct componentname *a_cnp)
  */
 static int
-nfs_link(ap)
-       struct vop_link_args /* {
-               struct vnode *a_tdvp;
-               struct vnode *a_vp;
-               struct componentname *a_cnp;
-       } */ *ap;
+nfs_link(struct vop_link_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct vnode *tdvp = ap->a_tdvp;
@@ -1838,16 +1834,13 @@ nfsmout:
 
 /*
  * nfs symbolic link create call
+ *
+ * nfs_symlink(struct vnode *a_dvp, struct vnode **a_vpp,
+ *             struct componentname *a_cnp, struct vattr *a_vap,
+ *             char *a_target)
  */
 static int
-nfs_symlink(ap)
-       struct vop_symlink_args /* {
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-               struct vattr *a_vap;
-               char *a_target;
-       } */ *ap;
+nfs_symlink(struct vop_symlink_args *ap)
 {
        struct vnode *dvp = ap->a_dvp;
        struct vattr *vap = ap->a_vap;
@@ -1938,15 +1931,12 @@ nfsmout:
 
 /*
  * nfs make dir call
+ *
+ * nfs_mkdir(struct vnode *a_dvp, struct vnode **a_vpp,
+ *          struct componentname *a_cnp, struct vattr *a_vap)
  */
 static int
-nfs_mkdir(ap)
-       struct vop_mkdir_args /* {
-               struct vnode *a_dvp;
-               struct vnode **a_vpp;
-               struct componentname *a_cnp;
-               struct vattr *a_vap;
-       } */ *ap;
+nfs_mkdir(struct vop_mkdir_args *ap)
 {
        struct vnode *dvp = ap->a_dvp;
        struct vattr *vap = ap->a_vap;
@@ -2022,14 +2012,12 @@ nfsmout:
 
 /*
  * nfs remove directory call
+ *
+ * nfs_rmdir(struct vnode *a_dvp, struct vnode *a_vp,
+ *          struct componentname *a_cnp)
  */
 static int
-nfs_rmdir(ap)
-       struct vop_rmdir_args /* {
-               struct vnode *a_dvp;
-               struct vnode *a_vp;
-               struct componentname *a_cnp;
-       } */ *ap;
+nfs_rmdir(struct vop_rmdir_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct vnode *dvp = ap->a_dvp;
@@ -2069,14 +2057,11 @@ nfsmout:
 
 /*
  * nfs readdir call
+ *
+ * nfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
  */
 static int
-nfs_readdir(ap)
-       struct vop_readdir_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               struct ucred *a_cred;
-       } */ *ap;
+nfs_readdir(struct vop_readdir_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -2441,7 +2426,7 @@ nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
                            if (doit) {
                                nfsm_getfh(fhp, fhsize, 1);
                                if (NFS_CMPFH(dnp, fhp, fhsize)) {
-                                   VREF(vp);
+                                   vref(vp);
                                    newvp = vp;
                                    np = dnp;
                                } else {
@@ -2536,9 +2521,7 @@ nfsmout:
  * nfs_rename() completes, but...
  */
 static int
-nfs_sillyrename(dvp, vp, cnp)
-       struct vnode *dvp, *vp;
-       struct componentname *cnp;
+nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
 {
        struct sillyrename *sp;
        struct nfsnode *np;
@@ -2554,7 +2537,7 @@ nfs_sillyrename(dvp, vp, cnp)
                M_NFSREQ, M_WAITOK);
        sp->s_cred = crdup(cnp->cn_cred);
        sp->s_dvp = dvp;
-       VREF(dvp);
+       vref(dvp);
 
        /* Fudge together a funny name */
        sp->s_namlen = sprintf(sp->s_name, ".nfsA%08x4.4", (int)cnp->cn_td);
@@ -2591,13 +2574,8 @@ bad:
  * *npp != NULL --> update the file handle in the vnode
  */
 static int
-nfs_lookitup(dvp, name, len, cred, td, npp)
-       struct vnode *dvp;
-       const char *name;
-       int len;
-       struct ucred *cred;
-       struct thread *td;
-       struct nfsnode **npp;
+nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
+            struct thread *td, struct nfsnode **npp)
 {
        u_int32_t *tl;
        caddr_t cp;
@@ -2629,7 +2607,7 @@ nfs_lookitup(dvp, name, len, cred, td, npp)
                    np->n_fhsize = fhlen;
                    newvp = NFSTOV(np);
                } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
-                   VREF(dvp);
+                   vref(dvp);
                    newvp = dvp;
                } else {
                    error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
@@ -2715,17 +2693,12 @@ nfsmout:
  *    Kernel Write might not be enabled and also figured copyout() would do
  *    a lot more work than bcopy() and also it currently happens in the
  *    context of the swapper process (2).
+ *
+ * nfs_bmap(struct vnode *a_vp, daddr_t a_bn, struct vnode **a_vpp,
+ *         daddr_t *a_bnp, int *a_runp, int *a_runb)
  */
 static int
-nfs_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;
+nfs_bmap(struct vop_bmap_args *ap)
 {
        struct vnode *vp = ap->a_vp;
 
@@ -2747,8 +2720,7 @@ nfs_bmap(ap)
  * request.
  */
 static int
-nfs_strategy(ap)
-       struct vop_strategy_args *ap;
+nfs_strategy(struct vop_strategy_args *ap)
 {
        struct buf *bp = ap->a_bp;
        struct thread *td;
@@ -2780,36 +2752,27 @@ nfs_strategy(ap)
  * Mmap a file
  *
  * NB Currently unsupported.
+ *
+ * nfs_mmap(struct vnode *a_vp, int a_fflags, struct ucred *a_cred,
+ *         struct thread *a_td)
  */
 /* ARGSUSED */
 static int
-nfs_mmap(ap)
-       struct vop_mmap_args /* {
-               struct vnode *a_vp;
-               int  a_fflags;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfs_mmap(struct vop_mmap_args *ap)
 {
-
        return (EINVAL);
 }
 
 /*
  * fsync vnode op. Just call nfs_flush() with commit == 1.
+ *
+ * nfs_fsync(struct vnodeop_desc *a_desc, struct vnode *a_vp,
+ *          struct ucred * a_cred, int a_waitfor, struct thread *a_td)
  */
 /* ARGSUSED */
 static int
-nfs_fsync(ap)
-       struct vop_fsync_args /* {
-               struct vnodeop_desc *a_desc;
-               struct vnode * a_vp;
-               struct ucred * a_cred;
-               int  a_waitfor;
-               struct thread * a_td;
-       } */ *ap;
+nfs_fsync(struct vop_fsync_args *ap)
 {
-
        return (nfs_flush(ap->a_vp, ap->a_waitfor, ap->a_td, 1));
 }
 
@@ -2819,11 +2782,7 @@ nfs_fsync(ap)
  *     associated with the vnode.
  */
 static int
-nfs_flush(vp, waitfor, td, commit)
-       struct vnode *vp;
-       int waitfor;
-       struct thread *td;
-       int commit;
+nfs_flush(struct vnode *vp, int waitfor, struct thread *td, int commit)
 {
        struct nfsnode *np = VTONFS(vp);
        struct buf *bp;
@@ -3058,16 +3017,12 @@ done:
 /*
  * NFS advisory byte-level locks.
  * Currently unsupported.
+ *
+ * nfs_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl,
+ *             int a_flags)
  */
 static int
-nfs_advlock(ap)
-       struct vop_advlock_args /* {
-               struct vnode *a_vp;
-               caddr_t  a_id;
-               int  a_op;
-               struct flock *a_fl;
-               int  a_flags;
-       } */ *ap;
+nfs_advlock(struct vop_advlock_args *ap)
 {
        struct nfsnode *np = VTONFS(ap->a_vp);
 
@@ -3081,12 +3036,11 @@ nfs_advlock(ap)
 
 /*
  * Print out the contents of an nfsnode.
+ *
+ * nfs_print(struct vnode *a_vp)
  */
 static int
-nfs_print(ap)
-       struct vop_print_args /* {
-               struct vnode *a_vp;
-       } */ *ap;
+nfs_print(struct vop_print_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -3103,12 +3057,11 @@ nfs_print(ap)
  * Just call nfs_writebp() with the force argument set to 1.
  *
  * NOTE: B_DONE may or may not be set in a_bp on call.
+ *
+ * nfs_bwrite(struct vnode *a_bp)
  */
 static int
-nfs_bwrite(ap)
-       struct vop_bwrite_args /* {
-               struct vnode *a_bp;
-       } */ *ap;
+nfs_bwrite(struct vop_bwrite_args *ap)
 {
        return (nfs_writebp(ap->a_bp, 1, curthread));
 }
@@ -3119,10 +3072,7 @@ nfs_bwrite(ap)
  * B_CACHE if this is a VMIO buffer.
  */
 int
-nfs_writebp(bp, force, td)
-       struct buf *bp;
-       int force;
-       struct thread *td;
+nfs_writebp(struct buf *bp, int force, struct thread *td)
 {
        int s;
        int oldflags = bp->b_flags;
@@ -3183,15 +3133,12 @@ nfs_writebp(bp, force, td)
  * nfs special file access vnode op.
  * Essentially just get vattr and then imitate iaccess() since the device is
  * local to the client.
+ *
+ * nfsspec_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
+ *               struct thread *a_td)
  */
 static int
-nfsspec_access(ap)
-       struct vop_access_args /* {
-               struct vnode *a_vp;
-               int  a_mode;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfsspec_access(struct vop_access_args *ap)
 {
        struct vattr *vap;
        gid_t *gp;
@@ -3248,15 +3195,12 @@ found:
 
 /*
  * Read wrapper for special devices.
+ *
+ * nfsspec_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
+ *             struct ucred *a_cred)
  */
 static int
-nfsspec_read(ap)
-       struct vop_read_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               struct ucred *a_cred;
-       } */ *ap;
+nfsspec_read(struct vop_read_args *ap)
 {
        struct nfsnode *np = VTONFS(ap->a_vp);
 
@@ -3265,20 +3209,17 @@ nfsspec_read(ap)
         */
        np->n_flag |= NACC;
        getnanotime(&np->n_atim);
-       return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap));
+       return (VOCALL(spec_vnode_vops, &ap->a_head));
 }
 
 /*
  * Write wrapper for special devices.
+ *
+ * nfsspec_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
+ *              struct ucred *a_cred)
  */
 static int
-nfsspec_write(ap)
-       struct vop_write_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               struct ucred *a_cred;
-       } */ *ap;
+nfsspec_write(struct vop_write_args *ap)
 {
        struct nfsnode *np = VTONFS(ap->a_vp);
 
@@ -3287,22 +3228,19 @@ nfsspec_write(ap)
         */
        np->n_flag |= NUPD;
        getnanotime(&np->n_mtim);
-       return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap));
+       return (VOCALL(spec_vnode_vops, &ap->a_head));
 }
 
 /*
  * Close wrapper for special devices.
  *
  * Update the times on the nfsnode then do device close.
+ *
+ * nfsspec_close(struct vnode *a_vp, int a_fflag, struct ucred *a_cred,
+ *              struct thread *a_td)
  */
 static int
-nfsspec_close(ap)
-       struct vop_close_args /* {
-               struct vnode *a_vp;
-               int  a_fflag;
-               struct ucred *a_cred;
-               struct thread *a_td;
-       } */ *ap;
+nfsspec_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -3320,20 +3258,17 @@ nfsspec_close(ap)
                        (void)VOP_SETATTR(vp, &vattr, nfs_vpcred(vp, ND_WRITE), ap->a_td);
                }
        }
-       return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap));
+       return (VOCALL(spec_vnode_vops, &ap->a_head));
 }
 
 /*
  * Read wrapper for fifos.
+ *
+ * nfsfifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
+ *             struct ucred *a_cred)
  */
 static int
-nfsfifo_read(ap)
-       struct vop_read_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               struct ucred *a_cred;
-       } */ *ap;
+nfsfifo_read(struct vop_read_args *ap)
 {
        struct nfsnode *np = VTONFS(ap->a_vp);
 
@@ -3342,20 +3277,17 @@ nfsfifo_read(ap)
         */
        np->n_flag |= NACC;
        getnanotime(&np->n_atim);
-       return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap));
+       return (VOCALL(fifo_vnode_vops, &ap->a_head));
 }
 
 /*
  * Write wrapper for fifos.
+ *
+ * nfsfifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
+ *              struct ucred *a_cred)
  */
 static int
-nfsfifo_write(ap)
-       struct vop_write_args /* {
-               struct vnode *a_vp;
-               struct uio *a_uio;
-               int  a_ioflag;
-               struct ucred *a_cred;
-       } */ *ap;
+nfsfifo_write(struct vop_write_args *ap)
 {
        struct nfsnode *np = VTONFS(ap->a_vp);
 
@@ -3364,21 +3296,18 @@ nfsfifo_write(ap)
         */
        np->n_flag |= NUPD;
        getnanotime(&np->n_mtim);
-       return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap));
+       return (VOCALL(fifo_vnode_vops, &ap->a_head));
 }
 
 /*
  * Close wrapper for fifos.
  *
  * Update the times on the nfsnode then do fifo close.
+ *
+ * nfsfifo_close(struct vnode *a_vp, int a_fflag, struct thread *a_td)
  */
 static int
-nfsfifo_close(ap)
-       struct vop_close_args /* {
-               struct vnode *a_vp;
-               int  a_fflag;
-               struct thread *a_td;
-       } */ *ap;
+nfsfifo_close(struct vop_close_args *ap)
 {
        struct vnode *vp = ap->a_vp;
        struct nfsnode *np = VTONFS(vp);
@@ -3402,6 +3331,6 @@ nfsfifo_close(ap)
                        (void)VOP_SETATTR(vp, &vattr, nfs_vpcred(vp, ND_WRITE), ap->a_td);
                }
        }
-       return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap));
+       return (VOCALL(fifo_vnode_vops, &ap->a_head));
 }