xref: /illumos-gate/usr/src/uts/common/fs/fs_subr.c (revision 87bfe94c)
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 /*
2627dd1e87SMark Shellenbaum  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27a3c49ce1SAlbert Lee  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
2880d5689fSPatrick Mooney  * Copyright 2017 Joyent, Inc.
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate  * Generic vnode operations.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/param.h>
367c478bd9Sstevel@tonic-gate #include <sys/systm.h>
377c478bd9Sstevel@tonic-gate #include <sys/errno.h>
387c478bd9Sstevel@tonic-gate #include <sys/fcntl.h>
397c478bd9Sstevel@tonic-gate #include <sys/flock.h>
407c478bd9Sstevel@tonic-gate #include <sys/statvfs.h>
417c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
427c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
437c478bd9Sstevel@tonic-gate #include <sys/proc.h>
447c478bd9Sstevel@tonic-gate #include <sys/user.h>
457c478bd9Sstevel@tonic-gate #include <sys/unistd.h>
467c478bd9Sstevel@tonic-gate #include <sys/cred.h>
477c478bd9Sstevel@tonic-gate #include <sys/poll.h>
487c478bd9Sstevel@tonic-gate #include <sys/debug.h>
497c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
507c478bd9Sstevel@tonic-gate #include <sys/stream.h>
517c478bd9Sstevel@tonic-gate #include <fs/fs_subr.h>
527a286c47SDai Ngo #include <fs/fs_reparse.h>
537a286c47SDai Ngo #include <sys/door.h>
547c478bd9Sstevel@tonic-gate #include <sys/acl.h>
557c478bd9Sstevel@tonic-gate #include <sys/share.h>
567c478bd9Sstevel@tonic-gate #include <sys/file.h>
577c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
587c478bd9Sstevel@tonic-gate #include <sys/file.h>
597c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h>
60fa9e4066Sahrens #include <acl/acl_common.h>
617a286c47SDai Ngo #include <sys/pathname.h>
627c478bd9Sstevel@tonic-gate 
63*87bfe94cSPatrick Mooney /* required for fs_reject_epoll */
64*87bfe94cSPatrick Mooney #include <sys/poll_impl.h>
65*87bfe94cSPatrick Mooney 
667c478bd9Sstevel@tonic-gate static callb_cpr_t *frlock_serialize_blocked(flk_cb_when_t, void *);
677c478bd9Sstevel@tonic-gate 
68dd29fa4aSprabahar /*
69dd29fa4aSprabahar  * Tunable to limit the number of retry to recover from STALE error.
70dd29fa4aSprabahar  */
71dd29fa4aSprabahar int fs_estale_retry = 5;
72dd29fa4aSprabahar 
737a286c47SDai Ngo /*
747a286c47SDai Ngo  * supports for reparse point door upcall
757a286c47SDai Ngo  */
767a286c47SDai Ngo static door_handle_t reparsed_door;
777a286c47SDai Ngo static kmutex_t reparsed_door_lock;
787a286c47SDai Ngo 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * The associated operation is not supported by the file system.
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate int
fs_nosys()837c478bd9Sstevel@tonic-gate fs_nosys()
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	return (ENOSYS);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * The associated operation is invalid (on this vnode).
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate int
fs_inval()927c478bd9Sstevel@tonic-gate fs_inval()
937c478bd9Sstevel@tonic-gate {
947c478bd9Sstevel@tonic-gate 	return (EINVAL);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * The associated operation is valid only for directories.
997c478bd9Sstevel@tonic-gate  */
1007c478bd9Sstevel@tonic-gate int
fs_notdir()1017c478bd9Sstevel@tonic-gate fs_notdir()
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 	return (ENOTDIR);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate /*
1077c478bd9Sstevel@tonic-gate  * Free the file system specific resources. For the file systems that
1087c478bd9Sstevel@tonic-gate  * do not support the forced unmount, it will be a nop function.
1097c478bd9Sstevel@tonic-gate  */
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1127c478bd9Sstevel@tonic-gate void
fs_freevfs(vfs_t * vfsp)1137c478bd9Sstevel@tonic-gate fs_freevfs(vfs_t *vfsp)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate /* ARGSUSED */
1187c478bd9Sstevel@tonic-gate int
fs_nosys_map(struct vnode * vp,offset_t off,struct as * as,caddr_t * addrp,size_t len,uchar_t prot,uchar_t maxprot,uint_t flags,struct cred * cr,caller_context_t * ct)11966848735SMarcel Telka fs_nosys_map(struct vnode *vp, offset_t off, struct as *as, caddr_t *addrp,
12066848735SMarcel Telka     size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr,
12166848735SMarcel Telka     caller_context_t *ct)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	return (ENOSYS);
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate /* ARGSUSED */
1277c478bd9Sstevel@tonic-gate int
fs_nosys_addmap(struct vnode * vp,offset_t off,struct as * as,caddr_t addr,size_t len,uchar_t prot,uchar_t maxprot,uint_t flags,struct cred * cr,caller_context_t * ct)12866848735SMarcel Telka fs_nosys_addmap(struct vnode *vp, offset_t off, struct as *as, caddr_t addr,
12966848735SMarcel Telka     size_t len, uchar_t prot, uchar_t maxprot, uint_t flags, struct cred *cr,
13066848735SMarcel Telka     caller_context_t *ct)
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	return (ENOSYS);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate /* ARGSUSED */
1367c478bd9Sstevel@tonic-gate int
fs_nosys_poll(vnode_t * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)13766848735SMarcel Telka fs_nosys_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
13866848735SMarcel Telka     struct pollhead **phpp, caller_context_t *ct)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	return (ENOSYS);
1417c478bd9Sstevel@tonic-gate }
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate  * The file system has nothing to sync to disk.  However, the
1467c478bd9Sstevel@tonic-gate  * VFS_SYNC operation must not fail.
1477c478bd9Sstevel@tonic-gate  */
1487c478bd9Sstevel@tonic-gate /* ARGSUSED */
1497c478bd9Sstevel@tonic-gate int
fs_sync(struct vfs * vfspp,short flag,cred_t * cr)1507c478bd9Sstevel@tonic-gate fs_sync(struct vfs *vfspp, short flag, cred_t *cr)
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	return (0);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
155da6c28aaSamw /*
156da6c28aaSamw  * Does nothing but VOP_FSYNC must not fail.
157da6c28aaSamw  */
158da6c28aaSamw /* ARGSUSED */
159da6c28aaSamw int
fs_fsync(vnode_t * vp,int syncflag,cred_t * cr,caller_context_t * ct)160da6c28aaSamw fs_fsync(vnode_t *vp, int syncflag, cred_t *cr, caller_context_t *ct)
161da6c28aaSamw {
162da6c28aaSamw 	return (0);
163da6c28aaSamw }
164da6c28aaSamw 
165da6c28aaSamw /*
166da6c28aaSamw  * Does nothing but VOP_PUTPAGE must not fail.
167da6c28aaSamw  */
168da6c28aaSamw /* ARGSUSED */
169da6c28aaSamw int
fs_putpage(vnode_t * vp,offset_t off,size_t len,int flags,cred_t * cr,caller_context_t * ctp)170da6c28aaSamw fs_putpage(vnode_t *vp, offset_t off, size_t len, int flags, cred_t *cr,
17166848735SMarcel Telka     caller_context_t *ctp)
172da6c28aaSamw {
173da6c28aaSamw 	return (0);
174da6c28aaSamw }
175da6c28aaSamw 
176da6c28aaSamw /*
177da6c28aaSamw  * Does nothing but VOP_IOCTL must not fail.
178da6c28aaSamw  */
179da6c28aaSamw /* ARGSUSED */
180da6c28aaSamw int
fs_ioctl(vnode_t * vp,int com,intptr_t data,int flag,cred_t * cred,int * rvalp)181da6c28aaSamw fs_ioctl(vnode_t *vp, int com, intptr_t data, int flag, cred_t *cred,
18266848735SMarcel Telka     int *rvalp)
183da6c28aaSamw {
184da6c28aaSamw 	return (0);
185da6c28aaSamw }
186da6c28aaSamw 
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate  * Read/write lock/unlock.  Does nothing.
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate /* ARGSUSED */
1917c478bd9Sstevel@tonic-gate int
fs_rwlock(vnode_t * vp,int write_lock,caller_context_t * ctp)1927c478bd9Sstevel@tonic-gate fs_rwlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
1937c478bd9Sstevel@tonic-gate {
1947c478bd9Sstevel@tonic-gate 	return (-1);
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /* ARGSUSED */
1987c478bd9Sstevel@tonic-gate void
fs_rwunlock(vnode_t * vp,int write_lock,caller_context_t * ctp)1997c478bd9Sstevel@tonic-gate fs_rwunlock(vnode_t *vp, int write_lock, caller_context_t *ctp)
2007c478bd9Sstevel@tonic-gate {
2017c478bd9Sstevel@tonic-gate }
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /*
2047c478bd9Sstevel@tonic-gate  * Compare two vnodes.
2057c478bd9Sstevel@tonic-gate  */
206da6c28aaSamw /*ARGSUSED2*/
2077c478bd9Sstevel@tonic-gate int
fs_cmp(vnode_t * vp1,vnode_t * vp2,caller_context_t * ct)208da6c28aaSamw fs_cmp(vnode_t *vp1, vnode_t *vp2, caller_context_t *ct)
2097c478bd9Sstevel@tonic-gate {
2107c478bd9Sstevel@tonic-gate 	return (vp1 == vp2);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /*
2147c478bd9Sstevel@tonic-gate  * No-op seek operation.
2157c478bd9Sstevel@tonic-gate  */
2167c478bd9Sstevel@tonic-gate /* ARGSUSED */
2177c478bd9Sstevel@tonic-gate int
fs_seek(vnode_t * vp,offset_t ooff,offset_t * noffp,caller_context_t * ct)218da6c28aaSamw fs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0);
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate /*
2247c478bd9Sstevel@tonic-gate  * File and record locking.
2257c478bd9Sstevel@tonic-gate  */
2267c478bd9Sstevel@tonic-gate /* ARGSUSED */
2277c478bd9Sstevel@tonic-gate int
fs_frlock(vnode_t * vp,int cmd,struct flock64 * bfp,int flag,offset_t offset,flk_callback_t * flk_cbp,cred_t * cr,caller_context_t * ct)22866848735SMarcel Telka fs_frlock(vnode_t *vp, int cmd, struct flock64 *bfp, int flag, offset_t offset,
22966848735SMarcel Telka     flk_callback_t *flk_cbp, cred_t *cr, caller_context_t *ct)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	int frcmd;
2327c478bd9Sstevel@tonic-gate 	int nlmid;
2337c478bd9Sstevel@tonic-gate 	int error = 0;
2347a5aac98SJerry Jelinek 	boolean_t skip_lock = B_FALSE;
2357c478bd9Sstevel@tonic-gate 	flk_callback_t serialize_callback;
2367c478bd9Sstevel@tonic-gate 	int serialize = 0;
237da6c28aaSamw 	v_mode_t mode;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 	switch (cmd) {
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate 	case F_GETLK:
2427c478bd9Sstevel@tonic-gate 	case F_O_GETLK:
2437c478bd9Sstevel@tonic-gate 		if (flag & F_REMOTELOCK) {
2447c478bd9Sstevel@tonic-gate 			frcmd = RCMDLCK;
245da6c28aaSamw 		} else if (flag & F_PXFSLOCK) {
2467c478bd9Sstevel@tonic-gate 			frcmd = PCMDLCK;
247da6c28aaSamw 		} else {
248da6c28aaSamw 			frcmd = 0;
249da6c28aaSamw 			bfp->l_pid = ttoproc(curthread)->p_pid;
250da6c28aaSamw 			bfp->l_sysid = 0;
2517c478bd9Sstevel@tonic-gate 		}
2527c478bd9Sstevel@tonic-gate 		break;
2537c478bd9Sstevel@tonic-gate 
2547a5aac98SJerry Jelinek 	case F_OFD_GETLK:
2557a5aac98SJerry Jelinek 		/*
2567a5aac98SJerry Jelinek 		 * TBD we do not support remote OFD locks at this time.
2577a5aac98SJerry Jelinek 		 */
2587a5aac98SJerry Jelinek 		if (flag & (F_REMOTELOCK | F_PXFSLOCK)) {
2597a5aac98SJerry Jelinek 			error = EINVAL;
2607a5aac98SJerry Jelinek 			goto done;
2617a5aac98SJerry Jelinek 		}
2627a5aac98SJerry Jelinek 		skip_lock = B_TRUE;
2637a5aac98SJerry Jelinek 		break;
2647a5aac98SJerry Jelinek 
2657c478bd9Sstevel@tonic-gate 	case F_SETLK_NBMAND:
2667c478bd9Sstevel@tonic-gate 		/*
2677c478bd9Sstevel@tonic-gate 		 * Are NBMAND locks allowed on this file?
2687c478bd9Sstevel@tonic-gate 		 */
2697c478bd9Sstevel@tonic-gate 		if (!vp->v_vfsp ||
2707c478bd9Sstevel@tonic-gate 		    !(vp->v_vfsp->vfs_flag & VFS_NBMAND)) {
2717c478bd9Sstevel@tonic-gate 			error = EINVAL;
2727c478bd9Sstevel@tonic-gate 			goto done;
2737c478bd9Sstevel@tonic-gate 		}
2747c478bd9Sstevel@tonic-gate 		if (vp->v_type != VREG) {
2757c478bd9Sstevel@tonic-gate 			error = EINVAL;
2767c478bd9Sstevel@tonic-gate 			goto done;
2777c478bd9Sstevel@tonic-gate 		}
2787c478bd9Sstevel@tonic-gate 		/*FALLTHROUGH*/
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	case F_SETLK:
281da6c28aaSamw 		if (flag & F_REMOTELOCK) {
282da6c28aaSamw 			frcmd = SETFLCK|RCMDLCK;
283da6c28aaSamw 		} else if (flag & F_PXFSLOCK) {
284da6c28aaSamw 			frcmd = SETFLCK|PCMDLCK;
285da6c28aaSamw 		} else {
286da6c28aaSamw 			frcmd = SETFLCK;
287da6c28aaSamw 			bfp->l_pid = ttoproc(curthread)->p_pid;
288da6c28aaSamw 			bfp->l_sysid = 0;
289da6c28aaSamw 		}
290da6c28aaSamw 		if (cmd == F_SETLK_NBMAND &&
291da6c28aaSamw 		    (bfp->l_type == F_RDLCK || bfp->l_type == F_WRLCK)) {
292da6c28aaSamw 			frcmd |= NBMLCK;
293da6c28aaSamw 		}
294b89a8333Snatalie li - Sun Microsystems - Irvine United States 
2957c478bd9Sstevel@tonic-gate 		if (nbl_need_check(vp)) {
2967c478bd9Sstevel@tonic-gate 			nbl_start_crit(vp, RW_WRITER);
2977c478bd9Sstevel@tonic-gate 			serialize = 1;
298da6c28aaSamw 			if (frcmd & NBMLCK) {
299da6c28aaSamw 				mode = (bfp->l_type == F_RDLCK) ?
300da6c28aaSamw 				    V_READ : V_RDANDWR;
301da6c28aaSamw 				if (vn_is_mapped(vp, mode)) {
302da6c28aaSamw 					error = EAGAIN;
303da6c28aaSamw 					goto done;
304da6c28aaSamw 				}
305da6c28aaSamw 			}
3067c478bd9Sstevel@tonic-gate 		}
3077c478bd9Sstevel@tonic-gate 		break;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	case F_SETLKW:
310da6c28aaSamw 		if (flag & F_REMOTELOCK) {
311da6c28aaSamw 			frcmd = SETFLCK|SLPFLCK|RCMDLCK;
312da6c28aaSamw 		} else if (flag & F_PXFSLOCK) {
313da6c28aaSamw 			frcmd = SETFLCK|SLPFLCK|PCMDLCK;
314da6c28aaSamw 		} else {
315da6c28aaSamw 			frcmd = SETFLCK|SLPFLCK;
316da6c28aaSamw 			bfp->l_pid = ttoproc(curthread)->p_pid;
317da6c28aaSamw 			bfp->l_sysid = 0;
318da6c28aaSamw 		}
319b89a8333Snatalie li - Sun Microsystems - Irvine United States 
3207c478bd9Sstevel@tonic-gate 		if (nbl_need_check(vp)) {
3217c478bd9Sstevel@tonic-gate 			nbl_start_crit(vp, RW_WRITER);
3227c478bd9Sstevel@tonic-gate 			serialize = 1;
3237c478bd9Sstevel@tonic-gate 		}
3247c478bd9Sstevel@tonic-gate 		break;
3257c478bd9Sstevel@tonic-gate 
3267a5aac98SJerry Jelinek 	case F_OFD_SETLK:
3277a5aac98SJerry Jelinek 	case F_OFD_SETLKW:
3287a5aac98SJerry Jelinek 	case F_FLOCK:
3297a5aac98SJerry Jelinek 	case F_FLOCKW:
3307a5aac98SJerry Jelinek 		/*
3317a5aac98SJerry Jelinek 		 * TBD we do not support remote OFD locks at this time.
3327a5aac98SJerry Jelinek 		 */
3337a5aac98SJerry Jelinek 		if (flag & (F_REMOTELOCK | F_PXFSLOCK)) {
3347a5aac98SJerry Jelinek 			error = EINVAL;
3357a5aac98SJerry Jelinek 			goto done;
3367a5aac98SJerry Jelinek 		}
3377a5aac98SJerry Jelinek 		skip_lock = B_TRUE;
3387a5aac98SJerry Jelinek 		break;
3397a5aac98SJerry Jelinek 
3407c478bd9Sstevel@tonic-gate 	case F_HASREMOTELOCKS:
3417c478bd9Sstevel@tonic-gate 		nlmid = GETNLMID(bfp->l_sysid);
3427c478bd9Sstevel@tonic-gate 		if (nlmid != 0) {	/* booted as a cluster */
3437c478bd9Sstevel@tonic-gate 			l_has_rmt(bfp) =
344da6c28aaSamw 			    cl_flk_has_remote_locks_for_nlmid(vp, nlmid);
3457c478bd9Sstevel@tonic-gate 		} else {		/* not booted as a cluster */
3467c478bd9Sstevel@tonic-gate 			l_has_rmt(bfp) = flk_has_remote_locks(vp);
3477c478bd9Sstevel@tonic-gate 		}
3487c478bd9Sstevel@tonic-gate 
3497c478bd9Sstevel@tonic-gate 		goto done;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	default:
3527c478bd9Sstevel@tonic-gate 		error = EINVAL;
3537c478bd9Sstevel@tonic-gate 		goto done;
3547c478bd9Sstevel@tonic-gate 	}
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	/*
3577c478bd9Sstevel@tonic-gate 	 * If this is a blocking lock request and we're serializing lock
3587c478bd9Sstevel@tonic-gate 	 * requests, modify the callback list to leave the critical region
3597c478bd9Sstevel@tonic-gate 	 * while we're waiting for the lock.
3607c478bd9Sstevel@tonic-gate 	 */
3617c478bd9Sstevel@tonic-gate 
3627c478bd9Sstevel@tonic-gate 	if (serialize && (frcmd & SLPFLCK) != 0) {
3637c478bd9Sstevel@tonic-gate 		flk_add_callback(&serialize_callback,
364da6c28aaSamw 		    frlock_serialize_blocked, vp, flk_cbp);
3657c478bd9Sstevel@tonic-gate 		flk_cbp = &serialize_callback;
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 
3687a5aac98SJerry Jelinek 	if (!skip_lock)
3697a5aac98SJerry Jelinek 		error = reclock(vp, bfp, frcmd, flag, offset, flk_cbp);
3707c478bd9Sstevel@tonic-gate 
37166848735SMarcel Telka 	if (serialize && (frcmd & SLPFLCK) != 0)
37266848735SMarcel Telka 		flk_del_callback(&serialize_callback);
37366848735SMarcel Telka 
3747c478bd9Sstevel@tonic-gate done:
3757c478bd9Sstevel@tonic-gate 	if (serialize)
3767c478bd9Sstevel@tonic-gate 		nbl_end_crit(vp);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	return (error);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate  * Callback when a lock request blocks and we are serializing requests.  If
3837c478bd9Sstevel@tonic-gate  * before sleeping, leave the critical region.  If after wakeup, reenter
3847c478bd9Sstevel@tonic-gate  * the critical region.
3857c478bd9Sstevel@tonic-gate  */
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate static callb_cpr_t *
frlock_serialize_blocked(flk_cb_when_t when,void * infop)3887c478bd9Sstevel@tonic-gate frlock_serialize_blocked(flk_cb_when_t when, void *infop)
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate 	vnode_t *vp = (vnode_t *)infop;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (when == FLK_BEFORE_SLEEP)
3937c478bd9Sstevel@tonic-gate 		nbl_end_crit(vp);
3947c478bd9Sstevel@tonic-gate 	else {
3957c478bd9Sstevel@tonic-gate 		nbl_start_crit(vp, RW_WRITER);
3967c478bd9Sstevel@tonic-gate 	}
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	return (NULL);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate  * Allow any flags.
4037c478bd9Sstevel@tonic-gate  */
4047c478bd9Sstevel@tonic-gate /* ARGSUSED */
4057c478bd9Sstevel@tonic-gate int
fs_setfl(vnode_t * vp,int oflags,int nflags,cred_t * cr,caller_context_t * ct)40666848735SMarcel Telka fs_setfl(vnode_t *vp, int oflags, int nflags, cred_t *cr, caller_context_t *ct)
4077c478bd9Sstevel@tonic-gate {
4087c478bd9Sstevel@tonic-gate 	return (0);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate /*
412*87bfe94cSPatrick Mooney  * Unlike poll(2), epoll should reject attempts to add normal files or
413*87bfe94cSPatrick Mooney  * directories to a given handle.  Most non-pseudo filesystems rely on
414*87bfe94cSPatrick Mooney  * fs_poll() as their implementation of polling behavior.  Exceptions to that
415*87bfe94cSPatrick Mooney  * rule (ufs) can use fs_reject_epoll(), so they don't require access to the
416*87bfe94cSPatrick Mooney  * inner details of poll.  Potential race conditions related to the poll module
417*87bfe94cSPatrick Mooney  * being loaded are avoided by implementing the check here in genunix.
4187c478bd9Sstevel@tonic-gate  */
419*87bfe94cSPatrick Mooney boolean_t
fs_reject_epoll()420*87bfe94cSPatrick Mooney fs_reject_epoll()
421*87bfe94cSPatrick Mooney {
422*87bfe94cSPatrick Mooney 	/* Check if the currently-active pollcache is epoll-enabled. */
423*87bfe94cSPatrick Mooney 	return (curthread->t_pollcache != NULL &&
424*87bfe94cSPatrick Mooney 	    (curthread->t_pollcache->pc_flag & PC_EPOLL) != 0);
425*87bfe94cSPatrick Mooney }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /* ARGSUSED */
4287c478bd9Sstevel@tonic-gate int
fs_poll(vnode_t * vp,short events,int anyyet,short * reventsp,struct pollhead ** phpp,caller_context_t * ct)42966848735SMarcel Telka fs_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
43066848735SMarcel Telka     struct pollhead **phpp, caller_context_t *ct)
4317c478bd9Sstevel@tonic-gate {
43280d5689fSPatrick Mooney 	/*
433*87bfe94cSPatrick Mooney 	 * Regular filesystems should reject epollers.  On the off chance that
434*87bfe94cSPatrick Mooney 	 * a non-epoll consumer expresses the desire for edge-triggered
435*87bfe94cSPatrick Mooney 	 * polling, we reject them too.  Yes, the expected error for this
436*87bfe94cSPatrick Mooney 	 * really is EPERM.
43780d5689fSPatrick Mooney 	 */
438*87bfe94cSPatrick Mooney 	if (fs_reject_epoll() || (events & POLLET) != 0) {
43980d5689fSPatrick Mooney 		return (EPERM);
44080d5689fSPatrick Mooney 	}
44180d5689fSPatrick Mooney 
4427c478bd9Sstevel@tonic-gate 	*reventsp = 0;
4437c478bd9Sstevel@tonic-gate 	if (events & POLLIN)
4447c478bd9Sstevel@tonic-gate 		*reventsp |= POLLIN;
4457c478bd9Sstevel@tonic-gate 	if (events & POLLRDNORM)
4467c478bd9Sstevel@tonic-gate 		*reventsp |= POLLRDNORM;
4477c478bd9Sstevel@tonic-gate 	if (events & POLLRDBAND)
4487c478bd9Sstevel@tonic-gate 		*reventsp |= POLLRDBAND;
4497c478bd9Sstevel@tonic-gate 	if (events & POLLOUT)
4507c478bd9Sstevel@tonic-gate 		*reventsp |= POLLOUT;
4517c478bd9Sstevel@tonic-gate 	if (events & POLLWRBAND)
4527c478bd9Sstevel@tonic-gate 		*reventsp |= POLLWRBAND;
453*87bfe94cSPatrick Mooney 
4547c478bd9Sstevel@tonic-gate 	return (0);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate  * POSIX pathconf() support.
4597c478bd9Sstevel@tonic-gate  */
4607c478bd9Sstevel@tonic-gate /* ARGSUSED */
4617c478bd9Sstevel@tonic-gate int
fs_pathconf(vnode_t * vp,int cmd,ulong_t * valp,cred_t * cr,caller_context_t * ct)46266848735SMarcel Telka fs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
46366848735SMarcel Telka     caller_context_t *ct)
4647c478bd9Sstevel@tonic-gate {
46566848735SMarcel Telka 	ulong_t val;
46666848735SMarcel Telka 	int error = 0;
4677c478bd9Sstevel@tonic-gate 	struct statvfs64 vfsbuf;
4687c478bd9Sstevel@tonic-gate 
4697c478bd9Sstevel@tonic-gate 	switch (cmd) {
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	case _PC_LINK_MAX:
4727c478bd9Sstevel@tonic-gate 		val = MAXLINK;
4737c478bd9Sstevel@tonic-gate 		break;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 	case _PC_MAX_CANON:
4767c478bd9Sstevel@tonic-gate 		val = MAX_CANON;
4777c478bd9Sstevel@tonic-gate 		break;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	case _PC_MAX_INPUT:
4807c478bd9Sstevel@tonic-gate 		val = MAX_INPUT;
4817c478bd9Sstevel@tonic-gate 		break;
4827c478bd9Sstevel@tonic-gate 
4837c478bd9Sstevel@tonic-gate 	case _PC_NAME_MAX:
4847c478bd9Sstevel@tonic-gate 		bzero(&vfsbuf, sizeof (vfsbuf));
4857c478bd9Sstevel@tonic-gate 		if (error = VFS_STATVFS(vp->v_vfsp, &vfsbuf))
4867c478bd9Sstevel@tonic-gate 			break;
4877c478bd9Sstevel@tonic-gate 		val = vfsbuf.f_namemax;
4887c478bd9Sstevel@tonic-gate 		break;
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 	case _PC_PATH_MAX:
4917c478bd9Sstevel@tonic-gate 	case _PC_SYMLINK_MAX:
4927c478bd9Sstevel@tonic-gate 		val = MAXPATHLEN;
4937c478bd9Sstevel@tonic-gate 		break;
4947c478bd9Sstevel@tonic-gate 
4957c478bd9Sstevel@tonic-gate 	case _PC_PIPE_BUF:
4967c478bd9Sstevel@tonic-gate 		val = PIPE_BUF;
4977c478bd9Sstevel@tonic-gate 		break;
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	case _PC_NO_TRUNC:
5007c478bd9Sstevel@tonic-gate 		if (vp->v_vfsp->vfs_flag & VFS_NOTRUNC)
5017c478bd9Sstevel@tonic-gate 			val = 1;	/* NOTRUNC is enabled for vp */
5027c478bd9Sstevel@tonic-gate 		else
5037c478bd9Sstevel@tonic-gate 			val = (ulong_t)-1;
5047c478bd9Sstevel@tonic-gate 		break;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	case _PC_VDISABLE:
5077c478bd9Sstevel@tonic-gate 		val = _POSIX_VDISABLE;
5087c478bd9Sstevel@tonic-gate 		break;
5097c478bd9Sstevel@tonic-gate 
5107c478bd9Sstevel@tonic-gate 	case _PC_CHOWN_RESTRICTED:
5117c478bd9Sstevel@tonic-gate 		if (rstchown)
5127c478bd9Sstevel@tonic-gate 			val = rstchown; /* chown restricted enabled */
5137c478bd9Sstevel@tonic-gate 		else
5147c478bd9Sstevel@tonic-gate 			val = (ulong_t)-1;
5157c478bd9Sstevel@tonic-gate 		break;
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	case _PC_FILESIZEBITS:
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 		/*
5207c478bd9Sstevel@tonic-gate 		 * If ever we come here it means that underlying file system
5217c478bd9Sstevel@tonic-gate 		 * does not recognise the command and therefore this
5227c478bd9Sstevel@tonic-gate 		 * configurable limit cannot be determined. We return -1
5237c478bd9Sstevel@tonic-gate 		 * and don't change errno.
5247c478bd9Sstevel@tonic-gate 		 */
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 		val = (ulong_t)-1;    /* large file support */
5277c478bd9Sstevel@tonic-gate 		break;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	case _PC_ACL_ENABLED:
5307c478bd9Sstevel@tonic-gate 		val = 0;
5317c478bd9Sstevel@tonic-gate 		break;
5327c478bd9Sstevel@tonic-gate 
533da6c28aaSamw 	case _PC_CASE_BEHAVIOR:
534da6c28aaSamw 		val = _CASE_SENSITIVE;
535da6c28aaSamw 		if (vfs_has_feature(vp->v_vfsp, VFSFT_CASEINSENSITIVE) == 1)
536da6c28aaSamw 			val |= _CASE_INSENSITIVE;
537da6c28aaSamw 		if (vfs_has_feature(vp->v_vfsp, VFSFT_NOCASESENSITIVE) == 1)
538da6c28aaSamw 			val &= ~_CASE_SENSITIVE;
539da6c28aaSamw 		break;
540da6c28aaSamw 
541da6c28aaSamw 	case _PC_SATTR_ENABLED:
542da6c28aaSamw 	case _PC_SATTR_EXISTS:
543da6c28aaSamw 		val = 0;
544e802abbdSTim Haley 		break;
545e802abbdSTim Haley 
546e802abbdSTim Haley 	case _PC_ACCESS_FILTERING:
547e802abbdSTim Haley 		val = 0;
548da6c28aaSamw 		break;
549da6c28aaSamw 
5507c478bd9Sstevel@tonic-gate 	default:
5517c478bd9Sstevel@tonic-gate 		error = EINVAL;
5527c478bd9Sstevel@tonic-gate 		break;
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	if (error == 0)
5567c478bd9Sstevel@tonic-gate 		*valp = val;
5577c478bd9Sstevel@tonic-gate 	return (error);
5587c478bd9Sstevel@tonic-gate }
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate  * Dispose of a page.
5627c478bd9Sstevel@tonic-gate  */
5637c478bd9Sstevel@tonic-gate /* ARGSUSED */
5647c478bd9Sstevel@tonic-gate void
fs_dispose(struct vnode * vp,page_t * pp,int fl,int dn,struct cred * cr,caller_context_t * ct)56566848735SMarcel Telka fs_dispose(struct vnode *vp, page_t *pp, int fl, int dn, struct cred *cr,
56666848735SMarcel Telka     caller_context_t *ct)
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate 	ASSERT(fl == B_FREE || fl == B_INVAL);
5707c478bd9Sstevel@tonic-gate 
5717c478bd9Sstevel@tonic-gate 	if (fl == B_FREE)
5727c478bd9Sstevel@tonic-gate 		page_free(pp, dn);
5737c478bd9Sstevel@tonic-gate 	else
5747c478bd9Sstevel@tonic-gate 		page_destroy(pp, dn);
5757c478bd9Sstevel@tonic-gate }
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate /* ARGSUSED */
5787c478bd9S