Print this page
NEX-15931 Panic removing files in SMB3 CA share
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Include in backports of:
NEX-9808 SMB3 persistent handles
NEX-15931 Panic removing files in SMB3 CA share
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Include in backports of:
NEX-9808 SMB3 persistent handles
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15555 SMB2 async redesign
NEX-15061 smtorture smb2.lock.cancel.cancel is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Also follow-up change to:
NEX-1643 dtrace provider for smbsrv (remove "done2" probes,
which don't make sense with the new async design)
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15555 SMB2 async redesign
NEX-15061 smtorture smb2.lock.cancel.cancel is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Also follow-up change to:
NEX-1643 dtrace provider for smbsrv (remove "done2" probes,
which don't make sense with the new async design)
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6042 SMB resilient handle lock replay
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-6041 Should pass the smbtorture lock tests
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
SMB-122 smbd core dumps in smbd_dc_update / smb_log
SMB-117 Win7 fails to open security properties
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb2_lock.c
+++ new/usr/src/uts/common/fs/smbsrv/smb2_lock.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
13 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14 14 */
15 15
16 16 /*
17 17 * Dispatch function for SMB2_LOCK
18 18 */
19 19
20 20 #include <smbsrv/smb2_kproto.h>
21 21
22 -struct SMB2_LOCK_ELEMENT {
22 +/*
23 + * [MS-SMB2] 2.2.26 LockSequenceIndex, LockSequenceNumber.
24 + */
25 +#define SMB2_LSN_SHIFT 4
26 +#define SMB2_LSN_MASK 0xf
27 +
28 +typedef struct SMB2_LOCK_ELEMENT {
23 29 uint64_t Offset;
24 30 uint64_t Length;
25 31 uint32_t Flags;
26 32 uint32_t reserved;
27 -};
33 +} lock_elem_t;
28 34
29 -static smb_sdrc_t smb2_lock_async(smb_request_t *);
30 -static uint32_t smb2_lock_exec(smb_request_t *, uint16_t);
31 -static uint32_t smb2_lock_elem(smb_request_t *, struct SMB2_LOCK_ELEMENT *);
35 +static uint32_t smb2_unlock(smb_request_t *);
36 +static uint32_t smb2__lock(smb_request_t *);
37 +static uint32_t smb2_lock_blocking(smb_request_t *);
32 38
39 +static boolean_t smb2_lock_chk_lockseq(smb_ofile_t *, uint32_t);
40 +static void smb2_lock_set_lockseq(smb_ofile_t *, uint32_t);
41 +
33 42 /*
34 43 * This is a somewhat arbitrary sanity limit on the length of the
35 44 * SMB2_LOCK_ELEMENT array. It usually has length one or two.
36 45 */
37 46 int smb2_lock_max_elem = 1024;
38 47
39 48 smb_sdrc_t
40 49 smb2_lock(smb_request_t *sr)
41 50 {
42 - struct SMB2_LOCK_ELEMENT elem;
51 + lock_elem_t *lvec, *lk;
43 52 smb2fid_t smb2fid;
44 - uint32_t save_offset;
45 53 uint32_t LockSequence;
46 54 uint32_t status;
47 55 uint16_t StructSize;
48 56 uint16_t LockCount;
49 57 uint16_t i;
50 - boolean_t MayBlock = B_FALSE;
51 - int rc = 0;
58 + int rc;
52 59
53 60 /*
54 - * SMB2 Lock request
61 + * Decode SMB2 Lock request
55 62 */
56 63 rc = smb_mbc_decodef(
57 64 &sr->smb_data, "wwlqq",
58 65 &StructSize, /* w */
59 66 &LockCount, /* w */
60 67 &LockSequence, /* l */
61 68 &smb2fid.persistent, /* q */
62 69 &smb2fid.temporal); /* q */
63 70 if (rc || StructSize != 48)
64 71 return (SDRC_ERROR);
65 72
73 + /*
74 + * Want FID lookup before the start probe.
75 + */
66 76 status = smb2sr_lookup_fid(sr, &smb2fid);
77 + DTRACE_SMB2_START(op__Lock, smb_request_t *, sr);
78 +
67 79 if (status)
68 - goto errout;
80 + goto errout; /* Bad FID */
69 81 if (sr->fid_ofile->f_node == NULL || LockCount == 0) {
70 82 status = NT_STATUS_INVALID_PARAMETER;
71 83 goto errout;
72 84 }
73 85 if (LockCount > smb2_lock_max_elem) {
74 86 status = NT_STATUS_INSUFFICIENT_RESOURCES;
75 87 goto errout;
76 88 }
77 89
78 90 /*
79 - * Process the array of SMB2_LOCK_ELEMENT structs
80 - * We do this twice. (it's always a short list)
81 - * The first time, just validate the flags, and check
82 - * if any of the locking request might need to block.
83 - * The second time (either here, or in the async
84 - * handler function) process the locks for real.
91 + * Check the LockSequence to determine whether a previous
92 + * lock request succeeded, but the client disconnected
93 + * (retaining a durable or resilient handle). If so, this
94 + * is a lock "replay". We'll find the lock sequence here
95 + * and return success without processing the lock again.
85 96 */
86 - save_offset = sr->smb_data.chain_offset;
97 + if (sr->session->dialect < SMB_VERS_2_1)
98 + LockSequence = 0;
99 + if ((sr->session->dialect == SMB_VERS_2_1) &&
100 + sr->fid_ofile->dh_vers != SMB2_RESILIENT)
101 + LockSequence = 0;
102 + /* dialect 3.0 or later can always use LockSequence */
103 +
104 + if (LockSequence != 0 &&
105 + smb2_lock_chk_lockseq(sr->fid_ofile, LockSequence)) {
106 + status = NT_STATUS_SUCCESS;
107 + goto errout;
108 + }
109 +
110 + /*
111 + * Parse the array of SMB2_LOCK_ELEMENT structs.
112 + * This array is free'd in smb_srm_fini.
113 + */
114 + lvec = smb_srm_zalloc(sr, LockCount * sizeof (*lvec));
87 115 for (i = 0; i < LockCount; i++) {
116 + lk = &lvec[i];
88 117 rc = smb_mbc_decodef(
89 118 &sr->smb_data, "qqll",
90 - &elem.Offset, /* q */
91 - &elem.Length, /* q */
92 - &elem.Flags, /* l */
93 - &elem.reserved); /* l */
119 + &lk->Offset, /* q */
120 + &lk->Length, /* q */
121 + &lk->Flags, /* l */
122 + &lk->reserved); /* l */
94 123 if (rc) {
95 124 status = NT_STATUS_INVALID_PARAMETER;
96 125 goto errout;
97 126 }
127 + }
98 128
99 - /*
100 - * Make sure the flags are valid;
101 - * Find out if we might block.
102 - */
103 - switch (elem.Flags) {
104 - case SMB2_LOCKFLAG_SHARED_LOCK:
105 - case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
106 - MayBlock = B_TRUE;
107 - break;
108 -
109 - /* BEGIN CSTYLED */
110 - case SMB2_LOCKFLAG_SHARED_LOCK |
111 - SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
112 - case SMB2_LOCKFLAG_EXCLUSIVE_LOCK |
113 - SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
114 - case SMB2_LOCKFLAG_UNLOCK:
115 - /* END CSTYLED */
116 - break;
117 -
118 - default:
119 - status = NT_STATUS_INVALID_PARAMETER;
120 - goto errout;
121 - }
129 + /*
130 + * [MS-SMB2] 3.3.5.14
131 + * If the flags of the [first element of] the Locks array
132 + * [has] SMB2_LOCKFLAG_UNLOCK set, the server MUST process
133 + * the lock array as a series of unlocks. Otherwise, it
134 + * MUST process the lock array as a series of lock requests.
135 + */
136 + sr->arg.lock.lvec = lvec;
137 + sr->arg.lock.lcnt = LockCount;
138 + sr->arg.lock.lseq = LockSequence;
139 + if (lvec[0].Flags & SMB2_LOCKFLAG_UNLOCK) {
140 + status = smb2_unlock(sr);
141 + } else {
142 + status = smb2__lock(sr);
122 143 }
123 144
124 - if (MayBlock) {
125 - /*
126 - * May need to block. "Go async".
127 - */
128 - status = smb2sr_go_async(sr, smb2_lock_async);
129 - goto errout;
145 + if (sr->fid_ofile->dh_persist) {
146 + smb2_dh_update_locks(sr, sr->fid_ofile);
130 147 }
131 148
132 - sr->smb_data.chain_offset = save_offset;
133 - status = smb2_lock_exec(sr, LockCount);
134 - if (status)
135 - goto errout;
149 +errout:
150 + sr->smb2_status = status;
151 + DTRACE_SMB2_DONE(op__Lock, smb_request_t *, sr);
136 152
153 + if (status) {
154 + smb2sr_put_error(sr, status);
155 + return (SDRC_SUCCESS);
156 + }
157 +
137 158 /*
138 - * SMB2 Lock reply (sync)
159 + * Encode SMB2 Lock reply
139 160 */
140 - StructSize = 4;
141 161 (void) smb_mbc_encodef(
142 162 &sr->reply, "w..",
143 - StructSize); /* w */
144 - /* reserved .. */
163 + 4); /* StructSize w */
164 + /* reserved .. */
145 165 return (SDRC_SUCCESS);
146 -
147 -errout:
148 - smb2sr_put_error(sr, status);
149 - return (SDRC_SUCCESS);
150 166 }
151 167
152 -static smb_sdrc_t
153 -smb2_lock_async(smb_request_t *sr)
168 +/*
169 + * Process what should be an array of unlock requests.
170 + */
171 +static uint32_t
172 +smb2_unlock(smb_request_t *sr)
154 173 {
155 - smb2fid_t smb2fid;
156 - uint32_t LockSequence;
157 - uint32_t status;
158 - uint16_t StructSize;
159 - uint16_t LockCount;
160 - int rc = 0;
174 + lock_elem_t *lk;
175 + lock_elem_t *lvec = sr->arg.lock.lvec;
176 + uint32_t LockCount = sr->arg.lock.lcnt;
177 + uint32_t LockSequence = sr->arg.lock.lseq;
178 + uint32_t status = 0;
179 + uint32_t pid = 0; /* SMB2 ignores lock PIDs. */
180 + int i;
161 181
162 - /*
163 - * Decode the lock request again. It should all decode
164 - * exactly the same as the first time we saw it. If not,
165 - * report an "internal error".
166 - */
167 - rc = smb_mbc_decodef(
168 - &sr->smb_data, "wwlqq",
169 - &StructSize, /* w */
170 - &LockCount, /* w */
171 - &LockSequence, /* l */
172 - &smb2fid.persistent, /* q */
173 - &smb2fid.temporal); /* q */
174 - if (rc || StructSize != 48)
175 - return (SDRC_ERROR);
182 + for (i = 0; i < LockCount; i++) {
183 + lk = &lvec[i];
176 184
177 - status = smb2sr_lookup_fid(sr, &smb2fid);
178 - if (status)
179 - goto errout;
180 - if (sr->fid_ofile->f_node == NULL || LockCount == 0) {
181 - status = NT_STATUS_INTERNAL_ERROR;
182 - goto errout;
185 + if (lk->Flags != SMB2_LOCKFLAG_UNLOCK) {
186 + status = NT_STATUS_INVALID_PARAMETER;
187 + break;
188 + }
189 +
190 + status = smb_unlock_range(sr, lk->Offset, lk->Length, pid);
191 + if (status != 0)
192 + break;
183 193 }
194 + if (status == 0 && LockSequence != 0) {
195 + smb2_lock_set_lockseq(sr->fid_ofile, LockSequence);
196 + }
184 197
185 - status = smb2_lock_exec(sr, LockCount);
186 - if (status)
187 - goto errout;
188 -
189 - /*
190 - * SMB2 Lock reply (async)
191 - */
192 - StructSize = 4;
193 - (void) smb_mbc_encodef(
194 - &sr->reply, "w..",
195 - StructSize); /* w */
196 - /* reserved .. */
197 - return (SDRC_SUCCESS);
198 -
199 -errout:
200 - smb2sr_put_error(sr, status);
201 - return (SDRC_SUCCESS);
198 + return (status);
202 199 }
203 200
204 201 /*
205 - * Execute the vector of locks. This is the common function called by
206 - * either the sync or async code paths. We've already decoded this
207 - * request once when we get here, so if there are any decode errors
208 - * then it's some kind of internal error.
202 + * Process what should be an array of lock requests.
209 203 */
210 204 static uint32_t
211 -smb2_lock_exec(smb_request_t *sr, uint16_t LockCount)
205 +smb2__lock(smb_request_t *sr)
212 206 {
213 - struct SMB2_LOCK_ELEMENT elem;
207 + lock_elem_t *lk;
208 + lock_elem_t *lvec = sr->arg.lock.lvec;
209 + uint32_t LockCount = sr->arg.lock.lcnt;
210 + uint32_t LockSequence = sr->arg.lock.lseq;
211 + uint32_t i;
212 + uint32_t ltype;
213 + uint32_t pid = 0; /* SMB2 ignores lock PIDs */
214 + uint32_t timeout = 0;
214 215 uint32_t status = 0;
215 - uint16_t i;
216 - int rc;
217 216
218 - /*
219 - * On entry, out position in the input data should be
220 - * after both the SMB2 header and the fixed part of
221 - * the SMB Lock request header (24).
222 - */
223 - ASSERT(sr->smb_data.chain_offset ==
224 - (sr->smb2_cmd_hdr + SMB2_HDR_SIZE + 24));
217 + for (i = 0; i < LockCount; i++) {
218 + lk = &lvec[i];
225 219
226 - /*
227 - * This is checked by our callers, but let's make sure.
228 - */
229 - ASSERT(sr->fid_ofile->f_node != NULL);
220 + switch (lk->Flags) {
230 221
231 - for (i = 0; i < LockCount; i++) {
232 - rc = smb_mbc_decodef(
233 - &sr->smb_data, "qqll",
234 - &elem.Offset, /* q */
235 - &elem.Length, /* q */
236 - &elem.Flags, /* l */
237 - &elem.reserved); /* l */
238 - if (rc) {
239 - status = NT_STATUS_INTERNAL_ERROR;
222 + case SMB2_LOCKFLAG_SHARED_LOCK:
223 + case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
224 + /*
225 + * Blocking locks have special rules:
226 + * Must be exactly one element, else
227 + * invalid parameter.
228 + */
229 + if (i == 0 && LockCount == 1) {
230 + status = smb2_lock_blocking(sr);
231 + return (status);
232 + }
233 + /* FALLTHROUGH */
234 + case SMB2_LOCKFLAG_UNLOCK:
235 + default:
236 + status = NT_STATUS_INVALID_PARAMETER;
237 + goto end_loop;
238 +
239 + /* BEGIN CSTYLED */
240 + case SMB2_LOCKFLAG_SHARED_LOCK |
241 + SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
242 + /* END CSTYLED */
243 + ltype = SMB_LOCK_TYPE_READONLY;
240 244 break;
241 - }
242 - status = smb2_lock_elem(sr, &elem);
243 - if (status)
245 +
246 + /* BEGIN CSTYLED */
247 + case SMB2_LOCKFLAG_EXCLUSIVE_LOCK |
248 + SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
249 + /* END CSTYLED */
250 + ltype = SMB_LOCK_TYPE_READWRITE;
244 251 break;
252 + }
253 +
254 + status = smb_lock_range(sr, lk->Offset, lk->Length, pid,
255 + ltype, timeout);
256 + if (status != 0) {
257 + goto end_loop;
258 + }
245 259 }
260 +
261 +end_loop:
262 + if (status != 0) {
263 + /*
264 + * Oh... we have to rollback.
265 + */
266 + while (i > 0) {
267 + --i;
268 + lk = &lvec[i];
269 + (void) smb_unlock_range(sr,
270 + lk->Offset, lk->Length, pid);
271 + }
272 + }
273 + if (status == 0 && LockSequence != 0)
274 + smb2_lock_set_lockseq(sr->fid_ofile, LockSequence);
275 +
246 276 return (status);
247 277 }
248 278
279 +/*
280 + * Handler for blocking lock requests, which may "go async".
281 + * Always exactly one lock request here.
282 + */
249 283 static uint32_t
250 -smb2_lock_elem(smb_request_t *sr, struct SMB2_LOCK_ELEMENT *elem)
284 +smb2_lock_blocking(smb_request_t *sr)
251 285 {
252 - smb_node_t *node = sr->fid_ofile->f_node;
286 + lock_elem_t *lk = sr->arg.lock.lvec;
287 + uint32_t LockCount = sr->arg.lock.lcnt;
288 + uint32_t LockSequence = sr->arg.lock.lseq;
253 289 uint32_t status;
254 290 uint32_t ltype;
255 - uint32_t timeout = 0;
291 + uint32_t pid = 0; /* SMB2 ignores lock PIDs */
292 + uint32_t timeout = UINT_MAX;
256 293
257 - switch (elem->Flags) {
294 + ASSERT(sr->fid_ofile->f_node != NULL);
295 + ASSERT(LockCount == 1);
296 +
297 + switch (lk->Flags) {
258 298 case SMB2_LOCKFLAG_SHARED_LOCK:
259 - timeout = UINT_MAX;
260 - /* FALLTHROUGH */
261 - case SMB2_LOCKFLAG_SHARED_LOCK | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
262 299 ltype = SMB_LOCK_TYPE_READONLY;
263 - status = smb_lock_range(sr,
264 - elem->Offset, elem->Length,
265 - timeout, ltype);
266 300 break;
267 301
268 302 case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
269 - timeout = UINT_MAX;
270 - /* FALLTHROUGH */
271 - case SMB2_LOCKFLAG_EXCLUSIVE_LOCK | SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
272 303 ltype = SMB_LOCK_TYPE_READWRITE;
273 - status = smb_lock_range(sr,
274 - elem->Offset, elem->Length,
275 - timeout, ltype);
276 304 break;
277 305
278 - case SMB2_LOCKFLAG_UNLOCK:
279 - status = smb_unlock_range(sr, node,
280 - elem->Offset, elem->Length);
281 - break;
306 + default:
307 + ASSERT(0);
308 + return (NT_STATUS_INTERNAL_ERROR);
309 + }
282 310
283 311 /*
284 - * We've already checked the flags previously, so any
285 - * surprises here are some kind of internal error.
312 + * Try the lock first with timeout=0 as we can often
313 + * get a lock without going async and avoid an extra
314 + * round trip with the client. Also, only go async
315 + * for status returns that mean we will block.
286 316 */
287 - default:
288 - status = NT_STATUS_INTERNAL_ERROR;
289 - break;
317 + status = smb_lock_range(sr, lk->Offset, lk->Length, pid, ltype, 0);
318 + if (status == NT_STATUS_LOCK_NOT_GRANTED ||
319 + status == NT_STATUS_FILE_LOCK_CONFLICT) {
320 + status = smb2sr_go_async(sr);
321 + if (status != 0)
322 + return (status);
323 + status = smb_lock_range(sr, lk->Offset, lk->Length,
324 + pid, ltype, timeout);
290 325 }
291 326
327 + if (status == 0 && LockSequence != 0)
328 + smb2_lock_set_lockseq(sr->fid_ofile, LockSequence);
329 +
292 330 return (status);
331 +}
332 +
333 +/*
334 + * Check whether we've stored a given LockSequence
335 + *
336 + * [MS-SMB2] 3.3.5.14
337 + *
338 + * The server verifies the LockSequence by performing the following steps:
339 + *
340 + * 1. The server MUST use LockSequenceIndex as an index into the
341 + * Open.LockSequenceArray in order to locate the sequence number entry.
342 + * If the index exceeds the maximum extent of the Open.LockSequenceArray,
343 + * or LockSequenceIndex is 0, or if the sequence number entry is empty,
344 + * the server MUST skip step 2 and continue lock/unlock processing.
345 + *
346 + * 2. The server MUST compare LockSequenceNumber to the SequenceNumber of
347 + * the entry located in step 1. If the sequence numbers are equal, the
348 + * server MUST complete the lock/unlock request with success. Otherwise,
349 + * the server MUST reset the entry value to empty and continue lock/unlock
350 + * processing.
351 + */
352 +boolean_t
353 +smb2_lock_chk_lockseq(smb_ofile_t *ofile, uint32_t lockseq)
354 +{
355 + uint32_t lsi;
356 + uint8_t lsn;
357 + boolean_t rv;
358 +
359 + /*
360 + * LockSequenceNumber is the low four bits.
361 + * LockSequenceIndex is the remaining 28 bits.
362 + * valid range is 1..64, which we convert to an
363 + * array index in the range 0..63
364 + */
365 + lsn = lockseq & SMB2_LSN_MASK;
366 + lsi = (lockseq >> SMB2_LSN_SHIFT);
367 + if (lsi == 0 || lsi > SMB_OFILE_LSEQ_MAX)
368 + return (B_FALSE);
369 + --lsi;
370 +
371 + mutex_enter(&ofile->f_mutex);
372 +
373 + if (ofile->f_lock_seq[lsi] == lsn) {
374 + rv = B_TRUE;
375 + } else {
376 + ofile->f_lock_seq[lsi] = (uint8_t)-1; /* "Empty" */
377 + rv = B_FALSE;
378 + }
379 +
380 + mutex_exit(&ofile->f_mutex);
381 +
382 + return (rv);
383 +}
384 +
385 +static void
386 +smb2_lock_set_lockseq(smb_ofile_t *ofile, uint32_t lockseq)
387 +{
388 + uint32_t lsi;
389 + uint8_t lsn;
390 +
391 + /*
392 + * LockSequenceNumber is the low four bits.
393 + * LockSequenceIndex is the remaining 28 bits.
394 + * valid range is 1..64, which we convert to an
395 + * array index in the range 0..63
396 + */
397 + lsn = lockseq & SMB2_LSN_MASK;
398 + lsi = (lockseq >> SMB2_LSN_SHIFT);
399 + if (lsi == 0 || lsi > SMB_OFILE_LSEQ_MAX) {
400 + cmn_err(CE_NOTE, "smb2_lock_set_lockseq, index=%u", lsi);
401 + return;
402 + }
403 + --lsi;
404 +
405 + mutex_enter(&ofile->f_mutex);
406 +
407 + ofile->f_lock_seq[lsi] = lsn;
408 +
409 + mutex_exit(&ofile->f_mutex);
293 410 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX