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 5*da6c28aaSamw * Common Development and Distribution License (the "License"). 6*da6c28aaSamw * 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 /* 22*da6c28aaSamw * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <sys/types.h> 297c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 307c478bd9Sstevel@tonic-gate #include <sys/param.h> 317c478bd9Sstevel@tonic-gate #include <sys/systm.h> 327c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 337c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 347c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 357c478bd9Sstevel@tonic-gate #include <sys/share.h> 367c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 377c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 387c478bd9Sstevel@tonic-gate #include <sys/debug.h> 397c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 407c478bd9Sstevel@tonic-gate #include <sys/errno.h> 417c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate int share_debug = 0; 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #ifdef DEBUG 467c478bd9Sstevel@tonic-gate static void print_shares(struct vnode *); 477c478bd9Sstevel@tonic-gate static void print_share(struct shrlock *); 487c478bd9Sstevel@tonic-gate #endif 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate static int isreadonly(struct vnode *); 517c478bd9Sstevel@tonic-gate static int lock_blocks_share(struct vnode *, struct shrlock *); 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* 547c478bd9Sstevel@tonic-gate * Add the share reservation shr to vp. 557c478bd9Sstevel@tonic-gate */ 567c478bd9Sstevel@tonic-gate int 577c478bd9Sstevel@tonic-gate add_share(struct vnode *vp, struct shrlock *shr) 587c478bd9Sstevel@tonic-gate { 597c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * An access of zero is not legal, however some older clients 637c478bd9Sstevel@tonic-gate * generate it anyways. Allow the request only if it is 647c478bd9Sstevel@tonic-gate * coming from a remote system. Be generous in what you 657c478bd9Sstevel@tonic-gate * accept and strict in what you send. 667c478bd9Sstevel@tonic-gate */ 677c478bd9Sstevel@tonic-gate if ((shr->s_access == 0) && (GETSYSID(shr->s_sysid) == 0)) { 687c478bd9Sstevel@tonic-gate return (EINVAL); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate /* 727c478bd9Sstevel@tonic-gate * Sanity check to make sure we have valid options. 737c478bd9Sstevel@tonic-gate * There is known overlap but it doesn't hurt to be careful. 747c478bd9Sstevel@tonic-gate */ 75*da6c28aaSamw if (shr->s_access & ~(F_RDACC|F_WRACC|F_RWACC|F_RMACC|F_MDACC)) { 767c478bd9Sstevel@tonic-gate return (EINVAL); 777c478bd9Sstevel@tonic-gate } 787c478bd9Sstevel@tonic-gate if (shr->s_deny & ~(F_NODNY|F_RDDNY|F_WRDNY|F_RWDNY|F_COMPAT| 79*da6c28aaSamw F_MANDDNY|F_RMDNY)) { 807c478bd9Sstevel@tonic-gate return (EINVAL); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * If the caller wants non-blocking mandatory semantics, make sure 857c478bd9Sstevel@tonic-gate * that there isn't already a conflicting lock. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate if (shr->s_deny & F_MANDDNY) { 887c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 897c478bd9Sstevel@tonic-gate if (lock_blocks_share(vp, shr)) { 907c478bd9Sstevel@tonic-gate return (EAGAIN); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate } 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 957c478bd9Sstevel@tonic-gate for (shrl = vp->v_shrlocks; shrl != NULL; shrl = shrl->next) { 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * If the share owner matches previous request 987c478bd9Sstevel@tonic-gate * do special handling. 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate if ((shrl->shr->s_sysid == shr->s_sysid) && 1017c478bd9Sstevel@tonic-gate (shrl->shr->s_pid == shr->s_pid) && 1027c478bd9Sstevel@tonic-gate (shrl->shr->s_own_len == shr->s_own_len) && 1037c478bd9Sstevel@tonic-gate bcmp(shrl->shr->s_owner, shr->s_owner, 1047c478bd9Sstevel@tonic-gate shr->s_own_len) == 0) { 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* 1077c478bd9Sstevel@tonic-gate * If the existing request is F_COMPAT and 1087c478bd9Sstevel@tonic-gate * is the first share then allow any F_COMPAT 1097c478bd9Sstevel@tonic-gate * from the same process. Trick: If the existing 1107c478bd9Sstevel@tonic-gate * F_COMPAT is write access then it must have 1117c478bd9Sstevel@tonic-gate * the same owner as the first. 1127c478bd9Sstevel@tonic-gate */ 1137c478bd9Sstevel@tonic-gate if ((shrl->shr->s_deny & F_COMPAT) && 1147c478bd9Sstevel@tonic-gate (shr->s_deny & F_COMPAT) && 1157c478bd9Sstevel@tonic-gate ((shrl->next == NULL) || 1167c478bd9Sstevel@tonic-gate (shrl->shr->s_access & F_WRACC))) 1177c478bd9Sstevel@tonic-gate break; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * If a first share has been done in compatibility mode 1227c478bd9Sstevel@tonic-gate * handle the special cases. 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate if ((shrl->shr->s_deny & F_COMPAT) && (shrl->next == NULL)) { 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate if (!(shr->s_deny & F_COMPAT)) { 1277c478bd9Sstevel@tonic-gate /* 1287c478bd9Sstevel@tonic-gate * If not compat and want write access or 1297c478bd9Sstevel@tonic-gate * want to deny read or 1307c478bd9Sstevel@tonic-gate * write exists, fails 1317c478bd9Sstevel@tonic-gate */ 1327c478bd9Sstevel@tonic-gate if ((shr->s_access & F_WRACC) || 1337c478bd9Sstevel@tonic-gate (shr->s_deny & F_RDDNY) || 1347c478bd9Sstevel@tonic-gate (shrl->shr->s_access & F_WRACC)) { 1357c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 1367c478bd9Sstevel@tonic-gate return (EAGAIN); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * If read only file allow, this may allow 1407c478bd9Sstevel@tonic-gate * a deny write but that is meaningless on 1417c478bd9Sstevel@tonic-gate * a read only file. 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate if (isreadonly(vp)) 1447c478bd9Sstevel@tonic-gate break; 1457c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 1467c478bd9Sstevel@tonic-gate return (EAGAIN); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate /* 1497c478bd9Sstevel@tonic-gate * This is a compat request and read access 1507c478bd9Sstevel@tonic-gate * and the first was also read access 1517c478bd9Sstevel@tonic-gate * we always allow it, otherwise we reject because 1527c478bd9Sstevel@tonic-gate * we have handled the only valid write case above. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate if ((shr->s_access == F_RDACC) && 1557c478bd9Sstevel@tonic-gate (shrl->shr->s_access == F_RDACC)) 1567c478bd9Sstevel@tonic-gate break; 1577c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 1587c478bd9Sstevel@tonic-gate return (EAGAIN); 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * If we are trying to share in compatibility mode 1637c478bd9Sstevel@tonic-gate * and the current share is compat (and not the first) 1647c478bd9Sstevel@tonic-gate * we don't know enough. 1657c478bd9Sstevel@tonic-gate */ 1667c478bd9Sstevel@tonic-gate if ((shrl->shr->s_deny & F_COMPAT) && (shr->s_deny & F_COMPAT)) 1677c478bd9Sstevel@tonic-gate continue; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * If this is a compat we check for what can't succeed. 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate if (shr->s_deny & F_COMPAT) { 1737c478bd9Sstevel@tonic-gate /* 1747c478bd9Sstevel@tonic-gate * If we want write access or 1757c478bd9Sstevel@tonic-gate * if anyone is denying read or 1767c478bd9Sstevel@tonic-gate * if anyone has write access we fail 1777c478bd9Sstevel@tonic-gate */ 1787c478bd9Sstevel@tonic-gate if ((shr->s_access & F_WRACC) || 1797c478bd9Sstevel@tonic-gate (shrl->shr->s_deny & F_RDDNY) || 1807c478bd9Sstevel@tonic-gate (shrl->shr->s_access & F_WRACC)) { 1817c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 1827c478bd9Sstevel@tonic-gate return (EAGAIN); 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * If the first was opened with only read access 1867c478bd9Sstevel@tonic-gate * and is a read only file we allow. 1877c478bd9Sstevel@tonic-gate */ 1887c478bd9Sstevel@tonic-gate if (shrl->next == NULL) { 1897c478bd9Sstevel@tonic-gate if ((shrl->shr->s_access == F_RDACC) && 1907c478bd9Sstevel@tonic-gate isreadonly(vp)) { 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate } 1937c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 1947c478bd9Sstevel@tonic-gate return (EAGAIN); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate /* 1977c478bd9Sstevel@tonic-gate * We still can't determine our fate so continue 1987c478bd9Sstevel@tonic-gate */ 1997c478bd9Sstevel@tonic-gate continue; 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate /* 2037c478bd9Sstevel@tonic-gate * Simple bitwise test, if we are trying to access what 2047c478bd9Sstevel@tonic-gate * someone else is denying or we are trying to deny 2057c478bd9Sstevel@tonic-gate * what someone else is accessing we fail. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate if ((shr->s_access & shrl->shr->s_deny) || 2087c478bd9Sstevel@tonic-gate (shr->s_deny & shrl->shr->s_access)) { 2097c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 2107c478bd9Sstevel@tonic-gate return (EAGAIN); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate shrl = kmem_alloc(sizeof (struct shrlocklist), KM_SLEEP); 2157c478bd9Sstevel@tonic-gate shrl->shr = kmem_alloc(sizeof (struct shrlock), KM_SLEEP); 2167c478bd9Sstevel@tonic-gate shrl->shr->s_access = shr->s_access; 2177c478bd9Sstevel@tonic-gate shrl->shr->s_deny = shr->s_deny; 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* 2207c478bd9Sstevel@tonic-gate * Make sure no other deny modes are also set with F_COMPAT 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_COMPAT) 2237c478bd9Sstevel@tonic-gate shrl->shr->s_deny = F_COMPAT; 2247c478bd9Sstevel@tonic-gate shrl->shr->s_sysid = shr->s_sysid; /* XXX ref cnt? */ 2257c478bd9Sstevel@tonic-gate shrl->shr->s_pid = shr->s_pid; 2267c478bd9Sstevel@tonic-gate shrl->shr->s_own_len = shr->s_own_len; 2277c478bd9Sstevel@tonic-gate shrl->shr->s_owner = kmem_alloc(shr->s_own_len, KM_SLEEP); 2287c478bd9Sstevel@tonic-gate bcopy(shr->s_owner, shrl->shr->s_owner, shr->s_own_len); 2297c478bd9Sstevel@tonic-gate shrl->next = vp->v_shrlocks; 2307c478bd9Sstevel@tonic-gate vp->v_shrlocks = shrl; 2317c478bd9Sstevel@tonic-gate #ifdef DEBUG 2327c478bd9Sstevel@tonic-gate if (share_debug) 2337c478bd9Sstevel@tonic-gate print_shares(vp); 2347c478bd9Sstevel@tonic-gate #endif 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate return (0); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * nlmid sysid pid 2437c478bd9Sstevel@tonic-gate * ===== ===== === 2447c478bd9Sstevel@tonic-gate * !=0 !=0 =0 in cluster; NLM lock 2457c478bd9Sstevel@tonic-gate * !=0 =0 =0 in cluster; special case for NLM lock 2467c478bd9Sstevel@tonic-gate * !=0 =0 !=0 in cluster; PXFS local lock 2477c478bd9Sstevel@tonic-gate * !=0 !=0 !=0 cannot happen 2487c478bd9Sstevel@tonic-gate * =0 !=0 =0 not in cluster; NLM lock 2497c478bd9Sstevel@tonic-gate * =0 =0 !=0 not in cluster; local lock 2507c478bd9Sstevel@tonic-gate * =0 =0 =0 cannot happen 2517c478bd9Sstevel@tonic-gate * =0 !=0 !=0 cannot happen 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate static int 2547c478bd9Sstevel@tonic-gate is_match_for_del(struct shrlock *shr, struct shrlock *element) 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate int nlmid1, nlmid2; 2577c478bd9Sstevel@tonic-gate int result = 0; 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate nlmid1 = GETNLMID(shr->s_sysid); 2607c478bd9Sstevel@tonic-gate nlmid2 = GETNLMID(element->s_sysid); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate if (nlmid1 != 0) { /* in a cluster */ 2637c478bd9Sstevel@tonic-gate if (GETSYSID(shr->s_sysid) != 0 && shr->s_pid == 0) { 2647c478bd9Sstevel@tonic-gate /* 2657c478bd9Sstevel@tonic-gate * Lock obtained through nlm server. Just need to 2667c478bd9Sstevel@tonic-gate * compare whole sysids. pid will always = 0. 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate result = shr->s_sysid == element->s_sysid; 2697c478bd9Sstevel@tonic-gate } else if (GETSYSID(shr->s_sysid) == 0 && shr->s_pid == 0) { 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * This is a special case. The NLM server wishes to 2727c478bd9Sstevel@tonic-gate * delete all share locks obtained through nlmid1. 2737c478bd9Sstevel@tonic-gate */ 2747c478bd9Sstevel@tonic-gate result = (nlmid1 == nlmid2); 2757c478bd9Sstevel@tonic-gate } else if (GETSYSID(shr->s_sysid) == 0 && shr->s_pid != 0) { 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * Lock obtained locally through PXFS. Match nlmids 2787c478bd9Sstevel@tonic-gate * and pids. 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate result = (nlmid1 == nlmid2 && 2817c478bd9Sstevel@tonic-gate shr->s_pid == element->s_pid); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate } else { /* not in a cluster */ 2847c478bd9Sstevel@tonic-gate result = ((shr->s_sysid == 0 && 2857c478bd9Sstevel@tonic-gate shr->s_pid == element->s_pid) || 2867c478bd9Sstevel@tonic-gate (shr->s_sysid != 0 && 2877c478bd9Sstevel@tonic-gate shr->s_sysid == element->s_sysid)); 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate return (result); 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate /* 2937c478bd9Sstevel@tonic-gate * Delete the given share reservation. Returns 0 if okay, EINVAL if the 2947c478bd9Sstevel@tonic-gate * share could not be found. If the share reservation is an NBMAND share 2957c478bd9Sstevel@tonic-gate * reservation, signal anyone waiting for the share to go away (e.g., 2967c478bd9Sstevel@tonic-gate * blocking lock requests). 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate int 3007c478bd9Sstevel@tonic-gate del_share(struct vnode *vp, struct shrlock *shr) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 3037c478bd9Sstevel@tonic-gate struct shrlocklist **shrlp; 3047c478bd9Sstevel@tonic-gate int found = 0; 3057c478bd9Sstevel@tonic-gate int is_nbmand = 0; 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 3087c478bd9Sstevel@tonic-gate /* 3097c478bd9Sstevel@tonic-gate * Delete the shares with the matching sysid and owner 3107c478bd9Sstevel@tonic-gate * But if own_len == 0 and sysid == 0 delete all with matching pid 3117c478bd9Sstevel@tonic-gate * But if own_len == 0 delete all with matching sysid. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate shrlp = &vp->v_shrlocks; 3147c478bd9Sstevel@tonic-gate while (*shrlp) { 3157c478bd9Sstevel@tonic-gate if ((shr->s_own_len == (*shrlp)->shr->s_own_len && 3167c478bd9Sstevel@tonic-gate (bcmp(shr->s_owner, (*shrlp)->shr->s_owner, 3177c478bd9Sstevel@tonic-gate shr->s_own_len) == 0)) || 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate (shr->s_own_len == 0 && 3207c478bd9Sstevel@tonic-gate is_match_for_del(shr, (*shrlp)->shr))) { 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate shrl = *shrlp; 3237c478bd9Sstevel@tonic-gate *shrlp = shrl->next; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_MANDDNY) 3267c478bd9Sstevel@tonic-gate is_nbmand = 1; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* XXX deref sysid */ 3297c478bd9Sstevel@tonic-gate kmem_free(shrl->shr->s_owner, shrl->shr->s_own_len); 3307c478bd9Sstevel@tonic-gate kmem_free(shrl->shr, sizeof (struct shrlock)); 3317c478bd9Sstevel@tonic-gate kmem_free(shrl, sizeof (struct shrlocklist)); 3327c478bd9Sstevel@tonic-gate found++; 3337c478bd9Sstevel@tonic-gate continue; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate shrlp = &(*shrlp)->next; 3367c478bd9Sstevel@tonic-gate } 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate if (is_nbmand) 3397c478bd9Sstevel@tonic-gate cv_broadcast(&vp->v_cv); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 3427c478bd9Sstevel@tonic-gate return (found ? 0 : EINVAL); 3437c478bd9Sstevel@tonic-gate } 3447c478bd9Sstevel@tonic-gate 3457c478bd9Sstevel@tonic-gate /* 3467c478bd9Sstevel@tonic-gate * Clean up all local share reservations that the given process has with 3477c478bd9Sstevel@tonic-gate * the given file. 3487c478bd9Sstevel@tonic-gate */ 3497c478bd9Sstevel@tonic-gate void 3507c478bd9Sstevel@tonic-gate cleanshares(struct vnode *vp, pid_t pid) 3517c478bd9Sstevel@tonic-gate { 3527c478bd9Sstevel@tonic-gate struct shrlock shr; 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if (vp->v_shrlocks == NULL) 3557c478bd9Sstevel@tonic-gate return; 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate shr.s_access = 0; 3587c478bd9Sstevel@tonic-gate shr.s_deny = 0; 3597c478bd9Sstevel@tonic-gate shr.s_pid = pid; 3607c478bd9Sstevel@tonic-gate shr.s_sysid = 0; 3617c478bd9Sstevel@tonic-gate shr.s_own_len = 0; 3627c478bd9Sstevel@tonic-gate shr.s_owner = NULL; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate (void) del_share(vp, &shr); 3657c478bd9Sstevel@tonic-gate } 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate static int 3687c478bd9Sstevel@tonic-gate is_match_for_has_remote(int32_t sysid1, int32_t sysid2) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate int result = 0; 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate if (GETNLMID(sysid1) != 0) { /* in a cluster */ 3737c478bd9Sstevel@tonic-gate if (GETSYSID(sysid1) != 0) { 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * Lock obtained through nlm server. Just need to 3767c478bd9Sstevel@tonic-gate * compare whole sysids. 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate result = (sysid1 == sysid2); 3797c478bd9Sstevel@tonic-gate } else if (GETSYSID(sysid1) == 0) { 3807c478bd9Sstevel@tonic-gate /* 3817c478bd9Sstevel@tonic-gate * This is a special case. The NLM server identified 3827c478bd9Sstevel@tonic-gate * by nlmid1 wishes to find out if it has obtained 3837c478bd9Sstevel@tonic-gate * any share locks on the vnode. 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate result = (GETNLMID(sysid1) == GETNLMID(sysid2)); 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate } else { /* not in a cluster */ 3887c478bd9Sstevel@tonic-gate result = ((sysid1 != 0 && sysid1 == sysid2) || 3897c478bd9Sstevel@tonic-gate (sysid1 == 0 && sysid2 != 0)); 3907c478bd9Sstevel@tonic-gate } 3917c478bd9Sstevel@tonic-gate return (result); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* 3967c478bd9Sstevel@tonic-gate * Determine whether there are any shares for the given vnode 3977c478bd9Sstevel@tonic-gate * with a remote sysid. Returns zero if not, non-zero if there are. 3987c478bd9Sstevel@tonic-gate * If sysid is non-zero then determine if this sysid has a share. 3997c478bd9Sstevel@tonic-gate * 4007c478bd9Sstevel@tonic-gate * Note that the return value from this function is potentially invalid 4017c478bd9Sstevel@tonic-gate * once it has been returned. The caller is responsible for providing its 4027c478bd9Sstevel@tonic-gate * own synchronization mechanism to ensure that the return value is useful. 4037c478bd9Sstevel@tonic-gate */ 4047c478bd9Sstevel@tonic-gate int 4057c478bd9Sstevel@tonic-gate shr_has_remote_shares(vnode_t *vp, int32_t sysid) 4067c478bd9Sstevel@tonic-gate { 4077c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 4087c478bd9Sstevel@tonic-gate int result = 0; 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 4117c478bd9Sstevel@tonic-gate shrl = vp->v_shrlocks; 4127c478bd9Sstevel@tonic-gate while (shrl) { 4137c478bd9Sstevel@tonic-gate if (is_match_for_has_remote(sysid, shrl->shr->s_sysid)) { 4147c478bd9Sstevel@tonic-gate 4157c478bd9Sstevel@tonic-gate result = 1; 4167c478bd9Sstevel@tonic-gate break; 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate shrl = shrl->next; 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 4217c478bd9Sstevel@tonic-gate return (result); 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate static int 4257c478bd9Sstevel@tonic-gate isreadonly(struct vnode *vp) 4267c478bd9Sstevel@tonic-gate { 4277c478bd9Sstevel@tonic-gate return (vp->v_type != VCHR && vp->v_type != VBLK && 4287c478bd9Sstevel@tonic-gate vp->v_type != VFIFO && vn_is_readonly(vp)); 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate #ifdef DEBUG 4327c478bd9Sstevel@tonic-gate static void 4337c478bd9Sstevel@tonic-gate print_shares(struct vnode *vp) 4347c478bd9Sstevel@tonic-gate { 4357c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate if (vp->v_shrlocks == NULL) { 4387c478bd9Sstevel@tonic-gate printf("<NULL>\n"); 4397c478bd9Sstevel@tonic-gate return; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate shrl = vp->v_shrlocks; 4437c478bd9Sstevel@tonic-gate while (shrl) { 4447c478bd9Sstevel@tonic-gate print_share(shrl->shr); 4457c478bd9Sstevel@tonic-gate shrl = shrl->next; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate static void 4507c478bd9Sstevel@tonic-gate print_share(struct shrlock *shr) 4517c478bd9Sstevel@tonic-gate { 4527c478bd9Sstevel@tonic-gate int i; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate if (shr == NULL) { 4557c478bd9Sstevel@tonic-gate printf("<NULL>\n"); 4567c478bd9Sstevel@tonic-gate return; 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate printf(" access(%d): ", shr->s_access); 4607c478bd9Sstevel@tonic-gate if (shr->s_access & F_RDACC) 4617c478bd9Sstevel@tonic-gate printf("R"); 4627c478bd9Sstevel@tonic-gate if (shr->s_access & F_WRACC) 4637c478bd9Sstevel@tonic-gate printf("W"); 4647c478bd9Sstevel@tonic-gate if ((shr->s_access & (F_RDACC|F_WRACC)) == 0) 4657c478bd9Sstevel@tonic-gate printf("N"); 4667c478bd9Sstevel@tonic-gate printf("\n"); 4677c478bd9Sstevel@tonic-gate printf(" deny: "); 4687c478bd9Sstevel@tonic-gate if (shr->s_deny & F_COMPAT) 4697c478bd9Sstevel@tonic-gate printf("C"); 4707c478bd9Sstevel@tonic-gate if (shr->s_deny & F_RDDNY) 4717c478bd9Sstevel@tonic-gate printf("R"); 4727c478bd9Sstevel@tonic-gate if (shr->s_deny & F_WRDNY) 4737c478bd9Sstevel@tonic-gate printf("W"); 4747c478bd9Sstevel@tonic-gate if (shr->s_deny == F_NODNY) 4757c478bd9Sstevel@tonic-gate printf("N"); 4767c478bd9Sstevel@tonic-gate printf("\n"); 4777c478bd9Sstevel@tonic-gate printf(" sysid: %d\n", shr->s_sysid); 4787c478bd9Sstevel@tonic-gate printf(" pid: %d\n", shr->s_pid); 4797c478bd9Sstevel@tonic-gate printf(" owner: [%d]", shr->s_own_len); 4807c478bd9Sstevel@tonic-gate printf("'"); 4817c478bd9Sstevel@tonic-gate for (i = 0; i < shr->s_own_len; i++) 4827c478bd9Sstevel@tonic-gate printf("%02x", (unsigned)shr->s_owner[i]); 4837c478bd9Sstevel@tonic-gate printf("'\n"); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate #endif 4867c478bd9Sstevel@tonic-gate 4877c478bd9Sstevel@tonic-gate /* 4887c478bd9Sstevel@tonic-gate * Return non-zero if the given I/O request conflicts with a registered 4897c478bd9Sstevel@tonic-gate * share reservation. 490*da6c28aaSamw * 491*da6c28aaSamw * A process is identified by the tuple (sysid, pid). When the caller 492*da6c28aaSamw * context is passed to nbl_share_conflict, the sysid and pid in the 493*da6c28aaSamw * caller context are used. Otherwise the sysid is zero, and the pid is 494*da6c28aaSamw * taken from the current process. 495*da6c28aaSamw * 496*da6c28aaSamw * Conflict Algorithm: 497*da6c28aaSamw * 1. An op request of NBL_READ will fail if a different 498*da6c28aaSamw * process has a mandatory share reservation with deny read. 499*da6c28aaSamw * 500*da6c28aaSamw * 2. An op request of NBL_WRITE will fail if a different 501*da6c28aaSamw * process has a mandatory share reservation with deny write. 502*da6c28aaSamw * 503*da6c28aaSamw * 3. An op request of NBL_READWRITE will fail if a different 504*da6c28aaSamw * process has a mandatory share reservation with deny read 505*da6c28aaSamw * or deny write. 506*da6c28aaSamw * 507*da6c28aaSamw * 4. An op request of NBL_REMOVE will fail if there is 508*da6c28aaSamw * a mandatory share reservation with an access of read, 509*da6c28aaSamw * write, or remove. (Anything other than meta data access). 510*da6c28aaSamw * 511*da6c28aaSamw * 5. An op request of NBL_RENAME will fail if there is 512*da6c28aaSamw * a mandatory share reservation with: 513*da6c28aaSamw * a) access write or access remove 514*da6c28aaSamw * or 515*da6c28aaSamw * b) access read and deny remove 516*da6c28aaSamw * 517*da6c28aaSamw * Otherwise there is no conflict and the op request succeeds. 518*da6c28aaSamw * 519*da6c28aaSamw * This behavior is required for interoperability between 520*da6c28aaSamw * the nfs server, cifs server, and local access. 521*da6c28aaSamw * This behavior can result in non-posix semantics. 522*da6c28aaSamw * 523*da6c28aaSamw * When mandatory share reservations are enabled, a process 524*da6c28aaSamw * should call nbl_share_conflict to determine if the 525*da6c28aaSamw * desired operation would conflict with an existing share 526*da6c28aaSamw * reservation. 527*da6c28aaSamw * 528*da6c28aaSamw * The call to nbl_share_conflict may be skipped if the 529*da6c28aaSamw * process has an existing share reservation and the operation 530*da6c28aaSamw * is being performed in the context of that existing share 531*da6c28aaSamw * reservation. 5327c478bd9Sstevel@tonic-gate */ 5337c478bd9Sstevel@tonic-gate int 534*da6c28aaSamw nbl_share_conflict(vnode_t *vp, nbl_op_t op, caller_context_t *ct) 5357c478bd9Sstevel@tonic-gate { 5367c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 5377c478bd9Sstevel@tonic-gate int conflict = 0; 538*da6c28aaSamw pid_t pid; 539*da6c28aaSamw int sysid; 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 5427c478bd9Sstevel@tonic-gate 543*da6c28aaSamw if (ct == NULL) { 544*da6c28aaSamw pid = curproc->p_pid; 545*da6c28aaSamw sysid = 0; 546*da6c28aaSamw } else { 547*da6c28aaSamw pid = ct->cc_pid; 548*da6c28aaSamw sysid = ct->cc_sysid; 549*da6c28aaSamw } 550*da6c28aaSamw 5517c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 5527c478bd9Sstevel@tonic-gate for (shrl = vp->v_shrlocks; shrl != NULL; shrl = shrl->next) { 553*da6c28aaSamw if (!(shrl->shr->s_deny & F_MANDDNY)) 554*da6c28aaSamw continue; 555*da6c28aaSamw /* 556*da6c28aaSamw * NBL_READ, NBL_WRITE, and NBL_READWRITE need to 557*da6c28aaSamw * check if the share reservation being examined 558*da6c28aaSamw * belongs to the current process. 559*da6c28aaSamw * NBL_REMOVE and NBL_RENAME do not. 560*da6c28aaSamw * This behavior is required by the conflict 561*da6c28aaSamw * algorithm described above. 562*da6c28aaSamw */ 5637c478bd9Sstevel@tonic-gate switch (op) { 5647c478bd9Sstevel@tonic-gate case NBL_READ: 565*da6c28aaSamw if ((shrl->shr->s_deny & F_RDDNY) && 566*da6c28aaSamw (shrl->shr->s_sysid != sysid || 567*da6c28aaSamw shrl->shr->s_pid != pid)) 5687c478bd9Sstevel@tonic-gate conflict = 1; 5697c478bd9Sstevel@tonic-gate break; 5707c478bd9Sstevel@tonic-gate case NBL_WRITE: 571*da6c28aaSamw if ((shrl->shr->s_deny & F_WRDNY) && 572*da6c28aaSamw (shrl->shr->s_sysid != sysid || 573*da6c28aaSamw shrl->shr->s_pid != pid)) 5747c478bd9Sstevel@tonic-gate conflict = 1; 5757c478bd9Sstevel@tonic-gate break; 5767c478bd9Sstevel@tonic-gate case NBL_READWRITE: 577*da6c28aaSamw if ((shrl->shr->s_deny & F_RWDNY) && 578*da6c28aaSamw (shrl->shr->s_sysid != sysid || 579*da6c28aaSamw shrl->shr->s_pid != pid)) 580*da6c28aaSamw conflict = 1; 581*da6c28aaSamw break; 582*da6c28aaSamw case NBL_REMOVE: 583*da6c28aaSamw if (shrl->shr->s_access & (F_RWACC|F_RMACC)) 5847c478bd9Sstevel@tonic-gate conflict = 1; 5857c478bd9Sstevel@tonic-gate break; 5867c478bd9Sstevel@tonic-gate case NBL_RENAME: 587*da6c28aaSamw if (shrl->shr->s_access & (F_WRACC|F_RMACC)) 588*da6c28aaSamw conflict = 1; 589*da6c28aaSamw 590*da6c28aaSamw else if ((shrl->shr->s_access & F_RDACC) && 591*da6c28aaSamw (shrl->shr->s_deny & F_RMDNY)) 5927c478bd9Sstevel@tonic-gate conflict = 1; 5937c478bd9Sstevel@tonic-gate break; 5947c478bd9Sstevel@tonic-gate #ifdef DEBUG 5957c478bd9Sstevel@tonic-gate default: 5967c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 5977c478bd9Sstevel@tonic-gate "nbl_share_conflict: bogus op (%d)", 5987c478bd9Sstevel@tonic-gate op); 5997c478bd9Sstevel@tonic-gate break; 6007c478bd9Sstevel@tonic-gate #endif 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate if (conflict) 6037c478bd9Sstevel@tonic-gate break; 6047c478bd9Sstevel@tonic-gate } 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 6077c478bd9Sstevel@tonic-gate return (conflict); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Return non-zero if the given lock request conflicts with an existing 6127c478bd9Sstevel@tonic-gate * non-blocking mandatory share reservation. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate int 6167c478bd9Sstevel@tonic-gate share_blocks_lock(vnode_t *vp, flock64_t *flkp) 6177c478bd9Sstevel@tonic-gate { 618*da6c28aaSamw caller_context_t ct; 619*da6c28aaSamw 6207c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 6217c478bd9Sstevel@tonic-gate 622*da6c28aaSamw ct.cc_pid = flkp->l_pid; 623*da6c28aaSamw ct.cc_sysid = flkp->l_sysid; 624*da6c28aaSamw ct.cc_caller_id = 0; 625*da6c28aaSamw 6267c478bd9Sstevel@tonic-gate if ((flkp->l_type == F_RDLCK || flkp->l_type == F_WRLCK) && 627*da6c28aaSamw nbl_share_conflict(vp, nbl_lock_to_op(flkp->l_type), &ct)) 6287c478bd9Sstevel@tonic-gate return (1); 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate return (0); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate /* 6347c478bd9Sstevel@tonic-gate * Wait for all share reservations to go away that block the given lock 6357c478bd9Sstevel@tonic-gate * request. Returns 0 after successfully waiting, or EINTR. 6367c478bd9Sstevel@tonic-gate */ 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate int 6397c478bd9Sstevel@tonic-gate wait_for_share(vnode_t *vp, flock64_t *flkp) 6407c478bd9Sstevel@tonic-gate { 6417c478bd9Sstevel@tonic-gate int result = 0; 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * We have to hold the vnode's lock before leaving the nbmand 6477c478bd9Sstevel@tonic-gate * critical region, to prevent a race with the thread that deletes 6487c478bd9Sstevel@tonic-gate * the share that's blocking us. Then we have to drop the lock 6497c478bd9Sstevel@tonic-gate * before reentering the critical region, to avoid a deadlock. 6507c478bd9Sstevel@tonic-gate */ 6517c478bd9Sstevel@tonic-gate while (result == 0 && share_blocks_lock(vp, flkp)) { 6527c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 6537c478bd9Sstevel@tonic-gate nbl_end_crit(vp); 6547c478bd9Sstevel@tonic-gate if (cv_wait_sig(&vp->v_cv, &vp->v_lock) == 0) 6557c478bd9Sstevel@tonic-gate result = EINTR; 6567c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 6577c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_WRITER); 6587c478bd9Sstevel@tonic-gate } 6597c478bd9Sstevel@tonic-gate 6607c478bd9Sstevel@tonic-gate return (result); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate /* 6647c478bd9Sstevel@tonic-gate * Determine if the given share reservation conflicts with any existing 6657c478bd9Sstevel@tonic-gate * locks or mapped regions for the file. This is used to compensate for 6667c478bd9Sstevel@tonic-gate * the fact that most Unix applications don't get a share reservation, so 6677c478bd9Sstevel@tonic-gate * we use existing locks as an indication of what files are open. 6687c478bd9Sstevel@tonic-gate * 6697c478bd9Sstevel@tonic-gate * XXX needs a better name to reflect that it also looks for mapped file 6707c478bd9Sstevel@tonic-gate * conflicts. 6717c478bd9Sstevel@tonic-gate * 6727c478bd9Sstevel@tonic-gate * Returns non-zero if there is a conflict, zero if okay. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate static int 6767c478bd9Sstevel@tonic-gate lock_blocks_share(vnode_t *vp, struct shrlock *shr) 6777c478bd9Sstevel@tonic-gate { 6787c478bd9Sstevel@tonic-gate struct flock64 lck; 6797c478bd9Sstevel@tonic-gate int error; 680*da6c28aaSamw v_mode_t mode = 0; 6817c478bd9Sstevel@tonic-gate 6827c478bd9Sstevel@tonic-gate if ((shr->s_deny & (F_RWDNY|F_COMPAT)) == 0) { 6837c478bd9Sstevel@tonic-gate /* if no deny mode, then there's no conflict */ 6847c478bd9Sstevel@tonic-gate return (0); 6857c478bd9Sstevel@tonic-gate } 6867c478bd9Sstevel@tonic-gate 687*da6c28aaSamw /* check for conflict with mapped region */ 688*da6c28aaSamw if ((shr->s_deny & F_RWDNY) == F_WRDNY) { 689*da6c28aaSamw mode = V_WRITE; 690*da6c28aaSamw } else if ((shr->s_deny & F_RWDNY) == F_RDDNY) { 691*da6c28aaSamw mode = V_READ; 692*da6c28aaSamw } else { 693*da6c28aaSamw mode = V_RDORWR; 694*da6c28aaSamw } 695*da6c28aaSamw if (vn_is_mapped(vp, mode)) 696*da6c28aaSamw return (1); 6977c478bd9Sstevel@tonic-gate 698*da6c28aaSamw lck.l_type = ((shr->s_deny & F_RDDNY) ? F_WRLCK : F_RDLCK); 6997c478bd9Sstevel@tonic-gate lck.l_whence = 0; 7007c478bd9Sstevel@tonic-gate lck.l_start = 0; 7017c478bd9Sstevel@tonic-gate lck.l_len = 0; /* to EOF */ 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate /* XXX should use non-NULL cred? */ 704*da6c28aaSamw error = VOP_FRLOCK(vp, F_GETLK, &lck, 0, 0, NULL, NULL, NULL); 7057c478bd9Sstevel@tonic-gate if (error != 0) { 7067c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "lock_blocks_share: unexpected error (%d)", 7077c478bd9Sstevel@tonic-gate error); 7087c478bd9Sstevel@tonic-gate return (1); 7097c478bd9Sstevel@tonic-gate } 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate return (lck.l_type == F_UNLCK ? 0 : 1); 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate /* 7157c478bd9Sstevel@tonic-gate * Determine if the given process has a NBMAND share reservation on the 7167c478bd9Sstevel@tonic-gate * given vnode. Returns 1 if the process has such a share reservation, 7177c478bd9Sstevel@tonic-gate * returns 0 otherwise. 7187c478bd9Sstevel@tonic-gate */ 7197c478bd9Sstevel@tonic-gate int 7207c478bd9Sstevel@tonic-gate proc_has_nbmand_share_on_vp(vnode_t *vp, pid_t pid) 7217c478bd9Sstevel@tonic-gate { 7227c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 7237c478bd9Sstevel@tonic-gate 7247c478bd9Sstevel@tonic-gate /* 7257c478bd9Sstevel@tonic-gate * Any NBMAND share reservation on the vp for this process? 7267c478bd9Sstevel@tonic-gate */ 7277c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 7287c478bd9Sstevel@tonic-gate for (shrl = vp->v_shrlocks; shrl != NULL; shrl = shrl->next) { 7297c478bd9Sstevel@tonic-gate if (shrl->shr->s_sysid == 0 && 7307c478bd9Sstevel@tonic-gate (shrl->shr->s_deny & F_MANDDNY) && 7317c478bd9Sstevel@tonic-gate (shrl->shr->s_pid == pid)) { 7327c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 7337c478bd9Sstevel@tonic-gate return (1); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate return (0); 7397c478bd9Sstevel@tonic-gate } 740