1a90cf9f2SGordon Ross /*
2a90cf9f2SGordon Ross * This file and its contents are supplied under the terms of the
3a90cf9f2SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0.
4a90cf9f2SGordon Ross * You may only use this file in accordance with the terms of version
5a90cf9f2SGordon Ross * 1.0 of the CDDL.
6a90cf9f2SGordon Ross *
7a90cf9f2SGordon Ross * A full copy of the text of the CDDL should have accompanied this
8a90cf9f2SGordon Ross * source. A copy of the CDDL is also available via the Internet at
9a90cf9f2SGordon Ross * http://www.illumos.org/license/CDDL.
10a90cf9f2SGordon Ross */
11a90cf9f2SGordon Ross
12a90cf9f2SGordon Ross /*
13148d1a41SMatt Barden * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
14a90cf9f2SGordon Ross */
15a90cf9f2SGordon Ross
16a90cf9f2SGordon Ross /*
17a90cf9f2SGordon Ross * Dispatch function for SMB2_LOCK
18a90cf9f2SGordon Ross */
19a90cf9f2SGordon Ross
20a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h>
21a90cf9f2SGordon Ross
226f58980aSGordon Ross /*
236f58980aSGordon Ross * [MS-SMB2] 2.2.26 LockSequenceIndex, LockSequenceNumber.
246f58980aSGordon Ross */
256f58980aSGordon Ross #define SMB2_LSN_SHIFT 4
266f58980aSGordon Ross #define SMB2_LSN_MASK 0xf
276f58980aSGordon Ross
280897f7fbSGordon Ross typedef struct SMB2_LOCK_ELEMENT {
29a90cf9f2SGordon Ross uint64_t Offset;
30a90cf9f2SGordon Ross uint64_t Length;
31a90cf9f2SGordon Ross uint32_t Flags;
32a90cf9f2SGordon Ross uint32_t reserved;
330897f7fbSGordon Ross } lock_elem_t;
34a90cf9f2SGordon Ross
350897f7fbSGordon Ross static uint32_t smb2_unlock(smb_request_t *);
360897f7fbSGordon Ross static uint32_t smb2_locks(smb_request_t *);
37148d1a41SMatt Barden static uint32_t smb2_lock_blocking(smb_request_t *);
38a90cf9f2SGordon Ross
396f58980aSGordon Ross static boolean_t smb2_lock_chk_lockseq(smb_ofile_t *, uint32_t);
406f58980aSGordon Ross static void smb2_lock_set_lockseq(smb_ofile_t *, uint32_t);
416f58980aSGordon Ross
42a90cf9f2SGordon Ross /*
43a90cf9f2SGordon Ross * This is a somewhat arbitrary sanity limit on the length of the
44a90cf9f2SGordon Ross * SMB2_LOCK_ELEMENT array. It usually has length one or two.
45a90cf9f2SGordon Ross */
46a90cf9f2SGordon Ross int smb2_lock_max_elem = 1024;
47a90cf9f2SGordon Ross
48a90cf9f2SGordon Ross smb_sdrc_t
smb2_lock(smb_request_t * sr)49a90cf9f2SGordon Ross smb2_lock(smb_request_t *sr)
50a90cf9f2SGordon Ross {
510897f7fbSGordon Ross lock_elem_t *lvec, *lk;
52a90cf9f2SGordon Ross smb2fid_t smb2fid;
53a90cf9f2SGordon Ross uint32_t LockSequence;
54a90cf9f2SGordon Ross uint32_t status;
55a90cf9f2SGordon Ross uint16_t StructSize;
56a90cf9f2SGordon Ross uint16_t LockCount;
57a90cf9f2SGordon Ross uint16_t i;
580897f7fbSGordon Ross int rc;
59a90cf9f2SGordon Ross
60a90cf9f2SGordon Ross /*
6193bc28dbSGordon Ross * Decode SMB2 Lock request
62a90cf9f2SGordon Ross */
63a90cf9f2SGordon Ross rc = smb_mbc_decodef(
64a90cf9f2SGordon Ross &sr->smb_data, "wwlqq",
65a90cf9f2SGordon Ross &StructSize, /* w */
66a90cf9f2SGordon Ross &LockCount, /* w */
67a90cf9f2SGordon Ross &LockSequence, /* l */
68a90cf9f2SGordon Ross &smb2fid.persistent, /* q */
69a90cf9f2SGordon Ross &smb2fid.temporal); /* q */
70a90cf9f2SGordon Ross if (rc || StructSize != 48)
71a90cf9f2SGordon Ross return (SDRC_ERROR);
72a90cf9f2SGordon Ross
7393bc28dbSGordon Ross /*
7493bc28dbSGordon Ross * Want FID lookup before the start probe.
7593bc28dbSGordon Ross */
76a90cf9f2SGordon Ross status = smb2sr_lookup_fid(sr, &smb2fid);
7793bc28dbSGordon Ross DTRACE_SMB2_START(op__Lock, smb_request_t *, sr);
7893bc28dbSGordon Ross
79a90cf9f2SGordon Ross if (status)
8093bc28dbSGordon Ross goto errout; /* Bad FID */
81a90cf9f2SGordon Ross if (sr->fid_ofile->f_node == NULL || LockCount == 0) {
82a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
83a90cf9f2SGordon Ross goto errout;
84a90cf9f2SGordon Ross }
85a90cf9f2SGordon Ross if (LockCount > smb2_lock_max_elem) {
86a90cf9f2SGordon Ross status = NT_STATUS_INSUFFICIENT_RESOURCES;
87a90cf9f2SGordon Ross goto errout;
88a90cf9f2SGordon Ross }
89a90cf9f2SGordon Ross
90a90cf9f2SGordon Ross /*
916f58980aSGordon Ross * Check the LockSequence to determine whether a previous
926f58980aSGordon Ross * lock request succeeded, but the client disconnected
936f58980aSGordon Ross * (retaining a durable or resilient handle). If so, this
946f58980aSGordon Ross * is a lock "replay". We'll find the lock sequence here
956f58980aSGordon Ross * and return success without processing the lock again.
966f58980aSGordon Ross */
976f58980aSGordon Ross if (sr->session->dialect < SMB_VERS_2_1)
986f58980aSGordon Ross LockSequence = 0;
996f58980aSGordon Ross if ((sr->session->dialect == SMB_VERS_2_1) &&
1006f58980aSGordon Ross sr->fid_ofile->dh_vers != SMB2_RESILIENT)
1016f58980aSGordon Ross LockSequence = 0;
1026f58980aSGordon Ross /* dialect 3.0 or later can always use LockSequence */
1036f58980aSGordon Ross
1046f58980aSGordon Ross if (LockSequence != 0 &&
1056f58980aSGordon Ross smb2_lock_chk_lockseq(sr->fid_ofile, LockSequence)) {
1066f58980aSGordon Ross status = NT_STATUS_SUCCESS;
107148d1a41SMatt Barden goto errout;
1086f58980aSGordon Ross }
1096f58980aSGordon Ross
1106f58980aSGordon Ross /*
1110897f7fbSGordon Ross * Parse the array of SMB2_LOCK_ELEMENT structs.
1120897f7fbSGordon Ross * This array is free'd in smb_srm_fini.
113a90cf9f2SGordon Ross */
1140897f7fbSGordon Ross lvec = smb_srm_zalloc(sr, LockCount * sizeof (*lvec));
115a90cf9f2SGordon Ross for (i = 0; i < LockCount; i++) {
1160897f7fbSGordon Ross lk = &lvec[i];
117a90cf9f2SGordon Ross rc = smb_mbc_decodef(
118a90cf9f2SGordon Ross &sr->smb_data, "qqll",
1190897f7fbSGordon Ross &lk->Offset, /* q */
1200897f7fbSGordon Ross &lk->Length, /* q */
1210897f7fbSGordon Ross &lk->Flags, /* l */
1220897f7fbSGordon Ross &lk->reserved); /* l */
123a90cf9f2SGordon Ross if (rc) {
124a90cf9f2SGordon Ross status = NT_STATUS_INVALID_PARAMETER;
125a90cf9f2SGordon Ross goto errout;
126a90cf9f2SGordon Ross }
1270897f7fbSGordon Ross }
128a90cf9f2SGordon Ross
129a90cf9f2SGordon Ross /*
1300897f7fbSGordon Ross * [MS-SMB2] 3.3.5.14
1310897f7fbSGordon Ross * If the flags of the [first element of] the Locks array
1320897f7fbSGordon Ross * [has] SMB2_LOCKFLAG_UNLOCK set, the server MUST process
1330897f7fbSGordon Ross * the lock array as a series of unlocks. Otherwise, it
1340897f7fbSGordon Ross * MUST process the lock array as a series of lock requests.
135a90cf9f2SGordon Ross */
1360897f7fbSGordon Ross sr->arg.lock.lvec = lvec;
1370897f7fbSGordon Ross sr->arg.lock.lcnt = LockCount;
1380897f7fbSGordon Ross sr->arg.lock.lseq = LockSequence;
1390897f7fbSGordon Ross if (lvec[0].Flags & SMB2_LOCKFLAG_UNLOCK) {
1400897f7fbSGordon Ross status = smb2_unlock(sr);
1410897f7fbSGordon Ross } else {
1420897f7fbSGordon Ross status = smb2_locks(sr);
143a90cf9f2SGordon Ross }
14493bc28dbSGordon Ross
145*8d94f651SGordon Ross if (sr->fid_ofile->dh_persist) {
146*8d94f651SGordon Ross smb2_dh_update_locks(sr, sr->fid_ofile);
147*8d94f651SGordon Ross }
148*8d94f651SGordon Ross
14993bc28dbSGordon Ross errout:
15093bc28dbSGordon Ross sr->smb2_status = status;
15193bc28dbSGordon Ross DTRACE_SMB2_DONE(op__Lock, smb_request_t *, sr);
15293bc28dbSGordon Ross
15393bc28dbSGordon Ross if (status) {
15493bc28dbSGordon Ross smb2sr_put_error(sr, status);
15593bc28dbSGordon Ross return (SDRC_SUCCESS);
15693bc28dbSGordon Ross }
157a90cf9f2SGordon Ross
158a90cf9f2SGordon Ross /*
159148d1a41SMatt Barden * Encode SMB2 Lock reply
160a90cf9f2SGordon Ross */
161a90cf9f2SGordon Ross (void) smb_mbc_encodef(
162a90cf9f2SGordon Ross &sr->reply, "w..",
1630897f7fbSGordon Ross 4); /* StructSize w */
164a90cf9f2SGordon Ross /* reserved .. */
165a90cf9f2SGordon Ross return (SDRC_SUCCESS);
166a90cf9f2SGordon Ross }
167a90cf9f2SGordon Ross
1680897f7fbSGordon Ross /*
1690897f7fbSGordon Ross * Process what should be an array of unlock requests.
1700897f7fbSGordon Ross */
1710897f7fbSGordon Ross static uint32_t
smb2_unlock(smb_request_t * sr)1720897f7fbSGordon Ross smb2_unlock(smb_request_t *sr)
1730897f7fbSGordon Ross {
1740897f7fbSGordon Ross lock_elem_t *lk;
1750897f7fbSGordon Ross lock_elem_t *lvec = sr->arg.lock.lvec;
1760897f7fbSGordon Ross uint32_t LockCount = sr->arg.lock.lcnt;
1770897f7fbSGordon Ross uint32_t LockSequence = sr->arg.lock.lseq;
1780897f7fbSGordon Ross uint32_t status = 0;
1790897f7fbSGordon Ross uint32_t pid = 0; /* SMB2 ignores lock PIDs. */
1800897f7fbSGordon Ross int i;
1810897f7fbSGordon Ross
1820897f7fbSGordon Ross for (i = 0; i < LockCount; i++) {
1830897f7fbSGordon Ross lk = &lvec[i];
1840897f7fbSGordon Ross
1850897f7fbSGordon Ross if (lk->Flags != SMB2_LOCKFLAG_UNLOCK) {
1860897f7fbSGordon Ross status = NT_STATUS_INVALID_PARAMETER;
1870897f7fbSGordon Ross break;
1880897f7fbSGordon Ross }
1890897f7fbSGordon Ross
1900897f7fbSGordon Ross status = smb_unlock_range(sr, lk->Offset, lk->Length, pid);
1910897f7fbSGordon Ross if (status != 0)
1920897f7fbSGordon Ross break;
1930897f7fbSGordon Ross }
1946f58980aSGordon Ross if (status == 0 && LockSequence != 0) {
1956f58980aSGordon Ross smb2_lock_set_lockseq(sr->fid_ofile, LockSequence);
1966f58980aSGordon Ross }
1970897f7fbSGordon Ross
1980897f7fbSGordon Ross return (status);
1990897f7fbSGordon Ross }
2000897f7fbSGordon Ross
2010897f7fbSGordon Ross /*
2020897f7fbSGordon Ross * Process what should be an array of lock requests.
2030897f7fbSGordon Ross */
2040897f7fbSGordon Ross static uint32_t
smb2_locks(smb_request_t * sr)2050897f7fbSGordon Ross smb2_locks(smb_request_t *sr)
2060897f7fbSGordon Ross {
2070897f7fbSGordon Ross lock_elem_t *lk;
2080897f7fbSGordon Ross lock_elem_t *lvec = sr->arg.lock.lvec;
2090897f7fbSGordon Ross uint32_t LockCount = sr->arg.lock.lcnt;
2106f58980aSGordon Ross uint32_t LockSequence = sr->arg.lock.lseq;
2110897f7fbSGordon Ross uint32_t i;
2120897f7fbSGordon Ross uint32_t ltype;
2130897f7fbSGordon Ross uint32_t pid = 0; /* SMB2 ignores lock PIDs */
2140897f7fbSGordon Ross uint32_t timeout = 0;
2150897f7fbSGordon Ross uint32_t status = 0;
2160897f7fbSGordon Ross
2170897f7fbSGordon Ross for (i = 0; i < LockCount; i++) {
2180897f7fbSGordon Ross lk = &lvec[i];
2190897f7fbSGordon Ross
2200897f7fbSGordon Ross switch (lk->Flags) {
2210897f7fbSGordon Ross
2220897f7fbSGordon Ross case SMB2_LOCKFLAG_SHARED_LOCK:
2230897f7fbSGordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
2240897f7fbSGordon Ross /*
2250897f7fbSGordon Ross * Blocking locks have special rules:
2260897f7fbSGordon Ross * Must be exactly one element, else
2270897f7fbSGordon Ross * invalid parameter.
2280897f7fbSGordon Ross */
2290897f7fbSGordon Ross if (i == 0 && LockCount == 1) {
230148d1a41SMatt Barden status = smb2_lock_blocking(sr);
2310897f7fbSGordon Ross return (status);
2320897f7fbSGordon Ross }
2330897f7fbSGordon Ross /* FALLTHROUGH */
2340897f7fbSGordon Ross case SMB2_LOCKFLAG_UNLOCK:
2350897f7fbSGordon Ross default:
2360897f7fbSGordon Ross status = NT_STATUS_INVALID_PARAMETER;
2370897f7fbSGordon Ross goto end_loop;
2380897f7fbSGordon Ross
2390897f7fbSGordon Ross /* BEGIN CSTYLED */
2400897f7fbSGordon Ross case SMB2_LOCKFLAG_SHARED_LOCK |
2410897f7fbSGordon Ross SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
2420897f7fbSGordon Ross /* END CSTYLED */
2430897f7fbSGordon Ross ltype = SMB_LOCK_TYPE_READONLY;
2440897f7fbSGordon Ross break;
2450897f7fbSGordon Ross
2460897f7fbSGordon Ross /* BEGIN CSTYLED */
2470897f7fbSGordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK |
2480897f7fbSGordon Ross SMB2_LOCKFLAG_FAIL_IMMEDIATELY:
2490897f7fbSGordon Ross /* END CSTYLED */
2500897f7fbSGordon Ross ltype = SMB_LOCK_TYPE_READWRITE;
2510897f7fbSGordon Ross break;
2520897f7fbSGordon Ross }
2530897f7fbSGordon Ross
2540897f7fbSGordon Ross status = smb_lock_range(sr, lk->Offset, lk->Length, pid,
2550897f7fbSGordon Ross ltype, timeout);
2560897f7fbSGordon Ross if (status != 0) {
2570897f7fbSGordon Ross goto end_loop;
2580897f7fbSGordon Ross }
2590897f7fbSGordon Ross }
2600897f7fbSGordon Ross
2610897f7fbSGordon Ross end_loop:
2620897f7fbSGordon Ross if (status != 0) {
2630897f7fbSGordon Ross /*
2640897f7fbSGordon Ross * Oh... we have to rollback.
2650897f7fbSGordon Ross */
2660897f7fbSGordon Ross while (i > 0) {
2670897f7fbSGordon Ross --i;
2680897f7fbSGordon Ross lk = &lvec[i];
2690897f7fbSGordon Ross (void) smb_unlock_range(sr,
2700897f7fbSGordon Ross lk->Offset, lk->Length, pid);
2710897f7fbSGordon Ross }
2720897f7fbSGordon Ross }
2736f58980aSGordon Ross if (status == 0 && LockSequence != 0)
2746f58980aSGordon Ross smb2_lock_set_lockseq(sr->fid_ofile, LockSequence);
2750897f7fbSGordon Ross
2760897f7fbSGordon Ross return (status);
2770897f7fbSGordon Ross }
2780897f7fbSGordon Ross
2790897f7fbSGordon Ross /*
280148d1a41SMatt Barden * Handler for blocking lock requests, which may "go async".
2810897f7fbSGordon Ross * Always exactly one lock request here.
2820897f7fbSGordon Ross */
283148d1a41SMatt Barden static uint32_t
smb2_lock_blocking(smb_request_t * sr)284148d1a41SMatt Barden smb2_lock_blocking(smb_request_t *sr)
285a90cf9f2SGordon Ross {
2860897f7fbSGordon Ross lock_elem_t *lk = sr->arg.lock.lvec;
2870897f7fbSGordon Ross uint32_t LockCount = sr->arg.lock.lcnt;
2886f58980aSGordon Ross uint32_t LockSequence = sr->arg.lock.lseq;
289a90cf9f2SGordon Ross uint32_t status;
2900897f7fbSGordon Ross uint32_t ltype;
2910897f7fbSGordon Ross uint32_t pid = 0; /* SMB2 ignores lock PIDs */
2920897f7fbSGordon Ross uint32_t timeout = UINT_MAX;
293a90cf9f2SGordon Ross
2940897f7fbSGordon Ross ASSERT(sr->fid_ofile->f_node != NULL);
2950897f7fbSGordon Ross ASSERT(LockCount == 1);
296a90cf9f2SGordon Ross
2970897f7fbSGordon Ross switch (lk->Flags) {
2980897f7fbSGordon Ross case SMB2_LOCKFLAG_SHARED_LOCK:
2990897f7fbSGordon Ross ltype = SMB_LOCK_TYPE_READONLY;
3000897f7fbSGordon Ross break;
3010897f7fbSGordon Ross
3020897f7fbSGordon Ross case SMB2_LOCKFLAG_EXCLUSIVE_LOCK:
3030897f7fbSGordon Ross ltype = SMB_LOCK_TYPE_READWRITE;
3040897f7fbSGordon Ross break;
3050897f7fbSGordon Ross
3060897f7fbSGordon Ross default:
3070897f7fbSGordon Ross ASSERT(0);
308148d1a41SMatt Barden return (NT_STATUS_INTERNAL_ERROR);
309a90cf9f2SGordon Ross }
310a90cf9f2SGordon Ross
311a90cf9f2SGordon Ross /*
312148d1a41SMatt Barden * Try the lock first with timeout=0 as we can often
313148d1a41SMatt Barden * get a lock without going async and avoid an extra
314148d1a41SMatt Barden * round trip with the client. Also, only go async
315148d1a41SMatt Barden * for status returns that mean we will block.
316a90cf9f2SGordon Ross */
317148d1a41SMatt Barden status = smb_lock_range(sr, lk->Offset, lk->Length, pid, ltype, 0);
318148d1a41SMatt Barden if (status == NT_STATUS_LOCK_NOT_GRANTED ||
319148d1a41SMatt Barden status == NT_STATUS_FILE_LOCK_CONFLICT) {
320148d1a41SMatt Barden status = smb2sr_go_async(sr);
321148d1a41SMatt Barden if (status != 0)
322148d1a41SMatt Barden return (status);
323148d1a41SMatt Barden status = smb_lock_range(sr, lk->Offset, lk->Length,
324148d1a41SMatt Barden pid, ltype, timeout);
325148d1a41SMatt Barden }
326148d1a41SMatt Barden
327148d1a41SMatt Barden if (status == 0 && LockSequence != 0)
328148d1a41SMatt Barden smb2_lock_set_lockseq(sr->fid_ofile, LockSequence);
329148d1a41SMatt Barden
330148d1a41SMatt Barden return (status);
331a90cf9f2SGordon Ross }
3326f58980aSGordon Ross
3336f58980aSGordon Ross /*
3346f58980aSGordon Ross * Check whether we've stored a given LockSequence
3356f58980aSGordon Ross *
3366f58980aSGordon Ross * [MS-SMB2] 3.3.5.14
3376f58980aSGordon Ross *
3386f58980aSGordon Ross * The server verifies the LockSequence by performing the following steps:
3396f58980aSGordon Ross *
3406f58980aSGordon Ross * 1. The server MUST use LockSequenceIndex as an index into the
3416f58980aSGordon Ross * Open.LockSequenceArray in order to locate the sequence number entry.
3426f58980aSGordon Ross * If the index exceeds the maximum extent of the Open.LockSequenceArray,
3436f58980aSGordon Ross * or LockSequenceIndex is 0, or if the sequence number entry is empty,
3446f58980aSGordon Ross * the server MUST skip step 2 and continue lock/unlock processing.
3456f58980aSGordon Ross *
3466f58980aSGordon Ross * 2. The server MUST compare LockSequenceNumber to the SequenceNumber of
3476f58980aSGordon Ross * the entry located in step 1. If the sequence numbers are equal, the
3486f58980aSGordon Ross * server MUST complete the lock/unlock request with success. Otherwise,
3496f58980aSGordon Ross * the server MUST reset the entry value to empty and continue lock/unlock
3506f58980aSGordon Ross * processing.
3516f58980aSGordon Ross */
3526f58980aSGordon Ross boolean_t
smb2_lock_chk_lockseq(smb_ofile_t * ofile,uint32_t lockseq)3536f58980aSGordon Ross smb2_lock_chk_lockseq(smb_ofile_t *ofile, uint32_t lockseq)
3546f58980aSGordon Ross {
3556f58980aSGordon Ross uint32_t lsi;
3566f58980aSGordon Ross uint8_t lsn;
3576f58980aSGordon Ross boolean_t rv;
3586f58980aSGordon Ross
3596f58980aSGordon Ross /*
3606f58980aSGordon Ross * LockSequenceNumber is the low four bits.
3616f58980aSGordon Ross * LockSequenceIndex is the remaining 28 bits.
3626f58980aSGordon Ross * valid range is 1..64, which we convert to an
3636f58980aSGordon Ross * array index in the range 0..63
3646f58980aSGordon Ross */
3656f58980aSGordon Ross lsn = lockseq & SMB2_LSN_MASK;
3666f58980aSGordon Ross lsi = (lockseq >> SMB2_LSN_SHIFT);
3676f58980aSGordon Ross if (lsi == 0 || lsi > SMB_OFILE_LSEQ_MAX)
3686f58980aSGordon Ross return (B_FALSE);
3696f58980aSGordon Ross --lsi;
3706f58980aSGordon Ross
3716f58980aSGordon Ross mutex_enter(&ofile->f_mutex);
3726f58980aSGordon Ross
3736f58980aSGordon Ross if (ofile->f_lock_seq[lsi] == lsn) {
3746f58980aSGordon Ross rv = B_TRUE;
3756f58980aSGordon Ross } else {
3766f58980aSGordon Ross ofile->f_lock_seq[lsi] = (uint8_t)-1; /* "Empty" */
3776f58980aSGordon Ross rv = B_FALSE;
3786f58980aSGordon Ross }
3796f58980aSGordon Ross
3806f58980aSGordon Ross mutex_exit(&ofile->f_mutex);
3816f58980aSGordon Ross
3826f58980aSGordon Ross return (rv);
3836f58980aSGordon Ross }
3846f58980aSGordon Ross
3856f58980aSGordon Ross static void
smb2_lock_set_lockseq(smb_ofile_t * ofile,uint32_t lockseq)3866f58980aSGordon Ross smb2_lock_set_lockseq(smb_ofile_t *ofile, uint32_t lockseq)
3876f58980aSGordon Ross {
3886f58980aSGordon Ross uint32_t lsi;
3896f58980aSGordon Ross uint8_t lsn;
3906f58980aSGordon Ross
3916f58980aSGordon Ross /*
3926f58980aSGordon Ross * LockSequenceNumber is the low four bits.
3936f58980aSGordon Ross * LockSequenceIndex is the remaining 28 bits.
3946f58980aSGordon Ross * valid range is 1..64, which we convert to an
3956f58980aSGordon Ross * array index in the range 0..63
3966f58980aSGordon Ross */
3976f58980aSGordon Ross lsn = lockseq & SMB2_LSN_MASK;
3986f58980aSGordon Ross lsi = (lockseq >> SMB2_LSN_SHIFT);
3996f58980aSGordon Ross if (lsi == 0 || lsi > SMB_OFILE_LSEQ_MAX) {
4006f58980aSGordon Ross cmn_err(CE_NOTE, "smb2_lock_set_lockseq, index=%u", lsi);
4016f58980aSGordon Ross return;
4026f58980aSGordon Ross }
4036f58980aSGordon Ross --lsi;
4046f58980aSGordon Ross
4056f58980aSGordon Ross mutex_enter(&ofile->f_mutex);
4066f58980aSGordon Ross
4076f58980aSGordon Ross ofile->f_lock_seq[lsi] = lsn;
4086f58980aSGordon Ross
4096f58980aSGordon Ross mutex_exit(&ofile->f_mutex);
4106f58980aSGordon Ross }
411