/* * * Copyright (c) 2004 The DragonFly Project. All rights reserved. * * This code is derived from software contributed to The DragonFly Project * by Matthew Dillon * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name of The DragonFly Project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific, prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $DragonFly: src/sys/kern/vfs_vopops.c,v 1.25 2006/05/06 02:43:12 dillon Exp $ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VOFFNAME(name) __CONCAT(__CONCAT(vop_,name),_vp_offsets) #define VDESCNAME(name) __CONCAT(__CONCAT(vop_,name),_desc) #define VARGSSTRUCT(name) struct __CONCAT(__CONCAT(vop_,name),_args) #define VNODEOP_DESC_INIT(name, flags, vpoffs, vpp, cred, proc, comp) \ struct vnodeop_desc VDESCNAME(name) = { \ __offsetof(struct vop_ops, __CONCAT(vop_, name)), \ #name, flags, vpoffs, vpp, cred, proc, comp } #define VNODEOP_DESC_INIT_SIMPLE(name) \ VNODEOP_DESC_INIT(name, 0, NULL, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_VP(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_vp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_VP_VPP(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_vp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ __offsetof(VARGSSTRUCT(name), a_vpp), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_VP_CRED(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_vp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cred), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_NCP(name) \ VNODEOP_DESC_INIT(name, 0, NULL, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_NCP2_CRED(name) \ VNODEOP_DESC_INIT(name, 0, NULL, \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cred), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_NCP_CRED(name) \ VNODEOP_DESC_INIT(name, 0, NULL, \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cred), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_NCP_VP_CRED(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_vp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cred), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_NCP_CRED_VPP(name) \ VNODEOP_DESC_INIT(name, 0, NULL, \ __offsetof(VARGSSTRUCT(name), a_vpp), \ __offsetof(VARGSSTRUCT(name), a_cred), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_DVP_VPP_CNP(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_dvp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ __offsetof(VARGSSTRUCT(name), a_vpp), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cnp)) #define VNODEOP_DESC_INIT_DVP_VPP_CRED(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_dvp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ __offsetof(VARGSSTRUCT(name), a_vpp), \ __offsetof(VARGSSTRUCT(name), a_cred), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET) #define VNODEOP_DESC_INIT_DVP_CNP(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_dvp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cnp)) #define VNODEOP_DESC_INIT_DVP_VP_CNP(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_dvp), \ __offsetof(VARGSSTRUCT(name), a_vp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cnp)) #define VNODEOP_DESC_INIT_TDVP_VP_CNP(name) \ static int VOFFNAME(name)[] = { \ __offsetof(VARGSSTRUCT(name), a_tdvp), \ __offsetof(VARGSSTRUCT(name), a_vp), \ VDESC_NO_OFFSET }; \ VNODEOP_DESC_INIT(name, 0, VOFFNAME(name), \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ VDESC_NO_OFFSET, \ __offsetof(VARGSSTRUCT(name), a_cnp)) VNODEOP_DESC_INIT_SIMPLE(default); VNODEOP_DESC_INIT_VP(islocked); VNODEOP_DESC_INIT_DVP_VPP_CNP(old_lookup); VNODEOP_DESC_INIT_DVP_VPP_CNP(old_create); VNODEOP_DESC_INIT_DVP_CNP(old_whiteout); VNODEOP_DESC_INIT_DVP_VPP_CNP(old_mknod); VNODEOP_DESC_INIT_VP_CRED(open); VNODEOP_DESC_INIT_VP(close); VNODEOP_DESC_INIT_VP_CRED(access); VNODEOP_DESC_INIT_VP(getattr); VNODEOP_DESC_INIT_VP_CRED(setattr); VNODEOP_DESC_INIT_VP_CRED(read); VNODEOP_DESC_INIT_VP_CRED(write); VNODEOP_DESC_INIT_VP_CRED(ioctl); VNODEOP_DESC_INIT_VP_CRED(poll); VNODEOP_DESC_INIT_VP(kqfilter); VNODEOP_DESC_INIT_VP(revoke); VNODEOP_DESC_INIT_VP_CRED(mmap); VNODEOP_DESC_INIT_VP(fsync); VNODEOP_DESC_INIT_DVP_VP_CNP(old_remove); VNODEOP_DESC_INIT_TDVP_VP_CNP(old_link); static int VOFFNAME(old_rename)[] = { __offsetof(VARGSSTRUCT(old_rename), a_fdvp), __offsetof(VARGSSTRUCT(old_rename), a_fvp), __offsetof(VARGSSTRUCT(old_rename), a_tdvp), __offsetof(VARGSSTRUCT(old_rename), a_tvp), VDESC_NO_OFFSET }; VNODEOP_DESC_INIT(old_rename, VDESC_VP0_WILLRELE|VDESC_VP1_WILLRELE| VDESC_VP2_WILLRELE|VDESC_VP3_WILLRELE| VDESC_VP2_WILLUNLOCK|VDESC_VP3_WILLUNLOCK, /* tdvp and tvp */ VOFFNAME(old_rename), VDESC_NO_OFFSET, VDESC_NO_OFFSET, VDESC_NO_OFFSET, __offsetof(VARGSSTRUCT(old_rename), a_fcnp)); VNODEOP_DESC_INIT_DVP_VPP_CNP(old_mkdir); VNODEOP_DESC_INIT_DVP_VP_CNP(old_rmdir); VNODEOP_DESC_INIT_DVP_VPP_CNP(old_symlink); VNODEOP_DESC_INIT_VP_CRED(readdir); VNODEOP_DESC_INIT_VP_CRED(readlink); VNODEOP_DESC_INIT_VP(inactive); VNODEOP_DESC_INIT_VP(reclaim); VNODEOP_DESC_INIT_VP(lock); VNODEOP_DESC_INIT_VP(unlock); VNODEOP_DESC_INIT_VP_VPP(bmap); VNODEOP_DESC_INIT_VP(strategy); VNODEOP_DESC_INIT_VP(print); VNODEOP_DESC_INIT_VP(pathconf); VNODEOP_DESC_INIT_VP(advlock); VNODEOP_DESC_INIT_VP_CRED(balloc); VNODEOP_DESC_INIT_VP(reallocblks); VNODEOP_DESC_INIT_VP(getpages); VNODEOP_DESC_INIT_VP(putpages); VNODEOP_DESC_INIT_VP(freeblks); VNODEOP_DESC_INIT_VP_CRED(getacl); VNODEOP_DESC_INIT_VP_CRED(setacl); VNODEOP_DESC_INIT_VP_CRED(aclcheck); VNODEOP_DESC_INIT_VP_CRED(getextattr); VNODEOP_DESC_INIT_VP_CRED(setextattr); VNODEOP_DESC_INIT_SIMPLE(mountctl); VNODEOP_DESC_INIT_NCP_CRED(nresolve); VNODEOP_DESC_INIT_DVP_VPP_CRED(nlookupdotdot); VNODEOP_DESC_INIT_NCP_CRED_VPP(ncreate); VNODEOP_DESC_INIT_NCP_CRED_VPP(nmkdir); VNODEOP_DESC_INIT_NCP_CRED_VPP(nmknod); VNODEOP_DESC_INIT_NCP_VP_CRED(nlink); VNODEOP_DESC_INIT_NCP_CRED_VPP(nsymlink); VNODEOP_DESC_INIT_NCP_CRED(nwhiteout); VNODEOP_DESC_INIT_NCP_CRED(nremove); VNODEOP_DESC_INIT_NCP_CRED(nrmdir); VNODEOP_DESC_INIT_NCP2_CRED(nrename); #define DO_OPS(ops, error, ap, vop_field) \ error = ops->vop_field(ap); /************************************************************************ * PRIMARY HIGH LEVEL VNODE OPERATIONS CALLS * ************************************************************************ * * These procedures are called directly from the kernel and/or fileops * code to perform file/device operations on the system. * * NOTE: The old namespace api functions such as vop_rename() are no longer * available for general use and have been renamed to vop_old_*(). Only * the code in vfs_default.c is allowed to call those ops. */ int vop_islocked(struct vop_ops *ops, struct vnode *vp, struct thread *td) { struct vop_islocked_args ap; int error; ap.a_head.a_desc = &vop_islocked_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_td = td; DO_OPS(ops, error, &ap, vop_islocked); return(error); } int vop_old_lookup(struct vop_ops *ops, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp) { struct vop_old_lookup_args ap; int error; ap.a_head.a_desc = &vop_old_lookup_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vpp = vpp; ap.a_cnp = cnp; DO_OPS(ops, error, &ap, vop_old_lookup); return(error); } int vop_old_create(struct vop_ops *ops, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { struct vop_old_create_args ap; int error; ap.a_head.a_desc = &vop_old_create_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vpp = vpp; ap.a_cnp = cnp; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_old_create); return(error); } int vop_old_whiteout(struct vop_ops *ops, struct vnode *dvp, struct componentname *cnp, int flags) { struct vop_old_whiteout_args ap; int error; ap.a_head.a_desc = &vop_old_whiteout_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_cnp = cnp; ap.a_flags = flags; DO_OPS(ops, error, &ap, vop_old_whiteout); return(error); } int vop_old_mknod(struct vop_ops *ops, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { struct vop_old_mknod_args ap; int error; ap.a_head.a_desc = &vop_old_mknod_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vpp = vpp; ap.a_cnp = cnp; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_old_mknod); return(error); } int vop_open(struct vop_ops *ops, struct vnode *vp, int mode, struct ucred *cred, struct file *fp) { struct vop_open_args ap; int error; ap.a_head.a_desc = &vop_open_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_fp = fp; ap.a_mode = mode; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_open); return(error); } int vop_close(struct vop_ops *ops, struct vnode *vp, int fflag) { struct vop_close_args ap; int error; ap.a_head.a_desc = &vop_close_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_fflag = fflag; DO_OPS(ops, error, &ap, vop_close); return(error); } int vop_access(struct vop_ops *ops, struct vnode *vp, int mode, struct ucred *cred) { struct vop_access_args ap; int error; ap.a_head.a_desc = &vop_access_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_mode = mode; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_access); return(error); } int vop_getattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap) { struct vop_getattr_args ap; struct namecache *ncp; int error; ap.a_head.a_desc = &vop_getattr_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_getattr); if ((ops->vv_flags & VVF_SUPPORTS_FSMID) == 0) { if ((ncp = TAILQ_FIRST(&vp->v_namecache)) != NULL) { if (ncp->nc_flag & NCF_FSMID) { ncp->nc_flag &= ~NCF_FSMID; ++ncp->nc_fsmid; } vap->va_fsmid = ncp->nc_fsmid; } } return(error); } int vop_setattr(struct vop_ops *ops, struct vnode *vp, struct vattr *vap, struct ucred *cred) { struct vop_setattr_args ap; int error; ap.a_head.a_desc = &vop_setattr_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_vap = vap; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_setattr); if (error == 0) cache_update_fsmid_vp(vp); return(error); } int vop_read(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct vop_read_args ap; int error; ap.a_head.a_desc = &vop_read_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_uio = uio; ap.a_ioflag = ioflag; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_read); return(error); } int vop_write(struct vop_ops *ops, struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred) { struct vop_write_args ap; int error; ap.a_head.a_desc = &vop_write_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_uio = uio; ap.a_ioflag = ioflag; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_write); if (error == 0) cache_update_fsmid_vp(vp); return(error); } int vop_ioctl(struct vop_ops *ops, struct vnode *vp, u_long command, caddr_t data, int fflag, struct ucred *cred) { struct vop_ioctl_args ap; int error; ap.a_head.a_desc = &vop_ioctl_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_command = command; ap.a_data = data; ap.a_fflag = fflag; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_ioctl); return(error); } int vop_poll(struct vop_ops *ops, struct vnode *vp, int events, struct ucred *cred) { struct vop_poll_args ap; int error; ap.a_head.a_desc = &vop_poll_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_events = events; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_poll); return(error); } int vop_kqfilter(struct vop_ops *ops, struct vnode *vp, struct knote *kn) { struct vop_kqfilter_args ap; int error; ap.a_head.a_desc = &vop_kqfilter_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_kn = kn; DO_OPS(ops, error, &ap, vop_kqfilter); return(error); } int vop_revoke(struct vop_ops *ops, struct vnode *vp, int flags) { struct vop_revoke_args ap; int error; ap.a_head.a_desc = &vop_revoke_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_flags = flags; DO_OPS(ops, error, &ap, vop_revoke); return(error); } int vop_mmap(struct vop_ops *ops, struct vnode *vp, int fflags, struct ucred *cred) { struct vop_mmap_args ap; int error; ap.a_head.a_desc = &vop_mmap_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_fflags = fflags; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_mmap); return(error); } int vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor) { struct vop_fsync_args ap; int error; ap.a_head.a_desc = &vop_fsync_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_waitfor = waitfor; DO_OPS(ops, error, &ap, vop_fsync); return(error); } int vop_old_remove(struct vop_ops *ops, struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct vop_old_remove_args ap; int error; ap.a_head.a_desc = &vop_old_remove_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vp = vp; ap.a_cnp = cnp; DO_OPS(ops, error, &ap, vop_old_remove); return(error); } int vop_old_link(struct vop_ops *ops, struct vnode *tdvp, struct vnode *vp, struct componentname *cnp) { struct vop_old_link_args ap; int error; ap.a_head.a_desc = &vop_old_link_desc; ap.a_head.a_ops = ops; ap.a_tdvp = tdvp; ap.a_vp = vp; ap.a_cnp = cnp; DO_OPS(ops, error, &ap, vop_old_link); return(error); } int vop_old_rename(struct vop_ops *ops, struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp, struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp) { struct vop_old_rename_args ap; int error; ap.a_head.a_desc = &vop_old_rename_desc; ap.a_head.a_ops = ops; ap.a_fdvp = fdvp; ap.a_fvp = fvp; ap.a_fcnp = fcnp; ap.a_tdvp = tdvp; ap.a_tvp = tvp; ap.a_tcnp = tcnp; DO_OPS(ops, error, &ap, vop_old_rename); return(error); } int vop_old_mkdir(struct vop_ops *ops, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap) { struct vop_old_mkdir_args ap; int error; ap.a_head.a_desc = &vop_old_mkdir_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vpp = vpp; ap.a_cnp = cnp; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_old_mkdir); return(error); } int vop_old_rmdir(struct vop_ops *ops, struct vnode *dvp, struct vnode *vp, struct componentname *cnp) { struct vop_old_rmdir_args ap; int error; ap.a_head.a_desc = &vop_old_rmdir_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vp = vp; ap.a_cnp = cnp; DO_OPS(ops, error, &ap, vop_old_rmdir); return(error); } int vop_old_symlink(struct vop_ops *ops, struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, struct vattr *vap, char *target) { struct vop_old_symlink_args ap; int error; ap.a_head.a_desc = &vop_old_symlink_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vpp = vpp; ap.a_cnp = cnp; ap.a_vap = vap; ap.a_target = target; DO_OPS(ops, error, &ap, vop_old_symlink); return(error); } int vop_readdir(struct vop_ops *ops, struct vnode *vp, struct uio *uio, struct ucred *cred, int *eofflag, int *ncookies, u_long **cookies) { struct vop_readdir_args ap; int error; ap.a_head.a_desc = &vop_readdir_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_uio = uio; ap.a_cred = cred; ap.a_eofflag = eofflag; ap.a_ncookies = ncookies; ap.a_cookies = cookies; DO_OPS(ops, error, &ap, vop_readdir); return(error); } int vop_readlink(struct vop_ops *ops, struct vnode *vp, struct uio *uio, struct ucred *cred) { struct vop_readlink_args ap; int error; ap.a_head.a_desc = &vop_readlink_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_uio = uio; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_readlink); return(error); } int vop_inactive(struct vop_ops *ops, struct vnode *vp) { struct vop_inactive_args ap; int error; ap.a_head.a_desc = &vop_inactive_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; DO_OPS(ops, error, &ap, vop_inactive); return(error); } int vop_reclaim(struct vop_ops *ops, struct vnode *vp) { struct vop_reclaim_args ap; int error; ap.a_head.a_desc = &vop_reclaim_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; DO_OPS(ops, error, &ap, vop_reclaim); return(error); } int vop_lock(struct vop_ops *ops, struct vnode *vp, int flags) { struct vop_lock_args ap; int error; ap.a_head.a_desc = &vop_lock_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_flags = flags; DO_OPS(ops, error, &ap, vop_lock); return(error); } int vop_unlock(struct vop_ops *ops, struct vnode *vp, int flags) { struct vop_unlock_args ap; int error; ap.a_head.a_desc = &vop_unlock_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_flags = flags; DO_OPS(ops, error, &ap, vop_unlock); return(error); } int vop_bmap(struct vop_ops *ops, struct vnode *vp, off_t loffset, struct vnode **vpp, off_t *doffsetp, int *runp, int *runb) { struct vop_bmap_args ap; int error; ap.a_head.a_desc = &vop_bmap_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_loffset = loffset; ap.a_vpp = vpp; ap.a_doffsetp = doffsetp; ap.a_runp = runp; ap.a_runb = runb; DO_OPS(ops, error, &ap, vop_bmap); return(error); } int vop_strategy(struct vop_ops *ops, struct vnode *vp, struct bio *bio) { struct vop_strategy_args ap; int error; ap.a_head.a_desc = &vop_strategy_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_bio = bio; DO_OPS(ops, error, &ap, vop_strategy); if (error == 0 && bio->bio_buf->b_cmd != BUF_CMD_READ) cache_update_fsmid_vp(vp); return(error); } int vop_print(struct vop_ops *ops, struct vnode *vp) { struct vop_print_args ap; int error; ap.a_head.a_desc = &vop_print_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; DO_OPS(ops, error, &ap, vop_print); return(error); } int vop_pathconf(struct vop_ops *ops, struct vnode *vp, int name, register_t *retval) { struct vop_pathconf_args ap; int error; ap.a_head.a_desc = &vop_pathconf_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_name = name; ap.a_retval = retval; DO_OPS(ops, error, &ap, vop_pathconf); return(error); } int vop_advlock(struct vop_ops *ops, struct vnode *vp, caddr_t id, int op, struct flock *fl, int flags) { struct vop_advlock_args ap; int error; ap.a_head.a_desc = &vop_advlock_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_id = id; ap.a_op = op; ap.a_fl = fl; ap.a_flags = flags; DO_OPS(ops, error, &ap, vop_advlock); return(error); } int vop_balloc(struct vop_ops *ops, struct vnode *vp, off_t startoffset, int size, struct ucred *cred, int flags, struct buf **bpp) { struct vop_balloc_args ap; int error; ap.a_head.a_desc = &vop_balloc_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_startoffset = startoffset; ap.a_size = size; ap.a_cred = cred; ap.a_flags = flags; ap.a_bpp = bpp; DO_OPS(ops, error, &ap, vop_balloc); return(error); } int vop_reallocblks(struct vop_ops *ops, struct vnode *vp, struct cluster_save *buflist) { struct vop_reallocblks_args ap; int error; ap.a_head.a_desc = &vop_reallocblks_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_buflist = buflist; DO_OPS(ops, error, &ap, vop_reallocblks); return(error); } int vop_getpages(struct vop_ops *ops, struct vnode *vp, vm_page_t *m, int count, int reqpage, vm_ooffset_t offset) { struct vop_getpages_args ap; int error; ap.a_head.a_desc = &vop_getpages_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_m = m; ap.a_count = count; ap.a_reqpage = reqpage; ap.a_offset = offset; DO_OPS(ops, error, &ap, vop_getpages); return(error); } int vop_putpages(struct vop_ops *ops, struct vnode *vp, vm_page_t *m, int count, int sync, int *rtvals, vm_ooffset_t offset) { struct vop_putpages_args ap; int error; ap.a_head.a_desc = &vop_putpages_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_m = m; ap.a_count = count; ap.a_sync = sync; ap.a_rtvals = rtvals; ap.a_offset = offset; DO_OPS(ops, error, &ap, vop_putpages); if (error == 0) cache_update_fsmid_vp(vp); return(error); } int vop_freeblks(struct vop_ops *ops, struct vnode *vp, off_t offset, int length) { struct vop_freeblks_args ap; int error; ap.a_head.a_desc = &vop_freeblks_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_offset = offset; ap.a_length = length; DO_OPS(ops, error, &ap, vop_freeblks); return(error); } int vop_getacl(struct vop_ops *ops, struct vnode *vp, acl_type_t type, struct acl *aclp, struct ucred *cred) { struct vop_getacl_args ap; int error; ap.a_head.a_desc = &vop_getacl_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_type = type; ap.a_aclp = aclp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_getacl); return(error); } int vop_setacl(struct vop_ops *ops, struct vnode *vp, acl_type_t type, struct acl *aclp, struct ucred *cred) { struct vop_setacl_args ap; int error; ap.a_head.a_desc = &vop_setacl_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_type = type; ap.a_aclp = aclp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_setacl); if (error == 0) cache_update_fsmid_vp(vp); return(error); } int vop_aclcheck(struct vop_ops *ops, struct vnode *vp, acl_type_t type, struct acl *aclp, struct ucred *cred) { struct vop_aclcheck_args ap; int error; ap.a_head.a_desc = &vop_aclcheck_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_type = type; ap.a_aclp = aclp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_aclcheck); return(error); } int vop_getextattr(struct vop_ops *ops, struct vnode *vp, char *name, struct uio *uio, struct ucred *cred) { struct vop_getextattr_args ap; int error; ap.a_head.a_desc = &vop_getextattr_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_name = name; ap.a_uio = uio; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_getextattr); return(error); } int vop_setextattr(struct vop_ops *ops, struct vnode *vp, char *name, struct uio *uio, struct ucred *cred) { struct vop_setextattr_args ap; int error; ap.a_head.a_desc = &vop_setextattr_desc; ap.a_head.a_ops = ops; ap.a_vp = vp; ap.a_name = name; ap.a_uio = uio; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_setextattr); if (error == 0) cache_update_fsmid_vp(vp); return(error); } int vop_mountctl(struct vop_ops *ops, int op, struct file *fp, const void *ctl, int ctllen, void *buf, int buflen, int *res) { struct vop_mountctl_args ap; int error; ap.a_head.a_desc = &vop_mountctl_desc; ap.a_head.a_ops = ops; ap.a_op = op; ap.a_ctl = ctl; ap.a_fp = fp; ap.a_ctllen = ctllen; ap.a_buf = buf; ap.a_buflen = buflen; ap.a_res = res; DO_OPS(ops, error, &ap, vop_mountctl); return(error); } /* * NEW API FUNCTIONS * * nresolve takes a locked ncp and a cred and resolves the ncp into a * positive or negative hit. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nresolve(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred) { struct vop_nresolve_args ap; int error; ap.a_head.a_desc = &vop_nresolve_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_nresolve); return(error); } /* * nlookupdotdot takes an unlocked directory, dvp, and looks up "..", returning * a locked parent directory in *vpp. If an error occurs *vpp will be NULL. */ int vop_nlookupdotdot(struct vop_ops *ops, struct vnode *dvp, struct vnode **vpp, struct ucred *cred) { struct vop_nlookupdotdot_args ap; int error; ap.a_head.a_desc = &vop_nlookupdotdot_desc; ap.a_head.a_ops = ops; ap.a_dvp = dvp; ap.a_vpp = vpp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_nlookupdotdot); return(error); } /* * ncreate takes a locked, resolved ncp that typically represents a negative * cache hit and creates the file or node specified by the ncp, cred, and * vattr. If no error occurs a locked vnode is returned in *vpp. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_ncreate(struct vop_ops *ops, struct namecache *ncp, struct vnode **vpp, struct ucred *cred, struct vattr *vap) { struct vop_ncreate_args ap; int error; ap.a_head.a_desc = &vop_ncreate_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_vpp = vpp; ap.a_cred = cred; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_ncreate); if (error == 0 && *vpp) cache_update_fsmid_vp(*vpp); return(error); } /* * nmkdir takes a locked, resolved ncp that typically represents a negative * cache hit and creates the directory specified by the ncp, cred, and * vattr. If no error occurs a locked vnode is returned in *vpp. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nmkdir(struct vop_ops *ops, struct namecache *ncp, struct vnode **vpp, struct ucred *cred, struct vattr *vap) { struct vop_nmkdir_args ap; int error; ap.a_head.a_desc = &vop_nmkdir_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_vpp = vpp; ap.a_cred = cred; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_nmkdir); if (error == 0 && *vpp) cache_update_fsmid_vp(*vpp); return(error); } /* * nmknod takes a locked, resolved ncp that typically represents a negative * cache hit and creates the node specified by the ncp, cred, and * vattr. If no error occurs a locked vnode is returned in *vpp. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nmknod(struct vop_ops *ops, struct namecache *ncp, struct vnode **vpp, struct ucred *cred, struct vattr *vap) { struct vop_nmknod_args ap; int error; ap.a_head.a_desc = &vop_nmknod_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_vpp = vpp; ap.a_cred = cred; ap.a_vap = vap; DO_OPS(ops, error, &ap, vop_nmknod); if (error == 0 && *vpp) cache_update_fsmid_vp(*vpp); return(error); } /* * nlink takes a locked, resolved ncp that typically represents a negative * cache hit and creates the node specified by the ncp, cred, and * existing vnode. The passed vp must be locked and will remain locked * on return, as does the ncp, whether an error occurs or not. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nlink(struct vop_ops *ops, struct namecache *ncp, struct vnode *vp, struct ucred *cred) { struct vop_nlink_args ap; int error; ap.a_head.a_desc = &vop_nlink_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_vp = vp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_nlink); if (error == 0) cache_update_fsmid(ncp); return(error); } /* * nsymlink takes a locked, resolved ncp that typically represents a negative * cache hit and creates a symbolic link based on cred, vap, and target (the * contents of the link). If no error occurs a locked vnode is returned in * *vpp. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nsymlink(struct vop_ops *ops, struct namecache *ncp, struct vnode **vpp, struct ucred *cred, struct vattr *vap, char *target) { struct vop_nsymlink_args ap; int error; ap.a_head.a_desc = &vop_nsymlink_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_vpp = vpp; ap.a_cred = cred; ap.a_vap = vap; ap.a_target = target; DO_OPS(ops, error, &ap, vop_nsymlink); if (error == 0) cache_update_fsmid(ncp); return(error); } /* * nwhiteout takes a locked, resolved ncp that can represent a positive or * negative hit and executes the whiteout function specified in flags. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nwhiteout(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred, int flags) { struct vop_nwhiteout_args ap; int error; ap.a_head.a_desc = &vop_nwhiteout_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_cred = cred; ap.a_flags = flags; DO_OPS(ops, error, &ap, vop_nwhiteout); if (error == 0) cache_update_fsmid(ncp); return(error); } /* * nremove takes a locked, resolved ncp that generally represents a * positive hit and removes the file. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nremove(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred) { struct vop_nremove_args ap; int error; ap.a_head.a_desc = &vop_nremove_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_nremove); if (error == 0) cache_update_fsmid(ncp); return(error); } /* * nrmdir takes a locked, resolved ncp that generally represents a * directory and removes the directory. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. */ int vop_nrmdir(struct vop_ops *ops, struct namecache *ncp, struct ucred *cred) { struct vop_nrmdir_args ap; int error; ap.a_head.a_desc = &vop_nrmdir_desc; ap.a_head.a_ops = ops; ap.a_ncp = ncp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_nrmdir); if (error == 0) cache_update_fsmid(ncp); return(error); } /* * nrename takes TWO locked, resolved ncp's and the cred of the caller * and renames the source ncp to the target ncp. The target ncp may * represent a positive or negative hit. * * The namecache is automatically adjusted by this function. The ncp * is left locked on return. The source ncp is typically changed to * a negative cache hit and the target ncp typically takes on the * source ncp's underlying file. */ int vop_nrename(struct vop_ops *ops, struct namecache *fncp, struct namecache *tncp, struct ucred *cred) { struct vop_nrename_args ap; int error; ap.a_head.a_desc = &vop_nrename_desc; ap.a_head.a_ops = ops; ap.a_fncp = fncp; ap.a_tncp = tncp; ap.a_cred = cred; DO_OPS(ops, error, &ap, vop_nrename); if (error == 0) { cache_update_fsmid(fncp); cache_update_fsmid(tncp); } return(error); } /************************************************************************ * PRIMARY VNODE OPERATIONS FORWARDING CALLS * ************************************************************************ * * These procedures are called from VFSs such as unionfs and nullfs * when they wish to forward an operation on one VFS to another. The * argument structure/message is modified and then directly passed to the * appropriate routine. This routines may also be called by initiators * who have an argument structure in hand rather then discreet arguments. */ int vop_vnoperate_ap(struct vop_generic_args *ap) { struct vop_ops *ops; int error; ops = ap->a_ops; error = VOCALL(ops, ap); return (error); } /* * This routine is called by the cache coherency layer to execute the actual * VFS operation. If a journaling layer is present we call though it, else * we call the native VOP functions. */ int vop_cache_operate_ap(struct vop_generic_args *ap) { struct vop_ops *ops; int error; ops = ap->a_ops; if (ops->vv_mount->mnt_vn_journal_ops) error = VOCALL(ops->vv_mount->mnt_vn_journal_ops, ap); else error = VOCALL(ops->vv_mount->mnt_vn_norm_ops, ap); return (error); } /* * This routine is called by the journaling layer to execute the actual * VFS operation. */ int vop_journal_operate_ap(struct vop_generic_args *ap) { struct vop_ops *ops; int error; ops = ap->a_ops; error = VOCALL(ops->vv_mount->mnt_vn_norm_ops, ap); return (error); } int vop_islocked_ap(struct vop_islocked_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_islocked); return(error); } int vop_open_ap(struct vop_open_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_open); return(error); } int vop_close_ap(struct vop_close_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_close); return(error); } int vop_access_ap(struct vop_access_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_access); return(error); } int vop_getattr_ap(struct vop_getattr_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_getattr); return(error); } int vop_setattr_ap(struct vop_setattr_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_setattr); return(error); } int vop_read_ap(struct vop_read_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_read); return(error); } int vop_write_ap(struct vop_write_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_write); return(error); } int vop_ioctl_ap(struct vop_ioctl_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_ioctl); return(error); } int vop_poll_ap(struct vop_poll_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_poll); return(error); } int vop_kqfilter_ap(struct vop_kqfilter_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_kqfilter); return(error); } int vop_revoke_ap(struct vop_revoke_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_revoke); return(error); } int vop_mmap_ap(struct vop_mmap_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_mmap); return(error); } int vop_fsync_ap(struct vop_fsync_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_fsync); return(error); } int vop_readdir_ap(struct vop_readdir_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_readdir); return(error); } int vop_readlink_ap(struct vop_readlink_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_readlink); return(error); } int vop_inactive_ap(struct vop_inactive_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_inactive); return(error); } int vop_reclaim_ap(struct vop_reclaim_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_reclaim); return(error); } int vop_lock_ap(struct vop_lock_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_lock); return(error); } int vop_unlock_ap(struct vop_unlock_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_unlock); return(error); } int vop_bmap_ap(struct vop_bmap_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_bmap); return(error); } int vop_strategy_ap(struct vop_strategy_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_strategy); return(error); } int vop_print_ap(struct vop_print_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_print); return(error); } int vop_pathconf_ap(struct vop_pathconf_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_pathconf); return(error); } int vop_advlock_ap(struct vop_advlock_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_advlock); return(error); } int vop_balloc_ap(struct vop_balloc_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_balloc); return(error); } int vop_reallocblks_ap(struct vop_reallocblks_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_reallocblks); return(error); } int vop_getpages_ap(struct vop_getpages_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_getpages); return(error); } int vop_putpages_ap(struct vop_putpages_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_putpages); return(error); } int vop_freeblks_ap(struct vop_freeblks_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_freeblks); return(error); } int vop_getacl_ap(struct vop_getacl_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_getacl); return(error); } int vop_setacl_ap(struct vop_setacl_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_setacl); return(error); } int vop_aclcheck_ap(struct vop_aclcheck_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_aclcheck); return(error); } int vop_getextattr_ap(struct vop_getextattr_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_getextattr); return(error); } int vop_setextattr_ap(struct vop_setextattr_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_setextattr); return(error); } int vop_mountctl_ap(struct vop_mountctl_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_mountctl); return(error); } int vop_nresolve_ap(struct vop_nresolve_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nresolve); return(error); } int vop_nlookupdotdot_ap(struct vop_nlookupdotdot_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nlookupdotdot); return(error); } int vop_ncreate_ap(struct vop_ncreate_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_ncreate); return(error); } int vop_nmkdir_ap(struct vop_nmkdir_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nmkdir); return(error); } int vop_nmknod_ap(struct vop_nmknod_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nmknod); return(error); } int vop_nlink_ap(struct vop_nlink_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nlink); return(error); } int vop_nsymlink_ap(struct vop_nsymlink_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nsymlink); return(error); } int vop_nwhiteout_ap(struct vop_nwhiteout_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nwhiteout); return(error); } int vop_nremove_ap(struct vop_nremove_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nremove); return(error); } int vop_nrmdir_ap(struct vop_nrmdir_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nrmdir); return(error); } int vop_nrename_ap(struct vop_nrename_args *ap) { int error; DO_OPS(ap->a_head.a_ops, error, ap, vop_nrename); return(error); }