1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1996-1998,2001,2003 Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/share.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/nbmlock.h> 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate int share_debug = 0; 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 48*7c478bd9Sstevel@tonic-gate static void print_shares(struct vnode *); 49*7c478bd9Sstevel@tonic-gate static void print_share(struct shrlock *); 50*7c478bd9Sstevel@tonic-gate #endif 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate static int isreadonly(struct vnode *); 53*7c478bd9Sstevel@tonic-gate static int lock_blocks_share(struct vnode *, struct shrlock *); 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * Add the share reservation shr to vp. 57*7c478bd9Sstevel@tonic-gate */ 58*7c478bd9Sstevel@tonic-gate int 59*7c478bd9Sstevel@tonic-gate add_share(struct vnode *vp, struct shrlock *shr) 60*7c478bd9Sstevel@tonic-gate { 61*7c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate /* 64*7c478bd9Sstevel@tonic-gate * An access of zero is not legal, however some older clients 65*7c478bd9Sstevel@tonic-gate * generate it anyways. Allow the request only if it is 66*7c478bd9Sstevel@tonic-gate * coming from a remote system. Be generous in what you 67*7c478bd9Sstevel@tonic-gate * accept and strict in what you send. 68*7c478bd9Sstevel@tonic-gate */ 69*7c478bd9Sstevel@tonic-gate if ((shr->s_access == 0) && (GETSYSID(shr->s_sysid) == 0)) { 70*7c478bd9Sstevel@tonic-gate return (EINVAL); 71*7c478bd9Sstevel@tonic-gate } 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate /* 74*7c478bd9Sstevel@tonic-gate * Sanity check to make sure we have valid options. 75*7c478bd9Sstevel@tonic-gate * There is known overlap but it doesn't hurt to be careful. 76*7c478bd9Sstevel@tonic-gate */ 77*7c478bd9Sstevel@tonic-gate if (shr->s_access & ~(F_RDACC|F_WRACC|F_RWACC)) { 78*7c478bd9Sstevel@tonic-gate return (EINVAL); 79*7c478bd9Sstevel@tonic-gate } 80*7c478bd9Sstevel@tonic-gate if (shr->s_deny & ~(F_NODNY|F_RDDNY|F_WRDNY|F_RWDNY|F_COMPAT| 81*7c478bd9Sstevel@tonic-gate F_MANDDNY)) { 82*7c478bd9Sstevel@tonic-gate return (EINVAL); 83*7c478bd9Sstevel@tonic-gate } 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate /* 86*7c478bd9Sstevel@tonic-gate * If the caller wants non-blocking mandatory semantics, make sure 87*7c478bd9Sstevel@tonic-gate * that there isn't already a conflicting lock. 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate if (shr->s_deny & F_MANDDNY) { 90*7c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 91*7c478bd9Sstevel@tonic-gate if (lock_blocks_share(vp, shr)) { 92*7c478bd9Sstevel@tonic-gate return (EAGAIN); 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 97*7c478bd9Sstevel@tonic-gate for (shrl = vp->v_shrlocks; shrl != NULL; shrl = shrl->next) { 98*7c478bd9Sstevel@tonic-gate /* 99*7c478bd9Sstevel@tonic-gate * If the share owner matches previous request 100*7c478bd9Sstevel@tonic-gate * do special handling. 101*7c478bd9Sstevel@tonic-gate */ 102*7c478bd9Sstevel@tonic-gate if ((shrl->shr->s_sysid == shr->s_sysid) && 103*7c478bd9Sstevel@tonic-gate (shrl->shr->s_pid == shr->s_pid) && 104*7c478bd9Sstevel@tonic-gate (shrl->shr->s_own_len == shr->s_own_len) && 105*7c478bd9Sstevel@tonic-gate bcmp(shrl->shr->s_owner, shr->s_owner, 106*7c478bd9Sstevel@tonic-gate shr->s_own_len) == 0) { 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * If the existing request is F_COMPAT and 110*7c478bd9Sstevel@tonic-gate * is the first share then allow any F_COMPAT 111*7c478bd9Sstevel@tonic-gate * from the same process. Trick: If the existing 112*7c478bd9Sstevel@tonic-gate * F_COMPAT is write access then it must have 113*7c478bd9Sstevel@tonic-gate * the same owner as the first. 114*7c478bd9Sstevel@tonic-gate */ 115*7c478bd9Sstevel@tonic-gate if ((shrl->shr->s_deny & F_COMPAT) && 116*7c478bd9Sstevel@tonic-gate (shr->s_deny & F_COMPAT) && 117*7c478bd9Sstevel@tonic-gate ((shrl->next == NULL) || 118*7c478bd9Sstevel@tonic-gate (shrl->shr->s_access & F_WRACC))) 119*7c478bd9Sstevel@tonic-gate break; 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * If a first share has been done in compatibility mode 124*7c478bd9Sstevel@tonic-gate * handle the special cases. 125*7c478bd9Sstevel@tonic-gate */ 126*7c478bd9Sstevel@tonic-gate if ((shrl->shr->s_deny & F_COMPAT) && (shrl->next == NULL)) { 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate if (!(shr->s_deny & F_COMPAT)) { 129*7c478bd9Sstevel@tonic-gate /* 130*7c478bd9Sstevel@tonic-gate * If not compat and want write access or 131*7c478bd9Sstevel@tonic-gate * want to deny read or 132*7c478bd9Sstevel@tonic-gate * write exists, fails 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate if ((shr->s_access & F_WRACC) || 135*7c478bd9Sstevel@tonic-gate (shr->s_deny & F_RDDNY) || 136*7c478bd9Sstevel@tonic-gate (shrl->shr->s_access & F_WRACC)) { 137*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 138*7c478bd9Sstevel@tonic-gate return (EAGAIN); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate /* 141*7c478bd9Sstevel@tonic-gate * If read only file allow, this may allow 142*7c478bd9Sstevel@tonic-gate * a deny write but that is meaningless on 143*7c478bd9Sstevel@tonic-gate * a read only file. 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate if (isreadonly(vp)) 146*7c478bd9Sstevel@tonic-gate break; 147*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 148*7c478bd9Sstevel@tonic-gate return (EAGAIN); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate /* 151*7c478bd9Sstevel@tonic-gate * This is a compat request and read access 152*7c478bd9Sstevel@tonic-gate * and the first was also read access 153*7c478bd9Sstevel@tonic-gate * we always allow it, otherwise we reject because 154*7c478bd9Sstevel@tonic-gate * we have handled the only valid write case above. 155*7c478bd9Sstevel@tonic-gate */ 156*7c478bd9Sstevel@tonic-gate if ((shr->s_access == F_RDACC) && 157*7c478bd9Sstevel@tonic-gate (shrl->shr->s_access == F_RDACC)) 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 160*7c478bd9Sstevel@tonic-gate return (EAGAIN); 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * If we are trying to share in compatibility mode 165*7c478bd9Sstevel@tonic-gate * and the current share is compat (and not the first) 166*7c478bd9Sstevel@tonic-gate * we don't know enough. 167*7c478bd9Sstevel@tonic-gate */ 168*7c478bd9Sstevel@tonic-gate if ((shrl->shr->s_deny & F_COMPAT) && (shr->s_deny & F_COMPAT)) 169*7c478bd9Sstevel@tonic-gate continue; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate /* 172*7c478bd9Sstevel@tonic-gate * If this is a compat we check for what can't succeed. 173*7c478bd9Sstevel@tonic-gate */ 174*7c478bd9Sstevel@tonic-gate if (shr->s_deny & F_COMPAT) { 175*7c478bd9Sstevel@tonic-gate /* 176*7c478bd9Sstevel@tonic-gate * If we want write access or 177*7c478bd9Sstevel@tonic-gate * if anyone is denying read or 178*7c478bd9Sstevel@tonic-gate * if anyone has write access we fail 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate if ((shr->s_access & F_WRACC) || 181*7c478bd9Sstevel@tonic-gate (shrl->shr->s_deny & F_RDDNY) || 182*7c478bd9Sstevel@tonic-gate (shrl->shr->s_access & F_WRACC)) { 183*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 184*7c478bd9Sstevel@tonic-gate return (EAGAIN); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate /* 187*7c478bd9Sstevel@tonic-gate * If the first was opened with only read access 188*7c478bd9Sstevel@tonic-gate * and is a read only file we allow. 189*7c478bd9Sstevel@tonic-gate */ 190*7c478bd9Sstevel@tonic-gate if (shrl->next == NULL) { 191*7c478bd9Sstevel@tonic-gate if ((shrl->shr->s_access == F_RDACC) && 192*7c478bd9Sstevel@tonic-gate isreadonly(vp)) { 193*7c478bd9Sstevel@tonic-gate break; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 196*7c478bd9Sstevel@tonic-gate return (EAGAIN); 197*7c478bd9Sstevel@tonic-gate } 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * We still can't determine our fate so continue 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate continue; 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * Simple bitwise test, if we are trying to access what 206*7c478bd9Sstevel@tonic-gate * someone else is denying or we are trying to deny 207*7c478bd9Sstevel@tonic-gate * what someone else is accessing we fail. 208*7c478bd9Sstevel@tonic-gate */ 209*7c478bd9Sstevel@tonic-gate if ((shr->s_access & shrl->shr->s_deny) || 210*7c478bd9Sstevel@tonic-gate (shr->s_deny & shrl->shr->s_access)) { 211*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 212*7c478bd9Sstevel@tonic-gate return (EAGAIN); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate shrl = kmem_alloc(sizeof (struct shrlocklist), KM_SLEEP); 217*7c478bd9Sstevel@tonic-gate shrl->shr = kmem_alloc(sizeof (struct shrlock), KM_SLEEP); 218*7c478bd9Sstevel@tonic-gate shrl->shr->s_access = shr->s_access; 219*7c478bd9Sstevel@tonic-gate shrl->shr->s_deny = shr->s_deny; 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * Make sure no other deny modes are also set with F_COMPAT 223*7c478bd9Sstevel@tonic-gate */ 224*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_COMPAT) 225*7c478bd9Sstevel@tonic-gate shrl->shr->s_deny = F_COMPAT; 226*7c478bd9Sstevel@tonic-gate shrl->shr->s_sysid = shr->s_sysid; /* XXX ref cnt? */ 227*7c478bd9Sstevel@tonic-gate shrl->shr->s_pid = shr->s_pid; 228*7c478bd9Sstevel@tonic-gate shrl->shr->s_own_len = shr->s_own_len; 229*7c478bd9Sstevel@tonic-gate shrl->shr->s_owner = kmem_alloc(shr->s_own_len, KM_SLEEP); 230*7c478bd9Sstevel@tonic-gate bcopy(shr->s_owner, shrl->shr->s_owner, shr->s_own_len); 231*7c478bd9Sstevel@tonic-gate shrl->next = vp->v_shrlocks; 232*7c478bd9Sstevel@tonic-gate vp->v_shrlocks = shrl; 233*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 234*7c478bd9Sstevel@tonic-gate if (share_debug) 235*7c478bd9Sstevel@tonic-gate print_shares(vp); 236*7c478bd9Sstevel@tonic-gate #endif 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate return (0); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * nlmid sysid pid 245*7c478bd9Sstevel@tonic-gate * ===== ===== === 246*7c478bd9Sstevel@tonic-gate * !=0 !=0 =0 in cluster; NLM lock 247*7c478bd9Sstevel@tonic-gate * !=0 =0 =0 in cluster; special case for NLM lock 248*7c478bd9Sstevel@tonic-gate * !=0 =0 !=0 in cluster; PXFS local lock 249*7c478bd9Sstevel@tonic-gate * !=0 !=0 !=0 cannot happen 250*7c478bd9Sstevel@tonic-gate * =0 !=0 =0 not in cluster; NLM lock 251*7c478bd9Sstevel@tonic-gate * =0 =0 !=0 not in cluster; local lock 252*7c478bd9Sstevel@tonic-gate * =0 =0 =0 cannot happen 253*7c478bd9Sstevel@tonic-gate * =0 !=0 !=0 cannot happen 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate static int 256*7c478bd9Sstevel@tonic-gate is_match_for_del(struct shrlock *shr, struct shrlock *element) 257*7c478bd9Sstevel@tonic-gate { 258*7c478bd9Sstevel@tonic-gate int nlmid1, nlmid2; 259*7c478bd9Sstevel@tonic-gate int result = 0; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate nlmid1 = GETNLMID(shr->s_sysid); 262*7c478bd9Sstevel@tonic-gate nlmid2 = GETNLMID(element->s_sysid); 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (nlmid1 != 0) { /* in a cluster */ 265*7c478bd9Sstevel@tonic-gate if (GETSYSID(shr->s_sysid) != 0 && shr->s_pid == 0) { 266*7c478bd9Sstevel@tonic-gate /* 267*7c478bd9Sstevel@tonic-gate * Lock obtained through nlm server. Just need to 268*7c478bd9Sstevel@tonic-gate * compare whole sysids. pid will always = 0. 269*7c478bd9Sstevel@tonic-gate */ 270*7c478bd9Sstevel@tonic-gate result = shr->s_sysid == element->s_sysid; 271*7c478bd9Sstevel@tonic-gate } else if (GETSYSID(shr->s_sysid) == 0 && shr->s_pid == 0) { 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * This is a special case. The NLM server wishes to 274*7c478bd9Sstevel@tonic-gate * delete all share locks obtained through nlmid1. 275*7c478bd9Sstevel@tonic-gate */ 276*7c478bd9Sstevel@tonic-gate result = (nlmid1 == nlmid2); 277*7c478bd9Sstevel@tonic-gate } else if (GETSYSID(shr->s_sysid) == 0 && shr->s_pid != 0) { 278*7c478bd9Sstevel@tonic-gate /* 279*7c478bd9Sstevel@tonic-gate * Lock obtained locally through PXFS. Match nlmids 280*7c478bd9Sstevel@tonic-gate * and pids. 281*7c478bd9Sstevel@tonic-gate */ 282*7c478bd9Sstevel@tonic-gate result = (nlmid1 == nlmid2 && 283*7c478bd9Sstevel@tonic-gate shr->s_pid == element->s_pid); 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate } else { /* not in a cluster */ 286*7c478bd9Sstevel@tonic-gate result = ((shr->s_sysid == 0 && 287*7c478bd9Sstevel@tonic-gate shr->s_pid == element->s_pid) || 288*7c478bd9Sstevel@tonic-gate (shr->s_sysid != 0 && 289*7c478bd9Sstevel@tonic-gate shr->s_sysid == element->s_sysid)); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate return (result); 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate 294*7c478bd9Sstevel@tonic-gate /* 295*7c478bd9Sstevel@tonic-gate * Delete the given share reservation. Returns 0 if okay, EINVAL if the 296*7c478bd9Sstevel@tonic-gate * share could not be found. If the share reservation is an NBMAND share 297*7c478bd9Sstevel@tonic-gate * reservation, signal anyone waiting for the share to go away (e.g., 298*7c478bd9Sstevel@tonic-gate * blocking lock requests). 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate int 302*7c478bd9Sstevel@tonic-gate del_share(struct vnode *vp, struct shrlock *shr) 303*7c478bd9Sstevel@tonic-gate { 304*7c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 305*7c478bd9Sstevel@tonic-gate struct shrlocklist **shrlp; 306*7c478bd9Sstevel@tonic-gate int found = 0; 307*7c478bd9Sstevel@tonic-gate int is_nbmand = 0; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 310*7c478bd9Sstevel@tonic-gate /* 311*7c478bd9Sstevel@tonic-gate * Delete the shares with the matching sysid and owner 312*7c478bd9Sstevel@tonic-gate * But if own_len == 0 and sysid == 0 delete all with matching pid 313*7c478bd9Sstevel@tonic-gate * But if own_len == 0 delete all with matching sysid. 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate shrlp = &vp->v_shrlocks; 316*7c478bd9Sstevel@tonic-gate while (*shrlp) { 317*7c478bd9Sstevel@tonic-gate if ((shr->s_own_len == (*shrlp)->shr->s_own_len && 318*7c478bd9Sstevel@tonic-gate (bcmp(shr->s_owner, (*shrlp)->shr->s_owner, 319*7c478bd9Sstevel@tonic-gate shr->s_own_len) == 0)) || 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate (shr->s_own_len == 0 && 322*7c478bd9Sstevel@tonic-gate is_match_for_del(shr, (*shrlp)->shr))) { 323*7c478bd9Sstevel@tonic-gate 324*7c478bd9Sstevel@tonic-gate shrl = *shrlp; 325*7c478bd9Sstevel@tonic-gate *shrlp = shrl->next; 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_MANDDNY) 328*7c478bd9Sstevel@tonic-gate is_nbmand = 1; 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate /* XXX deref sysid */ 331*7c478bd9Sstevel@tonic-gate kmem_free(shrl->shr->s_owner, shrl->shr->s_own_len); 332*7c478bd9Sstevel@tonic-gate kmem_free(shrl->shr, sizeof (struct shrlock)); 333*7c478bd9Sstevel@tonic-gate kmem_free(shrl, sizeof (struct shrlocklist)); 334*7c478bd9Sstevel@tonic-gate found++; 335*7c478bd9Sstevel@tonic-gate continue; 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate shrlp = &(*shrlp)->next; 338*7c478bd9Sstevel@tonic-gate } 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate if (is_nbmand) 341*7c478bd9Sstevel@tonic-gate cv_broadcast(&vp->v_cv); 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 344*7c478bd9Sstevel@tonic-gate return (found ? 0 : EINVAL); 345*7c478bd9Sstevel@tonic-gate } 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* 348*7c478bd9Sstevel@tonic-gate * Clean up all local share reservations that the given process has with 349*7c478bd9Sstevel@tonic-gate * the given file. 350*7c478bd9Sstevel@tonic-gate */ 351*7c478bd9Sstevel@tonic-gate void 352*7c478bd9Sstevel@tonic-gate cleanshares(struct vnode *vp, pid_t pid) 353*7c478bd9Sstevel@tonic-gate { 354*7c478bd9Sstevel@tonic-gate struct shrlock shr; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate if (vp->v_shrlocks == NULL) 357*7c478bd9Sstevel@tonic-gate return; 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate shr.s_access = 0; 360*7c478bd9Sstevel@tonic-gate shr.s_deny = 0; 361*7c478bd9Sstevel@tonic-gate shr.s_pid = pid; 362*7c478bd9Sstevel@tonic-gate shr.s_sysid = 0; 363*7c478bd9Sstevel@tonic-gate shr.s_own_len = 0; 364*7c478bd9Sstevel@tonic-gate shr.s_owner = NULL; 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate (void) del_share(vp, &shr); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate static int 370*7c478bd9Sstevel@tonic-gate is_match_for_has_remote(int32_t sysid1, int32_t sysid2) 371*7c478bd9Sstevel@tonic-gate { 372*7c478bd9Sstevel@tonic-gate int result = 0; 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate if (GETNLMID(sysid1) != 0) { /* in a cluster */ 375*7c478bd9Sstevel@tonic-gate if (GETSYSID(sysid1) != 0) { 376*7c478bd9Sstevel@tonic-gate /* 377*7c478bd9Sstevel@tonic-gate * Lock obtained through nlm server. Just need to 378*7c478bd9Sstevel@tonic-gate * compare whole sysids. 379*7c478bd9Sstevel@tonic-gate */ 380*7c478bd9Sstevel@tonic-gate result = (sysid1 == sysid2); 381*7c478bd9Sstevel@tonic-gate } else if (GETSYSID(sysid1) == 0) { 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * This is a special case. The NLM server identified 384*7c478bd9Sstevel@tonic-gate * by nlmid1 wishes to find out if it has obtained 385*7c478bd9Sstevel@tonic-gate * any share locks on the vnode. 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate result = (GETNLMID(sysid1) == GETNLMID(sysid2)); 388*7c478bd9Sstevel@tonic-gate } 389*7c478bd9Sstevel@tonic-gate } else { /* not in a cluster */ 390*7c478bd9Sstevel@tonic-gate result = ((sysid1 != 0 && sysid1 == sysid2) || 391*7c478bd9Sstevel@tonic-gate (sysid1 == 0 && sysid2 != 0)); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate return (result); 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate /* 398*7c478bd9Sstevel@tonic-gate * Determine whether there are any shares for the given vnode 399*7c478bd9Sstevel@tonic-gate * with a remote sysid. Returns zero if not, non-zero if there are. 400*7c478bd9Sstevel@tonic-gate * If sysid is non-zero then determine if this sysid has a share. 401*7c478bd9Sstevel@tonic-gate * 402*7c478bd9Sstevel@tonic-gate * Note that the return value from this function is potentially invalid 403*7c478bd9Sstevel@tonic-gate * once it has been returned. The caller is responsible for providing its 404*7c478bd9Sstevel@tonic-gate * own synchronization mechanism to ensure that the return value is useful. 405*7c478bd9Sstevel@tonic-gate */ 406*7c478bd9Sstevel@tonic-gate int 407*7c478bd9Sstevel@tonic-gate shr_has_remote_shares(vnode_t *vp, int32_t sysid) 408*7c478bd9Sstevel@tonic-gate { 409*7c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 410*7c478bd9Sstevel@tonic-gate int result = 0; 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 413*7c478bd9Sstevel@tonic-gate shrl = vp->v_shrlocks; 414*7c478bd9Sstevel@tonic-gate while (shrl) { 415*7c478bd9Sstevel@tonic-gate if (is_match_for_has_remote(sysid, shrl->shr->s_sysid)) { 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate result = 1; 418*7c478bd9Sstevel@tonic-gate break; 419*7c478bd9Sstevel@tonic-gate } 420*7c478bd9Sstevel@tonic-gate shrl = shrl->next; 421*7c478bd9Sstevel@tonic-gate } 422*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 423*7c478bd9Sstevel@tonic-gate return (result); 424*7c478bd9Sstevel@tonic-gate } 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static int 427*7c478bd9Sstevel@tonic-gate isreadonly(struct vnode *vp) 428*7c478bd9Sstevel@tonic-gate { 429*7c478bd9Sstevel@tonic-gate return (vp->v_type != VCHR && vp->v_type != VBLK && 430*7c478bd9Sstevel@tonic-gate vp->v_type != VFIFO && vn_is_readonly(vp)); 431*7c478bd9Sstevel@tonic-gate } 432*7c478bd9Sstevel@tonic-gate 433*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 434*7c478bd9Sstevel@tonic-gate static void 435*7c478bd9Sstevel@tonic-gate print_shares(struct vnode *vp) 436*7c478bd9Sstevel@tonic-gate { 437*7c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate if (vp->v_shrlocks == NULL) { 440*7c478bd9Sstevel@tonic-gate printf("<NULL>\n"); 441*7c478bd9Sstevel@tonic-gate return; 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate shrl = vp->v_shrlocks; 445*7c478bd9Sstevel@tonic-gate while (shrl) { 446*7c478bd9Sstevel@tonic-gate print_share(shrl->shr); 447*7c478bd9Sstevel@tonic-gate shrl = shrl->next; 448*7c478bd9Sstevel@tonic-gate } 449*7c478bd9Sstevel@tonic-gate } 450*7c478bd9Sstevel@tonic-gate 451*7c478bd9Sstevel@tonic-gate static void 452*7c478bd9Sstevel@tonic-gate print_share(struct shrlock *shr) 453*7c478bd9Sstevel@tonic-gate { 454*7c478bd9Sstevel@tonic-gate int i; 455*7c478bd9Sstevel@tonic-gate 456*7c478bd9Sstevel@tonic-gate if (shr == NULL) { 457*7c478bd9Sstevel@tonic-gate printf("<NULL>\n"); 458*7c478bd9Sstevel@tonic-gate return; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate printf(" access(%d): ", shr->s_access); 462*7c478bd9Sstevel@tonic-gate if (shr->s_access & F_RDACC) 463*7c478bd9Sstevel@tonic-gate printf("R"); 464*7c478bd9Sstevel@tonic-gate if (shr->s_access & F_WRACC) 465*7c478bd9Sstevel@tonic-gate printf("W"); 466*7c478bd9Sstevel@tonic-gate if ((shr->s_access & (F_RDACC|F_WRACC)) == 0) 467*7c478bd9Sstevel@tonic-gate printf("N"); 468*7c478bd9Sstevel@tonic-gate printf("\n"); 469*7c478bd9Sstevel@tonic-gate printf(" deny: "); 470*7c478bd9Sstevel@tonic-gate if (shr->s_deny & F_COMPAT) 471*7c478bd9Sstevel@tonic-gate printf("C"); 472*7c478bd9Sstevel@tonic-gate if (shr->s_deny & F_RDDNY) 473*7c478bd9Sstevel@tonic-gate printf("R"); 474*7c478bd9Sstevel@tonic-gate if (shr->s_deny & F_WRDNY) 475*7c478bd9Sstevel@tonic-gate printf("W"); 476*7c478bd9Sstevel@tonic-gate if (shr->s_deny == F_NODNY) 477*7c478bd9Sstevel@tonic-gate printf("N"); 478*7c478bd9Sstevel@tonic-gate printf("\n"); 479*7c478bd9Sstevel@tonic-gate printf(" sysid: %d\n", shr->s_sysid); 480*7c478bd9Sstevel@tonic-gate printf(" pid: %d\n", shr->s_pid); 481*7c478bd9Sstevel@tonic-gate printf(" owner: [%d]", shr->s_own_len); 482*7c478bd9Sstevel@tonic-gate printf("'"); 483*7c478bd9Sstevel@tonic-gate for (i = 0; i < shr->s_own_len; i++) 484*7c478bd9Sstevel@tonic-gate printf("%02x", (unsigned)shr->s_owner[i]); 485*7c478bd9Sstevel@tonic-gate printf("'\n"); 486*7c478bd9Sstevel@tonic-gate } 487*7c478bd9Sstevel@tonic-gate #endif 488*7c478bd9Sstevel@tonic-gate 489*7c478bd9Sstevel@tonic-gate /* 490*7c478bd9Sstevel@tonic-gate * Return non-zero if the given I/O request conflicts with a registered 491*7c478bd9Sstevel@tonic-gate * share reservation. 492*7c478bd9Sstevel@tonic-gate */ 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate int 495*7c478bd9Sstevel@tonic-gate nbl_share_conflict(vnode_t *vp, nbl_op_t op) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 498*7c478bd9Sstevel@tonic-gate int conflict = 0; 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 503*7c478bd9Sstevel@tonic-gate for (shrl = vp->v_shrlocks; shrl != NULL; shrl = shrl->next) { 504*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_sysid == 0 && 505*7c478bd9Sstevel@tonic-gate (shrl->shr->s_deny & F_MANDDNY) && 506*7c478bd9Sstevel@tonic-gate shrl->shr->s_pid != curproc->p_pid) { 507*7c478bd9Sstevel@tonic-gate switch (op) { 508*7c478bd9Sstevel@tonic-gate case NBL_READ: 509*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_RDDNY) 510*7c478bd9Sstevel@tonic-gate conflict = 1; 511*7c478bd9Sstevel@tonic-gate break; 512*7c478bd9Sstevel@tonic-gate case NBL_WRITE: 513*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_WRDNY) 514*7c478bd9Sstevel@tonic-gate conflict = 1; 515*7c478bd9Sstevel@tonic-gate break; 516*7c478bd9Sstevel@tonic-gate case NBL_READWRITE: 517*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_deny & F_RWDNY) 518*7c478bd9Sstevel@tonic-gate conflict = 1; 519*7c478bd9Sstevel@tonic-gate break; 520*7c478bd9Sstevel@tonic-gate case NBL_RENAME: 521*7c478bd9Sstevel@tonic-gate case NBL_REMOVE: 522*7c478bd9Sstevel@tonic-gate conflict = 1; 523*7c478bd9Sstevel@tonic-gate break; 524*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 525*7c478bd9Sstevel@tonic-gate default: 526*7c478bd9Sstevel@tonic-gate cmn_err(CE_PANIC, 527*7c478bd9Sstevel@tonic-gate "nbl_share_conflict: bogus op (%d)", 528*7c478bd9Sstevel@tonic-gate op); 529*7c478bd9Sstevel@tonic-gate break; 530*7c478bd9Sstevel@tonic-gate #endif 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate if (conflict) 534*7c478bd9Sstevel@tonic-gate break; 535*7c478bd9Sstevel@tonic-gate } 536*7c478bd9Sstevel@tonic-gate 537*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 538*7c478bd9Sstevel@tonic-gate return (conflict); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate /* 542*7c478bd9Sstevel@tonic-gate * Return non-zero if the given lock request conflicts with an existing 543*7c478bd9Sstevel@tonic-gate * non-blocking mandatory share reservation. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate 546*7c478bd9Sstevel@tonic-gate int 547*7c478bd9Sstevel@tonic-gate share_blocks_lock(vnode_t *vp, flock64_t *flkp) 548*7c478bd9Sstevel@tonic-gate { 549*7c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 550*7c478bd9Sstevel@tonic-gate 551*7c478bd9Sstevel@tonic-gate if ((flkp->l_type == F_RDLCK || flkp->l_type == F_WRLCK) && 552*7c478bd9Sstevel@tonic-gate nbl_share_conflict(vp, nbl_lock_to_op(flkp->l_type))) 553*7c478bd9Sstevel@tonic-gate return (1); 554*7c478bd9Sstevel@tonic-gate else 555*7c478bd9Sstevel@tonic-gate return (0); 556*7c478bd9Sstevel@tonic-gate } 557*7c478bd9Sstevel@tonic-gate 558*7c478bd9Sstevel@tonic-gate /* 559*7c478bd9Sstevel@tonic-gate * Wait for all share reservations to go away that block the given lock 560*7c478bd9Sstevel@tonic-gate * request. Returns 0 after successfully waiting, or EINTR. 561*7c478bd9Sstevel@tonic-gate */ 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate int 564*7c478bd9Sstevel@tonic-gate wait_for_share(vnode_t *vp, flock64_t *flkp) 565*7c478bd9Sstevel@tonic-gate { 566*7c478bd9Sstevel@tonic-gate int result = 0; 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate ASSERT(nbl_in_crit(vp)); 569*7c478bd9Sstevel@tonic-gate 570*7c478bd9Sstevel@tonic-gate /* 571*7c478bd9Sstevel@tonic-gate * We have to hold the vnode's lock before leaving the nbmand 572*7c478bd9Sstevel@tonic-gate * critical region, to prevent a race with the thread that deletes 573*7c478bd9Sstevel@tonic-gate * the share that's blocking us. Then we have to drop the lock 574*7c478bd9Sstevel@tonic-gate * before reentering the critical region, to avoid a deadlock. 575*7c478bd9Sstevel@tonic-gate */ 576*7c478bd9Sstevel@tonic-gate while (result == 0 && share_blocks_lock(vp, flkp)) { 577*7c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 578*7c478bd9Sstevel@tonic-gate nbl_end_crit(vp); 579*7c478bd9Sstevel@tonic-gate if (cv_wait_sig(&vp->v_cv, &vp->v_lock) == 0) 580*7c478bd9Sstevel@tonic-gate result = EINTR; 581*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 582*7c478bd9Sstevel@tonic-gate nbl_start_crit(vp, RW_WRITER); 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate 585*7c478bd9Sstevel@tonic-gate return (result); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate 588*7c478bd9Sstevel@tonic-gate /* 589*7c478bd9Sstevel@tonic-gate * Determine if the given share reservation conflicts with any existing 590*7c478bd9Sstevel@tonic-gate * locks or mapped regions for the file. This is used to compensate for 591*7c478bd9Sstevel@tonic-gate * the fact that most Unix applications don't get a share reservation, so 592*7c478bd9Sstevel@tonic-gate * we use existing locks as an indication of what files are open. 593*7c478bd9Sstevel@tonic-gate * 594*7c478bd9Sstevel@tonic-gate * XXX needs a better name to reflect that it also looks for mapped file 595*7c478bd9Sstevel@tonic-gate * conflicts. 596*7c478bd9Sstevel@tonic-gate * 597*7c478bd9Sstevel@tonic-gate * Returns non-zero if there is a conflict, zero if okay. 598*7c478bd9Sstevel@tonic-gate */ 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate static int 601*7c478bd9Sstevel@tonic-gate lock_blocks_share(vnode_t *vp, struct shrlock *shr) 602*7c478bd9Sstevel@tonic-gate { 603*7c478bd9Sstevel@tonic-gate struct flock64 lck; 604*7c478bd9Sstevel@tonic-gate int error; 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate /* 607*7c478bd9Sstevel@tonic-gate * We don't currently have a good way to match lock 608*7c478bd9Sstevel@tonic-gate * ownership with share ownership for remote requests. 609*7c478bd9Sstevel@tonic-gate * Fortunately, we know that only local processes (in particular, 610*7c478bd9Sstevel@tonic-gate * local CIFS servers) care about conflicts between locks and 611*7c478bd9Sstevel@tonic-gate * share reservations, and we can distinguish local processes from 612*7c478bd9Sstevel@tonic-gate * each other and from remote processes. 613*7c478bd9Sstevel@tonic-gate */ 614*7c478bd9Sstevel@tonic-gate ASSERT(shr->s_sysid == 0); 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate if ((shr->s_deny & (F_RWDNY|F_COMPAT)) == 0) { 617*7c478bd9Sstevel@tonic-gate /* if no deny mode, then there's no conflict */ 618*7c478bd9Sstevel@tonic-gate return (0); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate lck.l_type = ((shr->s_deny & F_RDDNY) ? F_WRLCK : F_RDLCK); 622*7c478bd9Sstevel@tonic-gate 623*7c478bd9Sstevel@tonic-gate lck.l_whence = 0; 624*7c478bd9Sstevel@tonic-gate lck.l_start = 0; 625*7c478bd9Sstevel@tonic-gate lck.l_len = 0; /* to EOF */ 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate /* would check here for conflict with mapped region */ 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate /* XXX should use non-NULL cred? */ 630*7c478bd9Sstevel@tonic-gate error = VOP_FRLOCK(vp, F_GETLK, &lck, 0, 0, NULL, NULL); 631*7c478bd9Sstevel@tonic-gate if (error != 0) { 632*7c478bd9Sstevel@tonic-gate cmn_err(CE_WARN, "lock_blocks_share: unexpected error (%d)", 633*7c478bd9Sstevel@tonic-gate error); 634*7c478bd9Sstevel@tonic-gate return (1); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate 637*7c478bd9Sstevel@tonic-gate return (lck.l_type == F_UNLCK ? 0 : 1); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * Determine if the given process has a NBMAND share reservation on the 642*7c478bd9Sstevel@tonic-gate * given vnode. Returns 1 if the process has such a share reservation, 643*7c478bd9Sstevel@tonic-gate * returns 0 otherwise. 644*7c478bd9Sstevel@tonic-gate */ 645*7c478bd9Sstevel@tonic-gate int 646*7c478bd9Sstevel@tonic-gate proc_has_nbmand_share_on_vp(vnode_t *vp, pid_t pid) 647*7c478bd9Sstevel@tonic-gate { 648*7c478bd9Sstevel@tonic-gate struct shrlocklist *shrl; 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate /* 651*7c478bd9Sstevel@tonic-gate * Any NBMAND share reservation on the vp for this process? 652*7c478bd9Sstevel@tonic-gate */ 653*7c478bd9Sstevel@tonic-gate mutex_enter(&vp->v_lock); 654*7c478bd9Sstevel@tonic-gate for (shrl = vp->v_shrlocks; shrl != NULL; shrl = shrl->next) { 655*7c478bd9Sstevel@tonic-gate if (shrl->shr->s_sysid == 0 && 656*7c478bd9Sstevel@tonic-gate (shrl->shr->s_deny & F_MANDDNY) && 657*7c478bd9Sstevel@tonic-gate (shrl->shr->s_pid == pid)) { 658*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 659*7c478bd9Sstevel@tonic-gate return (1); 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate mutex_exit(&vp->v_lock); 663*7c478bd9Sstevel@tonic-gate 664*7c478bd9Sstevel@tonic-gate return (0); 665*7c478bd9Sstevel@tonic-gate } 666