16600Sas200622 /* 26600Sas200622 * CDDL HEADER START 36600Sas200622 * 46600Sas200622 * The contents of this file are subject to the terms of the 56600Sas200622 * Common Development and Distribution License (the "License"). 66600Sas200622 * You may not use this file except in compliance with the License. 76600Sas200622 * 86600Sas200622 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 96600Sas200622 * or http://www.opensolaris.org/os/licensing. 106600Sas200622 * See the License for the specific language governing permissions 116600Sas200622 * and limitations under the License. 126600Sas200622 * 136600Sas200622 * When distributing Covered Code, include this CDDL HEADER in each 146600Sas200622 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 156600Sas200622 * If applicable, add the following below this CDDL HEADER, with the 166600Sas200622 * fields enclosed by brackets "[]" replaced with your own identifying 176600Sas200622 * information: Portions Copyright [yyyy] [name of copyright owner] 186600Sas200622 * 196600Sas200622 * CDDL HEADER END 206600Sas200622 */ 216600Sas200622 /* 228670SJose.Borrego@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 236600Sas200622 * Use is subject to license terms. 246600Sas200622 */ 256600Sas200622 /* 266600Sas200622 * SMB Locking library functions. 279231SAfshin.Ardakani@Sun.COM * 289231SAfshin.Ardakani@Sun.COM * You will notice that the functions in this file exit the lock of the session 299231SAfshin.Ardakani@Sun.COM * and reenter it before returning. They even assume that the lock has been 309231SAfshin.Ardakani@Sun.COM * entered in READER mode. The reason for that is a potential deadlock that may 319231SAfshin.Ardakani@Sun.COM * occur when an oplock needs to be broken and the function 329231SAfshin.Ardakani@Sun.COM * smb_session_break_oplock() is called. It should be noticed that the mutex of 339231SAfshin.Ardakani@Sun.COM * the smb node, the oplock of which needs to be broken, is also exited before 349231SAfshin.Ardakani@Sun.COM * calling smb_session_break_oplock(). The reason for that is the same: avoiding 359231SAfshin.Ardakani@Sun.COM * a deadlock. That complexity is due to the fact that the lock of the session 369231SAfshin.Ardakani@Sun.COM * is held during the treatment of a request. That complexity will go away when 379231SAfshin.Ardakani@Sun.COM * that is not the case anymore. 386600Sas200622 */ 396600Sas200622 40*10966SJordan.Brown@Sun.COM #include <smbsrv/smb_kproto.h> 416600Sas200622 #include <smbsrv/smb_fsops.h> 428670SJose.Borrego@Sun.COM #include <inet/tcp.h> 436600Sas200622 449021Samw@Sun.COM static void smb_oplock_wait(smb_node_t *); 456600Sas200622 466600Sas200622 /* 476600Sas200622 * Magic 0xFF 'S' 'M' 'B' 486600Sas200622 * smb_com a byte, the "first" command 496600Sas200622 * Error a 4-byte union, ignored in a request 506600Sas200622 * smb_flg a one byte set of eight flags 516600Sas200622 * smb_flg2 a two byte set of 16 flags 526600Sas200622 * . twelve reserved bytes, have a role 536600Sas200622 * in connectionless transports (IPX, UDP?) 546600Sas200622 * smb_tid a 16-bit tree ID, a mount point sorta, 556600Sas200622 * 0xFFFF is this command does not have 566600Sas200622 * or require a tree context 576600Sas200622 * smb_pid a 16-bit process ID 586600Sas200622 * smb_uid a 16-bit user ID, specific to this "session" 596600Sas200622 * and mapped to a system (bona-fide) UID 606600Sas200622 * smb_mid a 16-bit multiplex ID, used to differentiate 616600Sas200622 * multiple simultaneous requests from the same 626600Sas200622 * process (pid) (ref RPC "xid") 636600Sas200622 * 646600Sas200622 * SMB_COM_LOCKING_ANDX allows both locking and/or unlocking of file range(s). 656600Sas200622 * 666600Sas200622 * Client Request Description 676600Sas200622 * ================================== ================================= 686600Sas200622 * 696600Sas200622 * UCHAR WordCount; Count of parameter words = 8 706600Sas200622 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 716600Sas200622 * UCHAR AndXReserved; Reserved (must be 0) 726600Sas200622 * USHORT AndXOffset; Offset to next command WordCount 736600Sas200622 * USHORT Fid; File handle 746600Sas200622 * UCHAR LockType; See LockType table below 756600Sas200622 * UCHAR OplockLevel; The new oplock level 766600Sas200622 * ULONG Timeout; Milliseconds to wait for unlock 776600Sas200622 * USHORT NumberOfUnlocks; Num. unlock range structs following 786600Sas200622 * USHORT NumberOfLocks; Num. lock range structs following 796600Sas200622 * USHORT ByteCount; Count of data bytes 806600Sas200622 * LOCKING_ANDX_RANGE Unlocks[]; Unlock ranges 816600Sas200622 * LOCKING_ANDX_RANGE Locks[]; Lock ranges 826600Sas200622 * 836600Sas200622 * LockType Flag Name Value Description 846600Sas200622 * ============================ ===== ================================ 856600Sas200622 * 866600Sas200622 * LOCKING_ANDX_SHARED_LOCK 0x01 Read-only lock 876600Sas200622 * LOCKING_ANDX_OPLOCK_RELEASE 0x02 Oplock break notification 886600Sas200622 * LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 Change lock type 896600Sas200622 * LOCKING_ANDX_CANCEL_LOCK 0x08 Cancel outstanding request 906600Sas200622 * LOCKING_ANDX_LARGE_FILES 0x10 Large file locking format 916600Sas200622 * 926600Sas200622 * LOCKING_ANDX_RANGE Format 936600Sas200622 * ===================================================================== 946600Sas200622 * 956600Sas200622 * USHORT Pid; PID of process "owning" lock 966600Sas200622 * ULONG Offset; Offset to bytes to [un]lock 976600Sas200622 * ULONG Length; Number of bytes to [un]lock 986600Sas200622 * 996600Sas200622 * Large File LOCKING_ANDX_RANGE Format 1006600Sas200622 * ===================================================================== 1016600Sas200622 * 1026600Sas200622 * USHORT Pid; PID of process "owning" lock 1036600Sas200622 * USHORT Pad; Pad to DWORD align (mbz) 1046600Sas200622 * ULONG OffsetHigh; Offset to bytes to [un]lock 1056600Sas200622 * (high) 1066600Sas200622 * ULONG OffsetLow; Offset to bytes to [un]lock (low) 1076600Sas200622 * ULONG LengthHigh; Number of bytes to [un]lock 1086600Sas200622 * (high) 1096600Sas200622 * ULONG LengthLow; Number of bytes to [un]lock (low) 1106600Sas200622 * 1116600Sas200622 * Server Response Description 1126600Sas200622 * ================================== ================================= 1136600Sas200622 * 1146600Sas200622 * UCHAR WordCount; Count of parameter words = 2 1156600Sas200622 * UCHAR AndXCommand; Secondary (X) command; 0xFF = 1166600Sas200622 * none 1176600Sas200622 * UCHAR AndXReserved; Reserved (must be 0) 1186600Sas200622 * USHORT AndXOffset; Offset to next command WordCount 1196600Sas200622 * USHORT ByteCount; Count of data bytes = 0 1206600Sas200622 * 1216600Sas200622 */ 1226600Sas200622 1236600Sas200622 /* 1246600Sas200622 * smb_oplock_acquire 1256600Sas200622 * 1266600Sas200622 * Attempt to acquire an oplock. Note that the oplock granted may be 1278934SJose.Borrego@Sun.COM * none, i.e. the oplock was not granted. The result of the acquisition is 1288934SJose.Borrego@Sun.COM * provided in ol->ol_level. 1296600Sas200622 * 1306600Sas200622 * Grant an oplock to the requestor if this session is the only one 1316600Sas200622 * that has the file open, regardless of the number of instances of 1326600Sas200622 * the file opened by this session. 1336600Sas200622 * 1346600Sas200622 * However, if there is no oplock on this file and there is already 1356600Sas200622 * at least one open, we will not grant an oplock, even if the only 1366600Sas200622 * existing opens are from the same client. This is "server discretion." 1376600Sas200622 * 1386600Sas200622 * An oplock may need to be broken in order for one to be granted, and 1396600Sas200622 * depending on what action is taken by the other client (unlock or close), 1406600Sas200622 * an oplock may or may not be granted. (The breaking of an oplock is 1416600Sas200622 * done earlier in the calling path.) 1426600Sas200622 */ 1438934SJose.Borrego@Sun.COM void 1448934SJose.Borrego@Sun.COM smb_oplock_acquire(smb_node_t *node, smb_ofile_t *of, open_param_t *op) 1456600Sas200622 { 1468934SJose.Borrego@Sun.COM smb_session_t *session; 1478934SJose.Borrego@Sun.COM smb_oplock_t *ol; 1488934SJose.Borrego@Sun.COM clock_t time; 1498934SJose.Borrego@Sun.COM 1508934SJose.Borrego@Sun.COM SMB_NODE_VALID(node); 1518934SJose.Borrego@Sun.COM SMB_OFILE_VALID(of); 1528934SJose.Borrego@Sun.COM 1538934SJose.Borrego@Sun.COM ASSERT(node == SMB_OFILE_GET_NODE(of)); 1548934SJose.Borrego@Sun.COM 1558934SJose.Borrego@Sun.COM session = SMB_OFILE_GET_SESSION(of); 1568934SJose.Borrego@Sun.COM 1578934SJose.Borrego@Sun.COM if (!smb_session_oplocks_enable(session) || 1588934SJose.Borrego@Sun.COM smb_tree_has_feature(SMB_OFILE_GET_TREE(of), SMB_TREE_NO_OPLOCKS)) { 1598934SJose.Borrego@Sun.COM op->op_oplock_level = SMB_OPLOCK_NONE; 1608934SJose.Borrego@Sun.COM return; 1618934SJose.Borrego@Sun.COM } 1628934SJose.Borrego@Sun.COM 1638934SJose.Borrego@Sun.COM ol = &node->n_oplock; 1648934SJose.Borrego@Sun.COM time = MSEC_TO_TICK(smb_oplock_timeout) + ddi_get_lbolt(); 1658934SJose.Borrego@Sun.COM 1668934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 1676600Sas200622 1689021Samw@Sun.COM switch (node->n_state) { 1699021Samw@Sun.COM case SMB_NODE_STATE_OPLOCK_GRANTED: 1709021Samw@Sun.COM if (SMB_SESSION_GET_ID(session) == ol->ol_sess_id) { 1719021Samw@Sun.COM mutex_exit(&node->n_mutex); 1729021Samw@Sun.COM return; 1739021Samw@Sun.COM } 1749021Samw@Sun.COM break; 1759021Samw@Sun.COM case SMB_NODE_STATE_AVAILABLE: 1769021Samw@Sun.COM case SMB_NODE_STATE_OPLOCK_BREAKING: 1779021Samw@Sun.COM break; 1789021Samw@Sun.COM default: 1799021Samw@Sun.COM SMB_PANIC(); 1809021Samw@Sun.COM } 1819021Samw@Sun.COM 1828934SJose.Borrego@Sun.COM for (;;) { 1838934SJose.Borrego@Sun.COM int rc; 1846600Sas200622 1859021Samw@Sun.COM smb_oplock_wait(node); 1866600Sas200622 1878934SJose.Borrego@Sun.COM if (node->n_state == SMB_NODE_STATE_AVAILABLE) { 1888934SJose.Borrego@Sun.COM if ((op->op_oplock_level == SMB_OPLOCK_LEVEL_II) || 1898934SJose.Borrego@Sun.COM (op->op_oplock_level == SMB_OPLOCK_NONE) || 1908934SJose.Borrego@Sun.COM (node->n_open_count > 1)) { 1918934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 1928934SJose.Borrego@Sun.COM op->op_oplock_level = SMB_OPLOCK_NONE; 1938934SJose.Borrego@Sun.COM return; 1948934SJose.Borrego@Sun.COM } 1958934SJose.Borrego@Sun.COM ol->ol_ofile = of; 1968934SJose.Borrego@Sun.COM ol->ol_sess_id = SMB_SESSION_GET_ID(session); 1978934SJose.Borrego@Sun.COM ol->ol_level = op->op_oplock_level; 1988934SJose.Borrego@Sun.COM ol->ol_xthread = curthread; 1998934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_OPLOCK_GRANTED; 2008934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 2018934SJose.Borrego@Sun.COM if (smb_fsop_oplock_install(node, of->f_mode) == 0) { 2028934SJose.Borrego@Sun.COM smb_ofile_set_oplock_granted(of); 2038934SJose.Borrego@Sun.COM return; 2048934SJose.Borrego@Sun.COM } 2058934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 2068934SJose.Borrego@Sun.COM ASSERT(node->n_state == SMB_NODE_STATE_OPLOCK_GRANTED); 2078934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_AVAILABLE; 2088934SJose.Borrego@Sun.COM ol->ol_xthread = NULL; 2098934SJose.Borrego@Sun.COM op->op_oplock_level = SMB_OPLOCK_NONE; 2109021Samw@Sun.COM cv_broadcast(&ol->ol_cv); 2118934SJose.Borrego@Sun.COM break; 2126600Sas200622 } 2136600Sas200622 2148934SJose.Borrego@Sun.COM if (node->n_state == SMB_NODE_STATE_OPLOCK_GRANTED) { 2158934SJose.Borrego@Sun.COM if (SMB_SESSION_GET_ID(session) == ol->ol_sess_id) 2168934SJose.Borrego@Sun.COM break; 2178934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_OPLOCK_BREAKING; 2189231SAfshin.Ardakani@Sun.COM mutex_exit(&node->n_mutex); 2198934SJose.Borrego@Sun.COM smb_session_oplock_break( 2208934SJose.Borrego@Sun.COM SMB_OFILE_GET_SESSION(ol->ol_ofile), ol->ol_ofile); 2219231SAfshin.Ardakani@Sun.COM mutex_enter(&node->n_mutex); 2229231SAfshin.Ardakani@Sun.COM continue; 2238934SJose.Borrego@Sun.COM } 2246600Sas200622 2258934SJose.Borrego@Sun.COM ASSERT(node->n_state == SMB_NODE_STATE_OPLOCK_BREAKING); 2268934SJose.Borrego@Sun.COM 2278934SJose.Borrego@Sun.COM rc = cv_timedwait(&ol->ol_cv, &node->n_mutex, time); 2286600Sas200622 2298934SJose.Borrego@Sun.COM if (rc == -1) { 2308934SJose.Borrego@Sun.COM /* 2318934SJose.Borrego@Sun.COM * Oplock release timed out. 2328934SJose.Borrego@Sun.COM */ 2338934SJose.Borrego@Sun.COM if (node->n_state == SMB_NODE_STATE_OPLOCK_BREAKING) { 2348934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_AVAILABLE; 2358934SJose.Borrego@Sun.COM ol->ol_xthread = curthread; 2368934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 2378934SJose.Borrego@Sun.COM smb_fsop_oplock_uninstall(node); 2388934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 2398934SJose.Borrego@Sun.COM ol->ol_xthread = NULL; 2409021Samw@Sun.COM cv_broadcast(&ol->ol_cv); 2418934SJose.Borrego@Sun.COM } 2428934SJose.Borrego@Sun.COM } 2438934SJose.Borrego@Sun.COM } 2448934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 2456600Sas200622 } 2466600Sas200622 2476600Sas200622 /* 2486600Sas200622 * smb_oplock_break 2496600Sas200622 * 2506600Sas200622 * The oplock break may succeed for multiple reasons: file close, oplock 2516600Sas200622 * release, holder connection dropped, requesting client disconnect etc. 2528934SJose.Borrego@Sun.COM * 2538934SJose.Borrego@Sun.COM * Returns: 2546600Sas200622 * 2558934SJose.Borrego@Sun.COM * B_TRUE The oplock is broken. 2568934SJose.Borrego@Sun.COM * B_FALSE The oplock is being broken. This is returned if nowait is set 2578934SJose.Borrego@Sun.COM * to B_TRUE; 2586600Sas200622 */ 2598934SJose.Borrego@Sun.COM boolean_t 2609021Samw@Sun.COM smb_oplock_break(smb_node_t *node, smb_session_t *session, boolean_t nowait) 2618934SJose.Borrego@Sun.COM { 2628934SJose.Borrego@Sun.COM smb_oplock_t *ol; 2638934SJose.Borrego@Sun.COM clock_t time; 2646600Sas200622 2658934SJose.Borrego@Sun.COM SMB_NODE_VALID(node); 2668934SJose.Borrego@Sun.COM ol = &node->n_oplock; 2678934SJose.Borrego@Sun.COM time = MSEC_TO_TICK(smb_oplock_timeout) + ddi_get_lbolt(); 2686600Sas200622 2699021Samw@Sun.COM if (session != NULL) { 2709021Samw@Sun.COM mutex_enter(&node->n_mutex); 2719021Samw@Sun.COM if (SMB_SESSION_GET_ID(session) == ol->ol_sess_id) { 2729021Samw@Sun.COM mutex_exit(&node->n_mutex); 2739021Samw@Sun.COM return (B_TRUE); 2749021Samw@Sun.COM } 2759021Samw@Sun.COM } else { 2769021Samw@Sun.COM mutex_enter(&node->n_mutex); 2776600Sas200622 } 2786600Sas200622 2798934SJose.Borrego@Sun.COM for (;;) { 2808934SJose.Borrego@Sun.COM int rc; 2818934SJose.Borrego@Sun.COM 2829021Samw@Sun.COM smb_oplock_wait(node); 2836600Sas200622 2848934SJose.Borrego@Sun.COM if (node->n_state == SMB_NODE_STATE_AVAILABLE) { 2858934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 2868934SJose.Borrego@Sun.COM return (B_TRUE); 2876600Sas200622 } 2888934SJose.Borrego@Sun.COM 2898934SJose.Borrego@Sun.COM if (node->n_state == SMB_NODE_STATE_OPLOCK_GRANTED) { 2908934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_OPLOCK_BREAKING; 2919021Samw@Sun.COM mutex_exit(&node->n_mutex); 2928934SJose.Borrego@Sun.COM smb_session_oplock_break( 2938934SJose.Borrego@Sun.COM SMB_OFILE_GET_SESSION(ol->ol_ofile), ol->ol_ofile); 2949021Samw@Sun.COM mutex_enter(&node->n_mutex); 2959231SAfshin.Ardakani@Sun.COM continue; 2966600Sas200622 } 2976600Sas200622 2988934SJose.Borrego@Sun.COM ASSERT(node->n_state == SMB_NODE_STATE_OPLOCK_BREAKING); 2998934SJose.Borrego@Sun.COM if (nowait) { 3008934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 3018934SJose.Borrego@Sun.COM return (B_FALSE); 3028934SJose.Borrego@Sun.COM } 3038934SJose.Borrego@Sun.COM rc = cv_timedwait(&ol->ol_cv, &node->n_mutex, time); 3048934SJose.Borrego@Sun.COM if (rc == -1) { 3058934SJose.Borrego@Sun.COM /* 3068934SJose.Borrego@Sun.COM * Oplock release timed out. 3078934SJose.Borrego@Sun.COM */ 3088934SJose.Borrego@Sun.COM if (node->n_state == SMB_NODE_STATE_OPLOCK_BREAKING) { 3098934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_AVAILABLE; 3108934SJose.Borrego@Sun.COM ol->ol_xthread = curthread; 3118934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 3128934SJose.Borrego@Sun.COM smb_fsop_oplock_uninstall(node); 3138934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 3148934SJose.Borrego@Sun.COM ol->ol_xthread = NULL; 3159021Samw@Sun.COM cv_broadcast(&ol->ol_cv); 3166600Sas200622 break; 3176600Sas200622 } 3186600Sas200622 } 3198934SJose.Borrego@Sun.COM } 3208934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 3218934SJose.Borrego@Sun.COM return (B_TRUE); 3226600Sas200622 } 3236600Sas200622 3246600Sas200622 /* 3256600Sas200622 * smb_oplock_release 3266600Sas200622 * 3278934SJose.Borrego@Sun.COM * This function releases the oplock on the node passed in. If other threads 3288934SJose.Borrego@Sun.COM * were waiting for the oplock to be released they are signaled. 3296600Sas200622 */ 3308934SJose.Borrego@Sun.COM void 3318934SJose.Borrego@Sun.COM smb_oplock_release(smb_node_t *node, smb_ofile_t *of) 3328934SJose.Borrego@Sun.COM { 3338934SJose.Borrego@Sun.COM smb_oplock_t *ol; 3346600Sas200622 3358934SJose.Borrego@Sun.COM SMB_NODE_VALID(node); 3368934SJose.Borrego@Sun.COM ol = &node->n_oplock; 3378934SJose.Borrego@Sun.COM 3388934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 3399021Samw@Sun.COM smb_oplock_wait(node); 3408934SJose.Borrego@Sun.COM switch (node->n_state) { 3418934SJose.Borrego@Sun.COM case SMB_NODE_STATE_AVAILABLE: 3428934SJose.Borrego@Sun.COM break; 3436600Sas200622 3448934SJose.Borrego@Sun.COM case SMB_NODE_STATE_OPLOCK_GRANTED: 3458934SJose.Borrego@Sun.COM case SMB_NODE_STATE_OPLOCK_BREAKING: 3468934SJose.Borrego@Sun.COM if (ol->ol_ofile == of) { 3478934SJose.Borrego@Sun.COM node->n_state = SMB_NODE_STATE_AVAILABLE; 3488934SJose.Borrego@Sun.COM ol->ol_xthread = curthread; 3498934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 3508934SJose.Borrego@Sun.COM smb_fsop_oplock_uninstall(node); 3518934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 3528934SJose.Borrego@Sun.COM ol->ol_xthread = NULL; 3539021Samw@Sun.COM cv_broadcast(&ol->ol_cv); 3548934SJose.Borrego@Sun.COM } 3558934SJose.Borrego@Sun.COM break; 3566600Sas200622 3578934SJose.Borrego@Sun.COM default: 3588934SJose.Borrego@Sun.COM SMB_PANIC(); 3598934SJose.Borrego@Sun.COM } 3608934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 3616600Sas200622 } 3626600Sas200622 3636600Sas200622 /* 3646600Sas200622 * smb_oplock_conflict 3656600Sas200622 * 3666600Sas200622 * The two checks on "session" and "op" are primarily for the open path. 3679021Samw@Sun.COM * Other SMB functions may call smb_oplock_conflict() with a session 3686600Sas200622 * pointer so as to do the session check. 3696600Sas200622 */ 3706600Sas200622 boolean_t 3718934SJose.Borrego@Sun.COM smb_oplock_conflict(smb_node_t *node, smb_session_t *session, open_param_t *op) 3726600Sas200622 { 3738934SJose.Borrego@Sun.COM boolean_t rb; 3748934SJose.Borrego@Sun.COM 3758934SJose.Borrego@Sun.COM SMB_NODE_VALID(node); 3768934SJose.Borrego@Sun.COM SMB_SESSION_VALID(session); 3776600Sas200622 3788934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 3799021Samw@Sun.COM smb_oplock_wait(node); 3808934SJose.Borrego@Sun.COM switch (node->n_state) { 3818934SJose.Borrego@Sun.COM case SMB_NODE_STATE_AVAILABLE: 3828934SJose.Borrego@Sun.COM rb = B_FALSE; 3838934SJose.Borrego@Sun.COM break; 3848934SJose.Borrego@Sun.COM 3858934SJose.Borrego@Sun.COM case SMB_NODE_STATE_OPLOCK_GRANTED: 3868934SJose.Borrego@Sun.COM case SMB_NODE_STATE_OPLOCK_BREAKING: 3878934SJose.Borrego@Sun.COM if (SMB_SESSION_GET_ID(session) == node->n_oplock.ol_sess_id) { 3888934SJose.Borrego@Sun.COM rb = B_FALSE; 3898934SJose.Borrego@Sun.COM break; 3908934SJose.Borrego@Sun.COM } 3916600Sas200622 3928934SJose.Borrego@Sun.COM if (op != NULL) { 3938934SJose.Borrego@Sun.COM if (((op->desired_access & ~(FILE_READ_ATTRIBUTES | 3948934SJose.Borrego@Sun.COM FILE_WRITE_ATTRIBUTES | SYNCHRONIZE)) == 0) && 3958934SJose.Borrego@Sun.COM (op->create_disposition != FILE_SUPERSEDE) && 3968934SJose.Borrego@Sun.COM (op->create_disposition != FILE_OVERWRITE)) { 3978934SJose.Borrego@Sun.COM /* Attributs only */ 3988934SJose.Borrego@Sun.COM rb = B_FALSE; 3998934SJose.Borrego@Sun.COM break; 4008934SJose.Borrego@Sun.COM } 4018934SJose.Borrego@Sun.COM } 4028934SJose.Borrego@Sun.COM rb = B_TRUE; 4038934SJose.Borrego@Sun.COM break; 4048934SJose.Borrego@Sun.COM 4058934SJose.Borrego@Sun.COM default: 4068934SJose.Borrego@Sun.COM SMB_PANIC(); 4076600Sas200622 } 4088934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 4098934SJose.Borrego@Sun.COM return (rb); 4108934SJose.Borrego@Sun.COM } 4116600Sas200622 4128934SJose.Borrego@Sun.COM /* 4139021Samw@Sun.COM * smb_oplock_broadcast 4148934SJose.Borrego@Sun.COM * 4158934SJose.Borrego@Sun.COM * The the calling thread has the pointer to its context stored in ol_thread 4168934SJose.Borrego@Sun.COM * it resets that field. If any other thread is waiting for that field to 4178934SJose.Borrego@Sun.COM * turn to NULL it is signaled. 4188934SJose.Borrego@Sun.COM * 4198934SJose.Borrego@Sun.COM * Returns: 4208934SJose.Borrego@Sun.COM * B_TRUE Oplock unlocked 4218934SJose.Borrego@Sun.COM * B_FALSE Oplock still locked 4228934SJose.Borrego@Sun.COM */ 4238934SJose.Borrego@Sun.COM boolean_t 4249021Samw@Sun.COM smb_oplock_broadcast(smb_node_t *node) 4258934SJose.Borrego@Sun.COM { 4268934SJose.Borrego@Sun.COM smb_oplock_t *ol; 4278934SJose.Borrego@Sun.COM boolean_t rb; 4286600Sas200622 4298934SJose.Borrego@Sun.COM SMB_NODE_VALID(node); 4308934SJose.Borrego@Sun.COM ol = &node->n_oplock; 4318934SJose.Borrego@Sun.COM rb = B_FALSE; 4326600Sas200622 4338934SJose.Borrego@Sun.COM mutex_enter(&node->n_mutex); 4348934SJose.Borrego@Sun.COM if ((ol->ol_xthread != NULL) && (ol->ol_xthread == curthread)) { 4358934SJose.Borrego@Sun.COM ol->ol_xthread = NULL; 4369021Samw@Sun.COM cv_broadcast(&ol->ol_cv); 4378934SJose.Borrego@Sun.COM rb = B_TRUE; 4386600Sas200622 } 4398934SJose.Borrego@Sun.COM mutex_exit(&node->n_mutex); 4408934SJose.Borrego@Sun.COM return (rb); 4418934SJose.Borrego@Sun.COM } 4426600Sas200622 4438934SJose.Borrego@Sun.COM /* 4448934SJose.Borrego@Sun.COM * smb_oplock_wait 4458934SJose.Borrego@Sun.COM * 4469021Samw@Sun.COM * The mutex of the node must have been entered before calling this function. 4478934SJose.Borrego@Sun.COM * If the field ol_xthread is not NULL and doesn't contain the pointer to the 4488934SJose.Borrego@Sun.COM * context of the calling thread, the caller will sleep until that field is 4498934SJose.Borrego@Sun.COM * reset (set to NULL). 4508934SJose.Borrego@Sun.COM */ 4518934SJose.Borrego@Sun.COM static void 4529021Samw@Sun.COM smb_oplock_wait(smb_node_t *node) 4538934SJose.Borrego@Sun.COM { 4548934SJose.Borrego@Sun.COM smb_oplock_t *ol = &node->n_oplock; 4558934SJose.Borrego@Sun.COM 4568934SJose.Borrego@Sun.COM if ((ol->ol_xthread != NULL) && (ol->ol_xthread != curthread)) { 45710483SJose.Borrego@Sun.COM ASSERT(!MUTEX_HELD(&ol->ol_ofile->f_mutex)); 4588934SJose.Borrego@Sun.COM while (ol->ol_xthread != NULL) 4598934SJose.Borrego@Sun.COM cv_wait(&ol->ol_cv, &node->n_mutex); 4606600Sas200622 } 4616600Sas200622 } 462