1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 /*
  27  * smb_oplock_wait / smb_oplock_broadcast
  28  * When an oplock is being acquired, we must ensure that the acquisition
  29  * response is submitted to the network stack before any other operation
  30  * is permitted on the oplock.
  31  * In smb_oplock_acquire, oplock.ol_xthread is set to point to the worker
  32  * thread processing the command that is granting the oplock.
  33  * Other threads accessing the oplock will be suspended in smb_oplock_wait().
  34  * They will be awakened when the worker thread referenced in 'ol_xthread'
  35  * calls smb_oplock_broadcast().
  36  *
  37  * The purpose of this mechanism is to prevent another thread from
  38  * triggering an oplock break before the response conveying the grant
  39  * has been sent.
  40  */
  41 
  42 #include <smbsrv/smb_kproto.h>
  43 #include <sys/nbmlock.h>
  44 
  45 #define SMB_OPLOCK_IS_EXCLUSIVE(level)          \
  46         (((level) == SMB_OPLOCK_EXCLUSIVE) ||   \
  47         ((level) == SMB_OPLOCK_BATCH))
  48 
  49 static int smb_oplock_install_fem(smb_node_t *);
  50 static void smb_oplock_uninstall_fem(smb_node_t *);
  51 
  52 static void smb_oplock_wait(smb_node_t *);
  53 static void smb_oplock_wait_ack(smb_node_t *, uint32_t);
  54 static void smb_oplock_timedout(smb_node_t *);
  55 
  56 static smb_oplock_grant_t *smb_oplock_set_grant(smb_ofile_t *, uint8_t);
  57 void smb_oplock_clear_grant(smb_oplock_grant_t *);
  58 static int smb_oplock_insert_grant(smb_node_t *, smb_oplock_grant_t *);
  59 static void smb_oplock_remove_grant(smb_node_t *, smb_oplock_grant_t *);
  60 static smb_oplock_grant_t *smb_oplock_exclusive_grant(list_t *);
  61 static smb_oplock_grant_t *smb_oplock_get_grant(smb_oplock_t *, smb_ofile_t *);
  62 
  63 static void smb_oplock_sched_async_break(smb_oplock_grant_t *, uint8_t);
  64 static void smb_oplock_exec_async_break(void *);
  65 static void smb_oplock_break_levelII_locked(smb_node_t *);
  66 
  67 /*
  68  * smb_oplock_install_fem
  69  * Install fem monitor for cross protocol oplock breaking.
  70  */
  71 static int
  72 smb_oplock_install_fem(smb_node_t *node)
  73 {
  74         ASSERT(MUTEX_HELD(&node->n_oplock.ol_mutex));
  75 
  76         if (node->n_oplock.ol_fem == B_FALSE) {
  77                 if (smb_fem_oplock_install(node) != 0) {
  78                         cmn_err(CE_NOTE, "No oplock granted: "
  79                             "failed to install fem monitor %s",
  80                             node->vp->v_path);
  81                         return (-1);
  82                 }
  83                 node->n_oplock.ol_fem = B_TRUE;
  84         }
  85         return (0);
  86 }
  87 
  88 /*
  89  * smb_oplock_uninstall_fem
  90  * Uninstall fem monitor for cross protocol oplock breaking.
  91  */
  92 static void
  93 smb_oplock_uninstall_fem(smb_node_t *node)
  94 {
  95         ASSERT(MUTEX_HELD(&node->n_oplock.ol_mutex));
  96 
  97         if (node->n_oplock.ol_fem) {
  98                 smb_fem_oplock_uninstall(node);
  99                 node->n_oplock.ol_fem = B_FALSE;
 100         }
 101 }
 102 
 103 /*
 104  * This provides a way to fully disable oplocks, i.e. for testing.
 105  * You _really_ do _not_ want to turn this off, because if you do,
 106  * the clients send you very small read requests, and a _lot_ more
 107  * of them.  The skc_oplock_enable parameter can be used to enable
 108  * or disable exclusive oplocks.  Disabling that can be helpful
 109  * when there are clients not responding to oplock breaks.
 110  */
 111 int smb_oplocks_enabled = 1;
 112 
 113 /*
 114  * smb_oplock_acquire
 115  *
 116  * Attempt to acquire an oplock. Clients will request EXCLUSIVE or BATCH,
 117  * but might only be granted LEVEL_II or NONE.
 118  *
 119  * If oplocks are not supported on the tree, or node, grant NONE.
 120  * If nobody else has the file open, grant the requested level.
 121  * If any of the following are true, grant NONE:
 122  * - there is an exclusive oplock on the node
 123  * - op->op_oplock_levelII is B_FALSE (LEVEL_II not supported by open cmd.
 124  * - LEVEL_II oplocks are not supported for the session
 125  * - a BATCH oplock is requested on a named stream
 126  * - there are any range locks on the node (SMB writers)
 127  * Otherwise, grant LEVEL_II.
 128  *
 129  * ol->ol_xthread is set to the current thread to lock the oplock against
 130  * other operations until the acquire response is on the wire. When the
 131  * acquire response is on the wire, smb_oplock_broadcast() is called to
 132  * reset ol->ol_xthread and wake any waiting threads.
 133  */
 134 void
 135 smb_oplock_acquire(smb_request_t *sr, smb_node_t *node, smb_ofile_t *ofile)
 136 {
 137         smb_oplock_t            *ol;
 138         smb_oplock_grant_t      *og;
 139         list_t                  *grants;
 140         smb_arg_open_t          *op;
 141         smb_tree_t              *tree;
 142         smb_session_t           *session;
 143 
 144         SMB_NODE_VALID(node);
 145         SMB_OFILE_VALID(ofile);
 146 
 147         ASSERT(node == SMB_OFILE_GET_NODE(ofile));
 148         ASSERT(RW_LOCK_HELD(&node->n_lock));
 149 
 150         op = &sr->sr_open;
 151         tree = SMB_OFILE_GET_TREE(ofile);
 152         session = SMB_OFILE_GET_SESSION(ofile);
 153 
 154         if (smb_oplocks_enabled == 0 ||
 155             (op->op_oplock_level == SMB_OPLOCK_NONE) ||
 156             ((op->op_oplock_level == SMB_OPLOCK_BATCH) &&
 157             SMB_IS_STREAM(node))) {
 158                 op->op_oplock_level = SMB_OPLOCK_NONE;
 159                 return;
 160         }
 161 
 162         ol = &node->n_oplock;
 163         grants = &ol->ol_grants;
 164 
 165         mutex_enter(&ol->ol_mutex);
 166         smb_oplock_wait(node);
 167 
 168         /*
 169          * Even if there are no other opens, we might want to
 170          * grant only a Level II (shared) oplock so we avoid
 171          * ever granting exclusive oplocks.
 172          *
 173          * Borrowing the SMB_TREE_OPLOCKS flag to enable/disable
 174          * exclusive oplocks (for now).  See skc_oplock_enable,
 175          * which can now be taken as "exclusive oplock enable".
 176          * Should rename this parameter, and/or implement a new
 177          * multi-valued parameter for oplock enables.
 178          */
 179         if ((node->n_open_count > 1) ||
 180             (node->n_opening_count > 1) ||
 181             !smb_tree_has_feature(tree, SMB_TREE_OPLOCKS) ||
 182             smb_vop_other_opens(node->vp, ofile->f_mode)) {
 183                 /*
 184                  * There are other opens.
 185                  */
 186                 if ((!op->op_oplock_levelII) ||
 187                     (!smb_session_levelII_oplocks(session)) ||
 188                     (smb_oplock_exclusive_grant(grants) != NULL) ||
 189                     (smb_lock_range_access(sr, node, 0, 0, B_FALSE))) {
 190                         /*
 191                          * LevelII (shared) oplock not allowed,
 192                          * so reply with "none".
 193                          */
 194                         op->op_oplock_level = SMB_OPLOCK_NONE;
 195                         mutex_exit(&ol->ol_mutex);
 196                         return;
 197                 }
 198 
 199                 op->op_oplock_level = SMB_OPLOCK_LEVEL_II;
 200         }
 201 
 202         og = smb_oplock_set_grant(ofile, op->op_oplock_level);
 203         if (smb_oplock_insert_grant(node, og) != 0) {
 204                 smb_oplock_clear_grant(og);
 205                 op->op_oplock_level = SMB_OPLOCK_NONE;
 206                 mutex_exit(&ol->ol_mutex);
 207                 return;
 208         }
 209 
 210         ol->ol_xthread = curthread;
 211         mutex_exit(&ol->ol_mutex);
 212 }
 213 
 214 /*
 215  * smb_oplock_break
 216  *
 217  * Break granted oplocks according to the following rules:
 218  *
 219  * If there's an exclusive oplock granted on the node
 220  *  - if the BREAK_BATCH flags is specified and the oplock is not
 221  *    a batch oplock, no break is required.
 222  *  - if the session doesn't support LEVEL II oplocks, and 'brk' is
 223  *    BREAK_TO_LEVEL_II, do a BREAK_TO_NONE.
 224  *  - if the oplock is already breaking update the break level (if
 225  *    the requested break is to a lesser level), otherwise send an
 226  *    oplock break.
 227  *    Wait for acknowledgement of the break (unless NOWAIT flag is set)
 228  *
 229  * Otherwise:
 230  * If there are level II oplocks granted on the node, and the flags
 231  * indicate that they should be broken (BREAK_TO_NONE specified,
 232  * BREAK_EXCLUSIVE, BREAK_BATCH not specified) queue the levelII
 233  * break request for asynchronous processing.
 234  *
 235  * Returns:
 236  *       0 - oplock broken (or no break required)
 237  *  EAGAIN - oplock break request sent and would block
 238  *           awaiting the reponse but NOWAIT was specified
 239  *
 240  * NB: sr == NULL when called by FEM framework.
 241  */
 242 int
 243 smb_oplock_break(smb_request_t *sr, smb_node_t *node, uint32_t flags)
 244 {
 245         smb_oplock_t            *ol;
 246         smb_oplock_grant_t      *og;
 247         list_t                  *grants;
 248         uint32_t                timeout;
 249         uint8_t                 brk;
 250 
 251         SMB_NODE_VALID(node);
 252         ol = &node->n_oplock;
 253         grants = &ol->ol_grants;
 254 
 255         mutex_enter(&ol->ol_mutex);
 256         smb_oplock_wait(node);
 257 
 258         og = list_head(grants);
 259         if (og == NULL) {
 260                 mutex_exit(&ol->ol_mutex);
 261                 return (0);
 262         }
 263 
 264         SMB_OPLOCK_GRANT_VALID(og);
 265 
 266         /* break levelII oplocks */
 267         if (og->og_level == SMB_OPLOCK_LEVEL_II) {
 268                 mutex_exit(&ol->ol_mutex);
 269 
 270                 if ((flags & SMB_OPLOCK_BREAK_TO_NONE) &&
 271                     !(flags & SMB_OPLOCK_BREAK_EXCLUSIVE) &&
 272                     !(flags & SMB_OPLOCK_BREAK_BATCH))  {
 273                         smb_oplock_break_levelII(node);
 274                 }
 275                 return (0);
 276         }
 277 
 278         /* break exclusive oplock */
 279         if ((flags & SMB_OPLOCK_BREAK_BATCH) &&
 280             (og->og_level != SMB_OPLOCK_BATCH)) {
 281                 mutex_exit(&ol->ol_mutex);
 282                 return (0);
 283         }
 284 
 285         if ((flags & SMB_OPLOCK_BREAK_TO_LEVEL_II) &&
 286             smb_session_levelII_oplocks(og->og_session)) {
 287                 brk = SMB_OPLOCK_BREAK_TO_LEVEL_II;
 288         } else {
 289                 brk = SMB_OPLOCK_BREAK_TO_NONE;
 290         }
 291 
 292         switch (ol->ol_break) {
 293         case SMB_OPLOCK_NO_BREAK:
 294                 ol->ol_break = brk;
 295                 smb_oplock_sched_async_break(og, brk);
 296                 break;
 297         case SMB_OPLOCK_BREAK_TO_LEVEL_II:
 298                 if (brk == SMB_OPLOCK_BREAK_TO_NONE)
 299                         ol->ol_break = SMB_OPLOCK_BREAK_TO_NONE;
 300                 break;
 301         case SMB_OPLOCK_BREAK_TO_NONE:
 302         default:
 303                 break;
 304         }
 305 
 306         if (flags & SMB_OPLOCK_BREAK_NOWAIT) {
 307                 mutex_exit(&ol->ol_mutex);
 308                 return (EAGAIN);
 309         }
 310 
 311         if (sr && (sr->session == og->og_session) &&
 312             (sr->smb_uid == og->og_uid)) {
 313                 timeout = smb_oplock_min_timeout;
 314         } else {
 315                 timeout = smb_oplock_timeout;
 316         }
 317 
 318         mutex_exit(&ol->ol_mutex);
 319         smb_oplock_wait_ack(node, timeout);
 320         return (0);
 321 }
 322 
 323 /*
 324  * smb_oplock_break_levelII
 325  *
 326  * This is called after a file is modified in some way.  If there are
 327  * LevelII (shared) oplocks, break those to none.  If there is an
 328  * exclusive oplock, there can be no LevelII oplocks, so do nothing.
 329  *
 330  * LevelII (shared) oplock breaks are processed asynchronously.
 331  * Unlike exclusive oplock breaks, the thread initiating the break
 332  * is NOT blocked while the request is processed.
 333  *
 334  * There may be a thread with exclusive rights to oplock state for
 335  * this node (via ol_xthread in smb_oplock_wait) and if so, we must
 336  * avoid breaking oplocks until that's out of the way.  However, we
 337  * really don't want to block here, so when ol_xthread is set, we'll
 338  * just mark that a "break level II to none" is pending, and let the
 339  * exclusive thread do this work when it's done being exclusive.
 340  */
 341 void
 342 smb_oplock_break_levelII(smb_node_t *node)
 343 {
 344         smb_oplock_t            *ol;
 345 
 346         ol = &node->n_oplock;
 347         mutex_enter(&ol->ol_mutex);
 348 
 349         /* Instead of: smb_oplock_wait() ... */
 350         if (ol->ol_xthread != NULL) {
 351                 /* Defer the call to smb_oplock_broadcast(). */
 352                 ol->ol_brk_pending = SMB_OPLOCK_BREAK_TO_NONE;
 353         } else {
 354                 /* Equivalent of smb_oplock_wait() done. */
 355                 smb_oplock_break_levelII_locked(node);
 356         }
 357 
 358         mutex_exit(&ol->ol_mutex);
 359 }
 360 
 361 /*
 362  * smb_oplock_break_levelII_locked
 363  * Internal helper for smb_oplock_break_levelII()
 364  *
 365  * Called with the oplock mutex already held, and _after_
 366  * (the equivalent of) an smb_oplock_wait().
 367  */
 368 static void
 369 smb_oplock_break_levelII_locked(smb_node_t *node)
 370 {
 371         smb_oplock_t            *ol;
 372         smb_oplock_grant_t      *og;
 373         list_t                  *grants;
 374 
 375         ol = &node->n_oplock;
 376         grants = &ol->ol_grants;
 377 
 378         ASSERT(MUTEX_HELD(&ol->ol_mutex));
 379         ASSERT(ol->ol_xthread == NULL);
 380 
 381         while ((og = list_head(grants)) != NULL) {
 382                 SMB_OPLOCK_GRANT_VALID(og);
 383 
 384                 /*
 385                  * If there's an exclusive oplock, there are
 386                  * no LevelII oplocks, so do nothing.
 387                  */
 388                 if (SMB_OPLOCK_IS_EXCLUSIVE(og->og_level))
 389                         break;
 390 
 391                 smb_oplock_sched_async_break(og, SMB_OPLOCK_BREAK_TO_NONE);
 392                 smb_oplock_remove_grant(node, og);
 393                 smb_oplock_clear_grant(og);
 394         }
 395 }
 396 
 397 /*
 398  * Schedule a call to smb_session_oplock_break
 399  * using an smb_request on the owning session.
 400  */
 401 static void
 402 smb_oplock_sched_async_break(smb_oplock_grant_t *og, uint8_t brk)
 403 {
 404         smb_request_t           *sr;
 405         smb_ofile_t             *ofile;
 406 
 407         /*
 408          * Make sure we can get a hold on the ofile.  If we can't,
 409          * the file is closing, and there's no point scheduling an
 410          * oplock break on it.  (Also hold the tree and user.)
 411          * These holds account for the pointers we copy into the
 412          * smb_request fields: fid_ofile, tid_tree, uid_user.
 413          * These holds are released via smb_request_free after
 414          * the oplock break has been sent.
 415          */
 416         ofile = og->og_ofile;
 417         if (!smb_ofile_hold(ofile))
 418                 return;
 419         smb_tree_hold_internal(ofile->f_tree);
 420         smb_user_hold_internal(ofile->f_user);
 421 
 422         sr = smb_request_alloc(og->og_session, 0);
 423         sr->sr_state = SMB_REQ_STATE_SUBMITTED;
 424         sr->user_cr = zone_kcred();
 425         sr->fid_ofile = ofile;
 426         sr->tid_tree = ofile->f_tree;
 427         sr->uid_user = ofile->f_user;
 428 
 429         sr->arg.olbrk = *og; /* struct copy */
 430         sr->arg.olbrk.og_breaking = brk;
 431 
 432         (void) taskq_dispatch(
 433             sr->sr_server->sv_worker_pool,
 434             smb_oplock_exec_async_break, sr, TQ_SLEEP);
 435 }
 436 
 437 /*
 438  * smb_oplock_exec_async_break
 439  *
 440  * Called via the taskq to handle an asynchronous oplock break.
 441  * We have a hold on the ofile, which keeps the FID here valid.
 442  */
 443 static void
 444 smb_oplock_exec_async_break(void *arg)
 445 {
 446         smb_request_t *sr = arg;
 447         smb_oplock_grant_t *og = &sr->arg.olbrk;
 448 
 449         SMB_REQ_VALID(sr);
 450         SMB_OPLOCK_GRANT_VALID(og);
 451 
 452         mutex_enter(&sr->sr_mutex);
 453         sr->sr_worker = curthread;
 454         sr->sr_time_active = gethrtime();
 455 
 456         switch (sr->sr_state) {
 457         case SMB_REQ_STATE_SUBMITTED:
 458                 sr->sr_state = SMB_REQ_STATE_ACTIVE;
 459                 mutex_exit(&sr->sr_mutex);
 460 
 461                 /*
 462                  * This is where we actually do the deferred work
 463                  * requested by smb_oplock_sched_async_break().
 464                  */
 465                 smb_session_oplock_break(sr, og->og_breaking);
 466 
 467                 mutex_enter(&sr->sr_mutex);
 468                 /* FALLTHROUGH */
 469 
 470         default: /* typically cancelled */
 471                 sr->sr_state = SMB_REQ_STATE_COMPLETED;
 472                 mutex_exit(&sr->sr_mutex);
 473         }
 474 
 475         smb_request_free(sr);
 476 }
 477 
 478 /*
 479  * smb_oplock_wait_ack
 480  *
 481  * Timed wait for an oplock break acknowledgement (or oplock release).
 482  */
 483 static void
 484 smb_oplock_wait_ack(smb_node_t *node, uint32_t timeout)
 485 {
 486         smb_oplock_t    *ol;
 487         clock_t         time;
 488 
 489         ol = &node->n_oplock;
 490         mutex_enter(&ol->ol_mutex);
 491         time = MSEC_TO_TICK(timeout) + ddi_get_lbolt();
 492 
 493         while (ol->ol_break != SMB_OPLOCK_NO_BREAK) {
 494                 if (cv_timedwait(&ol->ol_cv, &ol->ol_mutex, time) < 0) {
 495                         smb_oplock_timedout(node);
 496                         cv_broadcast(&ol->ol_cv);
 497                         break;
 498                 }
 499         }
 500         mutex_exit(&ol->ol_mutex);
 501 }
 502 
 503 /*
 504  * smb_oplock_timedout
 505  *
 506  * An oplock break has not been acknowledged within timeout
 507  * 'smb_oplock_timeout'.
 508  * Set oplock grant to the desired break level.
 509  */
 510 static void
 511 smb_oplock_timedout(smb_node_t *node)
 512 {
 513         smb_oplock_t            *ol;
 514         smb_oplock_grant_t      *og;
 515         list_t                  *grants;
 516 
 517         ol = &node->n_oplock;
 518         grants = &ol->ol_grants;
 519 
 520         ASSERT(MUTEX_HELD(&ol->ol_mutex));
 521 
 522         og = smb_oplock_exclusive_grant(grants);
 523         if (og) {
 524                 switch (ol->ol_break) {
 525                 case SMB_OPLOCK_BREAK_TO_NONE:
 526                         og->og_level = SMB_OPLOCK_NONE;
 527                         smb_oplock_remove_grant(node, og);
 528                         smb_oplock_clear_grant(og);
 529                         break;
 530                 case SMB_OPLOCK_BREAK_TO_LEVEL_II:
 531                         og->og_level = SMB_OPLOCK_LEVEL_II;
 532                         break;
 533                 default:
 534                         SMB_PANIC();
 535                 }
 536         }
 537         ol->ol_break = SMB_OPLOCK_NO_BREAK;
 538 }
 539 
 540 /*
 541  * smb_oplock_release
 542  *
 543  * Release the oplock granted on ofile 'of'.
 544  * Wake any threads waiting for an oplock break acknowledgement for
 545  * this oplock.
 546  * This is called when the ofile is being closed.
 547  */
 548 void
 549 smb_oplock_release(smb_node_t *node, smb_ofile_t *of)
 550 {
 551         smb_oplock_t            *ol;
 552         smb_oplock_grant_t      *og;
 553 
 554         ol = &node->n_oplock;
 555         mutex_enter(&ol->ol_mutex);
 556         smb_oplock_wait(node);
 557 
 558         og = smb_oplock_get_grant(ol, of);
 559         if (og) {
 560                 smb_oplock_remove_grant(node, og);
 561                 smb_oplock_clear_grant(og);
 562 
 563                 if (ol->ol_break != SMB_OPLOCK_NO_BREAK) {
 564                         ol->ol_break = SMB_OPLOCK_NO_BREAK;
 565                         cv_broadcast(&ol->ol_cv);
 566                 }
 567         }
 568 
 569         mutex_exit(&ol->ol_mutex);
 570 }
 571 
 572 /*
 573  * smb_oplock_ack
 574  *
 575  * Process oplock acknowledgement received for ofile 'of'.
 576  * - oplock.ol_break is the break level that was requested.
 577  * - brk is the break level being acknowledged by the client.
 578  *
 579  * Update the oplock grant level to the lesser of ol_break and brk.
 580  * If the grant is now SMB_OPLOCK_NONE, remove the grant from the
 581  * oplock's grant list and delete it.
 582  * If the requested break level (ol_break) was NONE and the brk is
 583  * LEVEL_II, send another oplock break (NONE). Do not wait for an
 584  * acknowledgement.
 585  * Wake any threads waiting for the oplock break acknowledgement.
 586  */
 587 void
 588 smb_oplock_ack(smb_node_t *node, smb_ofile_t *of, uint8_t brk)
 589 {
 590         smb_oplock_t            *ol;
 591         smb_oplock_grant_t      *og;
 592 
 593         ol = &node->n_oplock;
 594         mutex_enter(&ol->ol_mutex);
 595         smb_oplock_wait(node);
 596 
 597         if ((ol->ol_break == SMB_OPLOCK_NO_BREAK) ||
 598             ((og = smb_oplock_get_grant(ol, of)) == NULL)) {
 599                 mutex_exit(&ol->ol_mutex);
 600                 return;
 601         }
 602 
 603         switch (brk) {
 604         case SMB_OPLOCK_BREAK_TO_NONE:
 605                 og->og_level = SMB_OPLOCK_NONE;
 606                 break;
 607         case SMB_OPLOCK_BREAK_TO_LEVEL_II:
 608                 if (ol->ol_break == SMB_OPLOCK_BREAK_TO_LEVEL_II) {
 609                         og->og_level = SMB_OPLOCK_LEVEL_II;
 610                 } else {
 611                         /* SMB_OPLOCK_BREAK_TO_NONE */
 612                         og->og_level = SMB_OPLOCK_NONE;
 613                         smb_oplock_sched_async_break(og,
 614                             SMB_OPLOCK_BREAK_TO_NONE);
 615                 }
 616                 break;
 617         default:
 618                 SMB_PANIC();
 619         }
 620 
 621         if (og->og_level == SMB_OPLOCK_NONE) {
 622                 smb_oplock_remove_grant(node, og);
 623                 smb_oplock_clear_grant(og);
 624         }
 625 
 626         ol->ol_break = SMB_OPLOCK_NO_BREAK;
 627         cv_broadcast(&ol->ol_cv);
 628 
 629         mutex_exit(&ol->ol_mutex);
 630 }
 631 
 632 /*
 633  * smb_oplock_broadcast
 634  *
 635  * Called when an open with oplock request completes.
 636  *
 637  * ol->ol_xthread identifies the thread that was performing an oplock
 638  * acquire. Other threads may be blocked awaiting completion of the
 639  * acquire.
 640  * If the calling thread is ol_xthread, wake any waiting threads.
 641  */
 642 void
 643 smb_oplock_broadcast(smb_node_t *node)
 644 {
 645         smb_oplock_t    *ol;
 646 
 647         SMB_NODE_VALID(node);
 648         ol = &node->n_oplock;
 649 
 650         mutex_enter(&ol->ol_mutex);
 651         if ((ol->ol_xthread != NULL) && (ol->ol_xthread == curthread)) {
 652                 ol->ol_xthread = NULL;
 653                 if (ol->ol_brk_pending) {
 654                         ol->ol_brk_pending = 0;
 655                         smb_oplock_break_levelII_locked(node);
 656                 }
 657                 cv_broadcast(&ol->ol_cv);
 658         }
 659         mutex_exit(&ol->ol_mutex);
 660 }
 661 
 662 /*
 663  * smb_oplock_wait
 664  *
 665  * Wait for the completion of an oplock acquire.
 666  * If ol_xthread is not NULL and doesn't contain the pointer to the
 667  * context of the calling thread, the caller will sleep until the
 668  * ol_xthread is reset to NULL (via smb_oplock_broadcast()).
 669  */
 670 static void
 671 smb_oplock_wait(smb_node_t *node)
 672 {
 673         smb_oplock_t    *ol;
 674 
 675         ol = &node->n_oplock;
 676         ASSERT(MUTEX_HELD(&ol->ol_mutex));
 677 
 678         if ((ol->ol_xthread != NULL) && (ol->ol_xthread != curthread)) {
 679                 while (ol->ol_xthread != NULL)
 680                         cv_wait(&ol->ol_cv, &ol->ol_mutex);
 681         }
 682 }
 683 
 684 /*
 685  * smb_oplock_set_grant
 686  */
 687 static smb_oplock_grant_t *
 688 smb_oplock_set_grant(smb_ofile_t *of, uint8_t level)
 689 {
 690         smb_oplock_grant_t      *og;
 691 
 692         og = &of->f_oplock_grant;
 693 
 694         og->og_magic = SMB_OPLOCK_GRANT_MAGIC;
 695         og->og_breaking = 0;
 696         og->og_level = level;
 697         og->og_ofile = of;
 698         og->og_fid = of->f_fid;
 699         og->og_tid = of->f_tree->t_tid;
 700         og->og_uid = of->f_user->u_uid;
 701         og->og_session = of->f_session;
 702         return (og);
 703 }
 704 
 705 /*
 706  * smb_oplock_clear_grant
 707  */
 708 void
 709 smb_oplock_clear_grant(smb_oplock_grant_t *og)
 710 {
 711         bzero(og, sizeof (smb_oplock_grant_t));
 712 }
 713 
 714 /*
 715  * smb_oplock_insert_grant
 716  *
 717  * If there are no grants in the oplock's list install the fem
 718  * monitor.
 719  * Insert the grant into the list and increment the grant count.
 720  */
 721 static int
 722 smb_oplock_insert_grant(smb_node_t *node, smb_oplock_grant_t *og)
 723 {
 724         smb_oplock_t *ol = &node->n_oplock;
 725 
 726         ASSERT(MUTEX_HELD(&ol->ol_mutex));
 727 
 728         if (ol->ol_count == 0) {
 729                 if (smb_oplock_install_fem(node) != 0)
 730                         return (-1);
 731         }
 732 
 733         list_insert_tail(&ol->ol_grants, og);
 734         ++ol->ol_count;
 735         return (0);
 736 }
 737 
 738 /*
 739  * smb_oplock_remove_grant
 740  *
 741  * Remove the oplock grant from the list, decrement the grant count
 742  * and, if there are no other grants in the list, uninstall the fem
 743  * monitor.
 744  */
 745 static void
 746 smb_oplock_remove_grant(smb_node_t *node, smb_oplock_grant_t *og)
 747 {
 748         smb_oplock_t *ol = &node->n_oplock;
 749 
 750         ASSERT(MUTEX_HELD(&ol->ol_mutex));
 751         ASSERT(ol->ol_count > 0);
 752 
 753         list_remove(&ol->ol_grants, og);
 754         if (--ol->ol_count == 0)
 755                 smb_oplock_uninstall_fem(node);
 756 }
 757 
 758 /*
 759  * smb_oplock_exclusive_grant
 760  *
 761  * If an exclusive (EXCLUSIVE or BATCH) oplock grant exists,
 762  * return it. Otherwise return NULL.
 763  */
 764 static smb_oplock_grant_t *
 765 smb_oplock_exclusive_grant(list_t *grants)
 766 {
 767         smb_oplock_grant_t      *og;
 768 
 769         og = list_head(grants);
 770         if (og) {
 771                 SMB_OPLOCK_GRANT_VALID(og);
 772                 if (SMB_OPLOCK_IS_EXCLUSIVE(og->og_level))
 773                         return (og);
 774         }
 775         return (NULL);
 776 }
 777 
 778 /*
 779  * smb_oplock_get_grant
 780  *
 781  * Find oplock grant corresponding to the specified ofile.
 782  */
 783 static smb_oplock_grant_t *
 784 smb_oplock_get_grant(smb_oplock_t *ol, smb_ofile_t *ofile)
 785 {
 786         ASSERT(MUTEX_HELD(&ol->ol_mutex));
 787 
 788         if (SMB_OFILE_OPLOCK_GRANTED(ofile))
 789                 return (&ofile->f_oplock_grant);
 790         else
 791                 return (NULL);
 792 }