1*6600Sas200622 /* 2*6600Sas200622 * CDDL HEADER START 3*6600Sas200622 * 4*6600Sas200622 * The contents of this file are subject to the terms of the 5*6600Sas200622 * Common Development and Distribution License (the "License"). 6*6600Sas200622 * You may not use this file except in compliance with the License. 7*6600Sas200622 * 8*6600Sas200622 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*6600Sas200622 * or http://www.opensolaris.org/os/licensing. 10*6600Sas200622 * See the License for the specific language governing permissions 11*6600Sas200622 * and limitations under the License. 12*6600Sas200622 * 13*6600Sas200622 * When distributing Covered Code, include this CDDL HEADER in each 14*6600Sas200622 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*6600Sas200622 * If applicable, add the following below this CDDL HEADER, with the 16*6600Sas200622 * fields enclosed by brackets "[]" replaced with your own identifying 17*6600Sas200622 * information: Portions Copyright [yyyy] [name of copyright owner] 18*6600Sas200622 * 19*6600Sas200622 * CDDL HEADER END 20*6600Sas200622 */ 21*6600Sas200622 /* 22*6600Sas200622 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*6600Sas200622 * Use is subject to license terms. 24*6600Sas200622 */ 25*6600Sas200622 26*6600Sas200622 #pragma ident "%Z%%M% %I% %E% SMI" 27*6600Sas200622 28*6600Sas200622 /* 29*6600Sas200622 * SMB Locking library functions. 30*6600Sas200622 */ 31*6600Sas200622 32*6600Sas200622 #include <smbsrv/smb_incl.h> 33*6600Sas200622 #include <smbsrv/smb_fsops.h> 34*6600Sas200622 35*6600Sas200622 /* 36*6600Sas200622 * Oplock functionality enable/disable 37*6600Sas200622 */ 38*6600Sas200622 39*6600Sas200622 /* 40*6600Sas200622 * Magic 0xFF 'S' 'M' 'B' 41*6600Sas200622 * smb_com a byte, the "first" command 42*6600Sas200622 * Error a 4-byte union, ignored in a request 43*6600Sas200622 * smb_flg a one byte set of eight flags 44*6600Sas200622 * smb_flg2 a two byte set of 16 flags 45*6600Sas200622 * . twelve reserved bytes, have a role 46*6600Sas200622 * in connectionless transports (IPX, UDP?) 47*6600Sas200622 * smb_tid a 16-bit tree ID, a mount point sorta, 48*6600Sas200622 * 0xFFFF is this command does not have 49*6600Sas200622 * or require a tree context 50*6600Sas200622 * smb_pid a 16-bit process ID 51*6600Sas200622 * smb_uid a 16-bit user ID, specific to this "session" 52*6600Sas200622 * and mapped to a system (bona-fide) UID 53*6600Sas200622 * smb_mid a 16-bit multiplex ID, used to differentiate 54*6600Sas200622 * multiple simultaneous requests from the same 55*6600Sas200622 * process (pid) (ref RPC "xid") 56*6600Sas200622 * 57*6600Sas200622 * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s). 58*6600Sas200622 * 59*6600Sas200622 * Client Request Description 60*6600Sas200622 * ================================== ================================= 61*6600Sas200622 * 62*6600Sas200622 * UCHAR WordCount; Count of parameter words = 8 63*6600Sas200622 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 64*6600Sas200622 * UCHAR AndXReserved; Reserved (must be 0) 65*6600Sas200622 * USHORT AndXOffset; Offset to next command WordCount 66*6600Sas200622 * USHORT Fid; File handle 67*6600Sas200622 * UCHAR LockType; See LockType table below 68*6600Sas200622 * UCHAR OplockLevel; The new oplock level 69*6600Sas200622 * ULONG Timeout; Milliseconds to wait for unlock 70*6600Sas200622 * USHORT NumberOfUnlocks; Num. unlock range structs following 71*6600Sas200622 * USHORT NumberOfLocks; Num. lock range structs following 72*6600Sas200622 * USHORT ByteCount; Count of data bytes 73*6600Sas200622 * LOCKING_ANDX_RANGE Unlocks[]; Unlock ranges 74*6600Sas200622 * LOCKING_ANDX_RANGE Locks[]; Lock ranges 75*6600Sas200622 * 76*6600Sas200622 * LockType Flag Name Value Description 77*6600Sas200622 * ============================ ===== ================================ 78*6600Sas200622 * 79*6600Sas200622 * LOCKING_ANDX_SHARED_LOCK 0x01 Read-only lock 80*6600Sas200622 * LOCKING_ANDX_OPLOCK_RELEASE 0x02 Oplock break notification 81*6600Sas200622 * LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 Change lock type 82*6600Sas200622 * LOCKING_ANDX_CANCEL_LOCK 0x08 Cancel outstanding request 83*6600Sas200622 * LOCKING_ANDX_LARGE_FILES 0x10 Large file locking format 84*6600Sas200622 * 85*6600Sas200622 * LOCKING_ANDX_RANGE Format 86*6600Sas200622 * ===================================================================== 87*6600Sas200622 * 88*6600Sas200622 * USHORT Pid; PID of process "owning" lock 89*6600Sas200622 * ULONG Offset; Offset to bytes to [un]lock 90*6600Sas200622 * ULONG Length; Number of bytes to [un]lock 91*6600Sas200622 * 92*6600Sas200622 * Large File LOCKING_ANDX_RANGE Format 93*6600Sas200622 * ===================================================================== 94*6600Sas200622 * 95*6600Sas200622 * USHORT Pid; PID of process "owning" lock 96*6600Sas200622 * USHORT Pad; Pad to DWORD align (mbz) 97*6600Sas200622 * ULONG OffsetHigh; Offset to bytes to [un]lock 98*6600Sas200622 * (high) 99*6600Sas200622 * ULONG OffsetLow; Offset to bytes to [un]lock (low) 100*6600Sas200622 * ULONG LengthHigh; Number of bytes to [un]lock 101*6600Sas200622 * (high) 102*6600Sas200622 * ULONG LengthLow; Number of bytes to [un]lock (low) 103*6600Sas200622 * 104*6600Sas200622 * Server Response Description 105*6600Sas200622 * ================================== ================================= 106*6600Sas200622 * 107*6600Sas200622 * UCHAR WordCount; Count of parameter words = 2 108*6600Sas200622 * UCHAR AndXCommand; Secondary (X) command; 0xFF = 109*6600Sas200622 * none 110*6600Sas200622 * UCHAR AndXReserved; Reserved (must be 0) 111*6600Sas200622 * USHORT AndXOffset; Offset to next command WordCount 112*6600Sas200622 * USHORT ByteCount; Count of data bytes = 0 113*6600Sas200622 * 114*6600Sas200622 */ 115*6600Sas200622 116*6600Sas200622 /* 117*6600Sas200622 * smb_oplock_acquire 118*6600Sas200622 * 119*6600Sas200622 * Attempt to acquire an oplock. Note that the oplock granted may be 120*6600Sas200622 * none, i.e. the oplock was not granted. 121*6600Sas200622 * 122*6600Sas200622 * Grant an oplock to the requestor if this session is the only one 123*6600Sas200622 * that has the file open, regardless of the number of instances of 124*6600Sas200622 * the file opened by this session. 125*6600Sas200622 * 126*6600Sas200622 * However, if there is no oplock on this file and there is already 127*6600Sas200622 * at least one open, we will not grant an oplock, even if the only 128*6600Sas200622 * existing opens are from the same client. This is "server discretion." 129*6600Sas200622 * 130*6600Sas200622 * An oplock may need to be broken in order for one to be granted, and 131*6600Sas200622 * depending on what action is taken by the other client (unlock or close), 132*6600Sas200622 * an oplock may or may not be granted. (The breaking of an oplock is 133*6600Sas200622 * done earlier in the calling path.) 134*6600Sas200622 * 135*6600Sas200622 * XXX: Node synchronization is not yet implemented. However, racing 136*6600Sas200622 * opens are handled thus: 137*6600Sas200622 * 138*6600Sas200622 * A racing oplock acquire can happen in the open path between 139*6600Sas200622 * smb_oplock_break() and smb_fsop_open(), but no later. (Once 140*6600Sas200622 * the file is open via smb_fsop_open()/VOP_OPEN, 141*6600Sas200622 * smb_fsop_oplock_install() will not be able to install an oplock, 142*6600Sas200622 * which requires an open count of 1.) 143*6600Sas200622 * 144*6600Sas200622 * Hence, we can safely break any oplock that came in after the 145*6600Sas200622 * smb_oplock_break() done previously in the open path, knowing that 146*6600Sas200622 * no other racing oplock acquisitions should be able to succeed 147*6600Sas200622 * because we already have the file open (see above). 148*6600Sas200622 * 149*6600Sas200622 * The type of oplock being requested is passed in op->my_flags. The result 150*6600Sas200622 * is also returned in op->my_flags. 151*6600Sas200622 * 152*6600Sas200622 * (Note that exclusive and batch oplocks are treated interchangeably.) 153*6600Sas200622 * 154*6600Sas200622 * The Returns NT status codes: 155*6600Sas200622 * NT_STATUS_SUCCESS 156*6600Sas200622 * NT_STATUS_CONNECTION_DISCONNECTED 157*6600Sas200622 */ 158*6600Sas200622 DWORD 159*6600Sas200622 smb_oplock_acquire( 160*6600Sas200622 smb_request_t *sr, 161*6600Sas200622 smb_ofile_t *of, 162*6600Sas200622 struct open_param *op) 163*6600Sas200622 { 164*6600Sas200622 smb_node_t *node; 165*6600Sas200622 unsigned int level; 166*6600Sas200622 167*6600Sas200622 ASSERT(sr); 168*6600Sas200622 ASSERT(of); 169*6600Sas200622 ASSERT(op); 170*6600Sas200622 ASSERT(op->fqi.last_attr.sa_vattr.va_type == VREG); 171*6600Sas200622 172*6600Sas200622 level = op->my_flags & MYF_OPLOCK_MASK; 173*6600Sas200622 174*6600Sas200622 op->my_flags &= ~MYF_OPLOCK_MASK; 175*6600Sas200622 176*6600Sas200622 if ((sr->sr_cfg->skc_oplock_enable == 0) || 177*6600Sas200622 (fsd_chkcap(&of->f_tree->t_fsd, FSOLF_DISABLE_OPLOCKS) > 0)) 178*6600Sas200622 return (NT_STATUS_SUCCESS); 179*6600Sas200622 180*6600Sas200622 if (!((MYF_IS_EXCLUSIVE_OPLOCK(level)) || 181*6600Sas200622 (MYF_IS_BATCH_OPLOCK(level)))) 182*6600Sas200622 return (NT_STATUS_SUCCESS); 183*6600Sas200622 184*6600Sas200622 node = of->f_node; 185*6600Sas200622 186*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_WRITER); 187*6600Sas200622 188*6600Sas200622 if (EXCLUSIVE_OPLOCK_IN_FORCE(node) || 189*6600Sas200622 BATCH_OPLOCK_IN_FORCE(node)) { 190*6600Sas200622 191*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 192*6600Sas200622 193*6600Sas200622 if (SMB_SAME_SESSION(sr->session, 194*6600Sas200622 node->n_oplock.op_ofile->f_session)) { 195*6600Sas200622 op->my_flags |= level; 196*6600Sas200622 return (NT_STATUS_SUCCESS); 197*6600Sas200622 } else if (SMB_ATTR_ONLY_OPEN(op)) { 198*6600Sas200622 ASSERT(!(op->my_flags & MYF_OPLOCK_MASK)); 199*6600Sas200622 return (NT_STATUS_SUCCESS); 200*6600Sas200622 } 201*6600Sas200622 202*6600Sas200622 smb_oplock_break(node); 203*6600Sas200622 204*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_WRITER); 205*6600Sas200622 } 206*6600Sas200622 207*6600Sas200622 if (smb_fsop_oplock_install(node, of->f_mode) != 0) { 208*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 209*6600Sas200622 return (NT_STATUS_SUCCESS); 210*6600Sas200622 } 211*6600Sas200622 212*6600Sas200622 node->n_oplock.op_ofile = of; 213*6600Sas200622 node->n_oplock.op_ipaddr = sr->session->ipaddr; 214*6600Sas200622 node->n_oplock.op_kid = sr->session->s_kid; 215*6600Sas200622 node->flags &= ~NODE_OPLOCKS_IN_FORCE; 216*6600Sas200622 217*6600Sas200622 if (MYF_IS_EXCLUSIVE_OPLOCK(level)) 218*6600Sas200622 node->flags |= NODE_EXCLUSIVE_OPLOCK; 219*6600Sas200622 220*6600Sas200622 if (MYF_IS_BATCH_OPLOCK(level)) 221*6600Sas200622 node->flags |= NODE_BATCH_OPLOCK; 222*6600Sas200622 223*6600Sas200622 op->my_flags |= level; 224*6600Sas200622 225*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 226*6600Sas200622 227*6600Sas200622 return (NT_STATUS_SUCCESS); 228*6600Sas200622 } 229*6600Sas200622 230*6600Sas200622 /* 231*6600Sas200622 * smb_oplock_break 232*6600Sas200622 * 233*6600Sas200622 * The oplock break may succeed for multiple reasons: file close, oplock 234*6600Sas200622 * release, holder connection dropped, requesting client disconnect etc. 235*6600Sas200622 * Whatever the reason, the oplock should be broken when this function 236*6600Sas200622 * returns. The exceptions are when the client making this request gets 237*6600Sas200622 * disconnected or when another client is handling the break and it gets 238*6600Sas200622 * disconnected. 239*6600Sas200622 * 240*6600Sas200622 * Returns NT status codes: 241*6600Sas200622 * NT_STATUS_SUCCESS No oplock in force, i.e. the 242*6600Sas200622 * oplock has been broken. 243*6600Sas200622 * NT_STATUS_CONNECTION_DISCONNECTED Requesting client disconnected. 244*6600Sas200622 * NT_STATUS_INTERNAL_ERROR 245*6600Sas200622 */ 246*6600Sas200622 247*6600Sas200622 void 248*6600Sas200622 smb_oplock_break(smb_node_t *node) 249*6600Sas200622 { 250*6600Sas200622 smb_session_t *oplock_session; 251*6600Sas200622 smb_ofile_t *oplock_ofile; 252*6600Sas200622 struct mbuf_chain mbc; 253*6600Sas200622 int retries = 0; 254*6600Sas200622 clock_t elapsed_time; 255*6600Sas200622 clock_t max_time; 256*6600Sas200622 boolean_t flag; 257*6600Sas200622 258*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_WRITER); 259*6600Sas200622 260*6600Sas200622 if (!OPLOCKS_IN_FORCE(node)) { 261*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 262*6600Sas200622 return; 263*6600Sas200622 } 264*6600Sas200622 265*6600Sas200622 if (node->n_oplock.op_flags & OPLOCK_FLAG_BREAKING) { 266*6600Sas200622 elapsed_time = 0; 267*6600Sas200622 max_time = MSEC_TO_TICK(smb_oplock_timeout * OPLOCK_RETRIES); 268*6600Sas200622 /* 269*6600Sas200622 * Another client is already attempting to break the oplock. 270*6600Sas200622 * We wait for it to finish. If the caller was trying to 271*6600Sas200622 * acquire an oplock, he should retry in case the client's 272*6600Sas200622 * connection was dropped while trying to break the oplock. 273*6600Sas200622 * 274*6600Sas200622 * If the holder's connection has been dropped, we yield to 275*6600Sas200622 * allow the thread handling the break to detect it and set 276*6600Sas200622 * the flags. 277*6600Sas200622 */ 278*6600Sas200622 while ((node->n_oplock.op_flags & OPLOCK_FLAG_BREAKING) && 279*6600Sas200622 (elapsed_time < max_time)) { 280*6600Sas200622 clock_t timeleft; 281*6600Sas200622 282*6600Sas200622 timeleft = smb_rwx_rwwait(&node->n_lock, max_time); 283*6600Sas200622 if (timeleft == -1) { 284*6600Sas200622 elapsed_time = max_time; 285*6600Sas200622 } else { 286*6600Sas200622 elapsed_time += max_time - timeleft; 287*6600Sas200622 } 288*6600Sas200622 } 289*6600Sas200622 /* 290*6600Sas200622 * If there are no oplocks in force we're done. 291*6600Sas200622 */ 292*6600Sas200622 if (!OPLOCKS_IN_FORCE(node)) { 293*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 294*6600Sas200622 return; 295*6600Sas200622 } else { 296*6600Sas200622 /* 297*6600Sas200622 * This is an anomalous condition. 298*6600Sas200622 * Cancel/release the oplock. 299*6600Sas200622 */ 300*6600Sas200622 smb_oplock_release(node, B_TRUE); 301*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 302*6600Sas200622 return; 303*6600Sas200622 } 304*6600Sas200622 } 305*6600Sas200622 306*6600Sas200622 oplock_ofile = node->n_oplock.op_ofile; 307*6600Sas200622 ASSERT(oplock_ofile); 308*6600Sas200622 309*6600Sas200622 oplock_session = oplock_ofile->f_session; 310*6600Sas200622 ASSERT(oplock_session); 311*6600Sas200622 312*6600Sas200622 /* 313*6600Sas200622 * Start oplock break. 314*6600Sas200622 */ 315*6600Sas200622 316*6600Sas200622 node->n_oplock.op_flags |= OPLOCK_FLAG_BREAKING; 317*6600Sas200622 318*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 319*6600Sas200622 320*6600Sas200622 max_time = MSEC_TO_TICK(smb_oplock_timeout); 321*6600Sas200622 do { 322*6600Sas200622 MBC_INIT(&mbc, MLEN); 323*6600Sas200622 (void) smb_encode_mbc(&mbc, "Mb19.wwwwbb3.ww10.", 324*6600Sas200622 SMB_COM_LOCKING_ANDX, oplock_ofile->f_tree->t_tid, 325*6600Sas200622 0xffff, 0, 0xffff, 8, 0xff, oplock_ofile->f_fid, 326*6600Sas200622 LOCKING_ANDX_OPLOCK_RELEASE); 327*6600Sas200622 328*6600Sas200622 flag = B_TRUE; 329*6600Sas200622 smb_rwx_rwenter(&oplock_session->s_lock, RW_WRITER); 330*6600Sas200622 while (flag) { 331*6600Sas200622 switch (oplock_session->s_state) { 332*6600Sas200622 case SMB_SESSION_STATE_DISCONNECTED: 333*6600Sas200622 case SMB_SESSION_STATE_TERMINATED: 334*6600Sas200622 smb_rwx_rwexit(&oplock_session->s_lock); 335*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_WRITER); 336*6600Sas200622 337*6600Sas200622 node->flags &= ~NODE_OPLOCKS_IN_FORCE; 338*6600Sas200622 node->n_oplock.op_flags &= 339*6600Sas200622 ~OPLOCK_FLAG_BREAKING; 340*6600Sas200622 node->n_oplock.op_ofile = NULL; 341*6600Sas200622 node->n_oplock.op_ipaddr = 0; 342*6600Sas200622 node->n_oplock.op_kid = 0; 343*6600Sas200622 344*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 345*6600Sas200622 346*6600Sas200622 return; 347*6600Sas200622 348*6600Sas200622 case SMB_SESSION_STATE_OPLOCK_BREAKING: 349*6600Sas200622 flag = B_FALSE; 350*6600Sas200622 break; 351*6600Sas200622 352*6600Sas200622 case SMB_SESSION_STATE_NEGOTIATED: 353*6600Sas200622 oplock_session->s_state = 354*6600Sas200622 SMB_SESSION_STATE_OPLOCK_BREAKING; 355*6600Sas200622 flag = B_FALSE; 356*6600Sas200622 break; 357*6600Sas200622 358*6600Sas200622 default: 359*6600Sas200622 (void) smb_rwx_rwwait(&oplock_session->s_lock, 360*6600Sas200622 -1); 361*6600Sas200622 break; 362*6600Sas200622 } 363*6600Sas200622 } 364*6600Sas200622 smb_rwx_rwexit(&oplock_session->s_lock); 365*6600Sas200622 366*6600Sas200622 (void) smb_session_send(oplock_session, 0, &mbc); 367*6600Sas200622 368*6600Sas200622 elapsed_time = 0; 369*6600Sas200622 370*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_WRITER); 371*6600Sas200622 while ((node->n_oplock.op_flags & OPLOCK_FLAG_BREAKING) && 372*6600Sas200622 (elapsed_time < max_time)) { 373*6600Sas200622 clock_t timeleft; 374*6600Sas200622 375*6600Sas200622 timeleft = smb_rwx_rwwait(&node->n_lock, max_time); 376*6600Sas200622 if (timeleft == -1) { 377*6600Sas200622 elapsed_time = max_time; 378*6600Sas200622 } else { 379*6600Sas200622 elapsed_time += max_time - timeleft; 380*6600Sas200622 } 381*6600Sas200622 } 382*6600Sas200622 383*6600Sas200622 if (!OPLOCKS_IN_FORCE(node)) { 384*6600Sas200622 /* 385*6600Sas200622 * smb_oplock_release() was called 386*6600Sas200622 */ 387*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 388*6600Sas200622 return; 389*6600Sas200622 } 390*6600Sas200622 } while (++retries < OPLOCK_RETRIES); 391*6600Sas200622 392*6600Sas200622 /* 393*6600Sas200622 * Retries exhausted and timed out. 394*6600Sas200622 * Cancel the oplock and continue. 395*6600Sas200622 */ 396*6600Sas200622 397*6600Sas200622 smb_oplock_release(node, B_TRUE); 398*6600Sas200622 399*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 400*6600Sas200622 } 401*6600Sas200622 402*6600Sas200622 /* 403*6600Sas200622 * smb_oplock_release 404*6600Sas200622 * 405*6600Sas200622 * This function uninstalls the FEM oplock monitors and 406*6600Sas200622 * clears all flags in relation to an oplock on the 407*6600Sas200622 * given node. 408*6600Sas200622 * 409*6600Sas200622 * The function can be called with the node->n_lock held 410*6600Sas200622 * or not held. 411*6600Sas200622 */ 412*6600Sas200622 413*6600Sas200622 void /*ARGSUSED*/ 414*6600Sas200622 smb_oplock_release(smb_node_t *node, boolean_t have_rwx) 415*6600Sas200622 { 416*6600Sas200622 if (!have_rwx) 417*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_WRITER); 418*6600Sas200622 419*6600Sas200622 if (!OPLOCKS_IN_FORCE(node)) { 420*6600Sas200622 if (!have_rwx) 421*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 422*6600Sas200622 return; 423*6600Sas200622 } 424*6600Sas200622 425*6600Sas200622 smb_fsop_oplock_uninstall(node); 426*6600Sas200622 427*6600Sas200622 node->flags &= ~NODE_OPLOCKS_IN_FORCE; 428*6600Sas200622 node->n_oplock.op_flags &= ~OPLOCK_FLAG_BREAKING; 429*6600Sas200622 node->n_oplock.op_ofile = NULL; 430*6600Sas200622 node->n_oplock.op_ipaddr = 0; 431*6600Sas200622 node->n_oplock.op_kid = 0; 432*6600Sas200622 433*6600Sas200622 if (!have_rwx) 434*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 435*6600Sas200622 } 436*6600Sas200622 437*6600Sas200622 /* 438*6600Sas200622 * smb_oplock_conflict 439*6600Sas200622 * 440*6600Sas200622 * The two checks on "session" and "op" are primarily for the open path. 441*6600Sas200622 * Other CIFS functions may call smb_oplock_conflict() with a session 442*6600Sas200622 * pointer so as to do the session check. 443*6600Sas200622 */ 444*6600Sas200622 445*6600Sas200622 boolean_t 446*6600Sas200622 smb_oplock_conflict(smb_node_t *node, smb_session_t *session, 447*6600Sas200622 struct open_param *op) 448*6600Sas200622 { 449*6600Sas200622 smb_session_t *oplock_session; 450*6600Sas200622 smb_ofile_t *oplock_ofile; 451*6600Sas200622 452*6600Sas200622 smb_rwx_rwenter(&node->n_lock, RW_READER); 453*6600Sas200622 454*6600Sas200622 if (!OPLOCKS_IN_FORCE(node)) { 455*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 456*6600Sas200622 return (B_FALSE); 457*6600Sas200622 } 458*6600Sas200622 459*6600Sas200622 oplock_ofile = node->n_oplock.op_ofile; 460*6600Sas200622 ASSERT(oplock_ofile); 461*6600Sas200622 462*6600Sas200622 oplock_session = oplock_ofile->f_session; 463*6600Sas200622 ASSERT(oplock_session); 464*6600Sas200622 465*6600Sas200622 if (SMB_SAME_SESSION(session, oplock_session)) { 466*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 467*6600Sas200622 return (B_FALSE); 468*6600Sas200622 } 469*6600Sas200622 470*6600Sas200622 if (SMB_ATTR_ONLY_OPEN(op)) { 471*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 472*6600Sas200622 return (B_FALSE); 473*6600Sas200622 } 474*6600Sas200622 475*6600Sas200622 smb_rwx_rwexit(&node->n_lock); 476*6600Sas200622 return (B_TRUE); 477*6600Sas200622 } 478