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>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-5844 want SMB2 ioctl FSCTL_SRV_COPYCHUNK
NEX-6124 smb_fsop_read/write should allow file != sr->fid_ofile
NEX-6125 smbtorture invalid response with smb2.ioctl
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@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>
NEX-2370 unable to save/modify files (zip,notepad,excel) on CIFS share from Windows 7
NEX-2039 Codenomicon failure in smb_write
re #7815 SMB server delivers old modification time...
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_write.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_write.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 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 #include <sys/sdt.h>
28 28 #include <smbsrv/smb_kproto.h>
29 29 #include <smbsrv/smb_fsops.h>
30 30 #include <smbsrv/netbios.h>
31 31
32 32
33 33 static int smb_write_truncate(smb_request_t *, smb_rw_param_t *);
34 34
35 35
36 36 /*
37 37 * Write count bytes at the specified offset in a file. The offset is
38 38 * limited to 32-bits. If the count is zero, the file is truncated to
39 39 * the length specified by the offset.
40 40 *
41 41 * The response count indicates the actual number of bytes written, which
42 42 * will equal the requested count on success. If request and response
43 43 * counts differ but there is no error, the client will assume that the
44 44 * server encountered a resource issue.
45 45 */
46 46 smb_sdrc_t
47 47 smb_pre_write(smb_request_t *sr)
48 48 {
49 49 smb_rw_param_t *param;
50 50 uint32_t off;
51 51 uint16_t count;
52 52 int rc;
53 53
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
54 54 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
55 55 sr->arg.rw = param;
56 56 param->rw_magic = SMB_RW_MAGIC;
57 57
58 58 rc = smbsr_decode_vwv(sr, "wwl", &sr->smb_fid, &count, &off);
59 59
60 60 param->rw_count = (uint32_t)count;
61 61 param->rw_offset = (uint64_t)off;
62 62 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
63 63
64 - DTRACE_SMB_2(op__Write__start, smb_request_t *, sr,
65 - smb_rw_param_t *, param);
64 + DTRACE_SMB_START(op__Write, smb_request_t *, sr); /* arg.rw */
66 65
67 66 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
68 67 }
69 68
70 69 void
71 70 smb_post_write(smb_request_t *sr)
72 71 {
73 - DTRACE_SMB_2(op__Write__done, smb_request_t *, sr,
74 - smb_rw_param_t *, sr->arg.rw);
72 + DTRACE_SMB_DONE(op__Write, smb_request_t *, sr); /* arg.rw */
75 73
76 74 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
77 75 }
78 76
79 77 smb_sdrc_t
80 78 smb_com_write(smb_request_t *sr)
81 79 {
82 80 smb_rw_param_t *param = sr->arg.rw;
83 81 int rc;
84 82
85 83 smbsr_lookup_file(sr);
86 84 if (sr->fid_ofile == NULL) {
87 85 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
88 86 return (SDRC_ERROR);
89 87 }
90 88
91 89 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
92 90
93 91 if (param->rw_count == 0) {
94 92 rc = smb_write_truncate(sr, param);
95 93 } else {
96 94 rc = smbsr_decode_data(sr, "D", ¶m->rw_vdb);
97 95
98 96 if ((rc != 0) || (param->rw_vdb.vdb_len != param->rw_count)) {
99 97 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
100 98 ERRDOS, ERROR_INVALID_PARAMETER);
101 99 return (SDRC_ERROR);
102 100 }
103 101
104 102 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
105 103
106 104 rc = smb_common_write(sr, param);
107 105 }
108 106
109 107 if (rc != 0) {
110 108 if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
111 109 smbsr_errno(sr, rc);
112 110 return (SDRC_ERROR);
113 111 }
114 112
115 113 rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
116 114 (uint16_t)param->rw_count, 0);
117 115 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
118 116 }
119 117
120 118 /*
121 119 * Write count bytes to a file and then close the file. This function
122 120 * can only be used to write to 32-bit offsets and the client must set
123 121 * WordCount (6 or 12) correctly in order to locate the data to be
124 122 * written. If an error occurs on the write, the file should still be
125 123 * closed. If Count is 0, the file is truncated (or extended) to offset.
126 124 *
127 125 * If the last_write time is non-zero, last_write should be used to set
128 126 * the mtime. Otherwise the file system stamps the mtime. Failure to
129 127 * set mtime should not result in an error response.
130 128 */
131 129 smb_sdrc_t
132 130 smb_pre_write_and_close(smb_request_t *sr)
133 131 {
134 132 smb_rw_param_t *param;
135 133 uint32_t off;
136 134 uint16_t count;
137 135 int rc;
138 136
139 137 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
140 138 sr->arg.rw = param;
141 139 param->rw_magic = SMB_RW_MAGIC;
142 140
143 141 if (sr->smb_wct == 12) {
|
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
144 142 rc = smbsr_decode_vwv(sr, "wwll12.", &sr->smb_fid,
145 143 &count, &off, ¶m->rw_last_write);
146 144 } else {
147 145 rc = smbsr_decode_vwv(sr, "wwll", &sr->smb_fid,
148 146 &count, &off, ¶m->rw_last_write);
149 147 }
150 148
151 149 param->rw_count = (uint32_t)count;
152 150 param->rw_offset = (uint64_t)off;
153 151
154 - DTRACE_SMB_2(op__WriteAndClose__start, smb_request_t *, sr,
155 - smb_rw_param_t *, param);
152 + DTRACE_SMB_START(op__WriteAndClose, smb_request_t *, sr); /* arg.rw */
156 153
157 154 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
158 155 }
159 156
160 157 void
161 158 smb_post_write_and_close(smb_request_t *sr)
162 159 {
163 - DTRACE_SMB_2(op__WriteAndClose__done, smb_request_t *, sr,
164 - smb_rw_param_t *, sr->arg.rw);
160 + DTRACE_SMB_DONE(op__WriteAndClose, smb_request_t *, sr); /* arg.rw */
165 161
166 162 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
167 163 }
168 164
169 165 smb_sdrc_t
170 166 smb_com_write_and_close(smb_request_t *sr)
171 167 {
172 168 smb_rw_param_t *param = sr->arg.rw;
173 169 uint16_t count;
174 170 int rc = 0;
175 171
176 172 smbsr_lookup_file(sr);
177 173 if (sr->fid_ofile == NULL) {
178 174 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
179 175 return (SDRC_ERROR);
180 176 }
181 177
182 178 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
183 179
184 180 if (param->rw_count == 0) {
185 181 rc = smb_write_truncate(sr, param);
186 182 } else {
187 183 /*
188 184 * There may be a bug here: should this be "3.#B"?
189 185 */
190 186 rc = smbsr_decode_data(sr, ".#B", param->rw_count,
191 187 ¶m->rw_vdb);
192 188
193 189 if ((rc != 0) || (param->rw_vdb.vdb_len != param->rw_count)) {
194 190 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
195 191 ERRDOS, ERROR_INVALID_PARAMETER);
196 192 return (SDRC_ERROR);
197 193 }
198 194
199 195 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
200 196
201 197 rc = smb_common_write(sr, param);
202 198 }
203 199
204 200 if (rc != 0) {
205 201 if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
206 202 smbsr_errno(sr, rc);
207 203 return (SDRC_ERROR);
208 204 }
209 205
210 206 smb_ofile_close(sr->fid_ofile, param->rw_last_write);
211 207
212 208 count = (uint16_t)param->rw_count;
213 209 rc = smbsr_encode_result(sr, 1, 0, "bww", 1, count, 0);
214 210 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
215 211 }
216 212
217 213 /*
218 214 * Write count bytes to a file at the specified offset and then unlock
219 215 * them. Write behind is safe because the client should have the range
220 216 * locked and this request is allowed to extend the file - note that
221 217 * offset is limited to 32-bits.
222 218 *
223 219 * Spec advice: it is an error for count to be zero. For compatibility,
224 220 * we take no action and return success.
225 221 *
226 222 * The SmbLockAndRead/SmbWriteAndUnlock sub-dialect is only valid on disk
227 223 * files. Reject any attempt to use it on other shares.
228 224 *
229 225 * The response count indicates the actual number of bytes written, which
230 226 * will equal the requested count on success. If request and response
231 227 * counts differ but there is no error, the client will assume that the
232 228 * server encountered a resource issue.
233 229 */
234 230 smb_sdrc_t
235 231 smb_pre_write_and_unlock(smb_request_t *sr)
236 232 {
237 233 smb_rw_param_t *param;
238 234 uint32_t off;
239 235 uint16_t count;
240 236 uint16_t remcnt;
241 237 int rc;
|
↓ open down ↓ |
67 lines elided |
↑ open up ↑ |
242 238
243 239 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
244 240 sr->arg.rw = param;
245 241 param->rw_magic = SMB_RW_MAGIC;
246 242
247 243 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid, &count, &off, &remcnt);
248 244
249 245 param->rw_count = (uint32_t)count;
250 246 param->rw_offset = (uint64_t)off;
251 247
252 - DTRACE_SMB_2(op__WriteAndUnlock__start, smb_request_t *, sr,
253 - smb_rw_param_t *, param);
248 + DTRACE_SMB_START(op__WriteAndUnlock, smb_request_t *, sr); /* arg.rw */
254 249
255 250 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
256 251 }
257 252
258 253 void
259 254 smb_post_write_and_unlock(smb_request_t *sr)
260 255 {
261 - DTRACE_SMB_2(op__WriteAndUnlock__done, smb_request_t *, sr,
262 - smb_rw_param_t *, sr->arg.rw);
256 + DTRACE_SMB_DONE(op__WriteAndUnlock, smb_request_t *, sr); /* arg.rw */
263 257
264 258 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
265 259 }
266 260
267 261 smb_sdrc_t
268 262 smb_com_write_and_unlock(smb_request_t *sr)
269 263 {
270 264 smb_rw_param_t *param = sr->arg.rw;
265 + uint32_t lk_pid;
271 266 uint32_t status;
272 267 int rc = 0;
273 268
274 269 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
275 270 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
276 271 return (SDRC_ERROR);
277 272 }
278 273
279 274 smbsr_lookup_file(sr);
280 275 if (sr->fid_ofile == NULL) {
281 276 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
282 277 return (SDRC_ERROR);
283 278 }
284 279
285 280 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
286 281
287 282 if (param->rw_count == 0) {
288 283 rc = smbsr_encode_result(sr, 1, 0, "bww", 1, 0, 0);
289 284 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
290 285 }
291 286
292 287
293 288 rc = smbsr_decode_data(sr, "D", ¶m->rw_vdb);
294 289
295 290 if ((rc != 0) || (param->rw_count != param->rw_vdb.vdb_len)) {
296 291 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
297 292 ERRDOS, ERROR_INVALID_PARAMETER);
298 293 return (SDRC_ERROR);
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
299 294 }
300 295
301 296 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
302 297
303 298 if ((rc = smb_common_write(sr, param)) != 0) {
304 299 if (sr->smb_error.status != NT_STATUS_FILE_LOCK_CONFLICT)
305 300 smbsr_errno(sr, rc);
306 301 return (SDRC_ERROR);
307 302 }
308 303
309 - status = smb_unlock_range(sr, sr->fid_ofile->f_node, param->rw_offset,
310 - (uint64_t)param->rw_count);
304 +
305 + /* Note: SMB1 locking uses 16-bit PIDs. */
306 + lk_pid = sr->smb_pid & 0xFFFF;
307 +
308 + status = smb_unlock_range(sr, param->rw_offset,
309 + (uint64_t)param->rw_count, lk_pid);
311 310 if (status != NT_STATUS_SUCCESS) {
312 311 smbsr_error(sr, NT_STATUS_RANGE_NOT_LOCKED,
313 312 ERRDOS, ERROR_NOT_LOCKED);
314 313 return (SDRC_ERROR);
315 314 }
316 315
317 316 rc = smbsr_encode_result(sr, 1, 0, "bww", 1,
318 317 (uint16_t)param->rw_count, 0);
319 318 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
320 319 }
321 320
322 321 /*
322 + * The SMB_COM_WRITE_RAW protocol was a negotiated option introduced in
323 + * SMB Core Plus to maximize performance when writing a large block
324 + * of data to a server. It's obsolete and no longer supported.
325 + *
326 + * We keep a handler for it so the dtrace provider can see if
327 + * the client tried to use this command.
328 + */
329 +smb_sdrc_t
330 +smb_pre_write_raw(smb_request_t *sr)
331 +{
332 + DTRACE_SMB_START(op__WriteRaw, smb_request_t *, sr);
333 + return (SDRC_SUCCESS);
334 +}
335 +
336 +void
337 +smb_post_write_raw(smb_request_t *sr)
338 +{
339 + DTRACE_SMB_DONE(op__WriteRaw, smb_request_t *, sr);
340 +}
341 +
342 +smb_sdrc_t
343 +smb_com_write_raw(struct smb_request *sr)
344 +{
345 + smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
346 + ERROR_NOT_SUPPORTED);
347 + return (SDRC_ERROR);
348 +}
349 +
350 +/*
323 351 * Write bytes to a file (SMB Core). This request was extended in
324 352 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
325 353 * 14, instead of 12, and including additional offset information.
326 354 *
327 355 * A ByteCount of 0 does not truncate the file - use SMB_COM_WRITE
328 356 * to truncate a file. A zero length merely transfers zero bytes.
329 357 *
330 358 * If bit 0 of WriteMode is set, Fid must refer to a disk file and
331 359 * the data must be on stable storage before responding.
332 360 *
333 361 * MS-SMB 3.3.5.8 update to LM 0.12 4.2.5:
334 362 * If CAP_LARGE_WRITEX is set, the byte count may be larger than the
335 363 * negotiated buffer size and the server is expected to write the
336 364 * number of bytes specified.
337 365 */
338 366 smb_sdrc_t
339 367 smb_pre_write_andx(smb_request_t *sr)
340 368 {
341 369 smb_rw_param_t *param;
342 370 uint32_t off_low;
343 371 uint32_t off_high;
344 372 uint16_t datalen_low;
345 373 uint16_t datalen_high;
346 374 uint16_t remcnt;
347 375 int rc;
348 376
349 377 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
350 378 sr->arg.rw = param;
351 379 param->rw_magic = SMB_RW_MAGIC;
352 380
353 381 if (sr->smb_wct == 14) {
354 382 rc = smbsr_decode_vwv(sr, "4.wl4.wwwwwl", &sr->smb_fid,
355 383 &off_low, ¶m->rw_mode, &remcnt, &datalen_high,
356 384 &datalen_low, ¶m->rw_dsoff, &off_high);
357 385
358 386 if (param->rw_dsoff >= 63)
359 387 param->rw_dsoff -= 63;
360 388 param->rw_offset = ((uint64_t)off_high << 32) | off_low;
361 389 } else if (sr->smb_wct == 12) {
362 390 rc = smbsr_decode_vwv(sr, "4.wl4.wwwww", &sr->smb_fid,
363 391 &off_low, ¶m->rw_mode, &remcnt, &datalen_high,
364 392 &datalen_low, ¶m->rw_dsoff);
365 393
366 394 if (param->rw_dsoff >= 59)
367 395 param->rw_dsoff -= 59;
368 396 param->rw_offset = (uint64_t)off_low;
369 397 /* off_high not present */
370 398 } else {
371 399 rc = -1;
372 400 }
373 401
374 402 param->rw_count = (uint32_t)datalen_low;
|
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
375 403
376 404 /*
377 405 * Work-around a Win7 bug, where it fails to set the
378 406 * CAP_LARGE_WRITEX flag during session setup. Assume
379 407 * a large write if the data remaining is >= 64k.
380 408 */
381 409 if ((sr->session->capabilities & CAP_LARGE_WRITEX) != 0 ||
382 410 (sr->smb_data.max_bytes > (sr->smb_data.chain_offset + 0xFFFF)))
383 411 param->rw_count |= ((uint32_t)datalen_high << 16);
384 412
385 - DTRACE_SMB_2(op__WriteX__start, smb_request_t *, sr,
386 - smb_rw_param_t *, param);
413 + DTRACE_SMB_START(op__WriteX, smb_request_t *, sr); /* arg.rw */
387 414
388 415 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
389 416 }
390 417
391 418 void
392 419 smb_post_write_andx(smb_request_t *sr)
393 420 {
394 - DTRACE_SMB_2(op__WriteX__done, smb_request_t *, sr,
395 - smb_rw_param_t *, sr->arg.rw);
421 + DTRACE_SMB_DONE(op__WriteX, smb_request_t *, sr); /* arg.rw */
396 422
397 423 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
398 424 }
399 425
400 426 smb_sdrc_t
401 427 smb_com_write_andx(smb_request_t *sr)
402 428 {
403 429 smb_rw_param_t *param = sr->arg.rw;
404 430 uint16_t count_high;
405 431 uint16_t count_low;
406 432 int rc;
407 433
408 434 ASSERT(param);
409 435 ASSERT(param->rw_magic == SMB_RW_MAGIC);
410 436
411 437 smbsr_lookup_file(sr);
412 438 if (sr->fid_ofile == NULL) {
413 439 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
414 440 return (SDRC_ERROR);
415 441 }
416 442
417 443 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
418 444
419 445 if (SMB_WRMODE_IS_STABLE(param->rw_mode) &&
420 446 STYPE_ISIPC(sr->tid_tree->t_res_type)) {
421 447 smbsr_error(sr, 0, ERRSRV, ERRaccess);
422 448 return (SDRC_ERROR);
423 449 }
424 450
425 451 rc = smbsr_decode_data(sr, "#.#B", param->rw_dsoff, param->rw_count,
426 452 ¶m->rw_vdb);
427 453
428 454 if ((rc != 0) || (param->rw_vdb.vdb_len != param->rw_count)) {
429 455 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
430 456 ERRDOS, ERROR_INVALID_PARAMETER);
431 457 return (SDRC_ERROR);
432 458 }
433 459
434 460 param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset;
435 461
436 462 if (param->rw_count != 0) {
437 463 if ((rc = smb_common_write(sr, param)) != 0) {
438 464 if (sr->smb_error.status !=
439 465 NT_STATUS_FILE_LOCK_CONFLICT)
440 466 smbsr_errno(sr, rc);
441 467 return (SDRC_ERROR);
442 468 }
443 469 }
444 470
445 471 count_low = param->rw_count & 0xFFFF;
446 472 count_high = (param->rw_count >> 16) & 0xFF;
447 473
448 474 rc = smbsr_encode_result(sr, 6, 0, "bb1.wwwwww",
449 475 6, sr->andx_com, 15, count_low, 0, count_high, 0, 0);
450 476
451 477 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
452 478 }
453 479
454 480 /*
455 481 * Common function for writing files or IPC/MSRPC named pipes.
456 482 *
457 483 * Returns errno values.
458 484 */
459 485 int
460 486 smb_common_write(smb_request_t *sr, smb_rw_param_t *param)
461 487 {
462 488 smb_ofile_t *ofile = sr->fid_ofile;
463 489 smb_node_t *node;
464 490 int stability = 0;
465 491 uint32_t lcount;
466 492 int rc = 0;
467 493
468 494 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
469 495 case STYPE_DISKTREE:
470 496 case STYPE_PRINTQ:
471 497 node = ofile->f_node;
472 498
473 499 if (!smb_node_is_dir(node)) {
474 500 rc = smb_lock_range_access(sr, node, param->rw_offset,
475 501 param->rw_count, B_TRUE);
476 502 if (rc != NT_STATUS_SUCCESS) {
477 503 smbsr_error(sr, NT_STATUS_FILE_LOCK_CONFLICT,
|
↓ open down ↓ |
72 lines elided |
↑ open up ↑ |
478 504 ERRDOS, ERROR_LOCK_VIOLATION);
479 505 return (EACCES);
480 506 }
481 507 }
482 508
483 509 if (SMB_WRMODE_IS_STABLE(param->rw_mode) ||
484 510 (node->flags & NODE_FLAGS_WRITE_THROUGH)) {
485 511 stability = FSYNC;
486 512 }
487 513
488 - rc = smb_fsop_write(sr, sr->user_cr, node,
514 + rc = smb_fsop_write(sr, sr->user_cr, node, ofile,
489 515 ¶m->rw_vdb.vdb_uio, &lcount, stability);
490 516
491 517 if (rc)
492 518 return (rc);
493 519
494 520 /*
495 521 * Used to have code here to set mtime.
496 522 * We have just done a write, so we know
497 523 * the file system will update mtime.
498 524 * No need to do it again here.
499 525 *
500 526 * However, keep track of the fact that
501 527 * we have written data via this handle.
502 528 */
503 529 ofile->f_written = B_TRUE;
504 530
505 - if (!smb_node_is_dir(node))
506 - smb_oplock_break_levelII(node);
531 + /* This revokes read cache delegations. */
532 + (void) smb_oplock_break_WRITE(node, ofile);
507 533
508 534 param->rw_count = lcount;
509 535 break;
510 536
511 537 case STYPE_IPC:
512 538 param->rw_count = param->rw_vdb.vdb_uio.uio_resid;
513 539
514 540 if ((rc = smb_opipe_write(sr, ¶m->rw_vdb.vdb_uio)) != 0)
515 541 param->rw_count = 0;
516 542 break;
517 543
518 544 default:
519 545 rc = EACCES;
520 546 break;
521 547 }
522 548
523 549 if (rc != 0)
524 550 return (rc);
525 551
526 552 mutex_enter(&ofile->f_mutex);
527 553 ofile->f_seek_pos = param->rw_offset + param->rw_count;
528 554 mutex_exit(&ofile->f_mutex);
529 555 return (rc);
530 556 }
531 557
532 558 /*
533 559 * Truncate a disk file to the specified offset.
534 560 * Typically, w_count will be zero here.
535 561 *
536 562 * Note that smb_write_andx cannot be used to reduce the file size so,
537 563 * if this is required, smb_write is called with a count of zero and
538 564 * the appropriate file length in offset. The file should be resized
539 565 * to the length specified by the offset.
540 566 *
541 567 * Returns errno values.
542 568 */
543 569 static int
544 570 smb_write_truncate(smb_request_t *sr, smb_rw_param_t *param)
545 571 {
546 572 smb_ofile_t *ofile = sr->fid_ofile;
547 573 smb_node_t *node = ofile->f_node;
548 574 smb_attr_t attr;
549 575 uint32_t status;
550 576 int rc;
551 577
552 578 if (STYPE_ISIPC(sr->tid_tree->t_res_type))
553 579 return (0);
554 580
555 581 mutex_enter(&node->n_mutex);
556 582 if (!smb_node_is_dir(node)) {
557 583 status = smb_lock_range_access(sr, node, param->rw_offset,
558 584 param->rw_count, B_TRUE);
559 585 if (status != NT_STATUS_SUCCESS) {
560 586 mutex_exit(&node->n_mutex);
561 587 smbsr_error(sr, NT_STATUS_FILE_LOCK_CONFLICT,
562 588 ERRDOS, ERROR_LOCK_VIOLATION);
563 589 return (EACCES);
564 590 }
565 591 }
566 592 mutex_exit(&node->n_mutex);
567 593
568 594 bzero(&attr, sizeof (smb_attr_t));
569 595 attr.sa_mask = SMB_AT_SIZE;
570 596 attr.sa_vattr.va_size = param->rw_offset;
571 597 rc = smb_node_setattr(sr, node, sr->user_cr, ofile, &attr);
572 598 if (rc != 0)
573 599 return (rc);
574 600
575 601 mutex_enter(&ofile->f_mutex);
576 602 ofile->f_seek_pos = param->rw_offset + param->rw_count;
577 603 mutex_exit(&ofile->f_mutex);
578 604 return (0);
579 605 }
|
↓ open down ↓ |
63 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX