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 2017 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 /* 17 * Dispatch function for SMB2_OPLOCK_BREAK 18 */ 19 20 #include <smbsrv/smb2_kproto.h> 21 #include <smbsrv/smb_oplock.h> 22 23 /* StructSize for the two "break" message formats. */ 24 #define SSZ_OPLOCK 24 25 #define SSZ_LEASE_ACK 36 26 #define SSZ_LEASE_BRK 44 27 28 #define NODE_FLAGS_DELETING (NODE_FLAGS_DELETE_ON_CLOSE |\ 29 NODE_FLAGS_DELETE_COMMITTED) 30 31 static const char lease_zero[UUID_LEN] = { 0 }; 32 33 static kmem_cache_t *smb_lease_cache = NULL; 34 35 void 36 smb2_lease_init() 37 { 38 if (smb_lease_cache != NULL) 39 return; 40 41 smb_lease_cache = kmem_cache_create("smb_lease_cache", 42 sizeof (smb_lease_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 43 } 44 45 void 46 smb2_lease_fini() 47 { 48 if (smb_lease_cache != NULL) { 49 kmem_cache_destroy(smb_lease_cache); 50 smb_lease_cache = NULL; 51 } 52 } 53 54 static void 55 smb2_lease_hold(smb_lease_t *ls) 56 { 57 mutex_enter(&ls->ls_mutex); 58 ls->ls_refcnt++; 59 mutex_exit(&ls->ls_mutex); 60 } 61 62 void 63 smb2_lease_rele(smb_lease_t *ls) 64 { 65 smb_llist_t *bucket; 66 67 mutex_enter(&ls->ls_mutex); 68 ls->ls_refcnt--; 69 if (ls->ls_refcnt != 0) { 70 mutex_exit(&ls->ls_mutex); 71 return; 72 } 73 mutex_exit(&ls->ls_mutex); 74 75 /* 76 * Get the list lock, then re-check the refcnt 77 * and if it's still zero, unlink & destroy. 78 */ 79 bucket = ls->ls_bucket; 80 smb_llist_enter(bucket, RW_WRITER); 81 82 mutex_enter(&ls->ls_mutex); 83 if (ls->ls_refcnt == 0) 84 smb_llist_remove(bucket, ls); 85 mutex_exit(&ls->ls_mutex); 86 87 if (ls->ls_refcnt == 0) { 88 mutex_destroy(&ls->ls_mutex); 89 kmem_cache_free(smb_lease_cache, ls); 90 } 91 92 smb_llist_exit(bucket); 93 } 94 95 /* 96 * Compute a hash from a uuid 97 * Based on mod_hash_bystr() 98 */ 99 static uint_t 100 smb_hash_uuid(const uint8_t *uuid) 101 { 102 char *k = (char *)uuid; 103 uint_t hash = 0; 104 uint_t g; 105 int i; 106 107 ASSERT(k); 108 for (i = 0; i < UUID_LEN; i++) { 109 hash = (hash << 4) + k[i]; 110 if ((g = (hash & 0xf0000000)) != 0) { 111 hash ^= (g >> 24); 112 hash ^= g; 113 } 114 } 115 return (hash); 116 } 117 118 /* 119 * Add or update a lease table entry for a new ofile. 120 * (in the per-session lease table) 121 * See [MS-SMB2] 3.3.5.9.8 122 * Handling the SMB2_CREATE_REQUEST_LEASE Create Context 123 */ 124 uint32_t 125 smb2_lease_create(smb_request_t *sr) 126 { 127 smb_arg_open_t *op = &sr->arg.open; 128 uint8_t *key = op->lease_key; 129 uint8_t *clnt = sr->session->clnt_uuid; 130 smb_ofile_t *of = sr->fid_ofile; 131 smb_hash_t *ht = sr->sr_server->sv_lease_ht; 132 smb_llist_t *bucket; 133 smb_lease_t *lease; 134 smb_lease_t *newlease; 135 size_t hashkey; 136 uint32_t status = NT_STATUS_INVALID_PARAMETER; 137 138 if (bcmp(key, lease_zero, UUID_LEN) == 0) 139 return (status); 140 141 /* 142 * Find or create, and add a ref for the new ofile. 143 */ 144 hashkey = smb_hash_uuid(key); 145 hashkey &= (ht->num_buckets - 1); 146 bucket = &ht->buckets[hashkey].b_list; 147 148 newlease = kmem_cache_alloc(smb_lease_cache, KM_SLEEP); 149 bzero(newlease, sizeof (smb_lease_t)); 150 mutex_init(&newlease->ls_mutex, NULL, MUTEX_DEFAULT, NULL); 151 newlease->ls_bucket = bucket; 152 newlease->ls_node = of->f_node; 153 newlease->ls_refcnt = 1; 154 newlease->ls_epoch = op->lease_epoch; 155 newlease->ls_version = op->lease_version; 156 bcopy(key, newlease->ls_key, UUID_LEN); 157 bcopy(clnt, newlease->ls_clnt, UUID_LEN); 158 159 smb_llist_enter(bucket, RW_WRITER); 160 for (lease = smb_llist_head(bucket); lease != NULL; 161 lease = smb_llist_next(bucket, lease)) { 162 /* 163 * Looking for this lease ID, on a node 164 * that's not being deleted. 165 */ 166 if (bcmp(lease->ls_key, key, UUID_LEN) == 0 && 167 bcmp(lease->ls_clnt, clnt, UUID_LEN) == 0 && 168 (lease->ls_node->flags & NODE_FLAGS_DELETING) == 0) 169 break; 170 } 171 if (lease != NULL) { 172 /* 173 * Found existing lease. Make sure it refers to 174 * the same node... 175 */ 176 if (lease->ls_node == of->f_node) { 177 smb2_lease_hold(lease); 178 } else { 179 /* Same lease ID, different node! */ 180 #ifdef DEBUG 181 cmn_err(CE_NOTE, "new lease on node %p (%s) " 182 "conflicts with existing node %p (%s)", 183 (void *) of->f_node, 184 of->f_node->od_name, 185 (void *) lease->ls_node, 186 lease->ls_node->od_name); 187 #endif 188 DTRACE_PROBE2(dup_lease, smb_request_t, sr, 189 smb_lease_t, lease); 190 lease = NULL; /* error */ 191 } 192 } else { 193 lease = newlease; 194 smb_llist_insert_head(bucket, lease); 195 newlease = NULL; /* don't free */ 196 } 197 smb_llist_exit(bucket); 198 199 if (newlease != NULL) { 200 mutex_destroy(&newlease->ls_mutex); 201 kmem_cache_free(smb_lease_cache, newlease); 202 } 203 204 if (lease != NULL) { 205 of->f_lease = lease; 206 status = NT_STATUS_SUCCESS; 207 } 208 209 return (status); 210 } 211 212 /* 213 * Find the lease for a given: client_uuid, lease_key 214 * Returns the lease with a new ref. 215 */ 216 smb_lease_t * 217 smb2_lease_lookup(smb_server_t *sv, uint8_t *clnt_uuid, uint8_t *lease_key) 218 { 219 smb_hash_t *ht = sv->sv_lease_ht; 220 smb_llist_t *bucket; 221 smb_lease_t *lease; 222 size_t hashkey; 223 224 hashkey = smb_hash_uuid(lease_key); 225 hashkey &= (ht->num_buckets - 1); 226 bucket = &ht->buckets[hashkey].b_list; 227 228 smb_llist_enter(bucket, RW_READER); 229 lease = smb_llist_head(bucket); 230 while (lease != NULL) { 231 if (bcmp(lease->ls_key, lease_key, UUID_LEN) == 0 && 232 bcmp(lease->ls_clnt, clnt_uuid, UUID_LEN) == 0) { 233 smb2_lease_hold(lease); 234 break; 235 } 236 lease = smb_llist_next(bucket, lease); 237 } 238 smb_llist_exit(bucket); 239 240 return (lease); 241 } 242 243 /* 244 * Find an smb_ofile_t in the current tree that shares the 245 * specified lease and has some oplock breaking flags set. 246 * If lease not found, NT_STATUS_OBJECT_NAME_NOT_FOUND. 247 * If ofile not breaking NT_STATUS_UNSUCCESSFUL. 248 * On success, ofile (held) in sr->fid_ofile. 249 */ 250 static uint32_t 251 find_breaking_ofile(smb_request_t *sr, uint8_t *lease_key) 252 { 253 smb_tree_t *tree = sr->tid_tree; 254 smb_lease_t *lease; 255 smb_llist_t *of_list; 256 smb_ofile_t *o; 257 uint32_t status = NT_STATUS_OBJECT_NAME_NOT_FOUND; 258 259 SMB_TREE_VALID(tree); 260 of_list = &tree->t_ofile_list; 261 262 smb_llist_enter(of_list, RW_READER); 263 for (o = smb_llist_head(of_list); o != NULL; 264 o = smb_llist_next(of_list, o)) { 265 266 ASSERT(o->f_magic == SMB_OFILE_MAGIC); 267 ASSERT(o->f_tree == tree); 268 269 if ((lease = o->f_lease) == NULL) 270 continue; // no lease 271 272 if (bcmp(lease->ls_key, lease_key, UUID_LEN) != 0) 273 continue; // wrong lease 274 275 /* 276 * Now we know the lease exists, so if we don't 277 * find an ofile with breaking flags, return: 278 */ 279 status = NT_STATUS_UNSUCCESSFUL; 280 281 if (o->f_oplock.og_breaking == 0) 282 continue; // not breaking 283 284 /* Found breaking ofile. */ 285 if (smb_ofile_hold(o)) { 286 sr->fid_ofile = o; 287 status = NT_STATUS_SUCCESS; 288 break; 289 } 290 } 291 smb_llist_exit(of_list); 292 293 return (status); 294 } 295 296 /* 297 * This is called by smb2_oplock_break_ack when the struct size 298 * indicates this is a lease break (SZ_LEASE). See: 299 * [MS-SMB2] 3.3.5.22.2 Processing a Lease Acknowledgment 300 */ 301 smb_sdrc_t 302 smb2_lease_break_ack(smb_request_t *sr) 303 { 304 smb_lease_t *lease; 305 smb_ofile_t *ofile; 306 uint8_t LeaseKey[UUID_LEN]; 307 uint32_t LeaseState; 308 uint32_t LeaseBreakTo; 309 uint32_t status; 310 int rc = 0; 311 312 if (sr->session->dialect < SMB_VERS_2_1) 313 return (SDRC_ERROR); 314 315 /* 316 * Decode an SMB2 Lease Acknowldgement 317 * [MS-SMB2] 2.2.24.2 318 * Note: Struct size decoded by caller. 319 */ 320 rc = smb_mbc_decodef( 321 &sr->smb_data, "6.#cl8.", 322 /* reserved 6. */ 323 UUID_LEN, /* # */ 324 LeaseKey, /* c */ 325 &LeaseState); /* l */ 326 /* duration 8. */ 327 if (rc != 0) 328 return (SDRC_ERROR); 329 330 status = find_breaking_ofile(sr, LeaseKey); 331 332 DTRACE_SMB2_START(op__OplockBreak, smb_request_t *, sr); 333 if (status != 0) 334 goto errout; 335 336 /* Success, so have sr->fid_ofile and lease */ 337 ofile = sr->fid_ofile; 338 lease = ofile->f_lease; 339 340 /* 341 * Process the lease break ack. 342 * 343 * If the new LeaseState has any bits in excess of 344 * the lease state we sent in the break, error... 345 */ 346 LeaseBreakTo = (lease->ls_breaking >> BREAK_SHIFT) & 347 OPLOCK_LEVEL_CACHE_MASK; 348 if ((LeaseState & ~LeaseBreakTo) != 0) { 349 status = NT_STATUS_REQUEST_NOT_ACCEPTED; 350 goto errout; 351 } 352 353 ofile->f_oplock.og_breaking = 0; 354 lease->ls_breaking = 0; 355 356 LeaseState |= OPLOCK_LEVEL_GRANULAR; 357 status = smb_oplock_ack_break(sr, ofile, &LeaseState); 358 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 359 (void) smb2sr_go_async(sr); 360 (void) smb_oplock_wait_break(ofile->f_node, 0); 361 status = NT_STATUS_SUCCESS; 362 } 363 364 ofile->f_oplock.og_state = LeaseState; 365 lease->ls_state = LeaseState & 366 OPLOCK_LEVEL_CACHE_MASK; 367 368 errout: 369 sr->smb2_status = status; 370 DTRACE_SMB2_DONE(op__OplockBreak, smb_request_t *, sr); 371 if (status) { 372 smb2sr_put_error(sr, status); 373 return (SDRC_SUCCESS); 374 } 375 376 /* 377 * Encode an SMB2 Lease Ack. response 378 * [MS-SMB2] 2.2.25.2 379 */ 380 LeaseState &= OPLOCK_LEVEL_CACHE_MASK; 381 (void) smb_mbc_encodef( 382 &sr->reply, "w6.#cl8.", 383 SSZ_LEASE_ACK, /* w */ 384 /* reserved 6. */ 385 UUID_LEN, /* # */ 386 LeaseKey, /* c */ 387 LeaseState); /* l */ 388 /* duration 8. */ 389 390 return (SDRC_SUCCESS); 391 392 } 393 394 /* 395 * Compose an SMB2 Lease Break Notification packet, including 396 * the SMB2 header and everything, in sr->reply. 397 * The caller will send it and free the request. 398 * 399 * [MS-SMB2] 2.2.23.2 Lease Break Notification 400 */ 401 void 402 smb2_lease_break_notification(smb_request_t *sr, uint32_t NewLevel, 403 boolean_t AckReq) 404 { 405 smb_ofile_t *ofile = sr->fid_ofile; 406 smb_oplock_grant_t *og = &ofile->f_oplock; 407 smb_lease_t *ls = ofile->f_lease; 408 uint32_t oldcache; 409 uint32_t newcache; 410 uint16_t Epoch; 411 uint16_t Flags; 412 413 /* 414 * Convert internal level to SMB2 415 */ 416 oldcache = og->og_state & OPLOCK_LEVEL_CACHE_MASK; 417 newcache = NewLevel & OPLOCK_LEVEL_CACHE_MASK; 418 if (ls->ls_version < 2) 419 Epoch = 0; 420 else 421 Epoch = ls->ls_epoch; 422 423 /* 424 * SMB2 Header 425 */ 426 sr->smb2_cmd_code = SMB2_OPLOCK_BREAK; 427 sr->smb2_hdr_flags = SMB2_FLAGS_SERVER_TO_REDIR; 428 sr->smb_tid = 0; 429 sr->smb_pid = 0; 430 sr->smb2_ssnid = 0; 431 sr->smb2_messageid = UINT64_MAX; 432 (void) smb2_encode_header(sr, B_FALSE); 433 434 /* 435 * SMB2 Oplock Break, variable part 436 * 437 * [MS-SMB2] says the current lease state preceeds the 438 * new lease state, but that looks like an error... 439 */ 440 Flags = AckReq ? SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED : 0; 441 (void) smb_mbc_encodef( 442 &sr->reply, "wwl#cll4.4.4.", 443 SSZ_LEASE_BRK, /* w */ 444 Epoch, /* w */ 445 Flags, /* l */ 446 SMB_LEASE_KEY_SZ, /* # */ 447 ls->ls_key, /* c */ 448 oldcache, /* cur.st l */ 449 newcache); /* new.st l */ 450 /* reserved (4.4.4.) */ 451 } 452 453 /* 454 * Client has an open handle and requests a lease. 455 * Convert SMB2 lease request info in to internal form, 456 * call common oplock code, convert result to SMB2. 457 * 458 * If necessary, "go async" here. 459 */ 460 void 461 smb2_lease_acquire(smb_request_t *sr) 462 { 463 smb_arg_open_t *op = &sr->arg.open; 464 smb_ofile_t *ofile = sr->fid_ofile; 465 smb_lease_t *lease = ofile->f_lease; 466 uint32_t status = NT_STATUS_OPLOCK_NOT_GRANTED; 467 uint32_t have, want; /* lease flags */ 468 boolean_t NewGrant = B_FALSE; 469 470 /* Only disk trees get oplocks. */ 471 ASSERT((sr->tid_tree->t_res_type & STYPE_MASK) == STYPE_DISKTREE); 472 473 /* 474 * Only plain files (for now). 475 * Later, test SMB2_CAP_DIRECTORY_LEASING 476 */ 477 if (!smb_node_is_file(ofile->f_node)) { 478 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 479 return; 480 } 481 482 if (!smb_tree_has_feature(sr->tid_tree, SMB_TREE_OPLOCKS)) { 483 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 484 return; 485 } 486 487 /* 488 * SMB2: Convert to internal form. 489 * Caller should have setup the lease. 490 */ 491 ASSERT(op->op_oplock_level == SMB2_OPLOCK_LEVEL_LEASE); 492 ASSERT(lease != NULL); 493 if (lease == NULL) { 494 op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; 495 return; 496 } 497 op->op_oplock_state = OPLOCK_LEVEL_GRANULAR | 498 (op->lease_state & CACHE_RWH); 499 500 /* 501 * Tree options may force shared oplocks, 502 * in which case we reduce the request. 503 */ 504 if (smb_tree_has_feature(sr->tid_tree, SMB_TREE_FORCE_L2_OPLOCK)) { 505 op->op_oplock_state &= ~WRITE_CACHING; 506 } 507 508 /* 509 * Disallow downgrade 510 * 511 * Note that open with a lease is not allowed to turn off 512 * any cache rights. If the client tries to "downgrade", 513 * any bits, just return the existing lease cache bits. 514 */ 515 have = lease->ls_state & CACHE_RWH; 516 want = op->op_oplock_state & CACHE_RWH; 517 if ((have & ~want) != 0) { 518 op->op_oplock_state = have | 519 OPLOCK_LEVEL_GRANULAR; 520 goto done; 521 } 522 523 /* 524 * Handle oplock requests in three parts: 525 * a: Requests with WRITE_CACHING 526 * b: Requests with HANDLE_CACHING 527 * c: Requests with READ_CACHING 528 * reducing the request before b and c. 529 * 530 * In each: first check if the lease grants the 531 * (possibly reduced) request, in which case we 532 * leave the lease unchanged and return what's 533 * granted by the lease. Otherwise, try to get 534 * the oplock, and if the succeeds, wait for any 535 * breaks, update the lease, and return. 536 */ 537 538 /* 539 * Try exclusive (request is RW or RWH) 540 */ 541 if ((op->op_oplock_state & WRITE_CACHING) != 0) { 542 want = op->op_oplock_state & CACHE_RWH; 543 if (have == want) 544 goto done; 545 546 status = smb_oplock_request(sr, ofile, 547 &op->op_oplock_state); 548 if (status == NT_STATUS_SUCCESS || 549 status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 550 NewGrant = B_TRUE; 551 goto done; 552 } 553 554 /* 555 * We did not get the exclusive oplock. 556 * 557 * There are odd rules about lease upgrade. 558 * If the existing lease grants R and the 559 * client fails to upgrade it to "RWH" 560 * (presumably due to handle conflicts) 561 * then just return the existing lease, 562 * even though upgrade to RH would work. 563 */ 564 if (have != 0) { 565 op->op_oplock_state = have | 566 OPLOCK_LEVEL_GRANULAR; 567 goto done; 568 } 569 570 /* 571 * Keep trying without write. 572 * Need to re-init op_oplock_state 573 */ 574 op->op_oplock_state = OPLOCK_LEVEL_GRANULAR | 575 (op->lease_state & CACHE_RH); 576 } 577 578 /* 579 * Try shared ("RH") 580 */ 581 if ((op->op_oplock_state & HANDLE_CACHING) != 0) { 582 want = op->op_oplock_state & CACHE_RWH; 583 if (have == want) 584 goto done; 585 586 status = smb_oplock_request(sr, ofile, 587 &op->op_oplock_state); 588 if (status == NT_STATUS_SUCCESS || 589 status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 590 NewGrant = B_TRUE; 591 goto done; 592 } 593 594 /* 595 * We did not get "RH", probably because 596 * ther were (old style) Level II oplocks. 597 * Continue, try for just read. 598 */ 599 op->op_oplock_state = OPLOCK_LEVEL_GRANULAR | 600 (op->lease_state & CACHE_R); 601 } 602 603 /* 604 * Try shared ("R") 605 */ 606 if ((op->op_oplock_state & READ_CACHING) != 0) { 607 want = op->op_oplock_state & CACHE_RWH; 608 if (have == want) 609 goto done; 610 611 status = smb_oplock_request(sr, ofile, 612 &op->op_oplock_state); 613 if (status == NT_STATUS_SUCCESS || 614 status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 615 NewGrant = B_TRUE; 616 goto done; 617 } 618 619 /* 620 * We did not get "R". 621 * Fall into "none". 622 */ 623 } 624 625 /* 626 * None of the above were able to get an oplock. 627 * The lease has no caching rights, and we didn't 628 * add any in this request. Return it as-is. 629 */ 630 op->op_oplock_state = OPLOCK_LEVEL_GRANULAR; 631 632 done: 633 if (NewGrant) { 634 /* 635 * After a new oplock grant, the status return 636 * may indicate we need to wait for breaks. 637 */ 638 if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) { 639 (void) smb2sr_go_async(sr); 640 (void) smb_oplock_wait_break(ofile->f_node, 0); 641 status = NT_STATUS_SUCCESS; 642 } 643 ASSERT(status == NT_STATUS_SUCCESS); 644 645 /* 646 * Keep track of what we got (in ofile->f_oplock.og_state) 647 * so we'll know what we had when sending a break later. 648 * Also update the lease with the new oplock state. 649 * Also track which ofile on the lease owns the oplock. 650 * The og_dialect here is the oplock dialect, not the 651 * SMB dialect. Leasing, so SMB 2.1 (or later). 652 */ 653 ofile->f_oplock.og_dialect = SMB_VERS_2_1; 654 ofile->f_oplock.og_state = op->op_oplock_state; 655 mutex_enter(&lease->ls_mutex); 656 lease->ls_state = op->op_oplock_state & CACHE_RWH; 657 lease->ls_oplock_ofile = ofile; 658 lease->ls_epoch++; 659 mutex_exit(&lease->ls_mutex); 660 } 661 662 /* 663 * Convert internal oplock state to SMB2 664 */ 665 op->op_oplock_level = SMB2_OPLOCK_LEVEL_LEASE; 666 op->lease_state = lease->ls_state & CACHE_RWH; 667 op->lease_flags = (lease->ls_breaking != 0) ? 668 SMB2_LEASE_FLAG_BREAK_IN_PROGRESS : 0; 669 op->lease_epoch = lease->ls_epoch; 670 op->lease_version = lease->ls_version; 671 } 672 673 /* 674 * This ofile has a lease and is about to close. 675 * Called by smb_ofile_close when there's a lease. 676 * 677 * With leases, just one ofile on a lease owns the oplock. 678 * If an ofile with a lease is closed and it's the one that 679 * owns the oplock, try to move the oplock to another ofile 680 * on the same lease. 681 */ 682 void 683 smb2_lease_ofile_close(smb_ofile_t *ofile) 684 { 685 smb_node_t *node = ofile->f_node; 686 smb_lease_t *lease = ofile->f_lease; 687 smb_ofile_t *o; 688 689 /* 690 * If this ofile was not the oplock owner for this lease, 691 * we can leave things as they are. 692 */ 693 if (lease->ls_oplock_ofile != ofile) 694 return; 695 696 /* 697 * Find another ofile to which we can move the oplock. 698 * The ofile must be open and allow a new ref. 699 */ 700 smb_llist_enter(&node->n_ofile_list, RW_READER); 701 FOREACH_NODE_OFILE(node, o) { 702 if (o == ofile) 703 continue; 704 if (o->f_lease != lease) 705 continue; 706 /* If we can get a hold, use this ofile. */ 707 if (smb_ofile_hold(o)) 708 break; 709 } 710 if (o == NULL) { 711 /* Normal for last close on a lease. */ 712 smb_llist_exit(&node->n_ofile_list); 713 return; 714 } 715 smb_oplock_move(node, ofile, o); 716 lease->ls_oplock_ofile = o; 717 718 smb_llist_exit(&node->n_ofile_list); 719 smb_ofile_release(o); 720 } 721