1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/
/*
* Copyright 2017 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMB_OPLOCK_H
#define _SMBSRV_SMB_OPLOCK_H
#include <smbsrv/ntifs.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* 2.1.1.10 Per Oplock
*
*
* ExclusiveOpen: The Open used to request the opportunistic lock.
*
* IIOplocks: A list of zero or more Opens used to request a LEVEL_TWO
* opportunistic lock, as specified in section 2.1.5.17.1.
*
* ROplocks: A list of zero or more Opens used to request a LEVEL_GRANULAR
* (RequestedOplockLevel: READ_CACHING) opportunistic lock, as specified in
* section 2.1.5.17.1.
*
* RHOplocks: A list of zero or more Opens used to request a LEVEL_GRANULAR
* (RequestedOplockLevel: (READ_CACHING|HANDLE_CACHING)) opportunistic lock,
* as specified in section 2.1.5.17.1.
*
* RHBreakQueue: A list of zero or more RHOpContext objects. This queue is
* used to track (READ_CACHING|HANDLE_CACHING) oplocks as they are breaking.
*
* WaitList: A list of zero or more Opens belonging to operations that are
* waiting for an oplock to break, as specified in section 2.1.4.12.
*
* State: The current state of the oplock, expressed as a combination of
* one or more flags. Valid flags are:
* [ As follows; Re-ordered a bit from the spec. ]
*/
/*
* READ_CACHING - Indicates that this Oplock represents an oplock
* that provides caching of reads; this provides the SMB 2.1 read
* caching lease, as described in [MS-SMB2] section 2.2.13.2.8.
*/
#define READ_CACHING OPLOCK_LEVEL_CACHE_READ /* 1 */
/*
* HANDLE_CACHING - Indicates that this Oplock represents an oplock
* that provides caching of handles; this provides the SMB 2.1 handle
* caching lease, as described in [MS-SMB2] section 2.2.13.2.8.
*/
#define HANDLE_CACHING OPLOCK_LEVEL_CACHE_HANDLE /* 2 */
/*
* WRITE_CACHING - Indicates that this Oplock represents an oplock
* that provides caching of writes; this provides the SMB 2.1 write
* caching lease, as described in [MS-SMB2] section 2.2.13.2.8.
*/
#define WRITE_CACHING OPLOCK_LEVEL_CACHE_WRITE /* 4 */
/*
* EXCLUSIVE - Indicates that this Oplock represents an oplock that
* can be held by exactly one client at a time. This flag always appears
* in combination with other flags that indicate the actual oplock level.
* For example, (READ_CACHING|WRITE_CACHING|EXCLUSIVE) represents a
* read caching and write caching oplock, which can be held by only
* one client at a time.
*/
#define EXCLUSIVE 0x00000010
/*
* MIXED_R_AND_RH - Always appears together with READ_CACHING and
* HANDLE_CACHING. Indicates that this Oplock represents an oplock
* on which at least one client has been granted a read caching oplock,
* and at least one other client has been granted a read caching and
* handle caching oplock.
*/
#define MIXED_R_AND_RH 0x00000020
/*
* LEVEL_TWO_OPLOCK - Indicates that this Oplock represents a
* Level 2 (also called Shared) oplock.
* Corresponds to SMB2_OPLOCK_LEVEL_II
*/
#define LEVEL_TWO_OPLOCK OPLOCK_LEVEL_TWO /* 0x100 */
/*
* LEVEL_ONE_OPLOCK - Indicates that this Oplock represents a
* Level 1 (also called Exclusive) oplock.
* Corresponds to SMB2_OPLOCK_LEVEL_EXCLUSIVE
*/
#define LEVEL_ONE_OPLOCK OPLOCK_LEVEL_ONE /* 0x200 */
/*
* BATCH_OPLOCK - Indicates that this Oplock represents a Batch oplock.
* Corresponds to SMB2_OPLOCK_LEVEL_BATCH
*/
#define BATCH_OPLOCK OPLOCK_LEVEL_BATCH /* 0x400 */
/* Note: ntifs.h OPLOCK_LEVEL_GRANULAR 0x800 */
/*
* Note that the oplock leasing implementation uses this shift
* to convert (i.e.) CACHE_READ to BREAK_TO_READ_CACHING etc.
* This relationship is checked in smb_srv_oplock.c
*/
#define BREAK_SHIFT 16
/*
* BREAK_TO_READ_CACHING - Indicates that this Oplock represents an
* oplock that is currently breaking to an oplock that provides
* caching of reads; the oplock has broken but the break has not yet
* been acknowledged.
*/
#define BREAK_TO_READ_CACHING 0x00010000
/*
* BREAK_TO_HANDLE_CACHING - Indicates that this Oplock represents an
* oplock that is currently breaking to an oplock that provides
* caching of handles; the oplock has broken but the break has not yet
* been acknowledged. Note: == (CACHE_HANDLE << BREAK_SHIFT)
*/
#define BREAK_TO_HANDLE_CACHING 0x00020000
/*
* BREAK_TO_WRITE_CACHING - Indicates that this Oplock represents an
* oplock that is currently breaking to an oplock that provides
* caching of writes; the oplock has broken but the break has
* not yet been acknowledged.
*/
#define BREAK_TO_WRITE_CACHING 0x00040000
/*
* BREAK_TO_NO_CACHING - Indicates that this Oplock represents an
* oplock that is currently breaking to None (that is, no oplock);
* the oplock has broken but the break has not yet been acknowledged.
*/
#define BREAK_TO_NO_CACHING 0x00080000
/*
* BREAK_TO_TWO - Indicates that this Oplock represents an oplock
* that is currently breaking from either Level 1 or Batch to Level 2;
* the oplock has broken but the break has not yet been acknowledged.
*/
#define BREAK_TO_TWO 0x00100000
/*
* BREAK_TO_NONE - Indicates that this Oplock represents an oplock
* that is currently breaking from either Level 1 or Batch to None
* (that is, no oplock); the oplock has broken but the break has
* not yet been acknowledged.
*/
#define BREAK_TO_NONE 0x00200000
/*
* BREAK_TO_TWO_TO_NONE - Indicates that this Oplock represents an
* oplock that is currently breaking from either Level 1 or Batch to
* None (that is, no oplock), and was previously breaking from Level 1
* or Batch to Level 2; the oplock has broken but the break has
* not yet been acknowledged.
*/
#define BREAK_TO_TWO_TO_NONE 0x00400000
/*
* NO_OPLOCK - Indicates that this Oplock does not represent a
* currently granted or breaking oplock. This is semantically
* equivalent to the Oplock object being entirely absent from a
* Stream. This flag always appears alone.
* Note we also have OPLOCK_LEVEL_NONE == 0 from ntifs.h
*/
#define NO_OPLOCK 0x10000000
/*
* An internal flag, non-overlapping wth other oplock flags,
* used only in smb_cmn_oplock.c (and here only to make clear
* that it does not overlap with an other flags above).
*/
#define PARENT_OBJECT 0x40000000
/*
* Also not in the spec, but convenient
*/
#define BREAK_LEVEL_MASK (\
BREAK_TO_READ_CACHING |\
BREAK_TO_WRITE_CACHING |\
BREAK_TO_HANDLE_CACHING |\
BREAK_TO_NO_CACHING)
#define BREAK_ANY (\
BREAK_LEVEL_MASK |\
BREAK_TO_TWO |\
BREAK_TO_NONE |\
BREAK_TO_TWO_TO_NONE)
/*
* Convenience macro to walk ofiles on a give node.
* Used as follows:
* FOREACH_NODE_OFILE(node, o) { muck_with(o); }
*/
#define FOREACH_NODE_OFILE(node, o) for \
(o = smb_llist_head(&node->n_ofile_list); \
o != NULL; \
o = smb_llist_next(&node->n_ofile_list, o))
/*
* Some short-hand names used in the oplock code.
*/
#define STATUS_NEW_HANDLE NT_STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE
#define STATUS_CANT_GRANT NT_STATUS_CANNOT_GRANT_REQUESTED_OPLOCK
typedef enum oplock_type {
LEVEL_NONE = OPLOCK_LEVEL_NONE,
LEVEL_TWO = OPLOCK_LEVEL_TWO,
LEVEL_ONE = OPLOCK_LEVEL_ONE,
LEVEL_BATCH = OPLOCK_LEVEL_BATCH,
LEVEL_GRANULAR = OPLOCK_LEVEL_GRANULAR
} oplock_type_t;
typedef enum oplock_cache_level {
CACHE_R = READ_CACHING,
CACHE_RH = READ_CACHING |
HANDLE_CACHING,
CACHE_RW = READ_CACHING |
WRITE_CACHING,
CACHE_RWH = READ_CACHING |
WRITE_CACHING |
HANDLE_CACHING,
} oplock_cache_t;
#ifdef __cplusplus
}
#endif
#endif /* _SMBSRV_SMB_OPLOCK_H */
|