18329232eSGordon Ross /*
28329232eSGordon Ross  * CDDL HEADER START
38329232eSGordon Ross  *
48329232eSGordon Ross  * The contents of this file are subject to the terms of the
58329232eSGordon Ross  * Common Development and Distribution License (the "License").
68329232eSGordon Ross  * You may not use this file except in compliance with the License.
78329232eSGordon Ross  *
88329232eSGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
98329232eSGordon Ross  * or http://www.opensolaris.org/os/licensing.
108329232eSGordon Ross  * See the License for the specific language governing permissions
118329232eSGordon Ross  * and limitations under the License.
128329232eSGordon Ross  *
138329232eSGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
148329232eSGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
158329232eSGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
168329232eSGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
178329232eSGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
188329232eSGordon Ross  *
198329232eSGordon Ross  * CDDL HEADER END
208329232eSGordon Ross  */
218329232eSGordon Ross 
228329232eSGordon Ross /*
238329232eSGordon Ross  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
248329232eSGordon Ross  * Copyright 2017, Joyent, Inc.
258329232eSGordon Ross  * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
268329232eSGordon Ross  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
278329232eSGordon Ross  */
288329232eSGordon Ross 
298329232eSGordon Ross /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
308329232eSGordon Ross /*	  All Rights Reserved	*/
318329232eSGordon Ross 
328329232eSGordon Ross /*
338329232eSGordon Ross  * University Copyright- Copyright (c) 1982, 1986, 1988
348329232eSGordon Ross  * The Regents of the University of California
358329232eSGordon Ross  * All Rights Reserved
368329232eSGordon Ross  *
378329232eSGordon Ross  * University Acknowledgment- Portions of this document are derived from
388329232eSGordon Ross  * software developed by the University of California, Berkeley, and its
398329232eSGordon Ross  * contributors.
408329232eSGordon Ross  */
418329232eSGordon Ross 
428329232eSGordon Ross /*
438329232eSGordon Ross  * This file contains those functions from fs/vnode.c that can be
448329232eSGordon Ross  * used with relatively little change.  Functions that differ
458329232eSGordon Ross  * significantly from that are in other files.
468329232eSGordon Ross  */
478329232eSGordon Ross 
488329232eSGordon Ross #include <sys/types.h>
498329232eSGordon Ross #include <sys/param.h>
508329232eSGordon Ross #include <sys/t_lock.h>
518329232eSGordon Ross #include <sys/errno.h>
528329232eSGordon Ross #include <sys/cred.h>
538329232eSGordon Ross #include <sys/user.h>
548329232eSGordon Ross #include <sys/uio.h>
558329232eSGordon Ross #include <sys/file.h>
568329232eSGordon Ross #include <sys/pathname.h>
578329232eSGordon Ross #include <sys/vfs.h>
588329232eSGordon Ross #include <sys/vfs_opreg.h>
598329232eSGordon Ross #include <sys/vnode.h>
608329232eSGordon Ross #include <sys/rwstlock.h>
618329232eSGordon Ross #include <sys/fem.h>
628329232eSGordon Ross #include <sys/stat.h>
638329232eSGordon Ross #include <sys/mode.h>
648329232eSGordon Ross #include <sys/conf.h>
658329232eSGordon Ross #include <sys/sysmacros.h>
668329232eSGordon Ross #include <sys/cmn_err.h>
678329232eSGordon Ross #include <sys/systm.h>
688329232eSGordon Ross #include <sys/kmem.h>
698329232eSGordon Ross #include <sys/atomic.h>
708329232eSGordon Ross #include <sys/debug.h>
718329232eSGordon Ross #include <sys/acl.h>
728329232eSGordon Ross #include <sys/nbmlock.h>
738329232eSGordon Ross #include <sys/fcntl.h>
748329232eSGordon Ross #include <sys/time.h>
758329232eSGordon Ross #include <fs/fs_subr.h>
768329232eSGordon Ross #include <fs/fs_reparse.h>
778329232eSGordon Ross 
788329232eSGordon Ross #include <libfksmbfs.h>
798329232eSGordon Ross 
808329232eSGordon Ross /* Determine if this vnode is a file that is read-only */
818329232eSGordon Ross #define	ISROFILE(vp)	\
828329232eSGordon Ross 	((vp)->v_type != VCHR && (vp)->v_type != VBLK && \
838329232eSGordon Ross 	    (vp)->v_type != VFIFO && vn_is_readonly(vp))
848329232eSGordon Ross 
858329232eSGordon Ross #define	VOPSTATS_UPDATE(vp, counter) ((void)vp)
868329232eSGordon Ross #define	VOPSTATS_UPDATE_IO(vp, counter, bytecounter, bytesval) \
878329232eSGordon Ross 	((void)vp, (void)bytesval)
888329232eSGordon Ross #define	VOPXID_MAP_CR(vp, cr)	((void)vp)
898329232eSGordon Ross 
908329232eSGordon Ross /*
918329232eSGordon Ross  * Excerpts from fs/vnode.c
928329232eSGordon Ross  */
938329232eSGordon Ross 
948329232eSGordon Ross /* Global used for empty/invalid v_path */
958329232eSGordon Ross char *vn_vpath_empty = "";
968329232eSGordon Ross 
978329232eSGordon Ross static int fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr);
988329232eSGordon Ross 
998329232eSGordon Ross /*
1008329232eSGordon Ross  * Convert stat(2) formats to vnode types and vice versa.  (Knows about
1018329232eSGordon Ross  * numerical order of S_IFMT and vnode types.)
1028329232eSGordon Ross  */
1038329232eSGordon Ross enum vtype iftovt_tab[] = {
1048329232eSGordon Ross 	VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
1058329232eSGordon Ross 	VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
1068329232eSGordon Ross };
1078329232eSGordon Ross 
1088329232eSGordon Ross ushort_t vttoif_tab[] = {
1098329232eSGordon Ross 	0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO,
1108329232eSGordon Ross 	S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0
1118329232eSGordon Ross };
1128329232eSGordon Ross 
1138329232eSGordon Ross /*
1148329232eSGordon Ross  * The system vnode cache.
1158329232eSGordon Ross  */
1168329232eSGordon Ross 
1178329232eSGordon Ross kmem_cache_t *vn_cache;
1188329232eSGordon Ross 
1198329232eSGordon Ross 
1208329232eSGordon Ross /*
1218329232eSGordon Ross  * Vnode operations vector.
1228329232eSGordon Ross  */
1238329232eSGordon Ross 
1248329232eSGordon Ross static const fs_operation_trans_def_t vn_ops_table[] = {
1258329232eSGordon Ross 	VOPNAME_OPEN, offsetof(struct vnodeops, vop_open),
1268329232eSGordon Ross 	    fs_nosys, fs_nosys,
1278329232eSGordon Ross 
1288329232eSGordon Ross 	VOPNAME_CLOSE, offsetof(struct vnodeops, vop_close),
1298329232eSGordon Ross 	    fs_nosys, fs_nosys,
1308329232eSGordon Ross 
1318329232eSGordon Ross 	VOPNAME_READ, offsetof(struct vnodeops, vop_read),
1328329232eSGordon Ross 	    fs_nosys, fs_nosys,
1338329232eSGordon Ross 
1348329232eSGordon Ross 	VOPNAME_WRITE, offsetof(struct vnodeops, vop_write),
1358329232eSGordon Ross 	    fs_nosys, fs_nosys,
1368329232eSGordon Ross 
1378329232eSGordon Ross 	VOPNAME_IOCTL, offsetof(struct vnodeops, vop_ioctl),
1388329232eSGordon Ross 	    fs_nosys, fs_nosys,
1398329232eSGordon Ross 
1408329232eSGordon Ross 	VOPNAME_SETFL, offsetof(struct vnodeops, vop_setfl),
1418329232eSGordon Ross 	    fs_setfl, fs_nosys,
1428329232eSGordon Ross 
1438329232eSGordon Ross 	VOPNAME_GETATTR, offsetof(struct vnodeops, vop_getattr),
1448329232eSGordon Ross 	    fs_nosys, fs_nosys,
1458329232eSGordon Ross 
1468329232eSGordon Ross 	VOPNAME_SETATTR, offsetof(struct vnodeops, vop_setattr),
1478329232eSGordon Ross 	    fs_nosys, fs_nosys,
1488329232eSGordon Ross 
1498329232eSGordon Ross 	VOPNAME_ACCESS, offsetof(struct vnodeops, vop_access),
1508329232eSGordon Ross 	    fs_nosys, fs_nosys,
1518329232eSGordon Ross 
1528329232eSGordon Ross 	VOPNAME_LOOKUP, offsetof(struct vnodeops, vop_lookup),
1538329232eSGordon Ross 	    fs_nosys, fs_nosys,
1548329232eSGordon Ross 
1558329232eSGordon Ross 	VOPNAME_CREATE, offsetof(struct vnodeops, vop_create),
1568329232eSGordon Ross 	    fs_nosys, fs_nosys,
1578329232eSGordon Ross 
1588329232eSGordon Ross 	VOPNAME_REMOVE, offsetof(struct vnodeops, vop_remove),
1598329232eSGordon Ross 	    fs_nosys, fs_nosys,
1608329232eSGordon Ross 
1618329232eSGordon Ross 	VOPNAME_LINK, offsetof(struct vnodeops, vop_link),
1628329232eSGordon Ross 	    fs_nosys, fs_nosys,
1638329232eSGordon Ross 
1648329232eSGordon Ross 	VOPNAME_RENAME, offsetof(struct vnodeops, vop_rename),
1658329232eSGordon Ross 	    fs_nosys, fs_nosys,
1668329232eSGordon Ross 
1678329232eSGordon Ross 	VOPNAME_MKDIR, offsetof(struct vnodeops, vop_mkdir),
1688329232eSGordon Ross 	    fs_nosys, fs_nosys,
1698329232eSGordon Ross 
1708329232eSGordon Ross 	VOPNAME_RMDIR, offsetof(struct vnodeops, vop_rmdir),
1718329232eSGordon Ross 	    fs_nosys, fs_nosys,
1728329232eSGordon Ross 
1738329232eSGordon Ross 	VOPNAME_READDIR, offsetof(struct vnodeops, vop_readdir),
1748329232eSGordon Ross 	    fs_nosys, fs_nosys,
1758329232eSGordon Ross 
1768329232eSGordon Ross 	VOPNAME_SYMLINK, offsetof(struct vnodeops, vop_symlink),
1778329232eSGordon Ross 	    fs_nosys, fs_nosys,
1788329232eSGordon Ross 
1798329232eSGordon Ross 	VOPNAME_READLINK, offsetof(struct vnodeops, vop_readlink),
1808329232eSGordon Ross 	    fs_nosys, fs_nosys,
1818329232eSGordon Ross 
1828329232eSGordon Ross 	VOPNAME_FSYNC, offsetof(struct vnodeops, vop_fsync),
1838329232eSGordon Ross 	    fs_nosys, fs_nosys,
1848329232eSGordon Ross 
1858329232eSGordon Ross 	VOPNAME_INACTIVE, offsetof(struct vnodeops, vop_inactive),
1868329232eSGordon Ross 	    fs_nosys, fs_nosys,
1878329232eSGordon Ross 
1888329232eSGordon Ross 	VOPNAME_FID, offsetof(struct vnodeops, vop_fid),
1898329232eSGordon Ross 	    fs_nosys, fs_nosys,
1908329232eSGordon Ross 
1918329232eSGordon Ross 	VOPNAME_RWLOCK, offsetof(struct vnodeops, vop_rwlock),
1928329232eSGordon Ross 	    fs_rwlock, fs_rwlock,
1938329232eSGordon Ross 
1948329232eSGordon Ross 	VOPNAME_RWUNLOCK, offsetof(struct vnodeops, vop_rwunlock),
195*8bbe90c1SToomas Soome 	    (fs_generic_func_p)(uintptr_t)fs_rwunlock,
196*8bbe90c1SToomas Soome 	    (fs_generic_func_p)(intptr_t)fs_rwunlock,	/* no errors allowed */
1978329232eSGordon Ross 
1988329232eSGordon Ross 	VOPNAME_SEEK, offsetof(struct vnodeops, vop_seek),
1998329232eSGordon Ross 	    fs_nosys, fs_nosys,
2008329232eSGordon Ross 
2018329232eSGordon Ross 	VOPNAME_CMP, offsetof(struct vnodeops, vop_cmp),
2028329232eSGordon Ross 	    fs_cmp, fs_cmp,		/* no errors allowed */
2038329232eSGordon Ross 
2048329232eSGordon Ross 	VOPNAME_FRLOCK, offsetof(struct vnodeops, vop_frlock),
2058329232eSGordon Ross 	    fs_frlock, fs_nosys,
2068329232eSGordon Ross 
2078329232eSGordon Ross 	VOPNAME_SPACE, offsetof(struct vnodeops, vop_space),
2088329232eSGordon Ross 	    fs_nosys, fs_nosys,
2098329232eSGordon Ross 
2108329232eSGordon Ross 	VOPNAME_REALVP, offsetof(struct vnodeops, vop_realvp),
2118329232eSGordon Ross 	    fs_nosys, fs_nosys,
2128329232eSGordon Ross 
2138329232eSGordon Ross 	VOPNAME_GETPAGE, offsetof(struct vnodeops, vop_getpage),
2148329232eSGordon Ross 	    fs_nosys, fs_nosys,
2158329232eSGordon Ross 
2168329232eSGordon Ross 	VOPNAME_PUTPAGE, offsetof(struct vnodeops, vop_putpage),
2178329232eSGordon Ross 	    fs_nosys, fs_nosys,
2188329232eSGordon Ross 
2198329232eSGordon Ross 	VOPNAME_MAP, offsetof(struct vnodeops, vop_map),
2208329232eSGordon Ross 	    (fs_generic_func_p) fs_nosys_map,
2218329232eSGordon Ross 	    (fs_generic_func_p) fs_nosys_map,
2228329232eSGordon Ross 
2238329232eSGordon Ross 	VOPNAME_ADDMAP, offsetof(struct vnodeops, vop_addmap),
2248329232eSGordon Ross 	    (fs_generic_func_p) fs_nosys_addmap,
2258329232eSGordon Ross 	    (fs_generic_func_p) fs_nosys_addmap,
2268329232eSGordon Ross 
2278329232eSGordon Ross 	VOPNAME_DELMAP, offsetof(struct vnodeops, vop_delmap),
2288329232eSGordon Ross 	    fs_nosys, fs_nosys,
2298329232eSGordon Ross 
2308329232eSGordon Ross 	VOPNAME_POLL, offsetof(struct vnodeops, vop_poll),
2318329232eSGordon Ross 	    (fs_generic_func_p) fs_poll, (fs_generic_func_p) fs_nosys_poll,
2328329232eSGordon Ross 
2338329232eSGordon Ross 	VOPNAME_DUMP, offsetof(struct vnodeops, vop_dump),
2348329232eSGordon Ross 	    fs_nosys, fs_nosys,
2358329232eSGordon Ross 
2368329232eSGordon Ross 	VOPNAME_PATHCONF, offsetof(struct vnodeops, vop_pathconf),
2378329232eSGordon Ross 	    fs_pathconf, fs_nosys,
2388329232eSGordon Ross 
2398329232eSGordon Ross 	VOPNAME_PAGEIO, offsetof(struct vnodeops, vop_pageio),
2408329232eSGordon Ross 	    fs_nosys, fs_nosys,
2418329232eSGordon Ross 
2428329232eSGordon Ross 	VOPNAME_DUMPCTL, offsetof(struct vnodeops, vop_dumpctl),
2438329232eSGordon Ross 	    fs_nosys, fs_nosys,
2448329232eSGordon Ross 
2458329232eSGordon Ross 	VOPNAME_DISPOSE, offsetof(struct vnodeops, vop_dispose),
246*8bbe90c1SToomas Soome 	    (fs_generic_func_p)(intptr_t)fs_dispose,
247*8bbe90c1SToomas Soome 	    (fs_generic_func_p)(intptr_t)fs_nodispose,
2488329232eSGordon Ross 
2498329232eSGordon Ross 	VOPNAME_SETSECATTR, offsetof(struct vnodeops, vop_setsecattr),
2508329232eSGordon Ross 	    fs_nosys, fs_nosys,
2518329232eSGordon Ross 
2528329232eSGordon Ross 	VOPNAME_GETSECATTR, offsetof(struct vnodeops, vop_getsecattr),
2538329232eSGordon Ross 	    fs_fab_acl, fs_nosys,
2548329232eSGordon Ross 
2558329232eSGordon Ross 	VOPNAME_SHRLOCK, offsetof(struct vnodeops, vop_shrlock),
2568329232eSGordon Ross 	    fs_shrlock, fs_nosys,
2578329232eSGordon Ross 
2588329232eSGordon Ross 	VOPNAME_VNEVENT, offsetof(struct vnodeops, vop_vnevent),
2598329232eSGordon Ross 	    (fs_generic_func_p) fs_vnevent_nosupport,
2608329232eSGordon Ross 	    (fs_generic_func_p) fs_vnevent_nosupport,
2618329232eSGordon Ross 
2628329232eSGordon Ross 	VOPNAME_REQZCBUF, offsetof(struct vnodeops, vop_reqzcbuf),
2638329232eSGordon Ross 	    fs_nosys, fs_nosys,
2648329232eSGordon Ross 
2658329232eSGordon Ross 	VOPNAME_RETZCBUF, offsetof(struct vnodeops, vop_retzcbuf),
2668329232eSGordon Ross 	    fs_nosys, fs_nosys,
2678329232eSGordon Ross 
2688329232eSGordon Ross 	NULL, 0, NULL, NULL
2698329232eSGordon Ross };
2708329232eSGordon Ross 
2718329232eSGordon Ross /* Extensible attribute (xva) routines. */
2728329232eSGordon Ross 
2738329232eSGordon Ross /*
2748329232eSGordon Ross  * Zero out the structure, set the size of the requested/returned bitmaps,
2758329232eSGordon Ross  * set AT_XVATTR in the embedded vattr_t's va_mask, and set up the pointer
2768329232eSGordon Ross  * to the returned attributes array.
2778329232eSGordon Ross  */
2788329232eSGordon Ross void
xva_init(xvattr_t * xvap)2798329232eSGordon Ross xva_init(xvattr_t *xvap)
2808329232eSGordon Ross {
2818329232eSGordon Ross 	bzero(xvap, sizeof (xvattr_t));
2828329232eSGordon Ross 	xvap->xva_mapsize = XVA_MAPSIZE;
2838329232eSGordon Ross 	xvap->xva_magic = XVA_MAGIC;
2848329232eSGordon Ross 	xvap->xva_vattr.va_mask = AT_XVATTR;
2858329232eSGordon Ross 	xvap->xva_rtnattrmapp = &(xvap->xva_rtnattrmap)[0];
2868329232eSGordon Ross }
2878329232eSGordon Ross 
2888329232eSGordon Ross /*
2898329232eSGordon Ross  * If AT_XVATTR is set, returns a pointer to the embedded xoptattr_t
2908329232eSGordon Ross  * structure.  Otherwise, returns NULL.
2918329232eSGordon Ross  */
2928329232eSGordon Ross xoptattr_t *
xva_getxoptattr(xvattr_t * xvap)2938329232eSGordon Ross xva_getxoptattr(xvattr_t *xvap)
2948329232eSGordon Ross {
2958329232eSGordon Ross 	xoptattr_t *xoap = NULL;
2968329232eSGordon Ross 	if (xvap->xva_vattr.va_mask & AT_XVATTR)
2978329232eSGordon Ross 		xoap = &xvap->xva_xoptattrs;
2988329232eSGordon Ross 	return (xoap);
2998329232eSGordon Ross }
3008329232eSGordon Ross 
3018329232eSGordon Ross // vska_compar
3028329232eSGordon Ross // create_vopstats_template
3038329232eSGordon Ross // new_vskstat
3048329232eSGordon Ross // vopstats_startup
3058329232eSGordon Ross // initialize_vopstats
3068329232eSGordon Ross // get_fstype_vopstats
3078329232eSGordon Ross // get_vskstat_anchor
3088329232eSGordon Ross // teardown_vopstats
3098329232eSGordon Ross 
3108329232eSGordon Ross /*
3118329232eSGordon Ross  * Read or write a vnode.  Called from kernel code.
3128329232eSGordon Ross  */
3138329232eSGordon Ross int
vn_rdwr(enum uio_rw rw,struct vnode * vp,caddr_t base,ssize_t len,offset_t offset,enum uio_seg seg,int ioflag,rlim64_t ulimit,cred_t * cr,ssize_t * residp)3148329232eSGordon Ross vn_rdwr(
3158329232eSGordon Ross 	enum uio_rw rw,
3168329232eSGordon Ross 	struct vnode *vp,
3178329232eSGordon Ross 	caddr_t base,
3188329232eSGordon Ross 	ssize_t len,
3198329232eSGordon Ross 	offset_t offset,
3208329232eSGordon Ross 	enum uio_seg seg,
3218329232eSGordon Ross 	int ioflag,
3228329232eSGordon Ross 	rlim64_t ulimit,	/* meaningful only if rw is UIO_WRITE */
3238329232eSGordon Ross 	cred_t *cr,
3248329232eSGordon Ross 	ssize_t *residp)
3258329232eSGordon Ross {
3268329232eSGordon Ross 	struct uio uio;
3278329232eSGordon Ross 	struct iovec iov;
3288329232eSGordon Ross 	int error;
3298329232eSGordon Ross 	int in_crit = 0;
3308329232eSGordon Ross 
3318329232eSGordon Ross 	if (rw == UIO_WRITE && ISROFILE(vp))
3328329232eSGordon Ross 		return (EROFS);
3338329232eSGordon Ross 
3348329232eSGordon Ross 	if (len < 0)
3358329232eSGordon Ross 		return (EIO);
3368329232eSGordon Ross 
3378329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
3388329232eSGordon Ross 
3398329232eSGordon Ross 	iov.iov_base = base;
3408329232eSGordon Ross 	iov.iov_len = len;
3418329232eSGordon Ross 	uio.uio_iov = &iov;
3428329232eSGordon Ross 	uio.uio_iovcnt = 1;
3438329232eSGordon Ross 	uio.uio_loffset = offset;
3448329232eSGordon Ross 	uio.uio_segflg = (short)seg;
3458329232eSGordon Ross 	uio.uio_resid = len;
3468329232eSGordon Ross 	uio.uio_llimit = ulimit;
3478329232eSGordon Ross 
3488329232eSGordon Ross 	/*
3498329232eSGordon Ross 	 * We have to enter the critical region before calling VOP_RWLOCK
3508329232eSGordon Ross 	 * to avoid a deadlock with ufs.
3518329232eSGordon Ross 	 */
3528329232eSGordon Ross 	if (nbl_need_check(vp)) {
3538329232eSGordon Ross 		int svmand;
3548329232eSGordon Ross 
3558329232eSGordon Ross 		nbl_start_crit(vp, RW_READER);
3568329232eSGordon Ross 		in_crit = 1;
3578329232eSGordon Ross 		error = nbl_svmand(vp, cr, &svmand);
3588329232eSGordon Ross 		if (error != 0)
3598329232eSGordon Ross 			goto done;
3608329232eSGordon Ross 		if (nbl_conflict(vp, rw == UIO_WRITE ? NBL_WRITE : NBL_READ,
3618329232eSGordon Ross 		    uio.uio_offset, uio.uio_resid, svmand, NULL)) {
3628329232eSGordon Ross 			error = EACCES;
3638329232eSGordon Ross 			goto done;
3648329232eSGordon Ross 		}
3658329232eSGordon Ross 	}
3668329232eSGordon Ross 
3678329232eSGordon Ross 	(void) VOP_RWLOCK(vp,
3688329232eSGordon Ross 	    rw == UIO_WRITE ? V_WRITELOCK_TRUE : V_WRITELOCK_FALSE, NULL);
3698329232eSGordon Ross 	if (rw == UIO_WRITE) {
3708329232eSGordon Ross 		uio.uio_fmode = FWRITE;
3718329232eSGordon Ross 		uio.uio_extflg = UIO_COPY_DEFAULT;
3728329232eSGordon Ross 		error = VOP_WRITE(vp, &uio, ioflag, cr, NULL);
3738329232eSGordon Ross 	} else {
3748329232eSGordon Ross 		uio.uio_fmode = FREAD;
3758329232eSGordon Ross 		uio.uio_extflg = UIO_COPY_CACHED;
3768329232eSGordon Ross 		error = VOP_READ(vp, &uio, ioflag, cr, NULL);
3778329232eSGordon Ross 	}
3788329232eSGordon Ross 	VOP_RWUNLOCK(vp,
3798329232eSGordon Ross 	    rw == UIO_WRITE ? V_WRITELOCK_TRUE : V_WRITELOCK_FALSE, NULL);
3808329232eSGordon Ross 	if (residp)
3818329232eSGordon Ross 		*residp = uio.uio_resid;
3828329232eSGordon Ross 	else if (uio.uio_resid)
3838329232eSGordon Ross 		error = EIO;
3848329232eSGordon Ross 
3858329232eSGordon Ross done:
3868329232eSGordon Ross 	if (in_crit)
3878329232eSGordon Ross 		nbl_end_crit(vp);
3888329232eSGordon Ross 	return (error);
3898329232eSGordon Ross }
3908329232eSGordon Ross 
3918329232eSGordon Ross /*
3928329232eSGordon Ross  * Incremend the hold on a vnode
3938329232eSGordon Ross  * (Real kernel uses a macro)
3948329232eSGordon Ross  */
3958329232eSGordon Ross void
vn_hold(struct vnode * vp)3968329232eSGordon Ross vn_hold(struct vnode *vp)
3978329232eSGordon Ross {
3988329232eSGordon Ross 	mutex_enter(&vp->v_lock);
3998329232eSGordon Ross 	(vp)->v_count++;
4008329232eSGordon Ross 	mutex_exit(&vp->v_lock);
4018329232eSGordon Ross }
4028329232eSGordon Ross 
4038329232eSGordon Ross /*
4048329232eSGordon Ross  * Release a vnode.  Call VOP_INACTIVE on last reference or
4058329232eSGordon Ross  * decrement reference count...
4068329232eSGordon Ross  */
4078329232eSGordon Ross void
vn_rele(vnode_t * vp)4088329232eSGordon Ross vn_rele(vnode_t *vp)
4098329232eSGordon Ross {
4108329232eSGordon Ross 	VERIFY(vp->v_count > 0);
4118329232eSGordon Ross 	mutex_enter(&vp->v_lock);
4128329232eSGordon Ross 	if (vp->v_count == 1) {
4138329232eSGordon Ross 		mutex_exit(&vp->v_lock);
4148329232eSGordon Ross 		VOP_INACTIVE(vp, CRED(), NULL);
4158329232eSGordon Ross 		return;
4168329232eSGordon Ross 	}
4178329232eSGordon Ross 	VN_RELE_LOCKED(vp);
4188329232eSGordon Ross 	mutex_exit(&vp->v_lock);
4198329232eSGordon Ross }
4208329232eSGordon Ross 
4218329232eSGordon Ross // vn_rele_dnlc
4228329232eSGordon Ross // vn_rele_stream
4238329232eSGordon Ross // vn_rele_inactive
4248329232eSGordon Ross // vn_rele_async
4258329232eSGordon Ross // vn_open, vn_openat
4268329232eSGordon Ross // vn_open_upgrade
4278329232eSGordon Ross // vn_open_downgrade
4288329232eSGordon Ross // vn_create, vn_createat
4298329232eSGordon Ross // vn_link, vn_linkat
4308329232eSGordon Ross // vn_rename, vn_renameat
4318329232eSGordon Ross // vn_remove, vn_removeat
4328329232eSGordon Ross 
4338329232eSGordon Ross 
4348329232eSGordon Ross /*
4358329232eSGordon Ross  * Utility function to compare equality of vnodes.
4368329232eSGordon Ross  * Compare the underlying real vnodes, if there are underlying vnodes.
4378329232eSGordon Ross  * This is a more thorough comparison than the VN_CMP() macro provides.
4388329232eSGordon Ross  */
4398329232eSGordon Ross int
vn_compare(vnode_t * vp1,vnode_t * vp2)4408329232eSGordon Ross vn_compare(vnode_t *vp1, vnode_t *vp2)
4418329232eSGordon Ross {
4428329232eSGordon Ross 	vnode_t *realvp;
4438329232eSGordon Ross 
4448329232eSGordon Ross 	if (vp1 != NULL && VOP_REALVP(vp1, &realvp, NULL) == 0)
4458329232eSGordon Ross 		vp1 = realvp;
4468329232eSGordon Ross 	if (vp2 != NULL && VOP_REALVP(vp2, &realvp, NULL) == 0)
4478329232eSGordon Ross 		vp2 = realvp;
4488329232eSGordon Ross 	return (VN_CMP(vp1, vp2));
4498329232eSGordon Ross }
4508329232eSGordon Ross 
4518329232eSGordon Ross // vn_vfslocks_buckets
4528329232eSGordon Ross // vn_vfslocks_getlock
4538329232eSGordon Ross // vn_vfslocks_rele
4548329232eSGordon Ross 
4558329232eSGordon Ross static krwlock_t vfsentry_ve_lock;
4568329232eSGordon Ross 
4578329232eSGordon Ross /*
4588329232eSGordon Ross  * vn_vfswlock_wait is used to implement a lock which is logically a
4598329232eSGordon Ross  * writers lock protecting the v_vfsmountedhere field.
4608329232eSGordon Ross  * vn_vfswlock_wait has been modified to be similar to vn_vfswlock,
4618329232eSGordon Ross  * except that it blocks to acquire the lock VVFSLOCK.
4628329232eSGordon Ross  *
4638329232eSGordon Ross  * traverse() and routines re-implementing part of traverse (e.g. autofs)
4648329232eSGordon Ross  * need to hold this lock. mount(), vn_rename(), vn_remove() and so on
4658329232eSGordon Ross  * need the non-blocking version of the writers lock i.e. vn_vfswlock
4668329232eSGordon Ross  */
4678329232eSGordon Ross int
vn_vfswlock_wait(vnode_t * vp)4688329232eSGordon Ross vn_vfswlock_wait(vnode_t *vp)
4698329232eSGordon Ross {
4708329232eSGordon Ross 
4718329232eSGordon Ross 	ASSERT(vp != NULL);
4728329232eSGordon Ross 
4738329232eSGordon Ross 	rw_enter(&vfsentry_ve_lock, RW_WRITER);
4748329232eSGordon Ross 
4758329232eSGordon Ross 	return (0);
4768329232eSGordon Ross }
4778329232eSGordon Ross 
4788329232eSGordon Ross int
vn_vfsrlock_wait(vnode_t * vp)4798329232eSGordon Ross vn_vfsrlock_wait(vnode_t *vp)
4808329232eSGordon Ross {
4818329232eSGordon Ross 
4828329232eSGordon Ross 	ASSERT(vp != NULL);
4838329232eSGordon Ross 
4848329232eSGordon Ross 	rw_enter(&vfsentry_ve_lock, RW_READER);
4858329232eSGordon Ross 
4868329232eSGordon Ross 	return (0);
4878329232eSGordon Ross }
4888329232eSGordon Ross 
4898329232eSGordon Ross /*
4908329232eSGordon Ross  * vn_vfswlock is used to implement a lock which is logically a writers lock
4918329232eSGordon Ross  * protecting the v_vfsmountedhere field.
4928329232eSGordon Ross  */
4938329232eSGordon Ross int
vn_vfswlock(vnode_t * vp)4948329232eSGordon Ross vn_vfswlock(vnode_t *vp)
4958329232eSGordon Ross {
4968329232eSGordon Ross 
4978329232eSGordon Ross 	if (vp == NULL)
4988329232eSGordon Ross 		return (EBUSY);
4998329232eSGordon Ross 
5008329232eSGordon Ross 	if (rw_tryenter(&vfsentry_ve_lock, RW_WRITER))
5018329232eSGordon Ross 		return (0);
5028329232eSGordon Ross 
5038329232eSGordon Ross 	return (EBUSY);
5048329232eSGordon Ross }
5058329232eSGordon Ross 
5068329232eSGordon Ross int
vn_vfsrlock(vnode_t * vp)5078329232eSGordon Ross vn_vfsrlock(vnode_t *vp)
5088329232eSGordon Ross {
5098329232eSGordon Ross 
5108329232eSGordon Ross 	if (vp == NULL)
5118329232eSGordon Ross 		return (EBUSY);
5128329232eSGordon Ross 
5138329232eSGordon Ross 	if (rw_tryenter(&vfsentry_ve_lock, RW_READER))
5148329232eSGordon Ross 		return (0);
5158329232eSGordon Ross 
5168329232eSGordon Ross 	return (EBUSY);
5178329232eSGordon Ross }
5188329232eSGordon Ross 
5198329232eSGordon Ross void
vn_vfsunlock(vnode_t * vp)5208329232eSGordon Ross vn_vfsunlock(vnode_t *vp)
5218329232eSGordon Ross {
5228329232eSGordon Ross 
5238329232eSGordon Ross 	rw_exit(&vfsentry_ve_lock);
5248329232eSGordon Ross }
5258329232eSGordon Ross 
5268329232eSGordon Ross int
vn_vfswlock_held(vnode_t * vp)5278329232eSGordon Ross vn_vfswlock_held(vnode_t *vp)
5288329232eSGordon Ross {
5298329232eSGordon Ross 	int held;
5308329232eSGordon Ross 
5318329232eSGordon Ross 	ASSERT(vp != NULL);
5328329232eSGordon Ross 
5338329232eSGordon Ross 	held = rw_write_held(&vfsentry_ve_lock);
5348329232eSGordon Ross 
5358329232eSGordon Ross 	return (held);
5368329232eSGordon Ross }
5378329232eSGordon Ross 
5388329232eSGordon Ross 
5398329232eSGordon Ross int
vn_make_ops(const char * name,const fs_operation_def_t * templ,vnodeops_t ** actual)5408329232eSGordon Ross vn_make_ops(
5418329232eSGordon Ross 	const char *name,			/* Name of file system */
5428329232eSGordon Ross 	const fs_operation_def_t *templ,	/* Operation specification */
5438329232eSGordon Ross 	vnodeops_t **actual)			/* Return the vnodeops */
5448329232eSGordon Ross {
5458329232eSGordon Ross 	int unused_ops;
5468329232eSGordon Ross 	int error;
5478329232eSGordon Ross 
5488329232eSGordon Ross 	*actual = (vnodeops_t *)kmem_alloc(sizeof (vnodeops_t), KM_SLEEP);
5498329232eSGordon Ross 
5508329232eSGordon Ross 	(*actual)->vnop_name = name;
5518329232eSGordon Ross 
5528329232eSGordon Ross 	error = fs_build_vector(*actual, &unused_ops, vn_ops_table, templ);
5538329232eSGordon Ross 	if (error) {
5548329232eSGordon Ross 		kmem_free(*actual, sizeof (vnodeops_t));
5558329232eSGordon Ross 	}
5568329232eSGordon Ross 
5578329232eSGordon Ross #if DEBUG
5588329232eSGordon Ross 	if (unused_ops != 0)
5598329232eSGordon Ross 		cmn_err(CE_WARN, "vn_make_ops: %s: %d operations supplied "
5608329232eSGordon Ross 		    "but not used", name, unused_ops);
5618329232eSGordon Ross #endif
5628329232eSGordon Ross 
5638329232eSGordon Ross 	return (error);
5648329232eSGordon Ross }
5658329232eSGordon Ross 
5668329232eSGordon Ross /*
5678329232eSGordon Ross  * Free the vnodeops created as a result of vn_make_ops()
5688329232eSGordon Ross  */
5698329232eSGordon Ross void
vn_freevnodeops(vnodeops_t * vnops)5708329232eSGordon Ross vn_freevnodeops(vnodeops_t *vnops)
5718329232eSGordon Ross {
5728329232eSGordon Ross 	kmem_free(vnops, sizeof (vnodeops_t));
5738329232eSGordon Ross }
5748329232eSGordon Ross 
5758329232eSGordon Ross /*
5768329232eSGordon Ross  * Vnode cache.
5778329232eSGordon Ross  */
5788329232eSGordon Ross 
5798329232eSGordon Ross /* ARGSUSED */
5808329232eSGordon Ross static int
vn_cache_constructor(void * buf,void * cdrarg,int kmflags)5818329232eSGordon Ross vn_cache_constructor(void *buf, void *cdrarg, int kmflags)
5828329232eSGordon Ross {
5838329232eSGordon Ross 	struct vnode *vp = buf;
5848329232eSGordon Ross 
5858329232eSGordon Ross 	bzero(vp, sizeof (*vp));
5868329232eSGordon Ross 	mutex_init(&vp->v_lock, NULL, MUTEX_DEFAULT, NULL);
5878329232eSGordon Ross 	rw_init(&vp->v_nbllock, NULL, RW_DEFAULT, NULL);
5888329232eSGordon Ross 	vp->v_path = vn_vpath_empty;
5898329232eSGordon Ross 	vp->v_fd = -1;
5908329232eSGordon Ross 	vp->v_st_dev = NODEV;
5918329232eSGordon Ross 
5928329232eSGordon Ross 	return (0);
5938329232eSGordon Ross }
5948329232eSGordon Ross 
5958329232eSGordon Ross /* ARGSUSED */
5968329232eSGordon Ross static void
vn_cache_destructor(void * buf,void * cdrarg)5978329232eSGordon Ross vn_cache_destructor(void *buf, void *cdrarg)
5988329232eSGordon Ross {
5998329232eSGordon Ross 	struct vnode *vp;
6008329232eSGordon Ross 
6018329232eSGordon Ross 	vp = buf;
6028329232eSGordon Ross 
6038329232eSGordon Ross 	rw_destroy(&vp->v_nbllock);
6048329232eSGordon Ross 	mutex_destroy(&vp->v_lock);
6058329232eSGordon Ross }
6068329232eSGordon Ross 
6078329232eSGordon Ross void
vn_create_cache(void)6088329232eSGordon Ross vn_create_cache(void)
6098329232eSGordon Ross {
6108329232eSGordon Ross 	vn_cache = kmem_cache_create("vn_cache", sizeof (struct vnode),
6118329232eSGordon Ross 	    VNODE_ALIGN, vn_cache_constructor, vn_cache_destructor, NULL, NULL,
6128329232eSGordon Ross 	    NULL, 0);
6138329232eSGordon Ross }
6148329232eSGordon Ross 
6158329232eSGordon Ross void
vn_destroy_cache(void)6168329232eSGordon Ross vn_destroy_cache(void)
6178329232eSGordon Ross {
6188329232eSGordon Ross 	kmem_cache_destroy(vn_cache);
6198329232eSGordon Ross }
6208329232eSGordon Ross 
6218329232eSGordon Ross /*
6228329232eSGordon Ross  * Used by file systems when fs-specific nodes (e.g., ufs inodes) are
6238329232eSGordon Ross  * cached by the file system and vnodes remain associated.
6248329232eSGordon Ross  */
6258329232eSGordon Ross void
vn_recycle(vnode_t * vp)6268329232eSGordon Ross vn_recycle(vnode_t *vp)
6278329232eSGordon Ross {
6288329232eSGordon Ross 	VERIFY(vp->v_path != NULL);
6298329232eSGordon Ross 
6308329232eSGordon Ross 	/*
6318329232eSGordon Ross 	 * XXX - This really belongs in vn_reinit(), but we have some issues
6328329232eSGordon Ross 	 * with the counts.  Best to have it here for clean initialization.
6338329232eSGordon Ross 	 */
6348329232eSGordon Ross 	vp->v_rdcnt = 0;
6358329232eSGordon Ross 	vp->v_wrcnt = 0;
6368329232eSGordon Ross 
6378329232eSGordon Ross 	/*
6388329232eSGordon Ross 	 * If FEM was in use...
6398329232eSGordon Ross 	 */
6408329232eSGordon Ross 
6418329232eSGordon Ross 	if (vp->v_path != vn_vpath_empty) {
6428329232eSGordon Ross 		kmem_free(vp->v_path, strlen(vp->v_path) + 1);
6438329232eSGordon Ross 		vp->v_path = vn_vpath_empty;
6448329232eSGordon Ross 	}
6458329232eSGordon Ross 	// vsd_free(vp);
6468329232eSGordon Ross }
6478329232eSGordon Ross 
6488329232eSGordon Ross /*
6498329232eSGordon Ross  * Used to reset the vnode fields including those that are directly accessible
6508329232eSGordon Ross  * as well as those which require an accessor function.
6518329232eSGordon Ross  */
6528329232eSGordon Ross void
vn_reinit(vnode_t * vp)6538329232eSGordon Ross vn_reinit(vnode_t *vp)
6548329232eSGordon Ross {
6558329232eSGordon Ross 	vp->v_count = 1;
6568329232eSGordon Ross 	// vp->v_count_dnlc = 0;
6578329232eSGordon Ross 	vp->v_vfsp = NULL;
6588329232eSGordon Ross 	vp->v_stream = NULL;
6598329232eSGordon Ross 	vp->v_vfsmountedhere = NULL;
6608329232eSGordon Ross 	vp->v_flag = 0;
6618329232eSGordon Ross 	vp->v_type = VNON;
6628329232eSGordon Ross 	vp->v_rdev = NODEV;
6638329232eSGordon Ross 
6648329232eSGordon Ross 	vp->v_xattrdir = NULL;
6658329232eSGordon Ross 
6668329232eSGordon Ross 	/*
6678329232eSGordon Ross 	 * In a few specific instances, vn_reinit() is used to initialize
6688329232eSGordon Ross 	 * locally defined vnode_t instances.  Lacking the construction offered
6698329232eSGordon Ross 	 * by vn_alloc(), these vnodes require v_path initialization.
6708329232eSGordon Ross 	 */
6718329232eSGordon Ross 	if (vp->v_path == NULL) {
6728329232eSGordon Ross 		vp->v_path = vn_vpath_empty;
6738329232eSGordon Ross 	}
6748329232eSGordon Ross 
6758329232eSGordon Ross 	/* Handles v_femhead, v_path, and the r/w/map counts */
6768329232eSGordon Ross 	vn_recycle(vp);
6778329232eSGordon Ross }
6788329232eSGordon Ross 
6798329232eSGordon Ross vnode_t *
vn_alloc(int kmflag)6808329232eSGordon Ross vn_alloc(int kmflag)
6818329232eSGordon Ross {
6828329232eSGordon Ross 	vnode_t *vp;
6838329232eSGordon Ross 
6848329232eSGordon Ross 	vp = kmem_cache_alloc(vn_cache, kmflag);
6858329232eSGordon Ross 
6868329232eSGordon Ross 	if (vp != NULL) {
6878329232eSGordon Ross 		// vp->v_femhead = NULL; /* Must be done before vn_reinit() */
6888329232eSGordon Ross 		// vp->v_fopdata = NULL;
6898329232eSGordon Ross 		vn_reinit(vp);
6908329232eSGordon Ross 	}
6918329232eSGordon Ross 
6928329232eSGordon Ross 	return (vp);
6938329232eSGordon Ross }
6948329232eSGordon Ross 
6958329232eSGordon Ross void
vn_free(vnode_t * vp)6968329232eSGordon Ross vn_free(vnode_t *vp)
6978329232eSGordon Ross {
6988329232eSGordon Ross 	extern vnode_t *rootdir;
6998329232eSGordon Ross 	ASSERT(vp != rootdir);
7008329232eSGordon Ross 
7018329232eSGordon Ross 	/*
7028329232eSGordon Ross 	 * Some file systems call vn_free() with v_count of zero,
7038329232eSGordon Ross 	 * some with v_count of 1.  In any case, the value should
7048329232eSGordon Ross 	 * never be anything else.
7058329232eSGordon Ross 	 */
7068329232eSGordon Ross 	ASSERT((vp->v_count == 0) || (vp->v_count == 1));
7078329232eSGordon Ross 	VERIFY(vp->v_path != NULL);
7088329232eSGordon Ross 	if (vp->v_path != vn_vpath_empty) {
7098329232eSGordon Ross 		kmem_free(vp->v_path, strlen(vp->v_path) + 1);
7108329232eSGordon Ross 		vp->v_path = vn_vpath_empty;
7118329232eSGordon Ross 	}
7128329232eSGordon Ross 
7138329232eSGordon Ross 	/* If FEM was in use... */
7148329232eSGordon Ross 
7158329232eSGordon Ross 	// vsd_free(vp);
7168329232eSGordon Ross 	kmem_cache_free(vn_cache, vp);
7178329232eSGordon Ross }
7188329232eSGordon Ross 
7198329232eSGordon Ross /*
7208329232eSGordon Ross  * vnode status changes, should define better states than 1, 0.
7218329232eSGordon Ross  */
7228329232eSGordon Ross void
vn_reclaim(vnode_t * vp)7238329232eSGordon Ross vn_reclaim(vnode_t *vp)
7248329232eSGordon Ross {
7258329232eSGordon Ross 	vfs_t   *vfsp = vp->v_vfsp;
7268329232eSGordon Ross 
7278329232eSGordon Ross 	if (vfsp == NULL ||
7288329232eSGordon Ross 	    vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) {
7298329232eSGordon Ross 		return;
7308329232eSGordon Ross 	}
7318329232eSGordon Ross 	(void) VFS_VNSTATE(vfsp, vp, VNTRANS_RECLAIMED);
7328329232eSGordon Ross }
7338329232eSGordon Ross 
7348329232eSGordon Ross void
vn_idle(vnode_t * vp)7358329232eSGordon Ross vn_idle(vnode_t *vp)
7368329232eSGordon Ross {
7378329232eSGordon Ross 	vfs_t   *vfsp = vp->v_vfsp;
7388329232eSGordon Ross 
7398329232eSGordon Ross 	if (vfsp == NULL ||
7408329232eSGordon Ross 	    vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) {
7418329232eSGordon Ross 		return;
7428329232eSGordon Ross 	}
7438329232eSGordon Ross 	(void) VFS_VNSTATE(vfsp, vp, VNTRANS_IDLED);
7448329232eSGordon Ross }
7458329232eSGordon Ross void
vn_exists(vnode_t * vp)7468329232eSGordon Ross vn_exists(vnode_t *vp)
7478329232eSGordon Ross {
7488329232eSGordon Ross 	vfs_t   *vfsp = vp->v_vfsp;
7498329232eSGordon Ross 
7508329232eSGordon Ross 	if (vfsp == NULL ||
7518329232eSGordon Ross 	    vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) {
7528329232eSGordon Ross 		return;
7538329232eSGordon Ross 	}
7548329232eSGordon Ross 	(void) VFS_VNSTATE(vfsp, vp, VNTRANS_EXISTS);
7558329232eSGordon Ross }
7568329232eSGordon Ross 
7578329232eSGordon Ross void
vn_invalid(vnode_t * vp)7588329232eSGordon Ross vn_invalid(vnode_t *vp)
7598329232eSGordon Ross {
7608329232eSGordon Ross }
7618329232eSGordon Ross 
7628329232eSGordon Ross /* Vnode event notification */
7638329232eSGordon Ross // vnevent_support()
7648329232eSGordon Ross // vnevent_...
7658329232eSGordon Ross 
7668329232eSGordon Ross /*
7678329232eSGordon Ross  * Vnode accessors.
7688329232eSGordon Ross  */
7698329232eSGordon Ross 
7708329232eSGordon Ross int
vn_is_readonly(vnode_t * vp)7718329232eSGordon Ross vn_is_readonly(vnode_t *vp)
7728329232eSGordon Ross {
7738329232eSGordon Ross 	return (vp->v_vfsp->vfs_flag & VFS_RDONLY);
7748329232eSGordon Ross }
7758329232eSGordon Ross 
7768329232eSGordon Ross int
vn_has_flocks(vnode_t * vp)7778329232eSGordon Ross vn_has_flocks(vnode_t *vp)
7788329232eSGordon Ross {
7798329232eSGordon Ross 	return (0);
7808329232eSGordon Ross }
7818329232eSGordon Ross 
7828329232eSGordon Ross int
vn_has_mandatory_locks(vnode_t * vp,int mode)7838329232eSGordon Ross vn_has_mandatory_locks(vnode_t *vp, int mode)
7848329232eSGordon Ross {
7858329232eSGordon Ross 	return (0);
7868329232eSGordon Ross }
7878329232eSGordon Ross 
7888329232eSGordon Ross int
vn_has_cached_data(vnode_t * vp)7898329232eSGordon Ross vn_has_cached_data(vnode_t *vp)
7908329232eSGordon Ross {
7918329232eSGordon Ross 	return (0);
7928329232eSGordon Ross }
7938329232eSGordon Ross 
7948329232eSGordon Ross // vn_can_change_zones
7958329232eSGordon Ross 
7968329232eSGordon Ross /*
7978329232eSGordon Ross  * Return nonzero if the vnode is a mount point, zero if not.
7988329232eSGordon Ross  */
7998329232eSGordon Ross int
vn_ismntpt(vnode_t * vp)8008329232eSGordon Ross vn_ismntpt(vnode_t *vp)
8018329232eSGordon Ross {
8028329232eSGordon Ross 	return (vp->v_vfsmountedhere != NULL);
8038329232eSGordon Ross }
8048329232eSGordon Ross 
8058329232eSGordon Ross /* Retrieve the vfs (if any) mounted on this vnode */
8068329232eSGordon Ross vfs_t *
vn_mountedvfs(vnode_t * vp)8078329232eSGordon Ross vn_mountedvfs(vnode_t *vp)
8088329232eSGordon Ross {
8098329232eSGordon Ross 	return (vp->v_vfsmountedhere);
8108329232eSGordon Ross }
8118329232eSGordon Ross 
8128329232eSGordon Ross /*
8138329232eSGordon Ross  * Return nonzero if the vnode is referenced by the dnlc, zero if not.
8148329232eSGordon Ross  * (no DNLC here)
8158329232eSGordon Ross  */
8168329232eSGordon Ross int
vn_in_dnlc(vnode_t * vp)8178329232eSGordon Ross vn_in_dnlc(vnode_t *vp)
8188329232eSGordon Ross {
8198329232eSGordon Ross 	return (0);
8208329232eSGordon Ross }
8218329232eSGordon Ross 
8228329232eSGordon Ross 
8238329232eSGordon Ross /*
8248329232eSGordon Ross  * vn_has_other_opens() checks whether a particular file is opened by more than
8258329232eSGordon Ross  * just the caller and whether the open is for read and/or write.
8268329232eSGordon Ross  * This routine is for calling after the caller has already called VOP_OPEN()
8278329232eSGordon Ross  * and the caller wishes to know if they are the only one with it open for
8288329232eSGordon Ross  * the mode(s) specified.
8298329232eSGordon Ross  *
8308329232eSGordon Ross  * Vnode counts are only kept on regular files (v_type=VREG).
8318329232eSGordon Ross  */
8328329232eSGordon Ross int
vn_has_other_opens(vnode_t * vp,v_mode_t mode)8338329232eSGordon Ross vn_has_other_opens(
8348329232eSGordon Ross 	vnode_t *vp,
8358329232eSGordon Ross 	v_mode_t mode)
8368329232eSGordon Ross {
8378329232eSGordon Ross 
8388329232eSGordon Ross 	ASSERT(vp != NULL);
8398329232eSGordon Ross 
8408329232eSGordon Ross 	switch (mode) {
8418329232eSGordon Ross 	case V_WRITE:
8428329232eSGordon Ross 		if (vp->v_wrcnt > 1)
8438329232eSGordon Ross 			return (V_TRUE);
8448329232eSGordon Ross 		break;
8458329232eSGordon Ross 	case V_RDORWR:
8468329232eSGordon Ross 		if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1))
8478329232eSGordon Ross 			return (V_TRUE);
8488329232eSGordon Ross 		break;
8498329232eSGordon Ross 	case V_RDANDWR:
8508329232eSGordon Ross 		if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1))
8518329232eSGordon Ross 			return (V_TRUE);
8528329232eSGordon Ross 		break;
8538329232eSGordon Ross 	case V_READ:
8548329232eSGordon Ross 		if (vp->v_rdcnt > 1)
8558329232eSGordon Ross 			return (V_TRUE);
8568329232eSGordon Ross 		break;
8578329232eSGordon Ross 	}
8588329232eSGordon Ross 
8598329232eSGordon Ross 	return (V_FALSE);
8608329232eSGordon Ross }
8618329232eSGordon Ross 
8628329232eSGordon Ross /*
8638329232eSGordon Ross  * vn_is_opened() checks whether a particular file is opened and
8648329232eSGordon Ross  * whether the open is for read and/or write.
8658329232eSGordon Ross  *
8668329232eSGordon Ross  * Vnode counts are only kept on regular files (v_type=VREG).
8678329232eSGordon Ross  */
8688329232eSGordon Ross int
vn_is_opened(vnode_t * vp,v_mode_t mode)8698329232eSGordon Ross vn_is_opened(
8708329232eSGordon Ross 	vnode_t *vp,
8718329232eSGordon Ross 	v_mode_t mode)
8728329232eSGordon Ross {
8738329232eSGordon Ross 
8748329232eSGordon Ross 	ASSERT(vp != NULL);
8758329232eSGordon Ross 
8768329232eSGordon Ross 	switch (mode) {
8778329232eSGordon Ross 	case V_WRITE:
8788329232eSGordon Ross 		if (vp->v_wrcnt)
8798329232eSGordon Ross 			return (V_TRUE);
8808329232eSGordon Ross 		break;
8818329232eSGordon Ross 	case V_RDANDWR:
8828329232eSGordon Ross 		if (vp->v_rdcnt && vp->v_wrcnt)
8838329232eSGordon Ross 			return (V_TRUE);
8848329232eSGordon Ross 		break;
8858329232eSGordon Ross 	case V_RDORWR:
8868329232eSGordon Ross 		if (vp->v_rdcnt || vp->v_wrcnt)
8878329232eSGordon Ross 			return (V_TRUE);
8888329232eSGordon Ross 		break;
8898329232eSGordon Ross 	case V_READ:
8908329232eSGordon Ross 		if (vp->v_rdcnt)
8918329232eSGordon Ross 			return (V_TRUE);
8928329232eSGordon Ross 		break;
8938329232eSGordon Ross 	}
8948329232eSGordon Ross 
8958329232eSGordon Ross 	return (V_FALSE);
8968329232eSGordon Ross }
8978329232eSGordon Ross 
8988329232eSGordon Ross /*
8998329232eSGordon Ross  * vn_is_mapped() checks whether a particular file is mapped and whether
9008329232eSGordon Ross  * the file is mapped read and/or write.  (no mmap here)
9018329232eSGordon Ross  */
9028329232eSGordon Ross int
vn_is_mapped(vnode_t * vp,v_mode_t mode)9038329232eSGordon Ross vn_is_mapped(
9048329232eSGordon Ross 	vnode_t *vp,
9058329232eSGordon Ross 	v_mode_t mode)
9068329232eSGordon Ross {
9078329232eSGordon Ross 	return (V_FALSE);
9088329232eSGordon Ross }
9098329232eSGordon Ross 
9108329232eSGordon Ross /*
9118329232eSGordon Ross  * Set the operations vector for a vnode.
9128329232eSGordon Ross  */
9138329232eSGordon Ross void
vn_setops(vnode_t * vp,vnodeops_t * vnodeops)9148329232eSGordon Ross vn_setops(vnode_t *vp, vnodeops_t *vnodeops)
9158329232eSGordon Ross {
9168329232eSGordon Ross 
9178329232eSGordon Ross 	ASSERT(vp != NULL);
9188329232eSGordon Ross 	ASSERT(vnodeops != NULL);
9198329232eSGordon Ross 
9208329232eSGordon Ross 	vp->v_op = vnodeops;
9218329232eSGordon Ross }
9228329232eSGordon Ross 
9238329232eSGordon Ross /*
9248329232eSGordon Ross  * Retrieve the operations vector for a vnode
9258329232eSGordon Ross  */
9268329232eSGordon Ross vnodeops_t *
vn_getops(vnode_t * vp)9278329232eSGordon Ross vn_getops(vnode_t *vp)
9288329232eSGordon Ross {
9298329232eSGordon Ross 
9308329232eSGordon Ross 	ASSERT(vp != NULL);
9318329232eSGordon Ross 
9328329232eSGordon Ross 	return (vp->v_op);
9338329232eSGordon Ross }
9348329232eSGordon Ross 
9358329232eSGordon Ross /*
9368329232eSGordon Ross  * Returns non-zero (1) if the vnodeops matches that of the vnode.
9378329232eSGordon Ross  * Returns zero (0) if not.
9388329232eSGordon Ross  */
9398329232eSGordon Ross int
vn_matchops(vnode_t * vp,vnodeops_t * vnodeops)9408329232eSGordon Ross vn_matchops(vnode_t *vp, vnodeops_t *vnodeops)
9418329232eSGordon Ross {
9428329232eSGordon Ross 	return (vn_getops(vp) == vnodeops);
9438329232eSGordon Ross }
9448329232eSGordon Ross 
9458329232eSGordon Ross // vn_matchopval
9468329232eSGordon Ross // fs_new_caller_id
9478329232eSGordon Ross 
9488329232eSGordon Ross // vn_clearpath
9498329232eSGordon Ross // vn_setpath_common
9508329232eSGordon Ross 
9518329232eSGordon Ross /* ARGSUSED */
9528329232eSGordon Ross void
vn_updatepath(vnode_t * pvp,vnode_t * vp,const char * name)9538329232eSGordon Ross vn_updatepath(vnode_t *pvp, vnode_t *vp, const char *name)
9548329232eSGordon Ross {
9558329232eSGordon Ross }
9568329232eSGordon Ross 
9578329232eSGordon Ross // vn_setpath...
9588329232eSGordon Ross // vn_renamepath
9598329232eSGordon Ross // vn_copypath
9608329232eSGordon Ross 
9618329232eSGordon Ross // vn_vmpss_usepageio
9628329232eSGordon Ross 
9638329232eSGordon Ross /* VOP_XXX() macros call the corresponding fop_xxx() function */
9648329232eSGordon Ross 
9658329232eSGordon Ross int
fop_open(vnode_t ** vpp,int mode,cred_t * cr,caller_context_t * ct)9668329232eSGordon Ross fop_open(
9678329232eSGordon Ross 	vnode_t **vpp,
9688329232eSGordon Ross 	int mode,
9698329232eSGordon Ross 	cred_t *cr,
9708329232eSGordon Ross 	caller_context_t *ct)
9718329232eSGordon Ross {
9728329232eSGordon Ross 	int ret;
9738329232eSGordon Ross 	vnode_t *vp = *vpp;
9748329232eSGordon Ross 
9758329232eSGordon Ross 	VN_HOLD(vp);
9768329232eSGordon Ross 	/*
9778329232eSGordon Ross 	 * Adding to the vnode counts before calling open
9788329232eSGordon Ross 	 * avoids the need for a mutex...
9798329232eSGordon Ross 	 */
9808329232eSGordon Ross 	if ((*vpp)->v_type == VREG) {
9818329232eSGordon Ross 		if (mode & FREAD)
9828329232eSGordon Ross 			atomic_inc_32(&(*vpp)->v_rdcnt);
9838329232eSGordon Ross 		if (mode & FWRITE)
9848329232eSGordon Ross 			atomic_inc_32(&(*vpp)->v_wrcnt);
9858329232eSGordon Ross 	}
9868329232eSGordon Ross 
9878329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
9888329232eSGordon Ross 
9898329232eSGordon Ross 	ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr, ct);
9908329232eSGordon Ross 
9918329232eSGordon Ross 	if (ret) {
9928329232eSGordon Ross 		/*
9938329232eSGordon Ross 		 * Use the saved vp just in case the vnode ptr got trashed
9948329232eSGordon Ross 		 * by the error.
9958329232eSGordon Ross 		 */
9968329232eSGordon Ross 		VOPSTATS_UPDATE(vp, open);
9978329232eSGordon Ross 		if ((vp->v_type == VREG) && (mode & FREAD))
9988329232eSGordon Ross 			atomic_dec_32(&vp->v_rdcnt);
9998329232eSGordon Ross 		if ((vp->v_type == VREG) && (mode & FWRITE))
10008329232eSGordon Ross 			atomic_dec_32(&vp->v_wrcnt);
10018329232eSGordon Ross 	} else {
10028329232eSGordon Ross 		/*
10038329232eSGordon Ross 		 * Some filesystems will return a different vnode,
10048329232eSGordon Ross 		 * but the same path was still used to open it.
10058329232eSGordon Ross 		 * So if we do change the vnode and need to
10068329232eSGordon Ross 		 * copy over the path, do so here, rather than special
10078329232eSGordon Ross 		 * casing each filesystem. Adjust the vnode counts to
10088329232eSGordon Ross 		 * reflect the vnode switch.
10098329232eSGordon Ross 		 */
10108329232eSGordon Ross 		VOPSTATS_UPDATE(*vpp, open);
10118329232eSGordon Ross 		if (*vpp != vp && *vpp != NULL) {
10128329232eSGordon Ross 			// vn_copypath(vp, *vpp);
10138329232eSGordon Ross 			if (((*vpp)->v_type == VREG) && (mode & FREAD))
10148329232eSGordon Ross 				atomic_inc_32(&(*vpp)->v_rdcnt);
10158329232eSGordon Ross 			if ((vp->v_type == VREG) && (mode & FREAD))
10168329232eSGordon Ross 				atomic_dec_32(&vp->v_rdcnt);
10178329232eSGordon Ross 			if (((*vpp)->v_type == VREG) && (mode & FWRITE))
10188329232eSGordon Ross 				atomic_inc_32(&(*vpp)->v_wrcnt);
10198329232eSGordon Ross 			if ((vp->v_type == VREG) && (mode & FWRITE))
10208329232eSGordon Ross 				atomic_dec_32(&vp->v_wrcnt);
10218329232eSGordon Ross 		}
10228329232eSGordon Ross 	}
10238329232eSGordon Ross 	VN_RELE(vp);
10248329232eSGordon Ross 	return (ret);
10258329232eSGordon Ross }
10268329232eSGordon Ross 
10278329232eSGordon Ross int
fop_close(vnode_t * vp,int flag,int count,offset_t offset,cred_t * cr,caller_context_t * ct)10288329232eSGordon Ross fop_close(
10298329232eSGordon Ross 	vnode_t *vp,
10308329232eSGordon Ross 	int flag,
10318329232eSGordon Ross 	int count,
10328329232eSGordon Ross 	offset_t offset,
10338329232eSGordon Ross 	cred_t *cr,
10348329232eSGordon Ross 	caller_context_t *ct)
10358329232eSGordon Ross {
10368329232eSGordon Ross 	int err;
10378329232eSGordon Ross 
10388329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
10398329232eSGordon Ross 
10408329232eSGordon Ross 	err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr, ct);
10418329232eSGordon Ross 	VOPSTATS_UPDATE(vp, close);
10428329232eSGordon Ross 	/*
10438329232eSGordon Ross 	 * Check passed in count to handle possible dups. Vnode counts are only
10448329232eSGordon Ross 	 * kept on regular files
10458329232eSGordon Ross 	 */
10468329232eSGordon Ross 	if ((vp->v_type == VREG) && (count == 1))  {
10478329232eSGordon Ross 		if (flag & FREAD) {
10488329232eSGordon Ross 			ASSERT(vp->v_rdcnt > 0);
10498329232eSGordon Ross 			atomic_dec_32(&vp->v_rdcnt);
10508329232eSGordon Ross 		}
10518329232eSGordon Ross 		if (flag & FWRITE) {
10528329232eSGordon Ross 			ASSERT(vp->v_wrcnt > 0);
10538329232eSGordon Ross 			atomic_dec_32(&vp->v_wrcnt);
10548329232eSGordon Ross 		}
10558329232eSGordon Ross 	}
10568329232eSGordon Ross 	return (err);
10578329232eSGordon Ross }
10588329232eSGordon Ross 
10598329232eSGordon Ross int
fop_read(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)10608329232eSGordon Ross fop_read(
10618329232eSGordon Ross 	vnode_t *vp,
10628329232eSGordon Ross 	uio_t *uiop,
10638329232eSGordon Ross 	int ioflag,
10648329232eSGordon Ross 	cred_t *cr,
10658329232eSGordon Ross 	caller_context_t *ct)
10668329232eSGordon Ross {
10678329232eSGordon Ross 	int	err;
10688329232eSGordon Ross 	ssize_t	resid_start = uiop->uio_resid;
10698329232eSGordon Ross 
10708329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
10718329232eSGordon Ross 
10728329232eSGordon Ross 	err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct);
10738329232eSGordon Ross 	VOPSTATS_UPDATE_IO(vp, read,
10748329232eSGordon Ross 	    read_bytes, (resid_start - uiop->uio_resid));
10758329232eSGordon Ross 	return (err);
10768329232eSGordon Ross }
10778329232eSGordon Ross 
10788329232eSGordon Ross int
fop_write(vnode_t * vp,uio_t * uiop,int ioflag,cred_t * cr,caller_context_t * ct)10798329232eSGordon Ross fop_write(
10808329232eSGordon Ross 	vnode_t *vp,
10818329232eSGordon Ross 	uio_t *uiop,
10828329232eSGordon Ross 	int ioflag,
10838329232eSGordon Ross 	cred_t *cr,
10848329232eSGordon Ross 	caller_context_t *ct)
10858329232eSGordon Ross {
10868329232eSGordon Ross 	int	err;
10878329232eSGordon Ross 	ssize_t	resid_start = uiop->uio_resid;
10888329232eSGordon Ross 
10898329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
10908329232eSGordon Ross 
10918329232eSGordon Ross 	err = (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct);
10928329232eSGordon Ross 	VOPSTATS_UPDATE_IO(vp, write,
10938329232eSGordon Ross 	    write_bytes, (resid_start - uiop->uio_resid));
10948329232eSGordon Ross 	return (err);
10958329232eSGordon Ross }
10968329232eSGordon Ross 
10978329232eSGordon Ross int
fop_ioctl(vnode_t * vp,int cmd,intptr_t arg,int flag,cred_t * cr,int * rvalp,caller_context_t * ct)10988329232eSGordon Ross fop_ioctl(
10998329232eSGordon Ross 	vnode_t *vp,
11008329232eSGordon Ross 	int cmd,
11018329232eSGordon Ross 	intptr_t arg,
11028329232eSGordon Ross 	int flag,
11038329232eSGordon Ross 	cred_t *cr,
11048329232eSGordon Ross 	int *rvalp,
11058329232eSGordon Ross 	caller_context_t *ct)
11068329232eSGordon Ross {
11078329232eSGordon Ross 	int	err;
11088329232eSGordon Ross 
11098329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
11108329232eSGordon Ross 
11118329232eSGordon Ross 	err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp, ct);
11128329232eSGordon Ross 	VOPSTATS_UPDATE(vp, ioctl);
11138329232eSGordon Ross 	return (err);
11148329232eSGordon Ross }
11158329232eSGordon Ross 
11168329232eSGordon Ross int
fop_setfl(vnode_t * vp,int oflags,int nflags,cred_t * cr,caller_context_t * ct)11178329232eSGordon Ross fop_setfl(
11188329232eSGordon Ross 	vnode_t *vp,
11198329232eSGordon Ross 	int oflags,
11208329232eSGordon Ross 	int nflags,
11218329232eSGordon Ross 	cred_t *cr,
11228329232eSGordon Ross 	caller_context_t *ct)
11238329232eSGordon Ross {
11248329232eSGordon Ross 	int	err;
11258329232eSGordon Ross 
11268329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
11278329232eSGordon Ross 
11288329232eSGordon Ross 	err = (*(vp)->v_op->vop_setfl)(vp, oflags, nflags, cr, ct);
11298329232eSGordon Ross 	VOPSTATS_UPDATE(vp, setfl);
11308329232eSGordon Ross 	return (err);
11318329232eSGordon Ross }
11328329232eSGordon Ross 
11338329232eSGordon Ross int
fop_getattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)11348329232eSGordon Ross fop_getattr(
11358329232eSGordon Ross 	vnode_t *vp,
11368329232eSGordon Ross 	vattr_t *vap,
11378329232eSGordon Ross 	int flags,
11388329232eSGordon Ross 	cred_t *cr,
11398329232eSGordon Ross 	caller_context_t *ct)
11408329232eSGordon Ross {
11418329232eSGordon Ross 	int	err;
11428329232eSGordon Ross 
11438329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
11448329232eSGordon Ross 
11458329232eSGordon Ross 	/*
11468329232eSGordon Ross 	 * If this file system doesn't understand the xvattr extensions
11478329232eSGordon Ross 	 * then turn off the xvattr bit.
11488329232eSGordon Ross 	 */
11498329232eSGordon Ross 	if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) {
11508329232eSGordon Ross 		vap->va_mask &= ~AT_XVATTR;
11518329232eSGordon Ross 	}
11528329232eSGordon Ross 
11538329232eSGordon Ross 	/*
11548329232eSGordon Ross 	 * We're only allowed to skip the ACL check iff we used a 32 bit
11558329232eSGordon Ross 	 * ACE mask with VOP_ACCESS() to determine permissions.
11568329232eSGordon Ross 	 */
11578329232eSGordon Ross 	if ((flags & ATTR_NOACLCHECK) &&
11588329232eSGordon Ross 	    vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) {
11598329232eSGordon Ross 		return (EINVAL);
11608329232eSGordon Ross 	}
11618329232eSGordon Ross 	err = (*(vp)->v_op->vop_getattr)(vp, vap, flags, cr, ct);
11628329232eSGordon Ross 	VOPSTATS_UPDATE(vp, getattr);
11638329232eSGordon Ross 	return (err);
11648329232eSGordon Ross }
11658329232eSGordon Ross 
11668329232eSGordon Ross int
fop_setattr(vnode_t * vp,vattr_t * vap,int flags,cred_t * cr,caller_context_t * ct)11678329232eSGordon Ross fop_setattr(
11688329232eSGordon Ross 	vnode_t *vp,
11698329232eSGordon Ross 	vattr_t *vap,
11708329232eSGordon Ross 	int flags,
11718329232eSGordon Ross 	cred_t *cr,
11728329232eSGordon Ross 	caller_context_t *ct)
11738329232eSGordon Ross {
11748329232eSGordon Ross 	int	err;
11758329232eSGordon Ross 
11768329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
11778329232eSGordon Ross 
11788329232eSGordon Ross 	/*
11798329232eSGordon Ross 	 * If this file system doesn't understand the xvattr extensions
11808329232eSGordon Ross 	 * then turn off the xvattr bit.
11818329232eSGordon Ross 	 */
11828329232eSGordon Ross 	if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) {
11838329232eSGordon Ross 		vap->va_mask &= ~AT_XVATTR;
11848329232eSGordon Ross 	}
11858329232eSGordon Ross 
11868329232eSGordon Ross 	/*
11878329232eSGordon Ross 	 * We're only allowed to skip the ACL check iff we used a 32 bit
11888329232eSGordon Ross 	 * ACE mask with VOP_ACCESS() to determine permissions.
11898329232eSGordon Ross 	 */
11908329232eSGordon Ross 	if ((flags & ATTR_NOACLCHECK) &&
11918329232eSGordon Ross 	    vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) {
11928329232eSGordon Ross 		return (EINVAL);
11938329232eSGordon Ross 	}
11948329232eSGordon Ross 	err = (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct);
11958329232eSGordon Ross 	VOPSTATS_UPDATE(vp, setattr);
11968329232eSGordon Ross 	return (err);
11978329232eSGordon Ross }
11988329232eSGordon Ross 
11998329232eSGordon Ross int
fop_access(vnode_t * vp,int mode,int flags,cred_t * cr,caller_context_t * ct)12008329232eSGordon Ross fop_access(
12018329232eSGordon Ross 	vnode_t *vp,
12028329232eSGordon Ross 	int mode,
12038329232eSGordon Ross 	int flags,
12048329232eSGordon Ross 	cred_t *cr,
12058329232eSGordon Ross 	caller_context_t *ct)
12068329232eSGordon Ross {
12078329232eSGordon Ross 	int	err;
12088329232eSGordon Ross 
12098329232eSGordon Ross 	if ((flags & V_ACE_MASK) &&
12108329232eSGordon Ross 	    vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) {
12118329232eSGordon Ross 		return (EINVAL);
12128329232eSGordon Ross 	}
12138329232eSGordon Ross 
12148329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
12158329232eSGordon Ross 
12168329232eSGordon Ross 	err = (*(vp)->v_op->vop_access)(vp, mode, flags, cr, ct);
12178329232eSGordon Ross 	VOPSTATS_UPDATE(vp, access);
12188329232eSGordon Ross 	return (err);
12198329232eSGordon Ross }
12208329232eSGordon Ross 
12218329232eSGordon Ross int
fop_lookup(vnode_t * dvp,char * nm,vnode_t ** vpp,pathname_t * pnp,int flags,vnode_t * rdir,cred_t * cr,caller_context_t * ct,int * deflags,pathname_t * ppnp)12228329232eSGordon Ross fop_lookup(
12238329232eSGordon Ross 	vnode_t *dvp,
12248329232eSGordon Ross 	char *nm,
12258329232eSGordon Ross 	vnode_t **vpp,
12268329232eSGordon Ross 	pathname_t *pnp,
12278329232eSGordon Ross 	int flags,
12288329232eSGordon Ross 	vnode_t *rdir,
12298329232eSGordon Ross 	cred_t *cr,
12308329232eSGordon Ross 	caller_context_t *ct,
12318329232eSGordon Ross 	int *deflags,		/* Returned per-dirent flags */
12328329232eSGordon Ross 	pathname_t *ppnp)	/* Returned case-preserved name in directory */
12338329232eSGordon Ross {
12348329232eSGordon Ross 	int ret;
12358329232eSGordon Ross 
12368329232eSGordon Ross 	/*
12378329232eSGordon Ross 	 * If this file system doesn't support case-insensitive access
12388329232eSGordon Ross 	 * and said access is requested, fail quickly.  It is required
12398329232eSGordon Ross 	 * that if the vfs supports case-insensitive lookup, it also
12408329232eSGordon Ross 	 * supports extended dirent flags.
12418329232eSGordon Ross 	 */
12428329232eSGordon Ross 	if (flags & FIGNORECASE &&
12438329232eSGordon Ross 	    (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
12448329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
12458329232eSGordon Ross 		return (EINVAL);
12468329232eSGordon Ross 
12478329232eSGordon Ross 	VOPXID_MAP_CR(dvp, cr);
12488329232eSGordon Ross 
12498329232eSGordon Ross 	/*
12508329232eSGordon Ross 	 * The real vnode.c would call xattr_dir_lookup here,
12518329232eSGordon Ross 	 * which inserts the special "System Attribute" files:
12528329232eSGordon Ross 	 * (SUNWattr_rw, SUNWattr_ro) into the xattr list.
12538329232eSGordon Ross 	 * Here the main focus is on testing xattr support,
12548329232eSGordon Ross 	 * so the system attribute stuff is ommitted.
12558329232eSGordon Ross 	 */
12568329232eSGordon Ross #if 0
12578329232eSGordon Ross 	if ((flags & LOOKUP_XATTR) && (flags & LOOKUP_HAVE_SYSATTR_DIR) == 0) {
12588329232eSGordon Ross 		// Don't need xattr support in libfksmbfs.
12598329232eSGordon Ross 		// ret = xattr_dir_lookup(dvp, vpp, flags, cr);
12608329232eSGordon Ross 		ret = EINVAL;
12618329232eSGordon Ross 	} else
12628329232eSGordon Ross #endif
12638329232eSGordon Ross 	{
12648329232eSGordon Ross 		ret = (*(dvp)->v_op->vop_lookup)
12658329232eSGordon Ross 		    (dvp, nm, vpp, pnp, flags, rdir, cr, ct, deflags, ppnp);
12668329232eSGordon Ross 	}
12678329232eSGordon Ross 	if (ret == 0 && *vpp) {
12688329232eSGordon Ross 		VOPSTATS_UPDATE(*vpp, lookup);
12698329232eSGordon Ross 		vn_updatepath(dvp, *vpp, nm);
12708329232eSGordon Ross 	}
12718329232eSGordon Ross 
12728329232eSGordon Ross 	return (ret);
12738329232eSGordon Ross }
12748329232eSGordon Ross 
12758329232eSGordon Ross int
fop_create(vnode_t * dvp,char * name,vattr_t * vap,vcexcl_t excl,int mode,vnode_t ** vpp,cred_t * cr,int flags,caller_context_t * ct,vsecattr_t * vsecp)12768329232eSGordon Ross fop_create(
12778329232eSGordon Ross 	vnode_t *dvp,
12788329232eSGordon Ross 	char *name,
12798329232eSGordon Ross 	vattr_t *vap,
12808329232eSGordon Ross 	vcexcl_t excl,
12818329232eSGordon Ross 	int mode,
12828329232eSGordon Ross 	vnode_t **vpp,
12838329232eSGordon Ross 	cred_t *cr,
12848329232eSGordon Ross 	int flags,
12858329232eSGordon Ross 	caller_context_t *ct,
12868329232eSGordon Ross 	vsecattr_t *vsecp)	/* ACL to set during create */
12878329232eSGordon Ross {
12888329232eSGordon Ross 	int ret;
12898329232eSGordon Ross 
12908329232eSGordon Ross 	if (vsecp != NULL &&
12918329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) {
12928329232eSGordon Ross 		return (EINVAL);
12938329232eSGordon Ross 	}
12948329232eSGordon Ross 	/*
12958329232eSGordon Ross 	 * If this file system doesn't support case-insensitive access
12968329232eSGordon Ross 	 * and said access is requested, fail quickly.
12978329232eSGordon Ross 	 */
12988329232eSGordon Ross 	if (flags & FIGNORECASE &&
12998329232eSGordon Ross 	    (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
13008329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
13018329232eSGordon Ross 		return (EINVAL);
13028329232eSGordon Ross 
13038329232eSGordon Ross 	VOPXID_MAP_CR(dvp, cr);
13048329232eSGordon Ross 
13058329232eSGordon Ross 	ret = (*(dvp)->v_op->vop_create)
13068329232eSGordon Ross 	    (dvp, name, vap, excl, mode, vpp, cr, flags, ct, vsecp);
13078329232eSGordon Ross 	if (ret == 0 && *vpp) {
13088329232eSGordon Ross 		VOPSTATS_UPDATE(*vpp, create);
13098329232eSGordon Ross 		vn_updatepath(dvp, *vpp, name);
13108329232eSGordon Ross 	}
13118329232eSGordon Ross 
13128329232eSGordon Ross 	return (ret);
13138329232eSGordon Ross }
13148329232eSGordon Ross 
13158329232eSGordon Ross int
fop_remove(vnode_t * dvp,char * nm,cred_t * cr,caller_context_t * ct,int flags)13168329232eSGordon Ross fop_remove(
13178329232eSGordon Ross 	vnode_t *dvp,
13188329232eSGordon Ross 	char *nm,
13198329232eSGordon Ross 	cred_t *cr,
13208329232eSGordon Ross 	caller_context_t *ct,
13218329232eSGordon Ross 	int flags)
13228329232eSGordon Ross {
13238329232eSGordon Ross 	int	err;
13248329232eSGordon Ross 
13258329232eSGordon Ross 	/*
13268329232eSGordon Ross 	 * If this file system doesn't support case-insensitive access
13278329232eSGordon Ross 	 * and said access is requested, fail quickly.
13288329232eSGordon Ross 	 */
13298329232eSGordon Ross 	if (flags & FIGNORECASE &&
13308329232eSGordon Ross 	    (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
13318329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
13328329232eSGordon Ross 		return (EINVAL);
13338329232eSGordon Ross 
13348329232eSGordon Ross 	VOPXID_MAP_CR(dvp, cr);
13358329232eSGordon Ross 
13368329232eSGordon Ross 	err = (*(dvp)->v_op->vop_remove)(dvp, nm, cr, ct, flags);
13378329232eSGordon Ross 	VOPSTATS_UPDATE(dvp, remove);
13388329232eSGordon Ross 	return (err);
13398329232eSGordon Ross }
13408329232eSGordon Ross 
13418329232eSGordon Ross int
fop_link(vnode_t * tdvp,vnode_t * svp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)13428329232eSGordon Ross fop_link(
13438329232eSGordon Ross 	vnode_t *tdvp,
13448329232eSGordon Ross 	vnode_t *svp,
13458329232eSGordon Ross 	char *tnm,
13468329232eSGordon Ross 	cred_t *cr,
13478329232eSGordon Ross 	caller_context_t *ct,
13488329232eSGordon Ross 	int flags)
13498329232eSGordon Ross {
13508329232eSGordon Ross 	int	err;
13518329232eSGordon Ross 
13528329232eSGordon Ross 	/*
13538329232eSGordon Ross 	 * If the target file system doesn't support case-insensitive access
13548329232eSGordon Ross 	 * and said access is requested, fail quickly.
13558329232eSGordon Ross 	 */
13568329232eSGordon Ross 	if (flags & FIGNORECASE &&
13578329232eSGordon Ross 	    (vfs_has_feature(tdvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
13588329232eSGordon Ross 	    vfs_has_feature(tdvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
13598329232eSGordon Ross 		return (EINVAL);
13608329232eSGordon Ross 
13618329232eSGordon Ross 	VOPXID_MAP_CR(tdvp, cr);
13628329232eSGordon Ross 
13638329232eSGordon Ross 	err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr, ct, flags);
13648329232eSGordon Ross 	VOPSTATS_UPDATE(tdvp, link);
13658329232eSGordon Ross 	return (err);
13668329232eSGordon Ross }
13678329232eSGordon Ross 
13688329232eSGordon Ross int
fop_rename(vnode_t * sdvp,char * snm,vnode_t * tdvp,char * tnm,cred_t * cr,caller_context_t * ct,int flags)13698329232eSGordon Ross fop_rename(
13708329232eSGordon Ross 	vnode_t *sdvp,
13718329232eSGordon Ross 	char *snm,
13728329232eSGordon Ross 	vnode_t *tdvp,
13738329232eSGordon Ross 	char *tnm,
13748329232eSGordon Ross 	cred_t *cr,
13758329232eSGordon Ross 	caller_context_t *ct,
13768329232eSGordon Ross 	int flags)
13778329232eSGordon Ross {
13788329232eSGordon Ross 	int	err;
13798329232eSGordon Ross 
13808329232eSGordon Ross 	/*
13818329232eSGordon Ross 	 * If the file system involved does not support
13828329232eSGordon Ross 	 * case-insensitive access and said access is requested, fail
13838329232eSGordon Ross 	 * quickly.
13848329232eSGordon Ross 	 */
13858329232eSGordon Ross 	if (flags & FIGNORECASE &&
13868329232eSGordon Ross 	    ((vfs_has_feature(sdvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
13878329232eSGordon Ross 	    vfs_has_feature(sdvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)))
13888329232eSGordon Ross 		return (EINVAL);
13898329232eSGordon Ross 
13908329232eSGordon Ross 	VOPXID_MAP_CR(tdvp, cr);
13918329232eSGordon Ross 
13928329232eSGordon Ross 	err = (*(sdvp)->v_op->vop_rename)(sdvp, snm, tdvp, tnm, cr, ct, flags);
13938329232eSGordon Ross 	VOPSTATS_UPDATE(sdvp, rename);
13948329232eSGordon Ross 	return (err);
13958329232eSGordon Ross }
13968329232eSGordon Ross 
13978329232eSGordon Ross int
fop_mkdir(vnode_t * dvp,char * dirname,vattr_t * vap,vnode_t ** vpp,cred_t * cr,caller_context_t * ct,int flags,vsecattr_t * vsecp)13988329232eSGordon Ross fop_mkdir(
13998329232eSGordon Ross 	vnode_t *dvp,
14008329232eSGordon Ross 	char *dirname,
14018329232eSGordon Ross 	vattr_t *vap,
14028329232eSGordon Ross 	vnode_t **vpp,
14038329232eSGordon Ross 	cred_t *cr,
14048329232eSGordon Ross 	caller_context_t *ct,
14058329232eSGordon Ross 	int flags,
14068329232eSGordon Ross 	vsecattr_t *vsecp)	/* ACL to set during create */
14078329232eSGordon Ross {
14088329232eSGordon Ross 	int ret;
14098329232eSGordon Ross 
14108329232eSGordon Ross 	if (vsecp != NULL &&
14118329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) {
14128329232eSGordon Ross 		return (EINVAL);
14138329232eSGordon Ross 	}
14148329232eSGordon Ross 	/*
14158329232eSGordon Ross 	 * If this file system doesn't support case-insensitive access
14168329232eSGordon Ross 	 * and said access is requested, fail quickly.
14178329232eSGordon Ross 	 */
14188329232eSGordon Ross 	if (flags & FIGNORECASE &&
14198329232eSGordon Ross 	    (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
14208329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
14218329232eSGordon Ross 		return (EINVAL);
14228329232eSGordon Ross 
14238329232eSGordon Ross 	VOPXID_MAP_CR(dvp, cr);
14248329232eSGordon Ross 
14258329232eSGordon Ross 	ret = (*(dvp)->v_op->vop_mkdir)
14268329232eSGordon Ross 	    (dvp, dirname, vap, vpp, cr, ct, flags, vsecp);
14278329232eSGordon Ross 	if (ret == 0 && *vpp) {
14288329232eSGordon Ross 		VOPSTATS_UPDATE(*vpp, mkdir);
14298329232eSGordon Ross 		vn_updatepath(dvp, *vpp, dirname);
14308329232eSGordon Ross 	}
14318329232eSGordon Ross 
14328329232eSGordon Ross 	return (ret);
14338329232eSGordon Ross }
14348329232eSGordon Ross 
14358329232eSGordon Ross int
fop_rmdir(vnode_t * dvp,char * nm,vnode_t * cdir,cred_t * cr,caller_context_t * ct,int flags)14368329232eSGordon Ross fop_rmdir(
14378329232eSGordon Ross 	vnode_t *dvp,
14388329232eSGordon Ross 	char *nm,
14398329232eSGordon Ross 	vnode_t *cdir,
14408329232eSGordon Ross 	cred_t *cr,
14418329232eSGordon Ross 	caller_context_t *ct,
14428329232eSGordon Ross 	int flags)
14438329232eSGordon Ross {
14448329232eSGordon Ross 	int	err;
14458329232eSGordon Ross 
14468329232eSGordon Ross 	/*
14478329232eSGordon Ross 	 * If this file system doesn't support case-insensitive access
14488329232eSGordon Ross 	 * and said access is requested, fail quickly.
14498329232eSGordon Ross 	 */
14508329232eSGordon Ross 	if (flags & FIGNORECASE &&
14518329232eSGordon Ross 	    (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
14528329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
14538329232eSGordon Ross 		return (EINVAL);
14548329232eSGordon Ross 
14558329232eSGordon Ross 	VOPXID_MAP_CR(dvp, cr);
14568329232eSGordon Ross 
14578329232eSGordon Ross 	err = (*(dvp)->v_op->vop_rmdir)(dvp, nm, cdir, cr, ct, flags);
14588329232eSGordon Ross 	VOPSTATS_UPDATE(dvp, rmdir);
14598329232eSGordon Ross 	return (err);
14608329232eSGordon Ross }
14618329232eSGordon Ross 
14628329232eSGordon Ross int
fop_readdir(vnode_t * vp,uio_t * uiop,cred_t * cr,int * eofp,caller_context_t * ct,int flags)14638329232eSGordon Ross fop_readdir(
14648329232eSGordon Ross 	vnode_t *vp,
14658329232eSGordon Ross 	uio_t *uiop,
14668329232eSGordon Ross 	cred_t *cr,
14678329232eSGordon Ross 	int *eofp,
14688329232eSGordon Ross 	caller_context_t *ct,
14698329232eSGordon Ross 	int flags)
14708329232eSGordon Ross {
14718329232eSGordon Ross 	int	err;
14728329232eSGordon Ross 	ssize_t	resid_start = uiop->uio_resid;
14738329232eSGordon Ross 
14748329232eSGordon Ross 	/*
14758329232eSGordon Ross 	 * If this file system doesn't support retrieving directory
14768329232eSGordon Ross 	 * entry flags and said access is requested, fail quickly.
14778329232eSGordon Ross 	 */
14788329232eSGordon Ross 	if (flags & V_RDDIR_ENTFLAGS &&
14798329232eSGordon Ross 	    vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS) == 0)
14808329232eSGordon Ross 		return (EINVAL);
14818329232eSGordon Ross 
14828329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
14838329232eSGordon Ross 
14848329232eSGordon Ross 	err = (*(vp)->v_op->vop_readdir)(vp, uiop, cr, eofp, ct, flags);
14858329232eSGordon Ross 	VOPSTATS_UPDATE_IO(vp, readdir,
14868329232eSGordon Ross 	    readdir_bytes, (resid_start - uiop->uio_resid));
14878329232eSGordon Ross 	return (err);
14888329232eSGordon Ross }
14898329232eSGordon Ross 
14908329232eSGordon Ross int
fop_symlink(vnode_t * dvp,char * linkname,vattr_t * vap,char * target,cred_t * cr,caller_context_t * ct,int flags)14918329232eSGordon Ross fop_symlink(
14928329232eSGordon Ross 	vnode_t *dvp,
14938329232eSGordon Ross 	char *linkname,
14948329232eSGordon Ross 	vattr_t *vap,
14958329232eSGordon Ross 	char *target,
14968329232eSGordon Ross 	cred_t *cr,
14978329232eSGordon Ross 	caller_context_t *ct,
14988329232eSGordon Ross 	int flags)
14998329232eSGordon Ross {
15008329232eSGordon Ross 	int	err;
15018329232eSGordon Ross 	xvattr_t xvattr;
15028329232eSGordon Ross 
15038329232eSGordon Ross 	/*
15048329232eSGordon Ross 	 * If this file system doesn't support case-insensitive access
15058329232eSGordon Ross 	 * and said access is requested, fail quickly.
15068329232eSGordon Ross 	 */
15078329232eSGordon Ross 	if (flags & FIGNORECASE &&
15088329232eSGordon Ross 	    (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 &&
15098329232eSGordon Ross 	    vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))
15108329232eSGordon Ross 		return (EINVAL);
15118329232eSGordon Ross 
15128329232eSGordon Ross 	VOPXID_MAP_CR(dvp, cr);
15138329232eSGordon Ross 
15148329232eSGordon Ross 	/* check for reparse point */
15158329232eSGordon Ross 	if ((vfs_has_feature(dvp->v_vfsp, VFSFT_REPARSE)) &&
15168329232eSGordon Ross 	    (strncmp(target, FS_REPARSE_TAG_STR,
15178329232eSGordon Ross 	    strlen(FS_REPARSE_TAG_STR)) == 0)) {
15188329232eSGordon Ross 		if (!fs_reparse_mark(target, vap, &xvattr))
15198329232eSGordon Ross 			vap = (vattr_t *)&xvattr;
15208329232eSGordon Ross 	}
15218329232eSGordon Ross 
15228329232eSGordon Ross 	err = (*(dvp)->v_op->vop_symlink)
15238329232eSGordon Ross 	    (dvp, linkname, vap, target, cr, ct, flags);
15248329232eSGordon Ross 	VOPSTATS_UPDATE(dvp, symlink);
15258329232eSGordon Ross 	return (err);
15268329232eSGordon Ross }
15278329232eSGordon Ross 
15288329232eSGordon Ross int
fop_readlink(vnode_t * vp,uio_t * uiop,cred_t * cr,caller_context_t * ct)15298329232eSGordon Ross fop_readlink(
15308329232eSGordon Ross 	vnode_t *vp,
15318329232eSGordon Ross 	uio_t *uiop,
15328329232eSGordon Ross 	cred_t *cr,
15338329232eSGordon Ross 	caller_context_t *ct)
15348329232eSGordon Ross {
15358329232eSGordon Ross 	int	err;
15368329232eSGordon Ross 
15378329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
15388329232eSGordon Ross 
15398329232eSGordon Ross 	err = (*(vp)->v_op->vop_readlink)(vp, uiop, cr, ct);
15408329232eSGordon Ross 	VOPSTATS_UPDATE(vp, readlink);
15418329232eSGordon Ross 	return (err);
15428329232eSGordon Ross }
15438329232eSGordon Ross 
15448329232eSGordon Ross int
fop_fsync(vnode_t * vp,int syncflag,cred_t * cr,caller_context_t * ct)15458329232eSGordon Ross fop_fsync(
15468329232eSGordon Ross 	vnode_t *vp,
15478329232eSGordon Ross 	int syncflag,
15488329232eSGordon Ross 	cred_t *cr,
15498329232eSGordon Ross 	caller_context_t *ct)
15508329232eSGordon Ross {
15518329232eSGordon Ross 	int	err;
15528329232eSGordon Ross 
15538329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
15548329232eSGordon Ross 
15558329232eSGordon Ross 	err = (*(vp)->v_op->vop_fsync)(vp, syncflag, cr, ct);
15568329232eSGordon Ross 	VOPSTATS_UPDATE(vp, fsync);
15578329232eSGordon Ross 	return (err);
15588329232eSGordon Ross }
15598329232eSGordon Ross 
15608329232eSGordon Ross void
fop_inactive(vnode_t * vp,cred_t * cr,caller_context_t * ct)15618329232eSGordon Ross fop_inactive(
15628329232eSGordon Ross 	vnode_t *vp,
15638329232eSGordon Ross 	cred_t *cr,
15648329232eSGordon Ross 	caller_context_t *ct)
15658329232eSGordon Ross {
15668329232eSGordon Ross 	/* Need to update stats before vop call since we may lose the vnode */
15678329232eSGordon Ross 	VOPSTATS_UPDATE(vp, inactive);
15688329232eSGordon Ross 
15698329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
15708329232eSGordon Ross 
15718329232eSGordon Ross 	(*(vp)->v_op->vop_inactive)(vp, cr, ct);
15728329232eSGordon Ross }
15738329232eSGordon Ross 
15748329232eSGordon Ross int
fop_fid(vnode_t * vp,fid_t * fidp,caller_context_t * ct)15758329232eSGordon Ross fop_fid(
15768329232eSGordon Ross 	vnode_t *vp,
15778329232eSGordon Ross 	fid_t *fidp,
15788329232eSGordon Ross 	caller_context_t *ct)
15798329232eSGordon Ross {
15808329232eSGordon Ross 	int	err;
15818329232eSGordon Ross 
15828329232eSGordon Ross 	err = (*(vp)->v_op->vop_fid)(vp, fidp, ct);
15838329232eSGordon Ross 	VOPSTATS_UPDATE(vp, fid);
15848329232eSGordon Ross 	return (err);
15858329232eSGordon Ross }
15868329232eSGordon Ross 
15878329232eSGordon Ross int
fop_rwlock(vnode_t * vp,int write_lock,caller_context_t * ct)15888329232eSGordon Ross fop_rwlock(
15898329232eSGordon Ross 	vnode_t *vp,
15908329232eSGordon Ross 	int write_lock,
15918329232eSGordon Ross 	caller_context_t *ct)
15928329232eSGordon Ross {
15938329232eSGordon Ross 	int	ret;
15948329232eSGordon Ross 
15958329232eSGordon Ross 	ret = ((*(vp)->v_op->vop_rwlock)(vp, write_lock, ct));
15968329232eSGordon Ross 	VOPSTATS_UPDATE(vp, rwlock);
15978329232eSGordon Ross 	return (ret);
15988329232eSGordon Ross }
15998329232eSGordon Ross 
16008329232eSGordon Ross void
fop_rwunlock(vnode_t * vp,int write_lock,caller_context_t * ct)16018329232eSGordon Ross fop_rwunlock(
16028329232eSGordon Ross 	vnode_t *vp,
16038329232eSGordon Ross 	int write_lock,
16048329232eSGordon Ross 	caller_context_t *ct)
16058329232eSGordon Ross {
16068329232eSGordon Ross 	(*(vp)->v_op->vop_rwunlock)(vp, write_lock, ct);
16078329232eSGordon Ross 	VOPSTATS_UPDATE(vp, rwunlock);
16088329232eSGordon Ross }
16098329232eSGordon Ross 
16108329232eSGordon Ross int
fop_seek(vnode_t * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)16118329232eSGordon Ross fop_seek(
16128329232eSGordon Ross 	vnode_t *vp,
16138329232eSGordon Ross 	offset_t ooff,
16148329232eSGordon Ross 	offset_t *noffp,
16158329232eSGordon Ross 	caller_context_t *ct)
16168329232eSGordon Ross {
16178329232eSGordon Ross 	int	err;
16188329232eSGordon Ross 
16198329232eSGordon Ross 	err = (*(vp)->v_op->vop_seek)(vp, ooff, noffp, ct);
16208329232eSGordon Ross 	VOPSTATS_UPDATE(vp, seek);
16218329232eSGordon Ross 	return (err);
16228329232eSGordon Ross }
16238329232eSGordon Ross 
16248329232eSGordon Ross int
fop_cmp(vnode_t * vp1,vnode_t * vp2,caller_context_t * ct)16258329232eSGordon Ross fop_cmp(
16268329232eSGordon Ross 	vnode_t *vp1,
16278329232eSGordon Ross 	vnode_t *vp2,
16288329232eSGordon Ross 	caller_context_t *ct)
16298329232eSGordon Ross {
16308329232eSGordon Ross 	int	err;
16318329232eSGordon Ross 
16328329232eSGordon Ross 	err = (*(vp1)->v_op->vop_cmp)(vp1, vp2, ct);
16338329232eSGordon Ross 	VOPSTATS_UPDATE(vp1, cmp);
16348329232eSGordon Ross 	return (err);
16358329232eSGordon Ross }
16368329232eSGordon Ross 
16378329232eSGordon Ross int
fop_frlock(vnode_t * vp,int cmd,flock64_t * bfp,int flag,offset_t offset,struct flk_callback * flk_cbp,cred_t * cr,caller_context_t * ct)16388329232eSGordon Ross fop_frlock(
16398329232eSGordon Ross 	vnode_t *vp,
16408329232eSGordon Ross 	int cmd,
16418329232eSGordon Ross 	flock64_t *bfp,
16428329232eSGordon Ross 	int flag,
16438329232eSGordon Ross 	offset_t offset,
16448329232eSGordon Ross 	struct flk_callback *flk_cbp,
16458329232eSGordon Ross 	cred_t *cr,
16468329232eSGordon Ross 	caller_context_t *ct)
16478329232eSGordon Ross {
16488329232eSGordon Ross 	int	err;
16498329232eSGordon Ross 
16508329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
16518329232eSGordon Ross 
16528329232eSGordon Ross 	err = (*(vp)->v_op->vop_frlock)
16538329232eSGordon Ross 	    (vp, cmd, bfp, flag, offset, flk_cbp, cr, ct);
16548329232eSGordon Ross 	VOPSTATS_UPDATE(vp, frlock);
16558329232eSGordon Ross 	return (err);
16568329232eSGordon Ross }
16578329232eSGordon Ross 
16588329232eSGordon Ross int
fop_space(vnode_t * vp,int cmd,flock64_t * bfp,int flag,offset_t offset,cred_t * cr,caller_context_t * ct)16598329232eSGordon Ross fop_space(
16608329232eSGordon Ross 	vnode_t *vp,
16618329232eSGordon Ross 	int cmd,
16628329232eSGordon Ross 	flock64_t *bfp,
16638329232eSGordon Ross 	int flag,
16648329232eSGordon Ross 	offset_t offset,
16658329232eSGordon Ross 	cred_t *cr,
16668329232eSGordon Ross 	caller_context_t *ct)
16678329232eSGordon Ross {
16688329232eSGordon Ross 	int	err;
16698329232eSGordon Ross 
16708329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
16718329232eSGordon Ross 
16728329232eSGordon Ross 	err = (*(vp)->v_op->vop_space)(vp, cmd, bfp, flag, offset, cr, ct);
16738329232eSGordon Ross 	VOPSTATS_UPDATE(vp, space);
16748329232eSGordon Ross 	return (err);
16758329232eSGordon Ross }
16768329232eSGordon Ross 
16778329232eSGordon Ross int
fop_realvp(vnode_t * vp,vnode_t ** vpp,caller_context_t * ct)16788329232eSGordon Ross fop_realvp(
16798329232eSGordon Ross 	vnode_t *vp,
16808329232eSGordon Ross 	vnode_t **vpp,
16818329232eSGordon Ross 	caller_context_t *ct)
16828329232eSGordon Ross {
16838329232eSGordon Ross 	int	err;
16848329232eSGordon Ross 
16858329232eSGordon Ross 	err = (*(vp)->v_op->vop_realvp)(vp, vpp, ct);
16868329232eSGordon Ross 	VOPSTATS_UPDATE(vp, realvp);
16878329232eSGordon Ross 	return (err);
16888329232eSGordon Ross }
16898329232eSGordon Ross 
16908329232eSGordon Ross int
fop_getpage(vnode_t * vp,offset_t off,size_t len,uint_t * protp,page_t ** plarr,size_t plsz,struct seg * seg,caddr_t addr,enum seg_rw rw,cred_t * cr,caller_context_t * ct)16918329232eSGordon Ross fop_getpage(
16928329232eSGordon Ross 	vnode_t *vp,
16938329232eSGordon Ross 	offset_t off,
16948329232eSGordon Ross 	size_t len,
16958329232eSGordon Ross 	uint_t *protp,
16968329232eSGordon Ross 	page_t **plarr,
16978329232eSGordon Ross 	size_t plsz,
16988329232eSGordon Ross 	struct seg *seg,
16998329232eSGordon Ross 	caddr_t addr,
17008329232eSGordon Ross 	enum seg_rw rw,
17018329232eSGordon Ross 	cred_t *cr,
17028329232eSGordon Ross 	caller_context_t *ct)
17038329232eSGordon Ross {
17048329232eSGordon Ross 	int	err;
17058329232eSGordon Ross 
17068329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
17078329232eSGordon Ross 
17088329232eSGordon Ross 	err = (*(vp)->v_op->vop_getpage)
17098329232eSGordon Ross 	    (vp, off, len, protp, plarr, plsz, seg, addr, rw, cr, ct);
17108329232eSGordon Ross 	VOPSTATS_UPDATE(vp, getpage);
17118329232eSGordon Ross 	return (err);
17128329232eSGordon Ross }
17138329232eSGordon Ross 
17148329232eSGordon Ross int
fop_putpage(vnode_t * vp,offset_t off,size_t len,int flags,cred_t * cr,caller_context_t * ct)17158329232eSGordon Ross fop_putpage(
17168329232eSGordon Ross 	vnode_t *vp,
17178329232eSGordon Ross 	offset_t off,
17188329232eSGordon Ross 	size_t len,
17198329232eSGordon Ross 	int flags,
17208329232eSGordon Ross 	cred_t *cr,
17218329232eSGordon Ross 	caller_context_t *ct)
17228329232eSGordon Ross {
17238329232eSGordon Ross 	int	err;
17248329232eSGordon Ross 
17258329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
17268329232eSGordon Ross 
17278329232eSGordon Ross 	err = (*(vp)->v_op->vop_putpage)(vp, off, len, flags, cr, ct);
17288329232eSGordon Ross 	VOPSTATS_UPDATE(vp, putpage);
17298329232eSGordon Ross 	return (err);
17308329232eSGordon Ross }
17318329232eSGordon Ross 
17328329232eSGordon Ross int
fop_map(vnode_t * vp,offset_t off,struct as * as,caddr_t * addrp,size_t len,uchar_t prot,uchar_t maxprot,uint_t flags,cred_t * cr,caller_context_t * ct)17338329232eSGordon Ross fop_map(
17348329232eSGordon Ross 	vnode_t *vp,
17358329232eSGordon Ross 	offset_t off,
17368329232eSGordon Ross 	struct as *as,
17378329232eSGordon Ross 	caddr_t *addrp,
17388329232eSGordon Ross 	size_t len,
17398329232eSGordon Ross 	uchar_t prot,
17408329232eSGordon Ross 	uchar_t maxprot,
17418329232eSGordon Ross 	uint_t flags,
17428329232eSGordon Ross 	cred_t *cr,
17438329232eSGordon Ross 	caller_context_t *ct)
17448329232eSGordon Ross {
17458329232eSGordon Ross 	int	err;
17468329232eSGordon Ross 
17478329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
17488329232eSGordon Ross 
17498329232eSGordon Ross 	err = (*(vp)->v_op->vop_map)
17508329232eSGordon Ross 	    (vp, off, as, addrp, len, prot, maxprot, flags, cr, ct);
17518329232eSGordon Ross 	VOPSTATS_UPDATE(vp, map);
17528329232eSGordon Ross 	return (err);
17538329232eSGordon Ross }
17548329232eSGordon Ross 
17558329232eSGordon Ross int
fop_addmap(vnode_t * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uchar_t prot,uchar_t maxprot,uint_t flags,cred_t * cr,caller_context_t * ct)17568329232eSGordon Ross fop_addmap(
17578329232eSGordon Ross 	vnode_t *vp,
17588329232eSGordon Ross 	offset_t off,
17598329232eSGordon Ross 	struct as *as,
17608329232eSGordon Ross 	caddr_t addr,
17618329232eSGordon Ross 	size_t len,
17628329232eSGordon Ross 	uchar_t prot,
17638329232eSGordon Ross 	uchar_t maxprot,
17648329232eSGordon Ross 	uint_t flags,
17658329232eSGordon Ross 	cred_t *cr,
17668329232eSGordon Ross 	caller_context_t *ct)
17678329232eSGordon Ross {
17688329232eSGordon Ross 	int error;
17698329232eSGordon Ross 
17708329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
17718329232eSGordon Ross 
17728329232eSGordon Ross 	error = (*(vp)->v_op->vop_addmap)
17738329232eSGordon Ross 	    (vp, off, as, addr, len, prot, maxprot, flags, cr, ct);
17748329232eSGordon Ross 
17758329232eSGordon Ross 	VOPSTATS_UPDATE(vp, addmap);
17768329232eSGordon Ross 	return (error);
17778329232eSGordon Ross }
17788329232eSGordon Ross 
17798329232eSGordon Ross int
fop_delmap(vnode_t * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uint_t prot,uint_t maxprot,uint_t flags,cred_t * cr,caller_context_t * ct)17808329232eSGordon Ross fop_delmap(
17818329232eSGordon Ross 	vnode_t *vp,
17828329232eSGordon Ross 	offset_t off,
17838329232eSGordon Ross 	struct as *as,
17848329232eSGordon Ross 	caddr_t addr,
17858329232eSGordon Ross 	size_t len,
17868329232eSGordon Ross 	uint_t prot,
17878329232eSGordon Ross 	uint_t maxprot,
17888329232eSGordon Ross 	uint_t flags,
17898329232eSGordon Ross 	cred_t *cr,
17908329232eSGordon Ross 	caller_context_t *ct)
17918329232eSGordon Ross {
17928329232eSGordon Ross 	int error;
17938329232eSGordon Ross 
17948329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
17958329232eSGordon Ross 
17968329232eSGordon Ross 	error = (*(vp)->v_op->vop_delmap)
17978329232eSGordon Ross 	    (vp, off, as, addr, len, prot, maxprot, flags, cr, ct);
17988329232eSGordon Ross 
17998329232eSGordon Ross 	VOPSTATS_UPDATE(vp, delmap);
18008329232eSGordon Ross 	return (error);
18018329232eSGordon Ross }
18028329232eSGordon Ross 
18038329232eSGordon Ross 
18048329232eSGordon Ross int
fop_poll(vnode_t * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)18058329232eSGordon Ross fop_poll(
18068329232eSGordon Ross 	vnode_t *vp,
18078329232eSGordon Ross 	short events,
18088329232eSGordon Ross 	int anyyet,
18098329232eSGordon Ross 	short *reventsp,
18108329232eSGordon Ross 	struct pollhead **phpp,
18118329232eSGordon Ross 	caller_context_t *ct)
18128329232eSGordon Ross {
18138329232eSGordon Ross 	int	err;
18148329232eSGordon Ross 
18158329232eSGordon Ross 	err = (*(vp)->v_op->vop_poll)(vp, events, anyyet, reventsp, phpp, ct);
18168329232eSGordon Ross 	VOPSTATS_UPDATE(vp, poll);
18178329232eSGordon Ross 	return (err);
18188329232eSGordon Ross }
18198329232eSGordon Ross 
18208329232eSGordon Ross int
fop_dump(vnode_t * vp,caddr_t addr,offset_t lbdn,offset_t dblks,caller_context_t * ct)18218329232eSGordon Ross fop_dump(
18228329232eSGordon Ross 	vnode_t *vp,
18238329232eSGordon Ross 	caddr_t addr,
18248329232eSGordon Ross 	offset_t lbdn,
18258329232eSGordon Ross 	offset_t dblks,
18268329232eSGordon Ross 	caller_context_t *ct)
18278329232eSGordon Ross {
18288329232eSGordon Ross 	int	err;
18298329232eSGordon Ross 
18308329232eSGordon Ross 	/* ensure lbdn and dblks can be passed safely to bdev_dump */
18318329232eSGordon Ross 	if ((lbdn != (daddr_t)lbdn) || (dblks != (int)dblks))
18328329232eSGordon Ross 		return (EIO);
18338329232eSGordon Ross 
18348329232eSGordon Ross 	err = (*(vp)->v_op->vop_dump)(vp, addr, lbdn, dblks, ct);
18358329232eSGordon Ross 	VOPSTATS_UPDATE(vp, dump);
18368329232eSGordon Ross 	return (err);
18378329232eSGordon Ross }
18388329232eSGordon Ross 
18398329232eSGordon Ross int
fop_pathconf(vnode_t * vp,int cmd,ulong_t * valp,cred_t * cr,caller_context_t * ct)18408329232eSGordon Ross fop_pathconf(
18418329232eSGordon Ross 	vnode_t *vp,
18428329232eSGordon Ross 	int cmd,
18438329232eSGordon Ross 	ulong_t *valp,
18448329232eSGordon Ross 	cred_t *cr,
18458329232eSGordon Ross 	caller_context_t *ct)
18468329232eSGordon Ross {
18478329232eSGordon Ross 	int	err;
18488329232eSGordon Ross 
18498329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
18508329232eSGordon Ross 
18518329232eSGordon Ross 	err = (*(vp)->v_op->vop_pathconf)(vp, cmd, valp, cr, ct);
18528329232eSGordon Ross 	VOPSTATS_UPDATE(vp, pathconf);
18538329232eSGordon Ross 	return (err);
18548329232eSGordon Ross }
18558329232eSGordon Ross 
18568329232eSGordon Ross int
fop_pageio(vnode_t * vp,struct page * pp,u_offset_t io_off,size_t io_len,int flags,cred_t * cr,caller_context_t * ct)18578329232eSGordon Ross fop_pageio(
18588329232eSGordon Ross 	vnode_t *vp,
18598329232eSGordon Ross 	struct page *pp,
18608329232eSGordon Ross 	u_offset_t io_off,
18618329232eSGordon Ross 	size_t io_len,
18628329232eSGordon Ross 	int flags,
18638329232eSGordon Ross 	cred_t *cr,
18648329232eSGordon Ross 	caller_context_t *ct)
18658329232eSGordon Ross {
18668329232eSGordon Ross 	int	err;
18678329232eSGordon Ross 
18688329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
18698329232eSGordon Ross 
18708329232eSGordon Ross 	err = (*(vp)->v_op->vop_pageio)(vp, pp, io_off, io_len, flags, cr, ct);
18718329232eSGordon Ross 	VOPSTATS_UPDATE(vp, pageio);
18728329232eSGordon Ross 	return (err);
18738329232eSGordon Ross }
18748329232eSGordon Ross 
18758329232eSGordon Ross int
fop_dumpctl(vnode_t * vp,int action,offset_t * blkp,caller_context_t * ct)18768329232eSGordon Ross fop_dumpctl(
18778329232eSGordon Ross 	vnode_t *vp,
18788329232eSGordon Ross 	int action,
18798329232eSGordon Ross 	offset_t *blkp,
18808329232eSGordon Ross 	caller_context_t *ct)
18818329232eSGordon Ross {
18828329232eSGordon Ross 	int	err;
18838329232eSGordon Ross 	err = (*(vp)->v_op->vop_dumpctl)(vp, action, blkp, ct);
18848329232eSGordon Ross 	VOPSTATS_UPDATE(vp, dumpctl);
18858329232eSGordon Ross 	return (err);
18868329232eSGordon Ross }
18878329232eSGordon Ross 
18888329232eSGordon Ross void
fop_dispose(vnode_t * vp,page_t * pp,int flag,int dn,cred_t * cr,caller_context_t * ct)18898329232eSGordon Ross fop_dispose(
18908329232eSGordon Ross 	vnode_t *vp,
18918329232eSGordon Ross 	page_t *pp,
18928329232eSGordon Ross 	int flag,
18938329232eSGordon Ross 	int dn,
18948329232eSGordon Ross 	cred_t *cr,
18958329232eSGordon Ross 	caller_context_t *ct)
18968329232eSGordon Ross {
18978329232eSGordon Ross 	/* Must do stats first since it's possible to lose the vnode */
18988329232eSGordon Ross 	VOPSTATS_UPDATE(vp, dispose);
18998329232eSGordon Ross 
19008329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
19018329232eSGordon Ross 
19028329232eSGordon Ross 	(*(vp)->v_op->vop_dispose)(vp, pp, flag, dn, cr, ct);
19038329232eSGordon Ross }
19048329232eSGordon Ross 
19058329232eSGordon Ross int
fop_setsecattr(vnode_t * vp,vsecattr_t * vsap,int flag,cred_t * cr,caller_context_t * ct)19068329232eSGordon Ross fop_setsecattr(
19078329232eSGordon Ross 	vnode_t *vp,
19088329232eSGordon Ross 	vsecattr_t *vsap,
19098329232eSGordon Ross 	int flag,
19108329232eSGordon Ross 	cred_t *cr,
19118329232eSGordon Ross 	caller_context_t *ct)
19128329232eSGordon Ross {
19138329232eSGordon Ross 	int	err;
19148329232eSGordon Ross 
19158329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
19168329232eSGordon Ross 
19178329232eSGordon Ross 	/*
19188329232eSGordon Ross 	 * We're only allowed to skip the ACL check iff we used a 32 bit
19198329232eSGordon Ross 	 * ACE mask with VOP_ACCESS() to determine permissions.
19208329232eSGordon Ross 	 */
19218329232eSGordon Ross 	if ((flag & ATTR_NOACLCHECK) &&
19228329232eSGordon Ross 	    vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) {
19238329232eSGordon Ross 		return (EINVAL);
19248329232eSGordon Ross 	}
19258329232eSGordon Ross 	err = (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr, ct);
19268329232eSGordon Ross 	VOPSTATS_UPDATE(vp, setsecattr);
19278329232eSGordon Ross 	return (err);
19288329232eSGordon Ross }
19298329232eSGordon Ross 
19308329232eSGordon Ross int
fop_getsecattr(vnode_t * vp,vsecattr_t * vsap,int flag,cred_t * cr,caller_context_t * ct)19318329232eSGordon Ross fop_getsecattr(
19328329232eSGordon Ross 	vnode_t *vp,
19338329232eSGordon Ross 	vsecattr_t *vsap,
19348329232eSGordon Ross 	int flag,
19358329232eSGordon Ross 	cred_t *cr,
19368329232eSGordon Ross 	caller_context_t *ct)
19378329232eSGordon Ross {
19388329232eSGordon Ross 	int	err;
19398329232eSGordon Ross 
19408329232eSGordon Ross 	/*
19418329232eSGordon Ross 	 * We're only allowed to skip the ACL check iff we used a 32 bit
19428329232eSGordon Ross 	 * ACE mask with VOP_ACCESS() to determine permissions.
19438329232eSGordon Ross 	 */
19448329232eSGordon Ross 	if ((flag & ATTR_NOACLCHECK) &&
19458329232eSGordon Ross 	    vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) {
19468329232eSGordon Ross 		return (EINVAL);
19478329232eSGordon Ross 	}
19488329232eSGordon Ross 
19498329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
19508329232eSGordon Ross 
19518329232eSGordon Ross 	err = (*(vp)->v_op->vop_getsecattr) (vp, vsap, flag, cr, ct);
19528329232eSGordon Ross 	VOPSTATS_UPDATE(vp, getsecattr);
19538329232eSGordon Ross 	return (err);
19548329232eSGordon Ross }
19558329232eSGordon Ross 
19568329232eSGordon Ross int
fop_shrlock(vnode_t * vp,int cmd,struct shrlock * shr,int flag,cred_t * cr,caller_context_t * ct)19578329232eSGordon Ross fop_shrlock(
19588329232eSGordon Ross 	vnode_t *vp,
19598329232eSGordon Ross 	int cmd,
19608329232eSGordon Ross 	struct shrlock *shr,
19618329232eSGordon Ross 	int flag,
19628329232eSGordon Ross 	cred_t *cr,
19638329232eSGordon Ross 	caller_context_t *ct)
19648329232eSGordon Ross {
19658329232eSGordon Ross 	int	err;
19668329232eSGordon Ross 
19678329232eSGordon Ross 	VOPXID_MAP_CR(vp, cr);
19688329232eSGordon Ross 
19698329232eSGordon Ross 	err = (*(vp)->v_op->vop_shrlock)(vp, cmd, shr, flag, cr, ct);
19708329232eSGordon Ross 	VOPSTATS_UPDATE(vp, shrlock);
19718329232eSGordon Ross 	return (err);
19728329232eSGordon Ross }
19738329232eSGordon Ross 
19748329232eSGordon Ross int
fop_vnevent(vnode_t * vp,vnevent_t vnevent,vnode_t * dvp,char * fnm,caller_context_t * ct)19758329232eSGordon Ross fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm,
19768329232eSGordon Ross     caller_context_t *ct)
19778329232eSGordon Ross {
19788329232eSGordon Ross 	int	err;
19798329232eSGordon Ross 
19808329232eSGordon Ross 	err = (*(vp)->v_op->vop_vnevent)(vp, vnevent, dvp, fnm, ct);
19818329232eSGordon Ross 	VOPSTATS_UPDATE(vp, vnevent);
19828329232eSGordon Ross 	return (err);
19838329232eSGordon Ross }
19848329232eSGordon Ross 
19858329232eSGordon Ross // fop_reqzcbuf
19868329232eSGordon Ross // fop_retzcbuf
19878329232eSGordon Ross 
19888329232eSGordon Ross // vsd_defaultdestructor
19898329232eSGordon Ross // vsd_create, vsd_destroy
19908329232eSGordon Ross // vsd_get, vsd_set
19918329232eSGordon Ross // vsd_free, vsd_realloc
19928329232eSGordon Ross 
19938329232eSGordon Ross static int
fs_reparse_mark(char * target,vattr_t * vap,xvattr_t * xvattr)19948329232eSGordon Ross fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr)
19958329232eSGordon Ross {
19968329232eSGordon Ross 	return (-1);
19978329232eSGordon Ross }
19988329232eSGordon Ross 
19998329232eSGordon Ross /*
20008329232eSGordon Ross  * Function to check whether a symlink is a reparse point.
20018329232eSGordon Ross  * Return B_TRUE if it is a reparse point, else return B_FALSE
20028329232eSGordon Ross  */
20038329232eSGordon Ross boolean_t
vn_is_reparse(vnode_t * vp,cred_t * cr,caller_context_t * ct)20048329232eSGordon Ross vn_is_reparse(vnode_t *vp, cred_t *cr, caller_context_t *ct)
20058329232eSGordon Ross {
20068329232eSGordon Ross 	xvattr_t xvattr;
20078329232eSGordon Ross 	xoptattr_t *xoap;
20088329232eSGordon Ross 
20098329232eSGordon Ross 	if ((vp->v_type != VLNK) ||
20108329232eSGordon Ross 	    !(vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR)))
20118329232eSGordon Ross 		return (B_FALSE);
20128329232eSGordon Ross 
20138329232eSGordon Ross 	xva_init(&xvattr);
20148329232eSGordon Ross 	xoap = xva_getxoptattr(&xvattr);
20158329232eSGordon Ross 	ASSERT(xoap);
20168329232eSGordon Ross 	XVA_SET_REQ(&xvattr, XAT_REPARSE);
20178329232eSGordon Ross 
20188329232eSGordon Ross 	if (VOP_GETATTR(vp, &xvattr.xva_vattr, 0, cr, ct))
20198329232eSGordon Ross 		return (B_FALSE);
20208329232eSGordon Ross 
20218329232eSGordon Ross 	if ((!(xvattr.xva_vattr.va_mask & AT_XVATTR)) ||
20228329232eSGordon Ross 	    (!(XVA_ISSET_RTN(&xvattr, XAT_REPARSE))))
20238329232eSGordon Ross 		return (B_FALSE);
20248329232eSGordon Ross 
20258329232eSGordon Ross 	return (xoap->xoa_reparse ? B_TRUE : B_FALSE);
20268329232eSGordon Ross }
2027