1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2021 Tintri by DDN, Inc. All rights reserved.
14  * Copyright 2021 RackTop Systems, Inc.
15  */
16 
17 /*
18  * (SMB1/SMB2) Server-level Oplock support.
19  *
20  * Conceptually, this is a separate layer on top of the
21  * file system (FS) layer oplock code in smb_cmn_oplock.c.
22  * If these layers were more distinct, the FS layer would
23  * need to use call-back functions (installed from here)
24  * to "indicate an oplock break to the server" (see below).
25  * As these layers are all in the same kernel module, the
26  * delivery of these break indications just uses a direct
27  * function call to smb_oplock_ind_break() below.
28  *
29  * This layer is responsible for handling the break indication,
30  * which often requires scheduling a taskq job in the server,
31  * and sending an oplock break mesage to the client using
32  * the appropriate protocol for the open handle affected.
33  *
34  * The details of composing an oplock break message, the
35  * protocol-specific details of requesting an oplock, and
36  * returning that oplock to the client are in the files:
37  *  smb_oplock.c, smb2_oplock.c, smb2_lease.c
38  */
39 
40 #include <smbsrv/smb2_kproto.h>
41 #include <smbsrv/smb_oplock.h>
42 
43 /*
44  * Verify relationship between BREAK_TO_... and CACHE bits,
45  * used when setting the BREAK_TO_... below.
46  */
47 #if BREAK_TO_READ_CACHING != (READ_CACHING << BREAK_SHIFT)
48 #error "BREAK_TO_READ_CACHING"
49 #endif
50 #if BREAK_TO_HANDLE_CACHING != (HANDLE_CACHING << BREAK_SHIFT)
51 #error "BREAK_TO_HANDLE_CACHING"
52 #endif
53 #if BREAK_TO_WRITE_CACHING != (WRITE_CACHING << BREAK_SHIFT)
54 #error "BREAK_TO_WRITE_CACHING"
55 #endif
56 #define	CACHE_RWH (READ_CACHING | WRITE_CACHING | HANDLE_CACHING)
57 
58 /*
59  * This is the timeout used in the thread that sends an
60  * oplock break and waits for the client to respond
61  * before it breaks the oplock locally.
62  */
63 int smb_oplock_timeout_ack = 30000; /* mSec. */
64 
65 /*
66  * This is the timeout used in threads that have just
67  * finished some sort of oplock request and now must
68  * wait for (possibly multiple) breaks to complete.
69  * This value must be at least a couple seconds LONGER
70  * than the ack timeout above so that I/O callers won't
71  * give up waiting before the local ack timeout.
72  */
73 int smb_oplock_timeout_def = 45000; /* mSec. */
74 
75 static void smb_oplock_async_break(void *);
76 static void smb_oplock_hdl_clear(smb_ofile_t *);
77 
78 
79 /*
80  * 2.1.5.17.3 Indicating an Oplock Break to the Server
81  *
82  * The inputs for indicating an oplock break to the server are:
83  *
84  *	BreakingOplockOpen: The Open used to request the oplock
85  *	  that is now breaking.
86  *	 NewOplockLevel: The type of oplock the requested oplock
87  *	  has been broken to.  Valid values are as follows:
88  *		LEVEL_NONE (that is, no oplock)
89  *		LEVEL_TWO
90  *		A combination of one or more of the following flags:
91  *			READ_CACHING
92  *			HANDLE_CACHING
93  *			WRITE_CACHING
94  *	AcknowledgeRequired: A Boolean value; TRUE if the server
95  *	  MUST acknowledge the oplock break, FALSE if not,
96  *	  as specified in section 2.1.5.18.
97  *	OplockCompletionStatus: The NTSTATUS code to return to the server.
98  *
99  * This algorithm simply represents the completion of an oplock request,
100  * as specified in section 2.1.5.17.1 or section 2.1.5.17.2. The server
101  * is expected to associate the return status from this algorithm with
102  * BreakingOplockOpen, which is the Open passed in when it requested
103  * the oplock that is now breaking.
104  *
105  * It is important to note that because several oplocks can be outstanding
106  * in parallel, although this algorithm represents the completion of an
107  * oplock request, it might not result in the completion of the algorithm
108  * that called it. In particular, calling this algorithm will result in
109  * completion of the caller only if BreakingOplockOpen is the same as the
110  * Open with which the calling algorithm was itself called. To mitigate
111  * confusion, each algorithm that refers to this section will specify
112  * whether that algorithm's operation terminates at that point or not.
113  *
114  * The object store MUST return OplockCompletionStatus,
115  * AcknowledgeRequired, and NewOplockLevel to the server (the algorithm is
116  * as specified in section 2.1.5.17.1 and section 2.1.5.17.2).
117  *
118  * Implementation:
119  *
120  * We use two versions of this function:
121  *	smb_oplock_ind_break_in_ack
122  *	smb_oplock_ind_break
123  *
124  * The first is used when we're handling an Oplock Break Ack.
125  * The second is used when other operations cause a break,
126  * generally in one of the smb_oplock_break_... functions.
127  *
128  * Note that these are call-back functions that may be called with the
129  * node ofile list rwlock held and the node oplock mutex entered, so
130  * these should ONLY schedule oplock break work, and MUST NOT attempt
131  * any actions that might require either of those locks.
132  */
133 
134 /*
135  * smb_oplock_ind_break_in_ack
136  *
137  * Variant of smb_oplock_ind_break() for the oplock Ack handler.
138  * When we need to indicate another oplock break from within the
139  * Ack handler (during the Ack. of some previous oplock break)
140  * we need to make sure this new break indication goes out only
141  * AFTER the reply to the current break ack. is sent out.
142  *
143  * In this case, we always have an SR (the break ack) so we can
144  * append the "ind break" work to the current SR and let the
145  * request hander thread do this work after the reply is sent.
146  * Note: this is always an SMB2 or later request, because this
147  * only happens for "granular" oplocks, which are SMB2-only.
148  *
149  * This is mostly the same as smb_oplock_ind_break() except:
150  * - The only CompletionStatus possible is STATUS_CANT_GRANT.
151  * - Instead of taskq_dispatch this appends the new SR to
152  *   the "post work" queue on the current SR.
153  *
154  * Note called with the node ofile list rwlock held and
155  * the oplock mutex entered.
156  */
157 void
158 smb_oplock_ind_break_in_ack(smb_request_t *ack_sr, smb_ofile_t *ofile,
159     uint32_t NewLevel, boolean_t AckRequired)
160 {
161 	smb_request_t *new_sr;
162 
163 	/*
164 	 * This should happen only with SMB2 or later,
165 	 * but in case that ever changes...
166 	 */
167 	if (ack_sr->session->dialect < SMB_VERS_2_BASE) {
168 		smb_oplock_ind_break(ofile, NewLevel,
169 		    AckRequired, STATUS_CANT_GRANT);
170 		return;
171 	}
172 
173 	/*
174 	 * We're going to schedule a request that will have a
175 	 * reference to this ofile. Get the hold first.
176 	 */
177 	if (ofile->f_oplock_closing ||
178 	    !smb_ofile_hold_olbrk(ofile)) {
179 		/* It's closing (or whatever).  Nothing to do. */
180 		return;
181 	}
182 
183 	/*
184 	 * When called from Ack processing, we want to use a
185 	 * request on the session doing the ack.  If we can't
186 	 * allocate a request on that session (because it's
187 	 * now disconnecting) just fall-back to the normal
188 	 * oplock break code path which deals with that.
189 	 * Once we have a request on the ack session, that
190 	 * session won't go away until the request is done.
191 	 */
192 	new_sr = smb_request_alloc(ack_sr->session, 0);
193 	if (new_sr == NULL) {
194 		smb_oplock_ind_break(ofile, NewLevel,
195 		    AckRequired, STATUS_CANT_GRANT);
196 		smb_ofile_release(ofile);
197 		return;
198 	}
199 
200 	new_sr->sr_state = SMB_REQ_STATE_SUBMITTED;
201 	new_sr->smb2_async = B_TRUE;
202 	new_sr->user_cr = zone_kcred();
203 	new_sr->fid_ofile = ofile;
204 	if (ofile->f_tree != NULL) {
205 		new_sr->tid_tree = ofile->f_tree;
206 		smb_tree_hold_internal(ofile->f_tree);
207 	}
208 	if (ofile->f_user != NULL) {
209 		new_sr->uid_user = ofile->f_user;
210 		smb_user_hold_internal(ofile->f_user);
211 	}
212 	new_sr->arg.olbrk.NewLevel = NewLevel;
213 	new_sr->arg.olbrk.AckRequired = AckRequired;
214 
215 	/*
216 	 * Using smb2_cmd_code to indicate what to call.
217 	 * work func. will call smb_oplock_send_brk
218 	 */
219 	new_sr->smb2_cmd_code = SMB2_OPLOCK_BREAK;
220 	smb2sr_append_postwork(ack_sr, new_sr);
221 }
222 
223 /*
224  * smb_oplock_ind_break
225  *
226  * This is the function described in [MS-FSA] 2.1.5.17.3
227  * which is called many places in the oplock break code.
228  *
229  * Schedule a request & taskq job to do oplock break work
230  * as requested by the FS-level code (smb_cmn_oplock.c).
231  *
232  * Note called with the node ofile list rwlock held and
233  * the oplock mutex entered.
234  */
235 void
236 smb_oplock_ind_break(smb_ofile_t *ofile, uint32_t NewLevel,
237     boolean_t AckRequired, uint32_t CompletionStatus)
238 {
239 	smb_server_t *sv = ofile->f_server;
240 	smb_request_t *sr = NULL;
241 
242 	/*
243 	 * See notes at smb_oplock_async_break re. CompletionStatus
244 	 * Check for any invalid codes here, so assert happens in
245 	 * the thread passing an unexpected value.
246 	 * The real work happens in a taskq job.
247 	 */
248 	switch (CompletionStatus) {
249 
250 	case NT_STATUS_SUCCESS:
251 	case STATUS_CANT_GRANT:
252 		/* Send break via taskq job. */
253 		break;
254 
255 	case STATUS_NEW_HANDLE:
256 		/* nothing to do (keep for observability) */
257 		return;
258 
259 	case NT_STATUS_OPLOCK_HANDLE_CLOSED:
260 		smb_oplock_hdl_clear(ofile);
261 		return;
262 
263 	default:
264 		ASSERT(0);
265 		return;
266 	}
267 
268 	/*
269 	 * We're going to schedule a request that will have a
270 	 * reference to this ofile. Get the hold first.
271 	 */
272 	if (ofile->f_oplock_closing ||
273 	    !smb_ofile_hold_olbrk(ofile)) {
274 		/* It's closing (or whatever).  Nothing to do. */
275 		return;
276 	}
277 
278 	/*
279 	 * We need a request allocated on the session that owns
280 	 * this ofile in order to safely send on that session.
281 	 *
282 	 * Note that while we hold a ref. on the ofile, it's
283 	 * f_session will not change.  An ofile in state
284 	 * _ORPHANED will have f_session == NULL, but the
285 	 * f_session won't _change_ while we have a ref,
286 	 * and won't be torn down under our feet.
287 	 * Same for f_tree and f_user
288 	 *
289 	 * If f_session is NULL, or it's in a state that doesn't
290 	 * allow new requests, use the special "server" session.
291 	 */
292 	if (ofile->f_session != NULL)
293 		sr = smb_request_alloc(ofile->f_session, 0);
294 	if (sr == NULL)
295 		sr = smb_request_alloc(sv->sv_session, 0);
296 
297 	sr->sr_state = SMB_REQ_STATE_SUBMITTED;
298 	sr->smb2_async = B_TRUE;
299 	sr->user_cr = zone_kcred();
300 	sr->fid_ofile = ofile;
301 	if (ofile->f_tree != NULL) {
302 		sr->tid_tree = ofile->f_tree;
303 		smb_tree_hold_internal(sr->tid_tree);
304 	}
305 	if (ofile->f_user != NULL) {
306 		sr->uid_user = ofile->f_user;
307 		smb_user_hold_internal(sr->uid_user);
308 	}
309 	sr->arg.olbrk.NewLevel = NewLevel;
310 	sr->arg.olbrk.AckRequired = AckRequired;
311 	sr->smb2_status = CompletionStatus;
312 
313 	(void) taskq_dispatch(
314 	    sv->sv_worker_pool,
315 	    smb_oplock_async_break, sr, TQ_SLEEP);
316 }
317 
318 /*
319  * smb_oplock_async_break
320  *
321  * Called via the taskq to handle an asynchronous oplock break.
322  * We have a hold on the ofile, which will be released in
323  * smb_request_free (via sr->fid_ofile)
324  *
325  * Note we have: sr->uid_user == NULL, sr->tid_tree == NULL.
326  * Nothing called here needs those.
327  *
328  * Note that NewLevel as provided by the FS up-call does NOT
329  * include the GRANULAR flag.  The SMB level is expected to
330  * keep track of how each oplock was acquired (by lease or
331  * traditional oplock request) and put the GRANULAR flag
332  * back into the oplock state when calling down to the
333  * FS-level code.  Also note that the lease break message
334  * carries only the cache flags, not the GRANULAR flag.
335  */
336 static void
337 smb_oplock_async_break(void *arg)
338 {
339 	smb_request_t	*sr = arg;
340 	uint32_t	CompletionStatus;
341 
342 	SMB_REQ_VALID(sr);
343 
344 	CompletionStatus = sr->smb2_status;
345 	sr->smb2_status = NT_STATUS_SUCCESS;
346 
347 	mutex_enter(&sr->sr_mutex);
348 	sr->sr_worker = curthread;
349 	sr->sr_state = SMB_REQ_STATE_ACTIVE;
350 	mutex_exit(&sr->sr_mutex);
351 
352 	/*
353 	 * Note that the CompletionStatus from the FS level
354 	 * (smb_cmn_oplock.c) encodes what kind of action we
355 	 * need to take at the SMB level.
356 	 */
357 	switch (CompletionStatus) {
358 
359 	case STATUS_CANT_GRANT:
360 	case NT_STATUS_SUCCESS:
361 		smb_oplock_send_brk(sr);
362 		break;
363 
364 	default:
365 		/* Checked by caller. */
366 		ASSERT(0);
367 		break;
368 	}
369 
370 	if (sr->dh_nvl_dirty) {
371 		sr->dh_nvl_dirty = B_FALSE;
372 		smb2_dh_update_nvfile(sr);
373 	}
374 
375 	sr->sr_state = SMB_REQ_STATE_COMPLETED;
376 	smb_request_free(sr);
377 }
378 
379 static void
380 smb_oplock_update(smb_request_t *sr, smb_ofile_t *ofile, uint32_t NewLevel)
381 {
382 	if (ofile->f_lease != NULL)
383 		ofile->f_lease->ls_state = NewLevel & CACHE_RWH;
384 	else
385 		ofile->f_oplock.og_state = NewLevel;
386 
387 	if (ofile->dh_persist) {
388 		smb2_dh_update_oplock(sr, ofile);
389 	}
390 }
391 
392 #ifdef DEBUG
393 int smb_oplock_debug_wait = 0;
394 #endif
395 
396 /*
397  * Send an oplock break over the wire, or if we can't,
398  * then process the oplock break locally.
399  *
400  * Note that we have sr->fid_ofile here but all the other
401  * normal sr members may be NULL:  uid_user, tid_tree.
402  * Also sr->session may or may not be the same session as
403  * the ofile came from (ofile->f_session) depending on
404  * whether this is a "live" open or an orphaned DH,
405  * where ofile->f_session will be NULL.
406  *
407  * Given that we don't always have a session, we determine
408  * the oplock type (lease etc) from f_oplock.og_dialect.
409  */
410 void
411 smb_oplock_send_brk(smb_request_t *sr)
412 {
413 	smb_ofile_t	*ofile;
414 	smb_lease_t	*lease;
415 	uint32_t	NewLevel;
416 	boolean_t	AckReq;
417 	uint32_t	status;
418 	int		rc;
419 
420 	ofile = sr->fid_ofile;
421 	NewLevel = sr->arg.olbrk.NewLevel;
422 	AckReq = sr->arg.olbrk.AckRequired;
423 	lease = ofile->f_lease;
424 
425 	/*
426 	 * Build the break message in sr->reply.
427 	 * It's free'd in smb_request_free().
428 	 * Also updates the lease and NewLevel.
429 	 */
430 	sr->reply.max_bytes = MLEN;
431 	if (lease != NULL) {
432 		/*
433 		 * The ofile has as lease.  Must be SMB2+
434 		 * Oplock state has changed, so update the epoch.
435 		 */
436 		mutex_enter(&lease->ls_mutex);
437 		lease->ls_epoch++;
438 		mutex_exit(&lease->ls_mutex);
439 
440 		/* Note, needs "old" state in ls_state */
441 		smb2_lease_break_notification(sr,
442 		    (NewLevel & CACHE_RWH), AckReq);
443 		NewLevel |= OPLOCK_LEVEL_GRANULAR;
444 	} else if (ofile->f_oplock.og_dialect >= SMB_VERS_2_BASE) {
445 		/*
446 		 * SMB2 using old-style oplock (no lease)
447 		 */
448 		smb2_oplock_break_notification(sr, NewLevel);
449 	} else {
450 		/*
451 		 * SMB1 clients should only get Level II oplocks if they
452 		 * set the capability indicating they know about them.
453 		 */
454 		if (NewLevel == OPLOCK_LEVEL_TWO &&
455 		    ofile->f_oplock.og_dialect < NT_LM_0_12)
456 			NewLevel = OPLOCK_LEVEL_NONE;
457 		smb1_oplock_break_notification(sr, NewLevel);
458 	}
459 
460 	/*
461 	 * Keep track of what we last sent to the client,
462 	 * preserving the GRANULAR flag (if a lease).
463 	 * If we're expecting an ACK, set og_breaking
464 	 * (or maybe lease->ls_breaking) so we can
465 	 * filter unsolicited ACKs.
466 	 */
467 	if (AckReq) {
468 		uint32_t BreakTo;
469 
470 		if (lease != NULL) {
471 			BreakTo = (NewLevel & CACHE_RWH) << BREAK_SHIFT;
472 			if (BreakTo == 0)
473 				BreakTo = BREAK_TO_NO_CACHING;
474 			lease->ls_breaking = BreakTo;
475 		} else {
476 			if ((NewLevel & LEVEL_TWO_OPLOCK) != 0)
477 				BreakTo = BREAK_TO_TWO;
478 			else
479 				BreakTo = BREAK_TO_NONE;
480 			ofile->f_oplock.og_breaking = BreakTo;
481 		}
482 		/* Will update ls/og_state in ack. */
483 	} else {
484 		smb_oplock_update(sr, ofile, NewLevel);
485 	}
486 
487 	/*
488 	 * Try to send the break message to the client.
489 	 * When we get to multi-channel, this is supposed to
490 	 * try to send on every channel before giving up.
491 	 */
492 	if (sr->session == ofile->f_session)
493 		rc = smb_session_send(sr->session, 0, &sr->reply);
494 	else
495 		rc = ENOTCONN;
496 
497 	if (rc == 0) {
498 		/*
499 		 * OK, we were able to send the break message.
500 		 * If no ack. required, we're done.
501 		 */
502 		if (!AckReq)
503 			return;
504 
505 		/*
506 		 * We're expecting an ACK.  Wait in this thread
507 		 * so we can log clients that don't respond.
508 		 *
509 		 * If debugging, may want to break after a
510 		 * short wait to look into why we might be
511 		 * holding up progress.  (i.e. locks?)
512 		 */
513 #ifdef DEBUG
514 		if (smb_oplock_debug_wait > 0) {
515 			status = smb_oplock_wait_break(ofile->f_node,
516 			    smb_oplock_debug_wait);
517 			if (status == 0)
518 				return;
519 			cmn_err(CE_NOTE, "clnt %s oplock break wait debug",
520 			    sr->session->ip_addr_str);
521 			debug_enter("oplock_wait");
522 		}
523 #endif
524 		status = smb_oplock_wait_break(ofile->f_node,
525 		    smb_oplock_timeout_ack);
526 		if (status == 0)
527 			return;
528 
529 		cmn_err(CE_NOTE, "clnt %s oplock break timeout",
530 		    sr->session->ip_addr_str);
531 		DTRACE_PROBE1(break_timeout, smb_ofile_t, ofile);
532 
533 		/*
534 		 * Will do local ack below.  Note, after timeout,
535 		 * do a break to none or "no caching" regardless
536 		 * of what the passed in cache level was.
537 		 * That means: clear all except GRANULAR.
538 		 */
539 		NewLevel &= OPLOCK_LEVEL_GRANULAR;
540 	} else {
541 		/*
542 		 * We were unable to send the oplock break request.
543 		 * Generally, that means we have no connection to this
544 		 * client right now, and this ofile will have state
545 		 * SMB_OFILE_STATE_ORPHANED.  We either close the handle
546 		 * or break the oplock locally, in which case the client
547 		 * gets the updated oplock state when they reconnect.
548 		 * Decide whether to keep or close.
549 		 *
550 		 * Relevant [MS-SMB2] sections:
551 		 *
552 		 * 3.3.4.6 Object Store Indicates an Oplock Break
553 		 * If Open.Connection is NULL, Open.IsResilient is FALSE,
554 		 * Open.IsDurable is FALSE and Open.IsPersistent is FALSE,
555 		 * the server SHOULD close the Open as specified in...
556 		 *
557 		 * 3.3.4.7 Object Store Indicates a Lease Break
558 		 * If Open.Connection is NULL, the server MUST close the
559 		 * Open as specified in ... for the following cases:
560 		 * - Open.IsResilient is FALSE, Open.IsDurable is FALSE,
561 		 *   and Open.IsPersistent is FALSE.
562 		 * - Lease.BreakToLeaseState does not contain
563 		 *   ...HANDLE_CACHING and Open.IsDurable is TRUE.
564 		 * If Lease.LeaseOpens is empty, (... local ack to "none").
565 		 */
566 
567 		/*
568 		 * See similar logic in smb_dh_should_save
569 		 */
570 		switch (ofile->dh_vers) {
571 		case SMB2_RESILIENT:
572 			break;			/* keep DH */
573 
574 		case SMB2_DURABLE_V2:
575 			if (ofile->dh_persist)
576 				break;		/* keep DH */
577 			/* FALLTHROUGH */
578 		case SMB2_DURABLE_V1:
579 			/* IS durable (v1 or v2) */
580 			if ((NewLevel & (OPLOCK_LEVEL_BATCH |
581 			    OPLOCK_LEVEL_CACHE_HANDLE)) != 0)
582 				break;		/* keep DH */
583 			/* FALLTHROUGH */
584 		case SMB2_NOT_DURABLE:
585 		default:
586 			smb_ofile_close(ofile, 0);
587 			return;
588 		}
589 		/* Keep this ofile (durable handle). */
590 
591 		if (!AckReq) {
592 			/* Nothing more to do. */
593 			return;
594 		}
595 	}
596 
597 	/*
598 	 * We get here after either an oplock break ack timeout,
599 	 * or a send failure for a durable handle type that we
600 	 * preserve rather than just close.  Do local ack.
601 	 */
602 	if (lease != NULL)
603 		lease->ls_breaking = 0;
604 	else
605 		ofile->f_oplock.og_breaking = 0;
606 
607 	status = smb_oplock_ack_break(sr, ofile, &NewLevel);
608 	if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
609 		/* Not expecting this status return. */
610 		cmn_err(CE_NOTE, "clnt local oplock ack wait?");
611 		(void) smb_oplock_wait_break(ofile->f_node,
612 		    smb_oplock_timeout_ack);
613 		status = 0;
614 	}
615 	if (status != 0) {
616 		cmn_err(CE_NOTE, "clnt local oplock ack, "
617 		    "status=0x%x", status);
618 	}
619 
620 	/* Update ls/og_state as if we heard from the client. */
621 	smb_oplock_update(sr, ofile, NewLevel);
622 }
623 
624 /*
625  * See: NT_STATUS_OPLOCK_HANDLE_CLOSED above and
626  * smb_ofile_close, smb_oplock_break_CLOSE.
627  *
628  * The FS-level oplock layer calls this to update the
629  * SMB-level state when a handle loses its oplock.
630  */
631 static void
632 smb_oplock_hdl_clear(smb_ofile_t *ofile)
633 {
634 	smb_lease_t *lease = ofile->f_lease;
635 
636 	if (lease != NULL) {
637 		if (lease->ls_oplock_ofile == ofile) {
638 			/*
639 			 * smb2_lease_ofile_close should have
640 			 * moved the oplock to another ofile.
641 			 */
642 			ASSERT(0);
643 			lease->ls_oplock_ofile = NULL;
644 		}
645 	}
646 	ofile->f_oplock.og_state = 0;
647 	ofile->f_oplock.og_breaking = 0;
648 }
649 
650 /*
651  * Wait up to "timeout" mSec. for the current oplock "breaking" flags
652  * to be cleared (by smb_oplock_ack_break or smb_oplock_break_CLOSE).
653  *
654  * Callers of the above public oplock functions:
655  *	smb_oplock_request()
656  *	smb_oplock_ack_break()
657  *	smb_oplock_break_OPEN() ...
658  * check for return status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS
659  * and call this function to wait for the break to complete.
660  *
661  * Most callers should use this default timeout, which they get
662  * by passing zero as the timeout arg.  This include places where
663  * we're about to do something that invalidates some cache.
664  */
665 uint32_t
666 smb_oplock_wait_break(smb_node_t *node, int timeout)  /* mSec. */
667 {
668 	smb_oplock_t	*ol;
669 	clock_t		time, rv;
670 	uint32_t	status = 0;
671 
672 	if (timeout == 0)
673 		timeout = smb_oplock_timeout_def;
674 
675 	SMB_NODE_VALID(node);
676 	ol = &node->n_oplock;
677 
678 	mutex_enter(&ol->ol_mutex);
679 	time = MSEC_TO_TICK(timeout) + ddi_get_lbolt();
680 
681 	while ((ol->ol_state & BREAK_ANY) != 0) {
682 		ol->waiters++;
683 		rv = cv_timedwait(&ol->WaitingOpenCV,
684 		    &ol->ol_mutex, time);
685 		ol->waiters--;
686 		if (rv < 0) {
687 			status = NT_STATUS_CANNOT_BREAK_OPLOCK;
688 			break;
689 		}
690 	}
691 
692 	mutex_exit(&ol->ol_mutex);
693 
694 	return (status);
695 }
696