xref: /titanic_54/usr/src/uts/common/os/share.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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