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