xref: /illumos-gate/usr/src/uts/common/fs/fs_subr.c (revision da6c28aa)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5dd29fa4aSprabahar  * Common Development and Distribution License (the "License").
6dd29fa4aSprabahar  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
227c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate /*
26f48205beScasper  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
277c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate /*
337c478bd9Sstevel@tonic-gate  * Generic vnode operations.
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate #include <sys/types.h>
367c478bd9Sstevel@tonic-gate #include <sys/param.h>
377c478bd9Sstevel@tonic-gate #include <sys/systm.h>
387c478bd9Sstevel@tonic-gate #include <sys/errno.h>
397c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
407c478bd9Sstevel@tonic-gate #include <sys/flock.h>
417c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
427c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
437c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
447c478bd9Sstevel@tonic-gate #include <sys/proc.h>
457c478bd9Sstevel@tonic-gate #include <sys/user.h>
467c478bd9Sstevel@tonic-gate #include <sys/unistd.h>
477c478bd9Sstevel@tonic-gate #include <sys/cred.h>
487c478bd9Sstevel@tonic-gate #include <sys/poll.h>
497c478bd9Sstevel@tonic-gate #include <sys/debug.h>
507c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
517c478bd9Sstevel@tonic-gate #include <sys/stream.h>
527c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
537c478bd9Sstevel@tonic-gate #include <sys/acl.h>
547c478bd9Sstevel@tonic-gate #include <sys/share.h>
557c478bd9Sstevel@tonic-gate #include <sys/file.h>
567c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
577c478bd9Sstevel@tonic-gate #include <sys/file.h>
587c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h>
59fa9e4066Sahrens #include <acl/acl_common.h>
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *);
627c478bd9Sstevel@tonic-gate 
63dd29fa4aSprabahar /*
64dd29fa4aSprabahar  * Tunable to limit the number of retry to recover from STALE error.
65dd29fa4aSprabahar  */
66dd29fa4aSprabahar int fs_estale_retry = 5;
67dd29fa4aSprabahar 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * The associated operation is not supported by the file system.
707c478bd9Sstevel@tonic-gate  */
717c478bd9Sstevel@tonic-gate int
727c478bd9Sstevel@tonic-gate fs_nosys()
737c478bd9Sstevel@tonic-gate {
747c478bd9Sstevel@tonic-gate 	return (ENOSYS);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate  * The associated operation is invalid (on this vnode).
797c478bd9Sstevel@tonic-gate  */
807c478bd9Sstevel@tonic-gate int
817c478bd9Sstevel@tonic-gate fs_inval()
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	return (EINVAL);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * The associated operation is valid only for directories.
887c478bd9Sstevel@tonic-gate  */
897c478bd9Sstevel@tonic-gate int
907c478bd9Sstevel@tonic-gate fs_notdir()
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	return (ENOTDIR);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Free the file system specific resources. For the file systems that
977c478bd9Sstevel@tonic-gate  * do not support the forced unmount, it will be a nop function.
987c478bd9Sstevel@tonic-gate  */
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1017c478bd9Sstevel@tonic-gate void
1027c478bd9Sstevel@tonic-gate fs_freevfs(vfs_t *vfsp)
1037c478bd9Sstevel@tonic-gate {
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /* ARGSUSED */
1077c478bd9Sstevel@tonic-gate int
1087c478bd9Sstevel@tonic-gate fs_nosys_map(struct vnode *vp,
1097c478bd9Sstevel@tonic-gate 	offset_t off,
1107c478bd9Sstevel@tonic-gate 	struct as *as,
1117c478bd9Sstevel@tonic-gate 	caddr_t *addrp,
1127c478bd9Sstevel@tonic-gate 	size_t len,
1137c478bd9Sstevel@tonic-gate 	uchar_t prot,
1147c478bd9Sstevel@tonic-gate 	uchar_t maxprot,
1157c478bd9Sstevel@tonic-gate 	uint_t flags,
116*da6c28aaSamw 	struct cred *cr,
117*da6c28aaSamw 	caller_context_t *ct)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	return (ENOSYS);
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate /* ARGSUSED */
1237c478bd9Sstevel@tonic-gate int
1247c478bd9Sstevel@tonic-gate fs_nosys_addmap(struct vnode *vp,
1257c478bd9Sstevel@tonic-gate 	offset_t off,
1267c478bd9Sstevel@tonic-gate 	struct as *as,
1277c478bd9Sstevel@tonic-gate 	caddr_t addr,
1287c478bd9Sstevel@tonic-gate 	size_t len,
1297c478bd9Sstevel@tonic-gate 	uchar_t prot,
1307c478bd9Sstevel@tonic-gate 	uchar_t maxprot,
1317c478bd9Sstevel@tonic-gate 	uint_t flags,
132*da6c28aaSamw 	struct cred *cr,
133*da6c28aaSamw 	caller_context_t *ct)
1347c478bd9Sstevel@tonic-gate {
1357c478bd9Sstevel@tonic-gate 	return (ENOSYS);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /* ARGSUSED */
1397c478bd9Sstevel@tonic-gate int
1407c478bd9Sstevel@tonic-gate fs_nosys_poll(vnode_t *vp,
1417c478bd9Sstevel@tonic-gate 	register short events,
1427c478bd9Sstevel@tonic-gate 	int anyyet,
1437c478bd9Sstevel@tonic-gate 	register short *reventsp,
144*da6c28aaSamw 	struct pollhead **phpp,
145*da6c28aaSamw 	caller_context_t *ct)
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 	return (ENOSYS);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate  * The file system has nothing to sync to disk.  However, the
1537c478bd9Sstevel@tonic-gate  * VFS_SYNC operation must not fail.
1547c478bd9Sstevel@tonic-gate  */
1557c478bd9Sstevel@tonic-gate /* ARGSUSED */
1567c478bd9Sstevel@tonic-gate int
1577c478bd9Sstevel@tonic-gate fs_sync(struct vfs *vfspp, short flag, cred_t *cr)
1587c478bd9Sstevel@tonic-gate {
1597c478bd9Sstevel@tonic-gate 	return (0);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
162*da6c28aaSamw /*
163*da6c28aaSamw  * Does nothing but VOP_FSYNC must not fail.
164*da6c28aaSamw  */
165*da6c28aaSamw /* ARGSUSED */
166*da6c28aaSamw int
167*da6c28aaSamw fs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
168*da6c28aaSamw {
169*da6c28aaSamw 	return (0);
170*da6c28aaSamw }
171*da6c28aaSamw 
172*da6c28aaSamw /*
173*da6c28aaSamw  * Does nothing but VOP_PUTPAGE must not fail.
174*da6c28aaSamw  */
175*da6c28aaSamw /* ARGSUSED */
176*da6c28aaSamw int
177*da6c28aaSamw fs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
178*da6c28aaSamw 	caller_context_t *ctp)
179*da6c28aaSamw {
180*da6c28aaSamw 	return (0);
181*da6c28aaSamw }
182*da6c28aaSamw 
183*da6c28aaSamw /*
184*da6c28aaSamw  * Does nothing but VOP_IOCTL must not fail.
185*da6c28aaSamw  */
186*da6c28aaSamw /* ARGSUSED */
187*da6c28aaSamw int
188*da6c28aaSamw fs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred,
189*da6c28aaSamw 	int *rvalp)
190*da6c28aaSamw {
191*da6c28aaSamw 	return (0);
192*da6c28aaSamw }
193*da6c28aaSamw 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate  * Read/write lock/unlock.  Does nothing.
1967c478bd9Sstevel@tonic-gate  */
1977c478bd9Sstevel@tonic-gate /* ARGSUSED */
1987c478bd9Sstevel@tonic-gate int
1997c478bd9Sstevel@tonic-gate fs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate 	return (-1);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate /* ARGSUSED */
2057c478bd9Sstevel@tonic-gate void
2067c478bd9Sstevel@tonic-gate fs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2077c478bd9Sstevel@tonic-gate {
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate /*
2117c478bd9Sstevel@tonic-gate  * Compare two vnodes.
2127c478bd9Sstevel@tonic-gate  */
213*da6c28aaSamw /*ARGSUSED2*/
2147c478bd9Sstevel@tonic-gate int
215*da6c28aaSamw fs_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate 	return (vp1 == vp2);
2187c478bd9Sstevel@tonic-gate }
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate /*
2217c478bd9Sstevel@tonic-gate  * No-op seek operation.
2227c478bd9Sstevel@tonic-gate  */
2237c478bd9Sstevel@tonic-gate /* ARGSUSED */
2247c478bd9Sstevel@tonic-gate int
225*da6c28aaSamw fs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate 	return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0);
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate /*
2317c478bd9Sstevel@tonic-gate  * File and record locking.
2327c478bd9Sstevel@tonic-gate  */
2337c478bd9Sstevel@tonic-gate /* ARGSUSED */
2347c478bd9Sstevel@tonic-gate int
2357c478bd9Sstevel@tonic-gate fs_frlock(register vnode_t *vp, int cmd, struct flock64 *bfp, int flag,
236*da6c28aaSamw 	offset_t offset, flk_callback_t *flk_cbp, cred_t *cr,
237*da6c28aaSamw 	caller_context_t *ct)
2387c478bd9Sstevel@tonic-gate {
2397c478bd9Sstevel@tonic-gate 	int frcmd;
2407c478bd9Sstevel@tonic-gate 	int nlmid;
2417c478bd9Sstevel@tonic-gate 	int error = 0;
2427c478bd9Sstevel@tonic-gate 	flk_callback_t serialize_callback;
2437c478bd9Sstevel@tonic-gate 	int serialize = 0;
244*da6c28aaSamw 	v_mode_t mode;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 	switch (cmd) {
2477c478bd9Sstevel@tonic-gate 
2487c478bd9Sstevel@tonic-gate 	case F_GETLK:
2497c478bd9Sstevel@tonic-gate 	case F_O_GETLK:
2507c478bd9Sstevel@tonic-gate 		if (flag & F_REMOTELOCK) {
2517c478bd9Sstevel@tonic-gate 			frcmd = RCMDLCK;
252*da6c28aaSamw 		} else if (flag & F_PXFSLOCK) {
2537c478bd9Sstevel@tonic-gate 			frcmd = PCMDLCK;
254*da6c28aaSamw 		} else {
255*da6c28aaSamw 			frcmd = 0;
256*da6c28aaSamw 			bfp->l_pid = ttoproc(curthread)->p_pid;
257*da6c28aaSamw 			bfp->l_sysid = 0;
2587c478bd9Sstevel@tonic-gate 		}
2597c478bd9Sstevel@tonic-gate 		break;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	case F_SETLK_NBMAND:
2627c478bd9Sstevel@tonic-gate 		/*
2637c478bd9Sstevel@tonic-gate 		 * Are NBMAND locks allowed on this file?
2647c478bd9Sstevel@tonic-gate 		 */
2657c478bd9Sstevel@tonic-gate 		if (!vp->v_vfsp ||
2667c478bd9Sstevel@tonic-gate 		    !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) {
2677c478bd9Sstevel@tonic-gate 			error = EINVAL;
2687c478bd9Sstevel@tonic-gate 			goto done;
2697c478bd9Sstevel@tonic-gate 		}
2707c478bd9Sstevel@tonic-gate 		if (vp->v_type != VREG) {
2717c478bd9Sstevel@tonic-gate 			error = EINVAL;
2727c478bd9Sstevel@tonic-gate 			goto done;
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 	case F_SETLK:
277*da6c28aaSamw 		if (flag & F_REMOTELOCK) {
278*da6c28aaSamw 			frcmd = SETFLCK|RCMDLCK;
279*da6c28aaSamw 		} else if (flag & F_PXFSLOCK) {
280*da6c28aaSamw 			frcmd = SETFLCK|PCMDLCK;
281*da6c28aaSamw 		} else {
282*da6c28aaSamw 			frcmd = SETFLCK;
283*da6c28aaSamw 			bfp->l_pid = ttoproc(curthread)->p_pid;
284*da6c28aaSamw 			bfp->l_sysid = 0;
285*da6c28aaSamw 		}
286*da6c28aaSamw 		if (cmd == F_SETLK_NBMAND &&
287*da6c28aaSamw 		    (bfp->l_type == F_RDLCK || bfp->l_type == F_WRLCK)) {
288*da6c28aaSamw 			frcmd |= NBMLCK;
289*da6c28aaSamw 		}
2907c478bd9Sstevel@tonic-gate 		/*
2917c478bd9Sstevel@tonic-gate 		 * Check whether there is an NBMAND share reservation that
2927c478bd9Sstevel@tonic-gate 		 * conflicts with the lock request.
2937c478bd9Sstevel@tonic-gate 		 */
2947c478bd9Sstevel@tonic-gate 		if (nbl_need_check(vp)) {
2957c478bd9Sstevel@tonic-gate 			nbl_start_crit(vp, RW_WRITER);
2967c478bd9Sstevel@tonic-gate 			serialize = 1;
297*da6c28aaSamw 			if (frcmd & NBMLCK) {
298*da6c28aaSamw 				mode = (bfp->l_type == F_RDLCK) ?
299*da6c28aaSamw 				    V_READ : V_RDANDWR;
300*da6c28aaSamw 				if (vn_is_mapped(vp, mode)) {
301*da6c28aaSamw 					error = EAGAIN;
302*da6c28aaSamw 					goto done;
303*da6c28aaSamw 				}
304*da6c28aaSamw 			}
3057c478bd9Sstevel@tonic-gate 			if (share_blocks_lock(vp, bfp)) {
3067c478bd9Sstevel@tonic-gate 				error = EAGAIN;
3077c478bd9Sstevel@tonic-gate 				goto done;
3087c478bd9Sstevel@tonic-gate 			}
3097c478bd9Sstevel@tonic-gate 		}
3107c478bd9Sstevel@tonic-gate 		break;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	case F_SETLKW:
313*da6c28aaSamw 		if (flag & F_REMOTELOCK) {
314*da6c28aaSamw 			frcmd = SETFLCK|SLPFLCK|RCMDLCK;
315*da6c28aaSamw 		} else if (flag & F_PXFSLOCK) {
316*da6c28aaSamw 			frcmd = SETFLCK|SLPFLCK|PCMDLCK;
317*da6c28aaSamw 		} else {
318*da6c28aaSamw 			frcmd = SETFLCK|SLPFLCK;
319*da6c28aaSamw 			bfp->l_pid = ttoproc(curthread)->p_pid;
320*da6c28aaSamw 			bfp->l_sysid = 0;
321*da6c28aaSamw 		}
3227c478bd9Sstevel@tonic-gate 		/*
3237c478bd9Sstevel@tonic-gate 		 * If there is an NBMAND share reservation that conflicts
3247c478bd9Sstevel@tonic-gate 		 * with the lock request, block until the conflicting share
3257c478bd9Sstevel@tonic-gate 		 * reservation goes away.
3267c478bd9Sstevel@tonic-gate 		 */
3277c478bd9Sstevel@tonic-gate 		if (nbl_need_check(vp)) {
3287c478bd9Sstevel@tonic-gate 			nbl_start_crit(vp, RW_WRITER);
3297c478bd9Sstevel@tonic-gate 			serialize = 1;
3307c478bd9Sstevel@tonic-gate 			if (share_blocks_lock(vp, bfp)) {
3317c478bd9Sstevel@tonic-gate 				error = wait_for_share(vp, bfp);
3327c478bd9Sstevel@tonic-gate 				if (error != 0)
3337c478bd9Sstevel@tonic-gate 					goto done;
3347c478bd9Sstevel@tonic-gate 			}
3357c478bd9Sstevel@tonic-gate 		}
3367c478bd9Sstevel@tonic-gate 		break;
3377c478bd9Sstevel@tonic-gate 
3387c478bd9Sstevel@tonic-gate 	case F_HASREMOTELOCKS:
3397c478bd9Sstevel@tonic-gate 		nlmid = GETNLMID(bfp->l_sysid);
3407c478bd9Sstevel@tonic-gate 		if (nlmid != 0) {	/* booted as a cluster */
3417c478bd9Sstevel@tonic-gate 			l_has_rmt(bfp) =
342*da6c28aaSamw 			    cl_flk_has_remote_locks_for_nlmid(vp, nlmid);
3437c478bd9Sstevel@tonic-gate 		} else {		/* not booted as a cluster */
3447c478bd9Sstevel@tonic-gate 			l_has_rmt(bfp) = flk_has_remote_locks(vp);
3457c478bd9Sstevel@tonic-gate 		}
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 		goto done;
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 	default:
3507c478bd9Sstevel@tonic-gate 		error = EINVAL;
3517c478bd9Sstevel@tonic-gate 		goto done;
3527c478bd9Sstevel@tonic-gate 	}
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 	/*
3557c478bd9Sstevel@tonic-gate 	 * If this is a blocking lock request and we're serializing lock
3567c478bd9Sstevel@tonic-gate 	 * requests, modify the callback list to leave the critical region
3577c478bd9Sstevel@tonic-gate 	 * while we're waiting for the lock.
3587c478bd9Sstevel@tonic-gate 	 */
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	if (serialize && (frcmd & SLPFLCK) != 0) {
3617c478bd9Sstevel@tonic-gate 		flk_add_callback(&serialize_callback,
362*da6c28aaSamw 		    frlock_serialize_blocked, vp, flk_cbp);
3637c478bd9Sstevel@tonic-gate 		flk_cbp = &serialize_callback;
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	error = reclock(vp, bfp, frcmd, flag, offset, flk_cbp);
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate done:
3697c478bd9Sstevel@tonic-gate 	if (serialize)
3707c478bd9Sstevel@tonic-gate 		nbl_end_crit(vp);
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate 	return (error);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate /*
3767c478bd9Sstevel@tonic-gate  * Callback when a lock request blocks and we are serializing requests.  If
3777c478bd9Sstevel@tonic-gate  * before sleeping, leave the critical region.  If after wakeup, reenter
3787c478bd9Sstevel@tonic-gate  * the critical region.
3797c478bd9Sstevel@tonic-gate  */
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate static callb_cpr_t *
3827c478bd9Sstevel@tonic-gate frlock_serialize_blocked(flk_cb_when_t when, void *infop)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate 	vnode_t *vp = (vnode_t *)infop;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	if (when == FLK_BEFORE_SLEEP)
3877c478bd9Sstevel@tonic-gate 		nbl_end_crit(vp);
3887c478bd9Sstevel@tonic-gate 	else {
3897c478bd9Sstevel@tonic-gate 		nbl_start_crit(vp, RW_WRITER);
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	return (NULL);
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate /*
3967c478bd9Sstevel@tonic-gate  * Allow any flags.
3977c478bd9Sstevel@tonic-gate  */
3987c478bd9Sstevel@tonic-gate /* ARGSUSED */
3997c478bd9Sstevel@tonic-gate int
400*da6c28aaSamw fs_setfl(
401*da6c28aaSamw 	vnode_t *vp,
402*da6c28aaSamw 	int oflags,
403*da6c28aaSamw 	int nflags,
404*da6c28aaSamw 	cred_t *cr,
405*da6c28aaSamw 	caller_context_t *ct)
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate 	return (0);
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate  * Return the answer requested to poll() for non-device files.
4127c478bd9Sstevel@tonic-gate  * Only POLLIN, POLLRDNORM, and POLLOUT are recognized.
4137c478bd9Sstevel@tonic-gate  */
4147c478bd9Sstevel@tonic-gate struct pollhead fs_pollhd;
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate /* ARGSUSED */
4177c478bd9Sstevel@tonic-gate int
4187c478bd9Sstevel@tonic-gate fs_poll(vnode_t *vp,
4197c478bd9Sstevel@tonic-gate 	register short events,
4207c478bd9Sstevel@tonic-gate 	int anyyet,
4217c478bd9Sstevel@tonic-gate 	register short *reventsp,
422*da6c28aaSamw 	struct pollhead **phpp,
423*da6c28aaSamw 	caller_context_t *ct)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate 	*reventsp = 0;
4267c478bd9Sstevel@tonic-gate 	if (events & POLLIN)
4277c478bd9Sstevel@tonic-gate 		*reventsp |= POLLIN;
4287c478bd9Sstevel@tonic-gate 	if (events & POLLRDNORM)
4297c478bd9Sstevel@tonic-gate 		*reventsp |= POLLRDNORM;
4307c478bd9Sstevel@tonic-gate 	if (events & POLLRDBAND)
4317c478bd9Sstevel@tonic-gate 		*reventsp |= POLLRDBAND;
4327c478bd9Sstevel@tonic-gate 	if (events & POLLOUT)
4337c478bd9Sstevel@tonic-gate 		*reventsp |= POLLOUT;
4347c478bd9Sstevel@tonic-gate 	if (events & POLLWRBAND)
4357c478bd9Sstevel@tonic-gate 		*reventsp |= POLLWRBAND;
4367c478bd9Sstevel@tonic-gate 	*phpp = !anyyet && !*reventsp ? &fs_pollhd : (struct pollhead *)NULL;
4377c478bd9Sstevel@tonic-gate 	return (0);
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate /*
4417c478bd9Sstevel@tonic-gate  * POSIX pathconf() support.
4427c478bd9Sstevel@tonic-gate  */
4437c478bd9Sstevel@tonic-gate /* ARGSUSED */
4447c478bd9Sstevel@tonic-gate int
445*da6c28aaSamw fs_pathconf(
446*da6c28aaSamw 	vnode_t *vp,
447*da6c28aaSamw 	int cmd,
448*da6c28aaSamw 	ulong_t *valp,
449*da6c28aaSamw 	cred_t *cr,
450*da6c28aaSamw 	caller_context_t *ct)
4517c478bd9Sstevel@tonic-gate {
4527c478bd9Sstevel@tonic-gate 	register ulong_t val;
4537c478bd9Sstevel@tonic-gate 	register int error = 0;
4547c478bd9Sstevel@tonic-gate 	struct statvfs64 vfsbuf;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	switch (cmd) {
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	case _PC_LINK_MAX:
4597c478bd9Sstevel@tonic-gate 		val = MAXLINK;
4607c478bd9Sstevel@tonic-gate 		break;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	case _PC_MAX_CANON:
4637c478bd9Sstevel@tonic-gate 		val = MAX_CANON;
4647c478bd9Sstevel@tonic-gate 		break;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	case _PC_MAX_INPUT:
4677c478bd9Sstevel@tonic-gate 		val = MAX_INPUT;
4687c478bd9Sstevel@tonic-gate 		break;
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	case _PC_NAME_MAX:
4717c478bd9Sstevel@tonic-gate 		bzero(&vfsbuf, sizeof (vfsbuf));
4727c478bd9Sstevel@tonic-gate 		if (error = VFS_STATVFS(vp->v_vfsp, &vfsbuf))
4737c478bd9Sstevel@tonic-gate 			break;
4747c478bd9Sstevel@tonic-gate 		val = vfsbuf.f_namemax;
4757c478bd9Sstevel@tonic-gate 		break;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate 	case _PC_PATH_MAX:
4787c478bd9Sstevel@tonic-gate 	case _PC_SYMLINK_MAX:
4797c478bd9Sstevel@tonic-gate 		val = MAXPATHLEN;
4807c478bd9Sstevel@tonic-gate 		break;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	case _PC_PIPE_BUF:
4837c478bd9Sstevel@tonic-gate 		val = PIPE_BUF;
4847c478bd9Sstevel@tonic-gate 		break;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	case _PC_NO_TRUNC:
4877c478bd9Sstevel@tonic-gate 		if (vp->v_vfsp->vfs_flag & VFS_NOTRUNC)
4887c478bd9Sstevel@tonic-gate 			val = 1;	/* NOTRUNC is enabled for vp */
4897c478bd9Sstevel@tonic-gate 		else
4907c478bd9Sstevel@tonic-gate 			val = (ulong_t)-1;
4917c478bd9Sstevel@tonic-gate 		break;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	case _PC_VDISABLE:
4947c478bd9Sstevel@tonic-gate 		val = _POSIX_VDISABLE;
4957c478bd9Sstevel@tonic-gate 		break;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	case _PC_CHOWN_RESTRICTED:
4987c478bd9Sstevel@tonic-gate 		if (rstchown)
4997c478bd9Sstevel@tonic-gate 			val = rstchown; /* chown restricted enabled */
5007c478bd9Sstevel@tonic-gate 		else
5017c478bd9Sstevel@tonic-gate 			val = (ulong_t)-1;
5027c478bd9Sstevel@tonic-gate 		break;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	case _PC_FILESIZEBITS:
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 		/*
5077c478bd9Sstevel@tonic-gate 		 * If ever we come here it means that underlying file system
5087c478bd9Sstevel@tonic-gate 		 * does not recognise the command and therefore this
5097c478bd9Sstevel@tonic-gate 		 * configurable limit cannot be determined. We return -1
5107c478bd9Sstevel@tonic-gate 		 * and don't change errno.
5117c478bd9Sstevel@tonic-gate 		 */
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 		val = (ulong_t)-1;    /* large file support */
5147c478bd9Sstevel@tonic-gate 		break;
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 	case _PC_ACL_ENABLED:
5177c478bd9Sstevel@tonic-gate 		val = 0;
5187c478bd9Sstevel@tonic-gate 		break;
5197c478bd9Sstevel@tonic-gate 
520*da6c28aaSamw 	case _PC_CASE_BEHAVIOR:
521*da6c28aaSamw 		val = _CASE_SENSITIVE;
522*da6c28aaSamw 		if (vfs_has_feature(vp->v_vfsp, VFSFT_CASEINSENSITIVE) == 1)
523*da6c28aaSamw 			val |= _CASE_INSENSITIVE;
524*da6c28aaSamw 		if (vfs_has_feature(vp->v_vfsp, VFSFT_NOCASESENSITIVE) == 1)
525*da6c28aaSamw 			val &= ~_CASE_SENSITIVE;
526*da6c28aaSamw 		break;
527*da6c28aaSamw 
528*da6c28aaSamw 	case _PC_SATTR_ENABLED:
529*da6c28aaSamw 	case _PC_SATTR_EXISTS:
530*da6c28aaSamw 		val = 0;
531*da6c28aaSamw 		break;
532*da6c28aaSamw 
5337c478bd9Sstevel@tonic-gate 	default:
5347c478bd9Sstevel@tonic-gate 		error = EINVAL;
5357c478bd9Sstevel@tonic-gate 		break;
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate 
5387c478bd9Sstevel@tonic-gate 	if (error == 0)
5397c478bd9Sstevel@tonic-gate 		*valp = val;
5407c478bd9Sstevel@tonic-gate 	return (error);
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate /*
5447c478bd9Sstevel@tonic-gate  * Dispose of a page.
5457c478bd9Sstevel@tonic-gate  */
5467c478bd9Sstevel@tonic-gate /* ARGSUSED */
5477c478bd9Sstevel@tonic-gate void
548*da6c28aaSamw fs_dispose(
549*da6c28aaSamw 	struct vnode *vp,
550*da6c28aaSamw 	page_t *pp,
551*da6c28aaSamw 	int fl,
552*da6c28aaSamw 	int dn,
553*da6c28aaSamw 	struct cred *cr,
554*da6c28aaSamw 	caller_context_t *ct)
5557c478bd9Sstevel@tonic-gate {
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	ASSERT(fl == B_FREE || fl == B_INVAL);
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	if (fl == B_FREE)
5607c478bd9Sstevel@tonic-gate 		page_free(pp, dn);
5617c478bd9Sstevel@tonic-gate 	else
5627c478bd9Sstevel@tonic-gate 		page_destroy(pp, dn);
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate /* ARGSUSED */
5667c478bd9Sstevel@tonic-gate void
567*da6c28aaSamw fs_nodispose(
568*da6c28aaSamw 	struct vnode *vp,
569*da6c28aaSamw 	page_t *pp,
570*da6c28aaSamw 	int fl,
571*da6c28aaSamw 	int dn,
572*da6c28aaSamw 	struct cred *cr,
573*da6c28aaSamw 	caller_context_t *ct)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	cmn_err(CE_PANIC, "fs_nodispose invoked");
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate /*
5797c478bd9Sstevel@tonic-gate  * fabricate acls for file systems that do not support acls.
5807c478bd9Sstevel@tonic-gate  */
5817c478bd9Sstevel@tonic-gate /* ARGSUSED */
5827c478bd9Sstevel@tonic-gate int
583*da6c28aaSamw fs_fab_acl(
584*da6c28aaSamw 	vnode_t *vp,
585*da6c28aaSamw 	vsecattr_t *vsecattr,
586*da6c28aaSamw 	int flag,
587*da6c28aaSamw 	cred_t *cr,
588*da6c28aaSamw 	caller_context_t *ct)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate 	aclent_t	*aclentp;
5917b3700d1Sszhou 	ace_t		*acep;
5927c478bd9Sstevel@tonic-gate 	struct vattr	vattr;
5937c478bd9Sstevel@tonic-gate 	int		error;
594*da6c28aaSamw 	size_t		aclsize;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	vsecattr->vsa_aclcnt	= 0;
597*da6c28aaSamw 	vsecattr->vsa_aclentsz	= 0;
5987c478bd9Sstevel@tonic-gate 	vsecattr->vsa_aclentp	= NULL;
5997c478bd9Sstevel@tonic-gate 	vsecattr->vsa_dfaclcnt	= 0;	/* Default ACLs are not fabricated */
6007c478bd9Sstevel@tonic-gate 	vsecattr->vsa_dfaclentp	= NULL;
6017c478bd9Sstevel@tonic-gate 
6027b3700d1Sszhou 	vattr.va_mask = AT_MODE | AT_UID | AT_GID;
603*da6c28aaSamw 	if (error = VOP_GETATTR(vp, &vattr, 0, cr, ct))
6047b3700d1Sszhou 		return (error);
6057b3700d1Sszhou 
606cf53598eSmarks 	if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) {
607*da6c28aaSamw 		aclsize = 4 * sizeof (aclent_t);
6087b3700d1Sszhou 		vsecattr->vsa_aclcnt	= 4; /* USER, GROUP, OTHER, and CLASS */
609*da6c28aaSamw 		vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
6107c478bd9Sstevel@tonic-gate 		aclentp = vsecattr->vsa_aclentp;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 		aclentp->a_type = USER_OBJ;	/* Owner */
6137c478bd9Sstevel@tonic-gate 		aclentp->a_perm = ((ushort_t)(vattr.va_mode & 0700)) >> 6;
6147c478bd9Sstevel@tonic-gate 		aclentp->a_id = vattr.va_uid;   /* Really undefined */
6157c478bd9Sstevel@tonic-gate 		aclentp++;
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 		aclentp->a_type = GROUP_OBJ;    /* Group */
6187c478bd9Sstevel@tonic-gate 		aclentp->a_perm = ((ushort_t)(vattr.va_mode & 0070)) >> 3;
6197c478bd9Sstevel@tonic-gate 		aclentp->a_id = vattr.va_gid;   /* Really undefined */
6207c478bd9Sstevel@tonic-gate 		aclentp++;
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate 		aclentp->a_type = OTHER_OBJ;    /* Other */
6237c478bd9Sstevel@tonic-gate 		aclentp->a_perm = vattr.va_mode & 0007;
624f48205beScasper 		aclentp->a_id = (gid_t)-1;	/* Really undefined */
6257c478bd9Sstevel@tonic-gate 		aclentp++;
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 		aclentp->a_type = CLASS_OBJ;    /* Class */
6287b3700d1Sszhou 		aclentp->a_perm = (ushort_t)(0007);
629f48205beScasper 		aclentp->a_id = (gid_t)-1;	/* Really undefined */
630cf53598eSmarks 	} else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) {
631*da6c28aaSamw 		aclsize = 6 * sizeof (ace_t);
6327b3700d1Sszhou 		vsecattr->vsa_aclcnt	= 6;
633*da6c28aaSamw 		vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
634*da6c28aaSamw 		vsecattr->vsa_aclentsz = aclsize;
6357b3700d1Sszhou 		acep = vsecattr->vsa_aclentp;
6367b3700d1Sszhou 		(void) memcpy(acep, trivial_acl, sizeof (ace_t) * 6);
6377b3700d1Sszhou 		adjust_ace_pair(acep, (vattr.va_mode & 0700) >> 6);
6387b3700d1Sszhou 		adjust_ace_pair(acep + 2, (vattr.va_mode & 0070) >> 3);
6397b3700d1Sszhou 		adjust_ace_pair(acep + 4, vattr.va_mode & 0007);
640cf53598eSmarks 	}
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 	return (0);
6437c478bd9Sstevel@tonic-gate }
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate /*
6467c478bd9Sstevel@tonic-gate  * Common code for implementing DOS share reservations
6477c478bd9Sstevel@tonic-gate  */
6487c478bd9Sstevel@tonic-gate /* ARGSUSED4 */
6497c478bd9Sstevel@tonic-gate int
650*da6c28aaSamw fs_shrlock(
651*da6c28aaSamw 	struct vnode *vp,
652*da6c28aaSamw 	int cmd,
653*da6c28aaSamw 	struct shrlock *shr,
654*da6c28aaSamw 	int flag,
655*da6c28aaSamw 	cred_t *cr,
656*da6c28aaSamw 	caller_context_t *ct)
6577c478bd9Sstevel@tonic-gate {
6587c478bd9Sstevel@tonic-gate 	int error;
6597c478bd9Sstevel@tonic-gate 
6607c478bd9Sstevel@tonic-gate 	/*
6617c478bd9Sstevel@tonic-gate 	 * Make sure that the file was opened with permissions appropriate
6627c478bd9Sstevel@tonic-gate 	 * for the request, and make sure the caller isn't trying to sneak
6637c478bd9Sstevel@tonic-gate 	 * in an NBMAND request.
6647c478bd9Sstevel@tonic-gate 	 */
6657c478bd9Sstevel@tonic-gate 	if (cmd == F_SHARE) {
6667c478bd9Sstevel@tonic-gate 		if (((shr->s_access & F_RDACC) && (flag & FREAD) == 0) ||
6677c478bd9Sstevel@tonic-gate 		    ((shr->s_access & F_WRACC) && (flag & FWRITE) == 0))
6687c478bd9Sstevel@tonic-gate 			return (EBADF);
669*da6c28aaSamw 		if (shr->s_access & (F_RMACC | F_MDACC))
670*da6c28aaSamw 			return (EINVAL);
671*da6c28aaSamw 		if (shr->s_deny & (F_MANDDNY | F_RMDNY))
6727c478bd9Sstevel@tonic-gate 			return (EINVAL);
6737c478bd9Sstevel@tonic-gate 	}
6747c478bd9Sstevel@tonic-gate 	if (cmd == F_SHARE_NBMAND) {
6757c478bd9Sstevel@tonic-gate 		/* make sure nbmand is allowed on the file */
6767c478bd9Sstevel@tonic-gate 		if (!vp->v_vfsp ||
6777c478bd9Sstevel@tonic-gate 		    !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) {
6787c478bd9Sstevel@tonic-gate 			return (EINVAL);
6797c478bd9Sstevel@tonic-gate 		}
6807c478bd9Sstevel@tonic-gate 		if (vp->v_type != VREG) {
6817c478bd9Sstevel@tonic-gate 			return (EINVAL);
6827c478bd9Sstevel@tonic-gate 		}
6837c478bd9Sstevel@tonic-gate 	}
6847c478bd9Sstevel@tonic-gate 
6857c478bd9Sstevel@tonic-gate 	nbl_start_crit(vp, RW_WRITER);
6867c478bd9Sstevel@tonic-gate 
6877c478bd9Sstevel@tonic-gate 	switch (cmd) {
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	case F_SHARE_NBMAND:
6907c478bd9Sstevel@tonic-gate 		shr->s_deny |= F_MANDDNY;
6917c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
6927c478bd9Sstevel@tonic-gate 	case F_SHARE:
6937c478bd9Sstevel@tonic-gate 		error = add_share(vp, shr);
6947c478bd9Sstevel@tonic-gate 		break;
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	case F_UNSHARE:
6977c478bd9Sstevel@tonic-gate 		error = del_share(vp, shr);
6987c478bd9Sstevel@tonic-gate 		break;
6997c478bd9Sstevel@tonic-gate 
7007c478bd9Sstevel@tonic-gate 	case F_HASREMOTELOCKS:
7017c478bd9Sstevel@tonic-gate 		/*
7027c478bd9Sstevel@tonic-gate 		 * We are overloading this command to refer to remote
7037c478bd9Sstevel@tonic-gate 		 * shares as well as remote locks, despite its name.
7047c478bd9Sstevel@tonic-gate 		 */
7057c478bd9Sstevel@tonic-gate 		shr->s_access = shr_has_remote_shares(vp, shr->s_sysid);
7067c478bd9Sstevel@tonic-gate 		error = 0;
7077c478bd9Sstevel@tonic-gate 		break;
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 	default:
7107c478bd9Sstevel@tonic-gate 		error = EINVAL;
7117c478bd9Sstevel@tonic-gate 		break;
7127c478bd9Sstevel@tonic-gate 	}
7137c478bd9Sstevel@tonic-gate 
7147c478bd9Sstevel@tonic-gate 	nbl_end_crit(vp);
7157c478bd9Sstevel@tonic-gate 	return (error);
7167c478bd9Sstevel@tonic-gate }
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
7197c478bd9Sstevel@tonic-gate int
720*da6c28aaSamw fs_vnevent_nosupport(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm,
721*da6c28aaSamw     caller_context_t *ct)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate 	ASSERT(vp != NULL);
7247c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
7257c478bd9Sstevel@tonic-gate }
7267c478bd9Sstevel@tonic-gate 
7277c478bd9Sstevel@tonic-gate /*ARGSUSED1*/
7287c478bd9Sstevel@tonic-gate int
729*da6c28aaSamw fs_vnevent_support(vnode_t *vp, vnevent_t e, vnode_t *dvp, char *fnm,
730*da6c28aaSamw     caller_context_t *ct)
7317c478bd9Sstevel@tonic-gate {
7327c478bd9Sstevel@tonic-gate 	ASSERT(vp != NULL);
7337c478bd9Sstevel@tonic-gate 	return (0);
7347c478bd9Sstevel@tonic-gate }
735fa9e4066Sahrens 
736fa9e4066Sahrens /*
737fa9e4066Sahrens  * return 1 for non-trivial ACL.
738fa9e4066Sahrens  *
739fa9e4066Sahrens  * NB: It is not necessary for the caller to VOP_RWLOCK since
740fa9e4066Sahrens  *	we only issue VOP_GETSECATTR.
741fa9e4066Sahrens  *
742fa9e4066Sahrens  * Returns 0 == trivial
743fa9e4066Sahrens  *         1 == NOT Trivial
744fa9e4066Sahrens  *	   <0 could not determine.
745fa9e4066Sahrens  */
746fa9e4066Sahrens int
747fa9e4066Sahrens fs_acl_nontrivial(vnode_t *vp, cred_t *cr)
748fa9e4066Sahrens {
749fa9e4066Sahrens 	ulong_t		acl_styles;
750fa9e4066Sahrens 	ulong_t		acl_flavor;
751fa9e4066Sahrens 	vsecattr_t 	vsecattr;
752fa9e4066Sahrens 	int 		error;
753fa9e4066Sahrens 	int		isnontrivial;
754fa9e4066Sahrens 
755fa9e4066Sahrens 	/* determine the forms of ACLs maintained */
756*da6c28aaSamw 	error = VOP_PATHCONF(vp, _PC_ACL_ENABLED, &acl_styles, cr, NULL);
757fa9e4066Sahrens 
758fa9e4066Sahrens 	/* clear bits we don't understand and establish default acl_style */
759fa9e4066Sahrens 	acl_styles &= (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED);
760fa9e4066Sahrens 	if (error || (acl_styles == 0))
761fa9e4066Sahrens 		acl_styles = _ACL_ACLENT_ENABLED;
762fa9e4066Sahrens 
763fa9e4066Sahrens 	vsecattr.vsa_aclentp = NULL;
764fa9e4066Sahrens 	vsecattr.vsa_dfaclentp = NULL;
765fa9e4066Sahrens 	vsecattr.vsa_aclcnt = 0;
766fa9e4066Sahrens 	vsecattr.vsa_dfaclcnt = 0;
767fa9e4066Sahrens 
768fa9e4066Sahrens 	while (acl_styles) {
769fa9e4066Sahrens 		/* select one of the styles as current flavor */
770fa9e4066Sahrens 		acl_flavor = 0;
771fa9e4066Sahrens 		if (acl_styles & _ACL_ACLENT_ENABLED) {
772fa9e4066Sahrens 			acl_flavor = _ACL_ACLENT_ENABLED;
773fa9e4066Sahrens 			vsecattr.vsa_mask = VSA_ACLCNT | VSA_DFACLCNT;
774fa9e4066Sahrens 		} else if (acl_styles & _ACL_ACE_ENABLED) {
775fa9e4066Sahrens 			acl_flavor = _ACL_ACE_ENABLED;
776fa9e4066Sahrens 			vsecattr.vsa_mask = VSA_ACECNT | VSA_ACE;
777fa9e4066Sahrens 		}
778fa9e4066Sahrens 
779fa9e4066Sahrens 		ASSERT(vsecattr.vsa_mask && acl_flavor);
780*da6c28aaSamw 		error = VOP_GETSECATTR(vp, &vsecattr, 0, cr, NULL);
781fa9e4066Sahrens 		if (error == 0)
782fa9e4066Sahrens 			break;
783fa9e4066Sahrens 
784fa9e4066Sahrens 		/* that flavor failed */
785fa9e4066Sahrens 		acl_styles &= ~acl_flavor;
786fa9e4066Sahrens 	}
787fa9e4066Sahrens 
788fa9e4066Sahrens 	/* if all styles fail then assume trivial */
789fa9e4066Sahrens 	if (acl_styles == 0)
790fa9e4066Sahrens 		return (0);
791fa9e4066Sahrens 
792fa9e4066Sahrens 	/* process the flavor that worked */
793fa9e4066Sahrens 	isnontrivial = 0;
794fa9e4066Sahrens 	if (acl_flavor & _ACL_ACLENT_ENABLED) {
795fa9e4066Sahrens 		if (vsecattr.vsa_aclcnt > MIN_ACL_ENTRIES)
796fa9e4066Sahrens 			isnontrivial = 1;
797fa9e4066Sahrens 		if (vsecattr.vsa_aclcnt && vsecattr.vsa_aclentp != NULL)
798fa9e4066Sahrens 			kmem_free(vsecattr.vsa_aclentp,
799fa9e4066Sahrens 			    vsecattr.vsa_aclcnt * sizeof (aclent_t));
800fa9e4066Sahrens 		if (vsecattr.vsa_dfaclcnt && vsecattr.vsa_dfaclentp != NULL)
801fa9e4066Sahrens 			kmem_free(vsecattr.vsa_dfaclentp,
802fa9e4066Sahrens 			    vsecattr.vsa_dfaclcnt * sizeof (aclent_t));
803fa9e4066Sahrens 	}
804fa9e4066Sahrens 	if (acl_flavor & _ACL_ACE_ENABLED) {
805fa9e4066Sahrens 
806fa9e4066Sahrens 		isnontrivial = ace_trivial(vsecattr.vsa_aclentp,
807fa9e4066Sahrens 		    vsecattr.vsa_aclcnt);
808fa9e4066Sahrens 
809fa9e4066Sahrens 		if (vsecattr.vsa_aclcnt && vsecattr.vsa_aclentp != NULL)
810fa9e4066Sahrens 			kmem_free(vsecattr.vsa_aclentp,
811fa9e4066Sahrens 			    vsecattr.vsa_aclcnt * sizeof (ace_t));
812fa9e4066Sahrens 		/* ACE has no vsecattr.vsa_dfaclcnt */
813fa9e4066Sahrens 	}
814fa9e4066Sahrens 	return (isnontrivial);
815fa9e4066Sahrens }
816dd29fa4aSprabahar 
817dd29fa4aSprabahar /*
818dd29fa4aSprabahar  * Check whether we need a retry to recover from STALE error.
819dd29fa4aSprabahar  */
820dd29fa4aSprabahar int
821dd29fa4aSprabahar fs_need_estale_retry(int retry_count)
822dd29fa4aSprabahar {
823dd29fa4aSprabahar 	if (retry_count < fs_estale_retry)
824dd29fa4aSprabahar 		return (1);
825dd29fa4aSprabahar 	else
826dd29fa4aSprabahar 		return (0);
827dd29fa4aSprabahar }
828*da6c28aaSamw 
829*da6c28aaSamw 
830*da6c28aaSamw static int (*fs_av_scan)(vnode_t *, cred_t *, int) = NULL;
831*da6c28aaSamw 
832*da6c28aaSamw /*
833*da6c28aaSamw  * Routine for anti-virus scanner to call to register its scanning routine.
834*da6c28aaSamw  */
835*da6c28aaSamw void
836*da6c28aaSamw fs_vscan_register(int (*av_scan)(vnode_t *, cred_t *, int))
837*da6c28aaSamw {
838*da6c28aaSamw 	fs_av_scan = av_scan;
839*da6c28aaSamw }
840*da6c28aaSamw 
841*da6c28aaSamw /*
842*da6c28aaSamw  * Routine for file systems to call to initiate anti-virus scanning.
843*da6c28aaSamw  * Scanning will only be done on REGular files (currently).
844*da6c28aaSamw  */
845*da6c28aaSamw int
846*da6c28aaSamw fs_vscan(vnode_t *vp, cred_t *cr, int async)
847*da6c28aaSamw {
848*da6c28aaSamw 	int ret = 0;
849*da6c28aaSamw 
850*da6c28aaSamw 	if (fs_av_scan && vp->v_type == VREG)
851*da6c28aaSamw 		ret = (*fs_av_scan)(vp, cr, async);
852*da6c28aaSamw 
853*da6c28aaSamw 	return (ret);
854*da6c28aaSamw }
855