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