Print this page
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-5665 SMB2 oplock leases
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
SMB-131 Don't allow setting delete-on-close on non empty dirs
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/smb_cmn_setfile.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_cmn_setfile.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Common functions supporting both:
28 28 * SMB1 Trans2 Set File/Path Info,
29 29 * SMB2 Set File Info
30 30 */
31 31
32 -#include <smbsrv/smb_kproto.h>
32 +#include <smbsrv/smb2_kproto.h>
33 33 #include <smbsrv/smb_fsops.h>
34 34
35 35 /*
36 36 * smb_set_basic_info
37 37 * [MS-FSCC] 2.4.7
38 38 * FileBasicInformation
39 39 * SMB_SET_FILE_BASIC_INFO
40 40 * SMB_FILE_BASIC_INFORMATION
41 41 *
42 42 * Sets basic file/path information.
43 43 *
44 44 * It is not valid to set FILE_ATTRIBUTE_DIRECTORY if the
45 45 * target is not a directory.
46 46 *
47 47 * For compatibility with windows servers:
48 48 * - if the specified attributes have ONLY FILE_ATTRIBUTE_NORMAL set
49 49 * clear (0) the file's attributes.
50 50 * - if the specified attributes are 0 do NOT change the file's attributes.
51 51 */
52 52 uint32_t
53 53 smb_set_basic_info(smb_request_t *sr, smb_setinfo_t *si)
54 54 {
55 55 smb_attr_t *attr = &si->si_attr;
56 56 smb_node_t *node = si->si_node;
57 57 uint64_t crtime, atime, mtime, ctime;
58 58 uint32_t attributes;
59 59 int rc;
60 60
61 61 if (smb_mbc_decodef(&si->si_data, "qqqql",
62 62 &crtime, &atime, &mtime, &ctime, &attributes) != 0)
63 63 return (NT_STATUS_INFO_LENGTH_MISMATCH);
64 64
65 65 if ((attributes & FILE_ATTRIBUTE_DIRECTORY) &&
66 66 (!smb_node_is_dir(node)))
67 67 return (NT_STATUS_INVALID_PARAMETER);
68 68
69 69 bzero(attr, sizeof (*attr));
70 70 if (atime != 0 && atime != (uint64_t)-1) {
71 71 smb_time_nt_to_unix(atime, &attr->sa_vattr.va_atime);
72 72 attr->sa_mask |= SMB_AT_ATIME;
73 73 }
74 74 if (mtime != 0 && mtime != (uint64_t)-1) {
75 75 smb_time_nt_to_unix(mtime, &attr->sa_vattr.va_mtime);
76 76 attr->sa_mask |= SMB_AT_MTIME;
77 77 }
78 78 if (ctime != 0 && ctime != (uint64_t)-1) {
79 79 smb_time_nt_to_unix(ctime, &attr->sa_vattr.va_ctime);
80 80 attr->sa_mask |= SMB_AT_CTIME;
81 81 }
82 82 if (crtime != 0 && crtime != (uint64_t)-1) {
83 83 smb_time_nt_to_unix(crtime, &attr->sa_crtime);
84 84 attr->sa_mask |= SMB_AT_CRTIME;
85 85 }
86 86
87 87 if (attributes != 0) {
88 88 attr->sa_dosattr = attributes;
89 89 attr->sa_mask |= SMB_AT_DOSATTR;
90 90 }
91 91
92 92 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
93 93 if (rc != 0)
94 94 return (smb_errno2status(rc));
95 95
96 96 return (0);
97 97 }
98 98
99 99 /*
100 100 * smb_set_eof_info
|
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
101 101 * FileEndOfFileInformation
102 102 * SMB_SET_FILE_END_OF_FILE_INFO
103 103 * SMB_FILE_END_OF_FILE_INFORMATION
104 104 */
105 105 uint32_t
106 106 smb_set_eof_info(smb_request_t *sr, smb_setinfo_t *si)
107 107 {
108 108 smb_attr_t *attr = &si->si_attr;
109 109 smb_node_t *node = si->si_node;
110 110 uint64_t eof;
111 + uint32_t status;
111 112 int rc;
112 113
113 114 if (smb_mbc_decodef(&si->si_data, "q", &eof) != 0)
114 115 return (NT_STATUS_INFO_LENGTH_MISMATCH);
115 116
116 117 if (smb_node_is_dir(node))
117 118 return (NT_STATUS_INVALID_PARAMETER);
118 119
119 - /* If opened by path, break exclusive oplock */
120 - if (sr->fid_ofile == NULL)
121 - (void) smb_oplock_break(sr, node,
122 - SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE);
120 + status = smb_oplock_break_SETINFO(node, sr->fid_ofile,
121 + FileEndOfFileInformation);
122 + if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
123 + if (sr->session->dialect >= SMB_VERS_2_BASE)
124 + (void) smb2sr_go_async(sr);
125 + (void) smb_oplock_wait_break(node, 0);
126 + status = 0;
127 + }
128 + if (status != 0)
129 + return (status);
123 130
124 131 bzero(attr, sizeof (*attr));
125 132 attr->sa_mask = SMB_AT_SIZE;
126 133 attr->sa_vattr.va_size = (u_offset_t)eof;
127 134 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
128 135 if (rc != 0)
129 136 return (smb_errno2status(rc));
130 137
131 - smb_oplock_break_levelII(node);
132 138 return (0);
133 139 }
134 140
135 141 /*
136 142 * smb_set_alloc_info
137 143 * FileAllocationInformation
138 144 * SMB_SET_FILE_ALLOCATION_INFO
139 145 * SMB_FILE_ALLOCATION_INFORMATION
140 146 */
141 147 uint32_t
142 148 smb_set_alloc_info(smb_request_t *sr, smb_setinfo_t *si)
143 149 {
144 150 smb_attr_t *attr = &si->si_attr;
145 151 smb_node_t *node = si->si_node;
146 152 uint64_t allocsz;
153 + uint32_t status;
147 154 int rc;
148 155
149 156 if (smb_mbc_decodef(&si->si_data, "q", &allocsz) != 0)
150 157 return (NT_STATUS_INFO_LENGTH_MISMATCH);
151 158
152 159 if (smb_node_is_dir(node))
153 160 return (NT_STATUS_INVALID_PARAMETER);
154 161
155 - /* If opened by path, break exclusive oplock */
156 - if (sr->fid_ofile == NULL)
157 - (void) smb_oplock_break(sr, node,
158 - SMB_OPLOCK_BREAK_EXCLUSIVE | SMB_OPLOCK_BREAK_TO_NONE);
162 + status = smb_oplock_break_SETINFO(node, sr->fid_ofile,
163 + FileAllocationInformation);
164 + if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
165 + if (sr->session->dialect >= SMB_VERS_2_BASE)
166 + (void) smb2sr_go_async(sr);
167 + (void) smb_oplock_wait_break(node, 0);
168 + status = 0;
169 + }
170 + if (status != 0)
171 + return (status);
159 172
160 173 bzero(attr, sizeof (*attr));
161 174 attr->sa_mask = SMB_AT_ALLOCSZ;
162 175 attr->sa_allocsz = (u_offset_t)allocsz;
163 176 rc = smb_node_setattr(sr, node, sr->user_cr, sr->fid_ofile, attr);
164 177 if (rc != 0)
165 178 return (smb_errno2status(rc));
166 179
167 - smb_oplock_break_levelII(node);
168 180 return (0);
169 181 }
170 182
171 183 /*
172 184 * smb_set_disposition_info
173 185 * See:
174 186 * FileDispositionInformation
175 187 * SMB_SET_FILE_DISPOSITION_INFO
176 188 * SMB_FILE_DISPOSITION_INFORMATION
177 189 *
178 190 * Set/Clear DELETE_ON_CLOSE flag for an open file.
179 191 * File should have been opened with DELETE access otherwise
180 192 * the operation is not permitted.
181 193 *
182 194 * NOTE: The node should be marked delete-on-close upon the receipt
183 195 * of the Trans2SetFileInfo(SetDispositionInfo) if mark_delete is set.
184 196 * It is different than both SmbNtCreateAndX and SmbNtTransact, which
185 197 * set delete-on-close on the ofile and defer setting the flag on the
186 198 * node until the file is closed.
187 199 *
188 200 * Observation of Windows 2000 indicates the following:
189 201 *
190 202 * 1) If a file is not opened with delete-on-close create options and
191 203 * the delete-on-close is set via Trans2SetFileInfo(SetDispositionInfo)
192 204 * using that open file handle, any subsequent open requests will fail
193 205 * with DELETE_PENDING.
194 206 *
195 207 * 2) If a file is opened with delete-on-close create options and the
196 208 * client attempts to unset delete-on-close via Trans2SetFileInfo
197 209 * (SetDispositionInfo) prior to the file close, any subsequent open
198 210 * requests will still fail with DELETE_PENDING after the file is closed.
199 211 *
200 212 * 3) If a file is opened with delete-on-close create options and that
201 213 * file handle (not the last open handle and the only file handle
202 214 * with delete-on-close set) is closed. Any subsequent open requests
203 215 * will fail with DELETE_PENDING. Unsetting delete-on-close via
|
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
204 216 * Trans2SetFileInfo(SetDispositionInfo) at this time will unset the
205 217 * node delete-on-close flag, which will result in the file not being
206 218 * removed even after the last file handle is closed.
207 219 */
208 220 uint32_t
209 221 smb_set_disposition_info(smb_request_t *sr, smb_setinfo_t *si)
210 222 {
211 223 smb_node_t *node = si->si_node;
212 224 smb_ofile_t *of = sr->fid_ofile;
213 225 uint8_t mark_delete;
226 + uint32_t status;
214 227 uint32_t flags = 0;
215 228
216 229 if (smb_mbc_decodef(&si->si_data, "b", &mark_delete) != 0)
217 230 return (NT_STATUS_INFO_LENGTH_MISMATCH);
218 231
219 232 if ((of == NULL) || !(smb_ofile_granted_access(of) & DELETE))
220 233 return (NT_STATUS_ACCESS_DENIED);
221 234
222 - if (mark_delete) {
223 - if (SMB_TREE_SUPPORTS_CATIA(sr))
224 - flags |= SMB_CATIA;
225 - return (smb_node_set_delete_on_close(node, of->f_cr, flags));
226 - } else {
235 + if (mark_delete == 0) {
227 236 smb_node_reset_delete_on_close(node);
237 + return (NT_STATUS_SUCCESS);
228 238 }
229 239
230 - return (NT_STATUS_SUCCESS);
240 + /*
241 + * Break any oplock handle caching.
242 + */
243 + status = smb_oplock_break_SETINFO(node, of,
244 + FileDispositionInformation);
245 + if (status == NT_STATUS_OPLOCK_BREAK_IN_PROGRESS) {
246 + if (sr->session->dialect >= SMB_VERS_2_BASE)
247 + (void) smb2sr_go_async(sr);
248 + (void) smb_oplock_wait_break(node, 0);
249 + status = 0;
250 + }
251 + if (status != 0)
252 + return (status);
253 +
254 + if (SMB_TREE_SUPPORTS_CATIA(sr))
255 + flags |= SMB_CATIA;
256 +
257 + return (smb_node_set_delete_on_close(node, of->f_cr, flags));
231 258 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX