Print this page
NEX-17289 Minimal SMB 3.0.2 support
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@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-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-3662 Backport illumos 1501: taskq_create_proc ... TQ_DYNAMIC puts tasks in p0 (take 2)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Marcel Telka <marcel.telka@nexenta.com>
NEX-3576 RPC error when displaying open files via Windows MMC
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-2188 Browsing top level share produces RPC error 1728
SMB-69 read-raw, write-raw are dead code
SMB-39 Use AF_UNIX pipes for RPC
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_read.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_read.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 2015 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <smbsrv/smb_kproto.h>
27 27 #include <smbsrv/smb_fsops.h>
28 28
29 29 /*
30 30 * The maximum number of bytes to return from SMB Core
31 31 * SmbRead or SmbLockAndRead.
32 32 */
33 33 #define SMB_CORE_READ_MAX 4432
34 34
35 35 /*
36 36 * The limit in bytes for SmbReadX.
37 37 */
38 38 #define SMB_READX_MAX 0x10000
39 39
40 40 int smb_common_read(smb_request_t *, smb_rw_param_t *);
41 41
42 42 /*
43 43 * Read bytes from a file or named pipe (SMB Core).
44 44 *
45 45 * The requested count specifies the number of bytes desired. Offset
46 46 * is limited to 32 bits, so this client request is inappropriate for
47 47 * files with 64 bit offsets.
48 48 *
49 49 * On return, count is the number of bytes actually being returned, which
50 50 * may be less than the count requested only if a read specifies bytes
51 51 * beyond the current file size. In this case only the bytes that exist
52 52 * are returned. A read completely beyond the end of file results in a
53 53 * response of length zero. This is the only circumstance when a zero
54 54 * length response is generated. A count returned which is less than the
55 55 * count requested is the end of file indicator.
56 56 */
57 57 smb_sdrc_t
58 58 smb_pre_read(smb_request_t *sr)
59 59 {
60 60 smb_rw_param_t *param;
61 61 uint32_t off_low;
62 62 uint16_t count;
63 63 uint16_t remcnt;
64 64 int rc;
65 65
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
66 66 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
67 67 sr->arg.rw = param;
68 68
69 69 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
70 70 &count, &off_low, &remcnt);
71 71
72 72 param->rw_offset = (uint64_t)off_low;
73 73 param->rw_count = (uint32_t)count;
74 74 param->rw_mincnt = 0;
75 75
76 - DTRACE_SMB_2(op__Read__start, smb_request_t *, sr,
77 - smb_rw_param_t *, param);
76 + DTRACE_SMB_START(op__Read, smb_request_t *, sr); /* arg.rw */
78 77
79 78 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
80 79 }
81 80
82 81 void
83 82 smb_post_read(smb_request_t *sr)
84 83 {
85 - DTRACE_SMB_2(op__Read__done, smb_request_t *, sr,
86 - smb_rw_param_t *, sr->arg.rw);
84 + DTRACE_SMB_DONE(op__Read, smb_request_t *, sr); /* arg.rw */
87 85
88 86 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
89 87 }
90 88
91 89 smb_sdrc_t
92 90 smb_com_read(smb_request_t *sr)
93 91 {
94 92 smb_rw_param_t *param = sr->arg.rw;
95 93 uint16_t count;
96 94 int rc;
97 95
98 96 smbsr_lookup_file(sr);
99 97 if (sr->fid_ofile == NULL) {
100 98 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
101 99 return (SDRC_ERROR);
102 100 }
103 101
104 102 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
105 103
106 104 if (param->rw_count > SMB_CORE_READ_MAX)
107 105 param->rw_count = SMB_CORE_READ_MAX;
108 106
109 107 if ((rc = smb_common_read(sr, param)) != 0) {
110 108 smbsr_errno(sr, rc);
111 109 return (SDRC_ERROR);
112 110 }
113 111
114 112 count = (uint16_t)param->rw_count;
115 113 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
116 114 5, count, VAR_BCC, 0x01, count, &sr->raw_data);
117 115
118 116 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
119 117 }
120 118
121 119 /*
122 120 * Lock and read bytes from a file (SMB Core Plus). The SmbLockAndRead/
123 121 * SmbLockAndWrite sub-dialect is only valid on disk files: reject any
124 122 * attempt to use it on non-disk shares.
125 123 *
126 124 * The requested count specifies the number of bytes desired. Offset
127 125 * specifies the offset in the file of the first byte to be locked then
128 126 * read. Note that offset is limited to 32 bits, so this client request
129 127 * is inappropriate for files with 64 bit offsets.
130 128 *
131 129 * As with SMB_LOCK_BYTE_RANGE request, if the lock cannot be granted
132 130 * immediately an error should be returned to the client. If an error
133 131 * occurs on the lock, the bytes should not be read.
134 132 *
135 133 * On return, count is the number of bytes actually being returned, which
136 134 * may be less than the count requested only if a read specifies bytes
137 135 * beyond the current file size. In this case only the bytes that exist
138 136 * are returned. A read completely beyond the end of file results in a
139 137 * response of length zero. This is the only circumstance when a zero
140 138 * length response is generated. A count returned which is less than the
141 139 * count requested is the end of file indicator.
142 140 */
143 141 smb_sdrc_t
144 142 smb_pre_lock_and_read(smb_request_t *sr)
145 143 {
146 144 smb_rw_param_t *param;
147 145 uint32_t off_low;
148 146 uint16_t count;
149 147 uint16_t remcnt;
150 148 int rc;
151 149
|
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
152 150 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
153 151 sr->arg.rw = param;
154 152
155 153 rc = smbsr_decode_vwv(sr, "wwlw", &sr->smb_fid,
156 154 &count, &off_low, &remcnt);
157 155
158 156 param->rw_offset = (uint64_t)off_low;
159 157 param->rw_count = (uint32_t)count;
160 158 param->rw_mincnt = 0;
161 159
162 - DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr,
163 - smb_rw_param_t *, param);
160 + DTRACE_SMB_START(op__LockAndRead, smb_request_t *, sr); /* arg.rw */
164 161
165 162 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
166 163 }
167 164
168 165 void
169 166 smb_post_lock_and_read(smb_request_t *sr)
170 167 {
171 - DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr,
172 - smb_rw_param_t *, sr->arg.rw);
168 + DTRACE_SMB_DONE(op__LockAndRead, smb_request_t *, sr); /* arg.rw */
173 169
174 170 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
175 171 }
176 172
177 173 smb_sdrc_t
178 174 smb_com_lock_and_read(smb_request_t *sr)
179 175 {
180 176 smb_rw_param_t *param = sr->arg.rw;
181 177 DWORD status;
178 + uint32_t lk_pid;
182 179 uint16_t count;
183 180 int rc;
184 181
185 182 if (STYPE_ISDSK(sr->tid_tree->t_res_type) == 0) {
186 183 smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERRnoaccess);
187 184 return (SDRC_ERROR);
188 185 }
189 186
190 187 smbsr_lookup_file(sr);
191 188 if (sr->fid_ofile == NULL) {
192 189 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
193 190 return (SDRC_ERROR);
194 191 }
195 192
196 193 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
197 194
195 + /* Note: SMB1 locking uses 16-bit PIDs. */
196 + lk_pid = sr->smb_pid & 0xFFFF;
197 +
198 198 status = smb_lock_range(sr, param->rw_offset, (uint64_t)param->rw_count,
199 - 0, SMB_LOCK_TYPE_READWRITE);
199 + lk_pid, SMB_LOCK_TYPE_READWRITE, 0);
200 200
201 201 if (status != NT_STATUS_SUCCESS) {
202 202 smb_lock_range_error(sr, status);
203 203 return (SDRC_ERROR);
204 204 }
205 205
206 206 if (param->rw_count > SMB_CORE_READ_MAX)
207 207 param->rw_count = SMB_CORE_READ_MAX;
208 208
209 209 if ((rc = smb_common_read(sr, param)) != 0) {
210 210 smbsr_errno(sr, rc);
211 211 return (SDRC_ERROR);
|
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
212 212 }
213 213
214 214 count = (uint16_t)param->rw_count;
215 215 rc = smbsr_encode_result(sr, 5, VAR_BCC, "bw8.wbwC",
216 216 5, count, VAR_BCC, 0x1, count, &sr->raw_data);
217 217
218 218 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
219 219 }
220 220
221 221 /*
222 + * The SMB_COM_READ_RAW protocol was a negotiated option introduced in
223 + * SMB Core Plus to maximize performance when reading a large block
224 + * of data from a server. It's obsolete and no longer supported.
225 + *
226 + * We keep a handler for it so the dtrace provider can see if
227 + * the client tried to use this command.
228 + */
229 +smb_sdrc_t
230 +smb_pre_read_raw(smb_request_t *sr)
231 +{
232 + DTRACE_SMB_START(op__ReadRaw, smb_request_t *, sr);
233 + return (SDRC_SUCCESS);
234 +}
235 +
236 +void
237 +smb_post_read_raw(smb_request_t *sr)
238 +{
239 + DTRACE_SMB_DONE(op__ReadRaw, smb_request_t *, sr);
240 +}
241 +
242 +smb_sdrc_t
243 +smb_com_read_raw(smb_request_t *sr)
244 +{
245 + smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS,
246 + ERROR_NOT_SUPPORTED);
247 + return (SDRC_ERROR);
248 +}
249 +
250 +/*
222 251 * Read bytes from a file (SMB Core). This request was extended in
223 252 * LM 0.12 to support 64-bit offsets, indicated by sending a wct of
224 253 * 12 and including additional offset information.
225 254 *
226 255 * MS-SMB 3.3.5.7 update to LM 0.12 4.2.4:
227 256 * If wct is 12 and CAP_LARGE_READX is set, the count may be larger
228 257 * than the negotiated buffer size. If maxcnt_high is 0xFF, it must
229 258 * be ignored. Otherwise, maxcnt_high represents the upper 16 bits
230 259 * of rw_count.
231 260 */
232 261 smb_sdrc_t
233 262 smb_pre_read_andx(smb_request_t *sr)
234 263 {
235 264 smb_rw_param_t *param;
236 265 uint32_t off_low;
237 266 uint32_t off_high;
238 267 uint32_t maxcnt_high;
239 268 uint16_t maxcnt_low;
240 269 uint16_t mincnt;
241 270 uint16_t remcnt;
242 271 int rc;
243 272
244 273 param = kmem_zalloc(sizeof (smb_rw_param_t), KM_SLEEP);
245 274 sr->arg.rw = param;
246 275
247 276 if (sr->smb_wct == 12) {
248 277 rc = smbsr_decode_vwv(sr, "b3.wlwwlwl", ¶m->rw_andx,
249 278 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
250 279 &remcnt, &off_high);
251 280
252 281 param->rw_offset = ((uint64_t)off_high << 32) |
253 282 (uint64_t)off_low;
254 283
255 284 param->rw_count = (uint32_t)maxcnt_low;
256 285
257 286 if ((sr->session->capabilities & CAP_LARGE_READX) &&
258 287 (maxcnt_high < 0xFF))
259 288 param->rw_count |= maxcnt_high << 16;
260 289 } else {
|
↓ open down ↓ |
29 lines elided |
↑ open up ↑ |
261 290 rc = smbsr_decode_vwv(sr, "b3.wlwwlw", ¶m->rw_andx,
262 291 &sr->smb_fid, &off_low, &maxcnt_low, &mincnt, &maxcnt_high,
263 292 &remcnt);
264 293
265 294 param->rw_offset = (uint64_t)off_low;
266 295 param->rw_count = (uint32_t)maxcnt_low;
267 296 }
268 297
269 298 param->rw_mincnt = 0;
270 299
271 - DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr,
272 - smb_rw_param_t *, param);
300 + DTRACE_SMB_START(op__ReadX, smb_request_t *, sr); /* arg.rw */
273 301
274 302 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
275 303 }
276 304
277 305 void
278 306 smb_post_read_andx(smb_request_t *sr)
279 307 {
280 - DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr,
281 - smb_rw_param_t *, sr->arg.rw);
308 + DTRACE_SMB_DONE(op__ReadX, smb_request_t *, sr); /* arg.rw */
282 309
283 310 kmem_free(sr->arg.rw, sizeof (smb_rw_param_t));
284 311 }
285 312
286 313 smb_sdrc_t
287 314 smb_com_read_andx(smb_request_t *sr)
288 315 {
289 316 smb_rw_param_t *param = sr->arg.rw;
290 317 uint16_t datalen_high;
291 318 uint16_t datalen_low;
292 319 uint16_t data_offset;
293 320 uint16_t offset2;
294 321 int rc;
295 322
296 323 smbsr_lookup_file(sr);
297 324 if (sr->fid_ofile == NULL) {
298 325 smbsr_error(sr, NT_STATUS_INVALID_HANDLE, ERRDOS, ERRbadfid);
299 326 return (SDRC_ERROR);
300 327 }
301 328
302 329 sr->user_cr = smb_ofile_getcred(sr->fid_ofile);
303 330
304 331 if (param->rw_count >= SMB_READX_MAX)
305 332 param->rw_count = 0;
306 333
307 334 if ((rc = smb_common_read(sr, param)) != 0) {
308 335 smbsr_errno(sr, rc);
309 336 return (SDRC_ERROR);
310 337 }
311 338
312 339 datalen_low = param->rw_count & 0xFFFF;
313 340 datalen_high = (param->rw_count >> 16) & 0xFF;
314 341
315 342 /*
316 343 * If this is a secondary command, the data offset
317 344 * includes the previous wct + sizeof(wct).
318 345 */
319 346 data_offset = (sr->andx_prev_wct == 0) ? 0 : sr->andx_prev_wct + 1;
320 347
321 348 if (STYPE_ISIPC(sr->tid_tree->t_res_type)) {
322 349 data_offset += 60;
323 350 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 60;
324 351
325 352 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wbC",
326 353 12, /* wct */
327 354 param->rw_andx, /* secondary andx command */
328 355 offset2, /* offset to next command */
329 356 0, /* set to 0 for named pipes */
330 357 datalen_low, /* data byte count */
331 358 data_offset, /* offset from start to data */
332 359 datalen_high, /* data byte count */
333 360 VAR_BCC, /* BCC marker */
334 361 0x00, /* padding */
335 362 &sr->raw_data);
336 363 } else {
337 364 data_offset += 59;
338 365 offset2 = (param->rw_andx == 0xFF) ? 0 : param->rw_count + 59;
339 366
340 367 rc = smbsr_encode_result(sr, 12, VAR_BCC, "bb1.ww4.www8.wC",
341 368 12, /* wct */
342 369 param->rw_andx, /* secondary andx command */
343 370 offset2, /* offset to next command */
344 371 -1, /* must be -1 for regular files */
345 372 datalen_low, /* data byte count */
346 373 data_offset, /* offset from start to data */
347 374 datalen_high, /* data byte count */
348 375 VAR_BCC, /* BCC marker */
349 376 &sr->raw_data);
350 377 }
|
↓ open down ↓ |
59 lines elided |
↑ open up ↑ |
351 378
352 379 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
353 380 }
354 381
355 382 /*
356 383 * Common function for reading files or IPC/MSRPC named pipes. All
357 384 * protocol read functions should lookup the fid before calling this
358 385 * function. We can't move the fid lookup here because lock-and-read
359 386 * requires the fid to do locking before attempting the read.
360 387 *
361 - * Reading from a file should break oplocks on the file to LEVEL_II.
362 - * A call to smb_oplock_break(SMB_OPLOCK_BREAK_TO_LEVEL_II) is not
363 - * required as it is a no-op. If there's anything greater than a
364 - * LEVEL_II oplock on the file, the oplock MUST be owned by the ofile
365 - * on which the read is occuring and therefore would not be broken.
388 + * Reading from a file does not break oplocks because any need for
389 + * breaking before read is handled in open.
366 390 *
367 391 * Returns errno values.
368 392 */
369 393 int
370 394 smb_common_read(smb_request_t *sr, smb_rw_param_t *param)
371 395 {
372 396 smb_ofile_t *ofile = sr->fid_ofile;
373 397 smb_node_t *node;
374 398 smb_vdb_t *vdb = ¶m->rw_vdb;
375 399 struct mbuf *top;
376 400 int rc;
377 401
378 402 vdb->vdb_tag = 0;
379 403 vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0];
380 404 vdb->vdb_uio.uio_iovcnt = MAX_IOVEC;
381 405 vdb->vdb_uio.uio_resid = param->rw_count;
382 406 vdb->vdb_uio.uio_loffset = (offset_t)param->rw_offset;
383 407 vdb->vdb_uio.uio_segflg = UIO_SYSSPACE;
384 408 vdb->vdb_uio.uio_extflg = UIO_COPY_DEFAULT;
385 409
386 410 switch (sr->tid_tree->t_res_type & STYPE_MASK) {
387 411 case STYPE_DISKTREE:
388 412 node = ofile->f_node;
389 413
390 414 if (!smb_node_is_dir(node)) {
391 415 rc = smb_lock_range_access(sr, node, param->rw_offset,
392 416 param->rw_count, B_FALSE);
393 417 if (rc != NT_STATUS_SUCCESS) {
394 418 rc = ERANGE;
395 419 break;
396 420 }
397 421 }
398 422
399 423 if ((ofile->f_flags & SMB_OFLAGS_EXECONLY) &&
400 424 !(sr->smb_flg2 & SMB_FLAGS2_READ_IF_EXECUTE)) {
401 425 /*
402 426 * SMB_FLAGS2_READ_IF_EXECUTE: permit execute-only
403 427 * reads.
404 428 *
405 429 * Reject request if the file has been opened
|
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
406 430 * execute-only and SMB_FLAGS2_READ_IF_EXECUTE is not
407 431 * set.
408 432 */
409 433 rc = EACCES;
410 434 break;
411 435 }
412 436
413 437 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
414 438 top = smb_mbuf_allocate(&vdb->vdb_uio);
415 439
416 - rc = smb_fsop_read(sr, sr->user_cr, node, &vdb->vdb_uio);
440 + rc = smb_fsop_read(sr, sr->user_cr, node, ofile,
441 + &vdb->vdb_uio, 0);
417 442
418 443 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
419 444 smb_mbuf_trim(top, sr->raw_data.max_bytes);
420 445 MBC_ATTACH_MBUF(&sr->raw_data, top);
421 446 break;
422 447
423 448 case STYPE_IPC:
424 449 sr->raw_data.max_bytes = vdb->vdb_uio.uio_resid;
425 450 top = smb_mbuf_allocate(&vdb->vdb_uio);
426 451
427 452 rc = smb_opipe_read(sr, &vdb->vdb_uio);
428 453
429 454 sr->raw_data.max_bytes -= vdb->vdb_uio.uio_resid;
430 455 smb_mbuf_trim(top, sr->raw_data.max_bytes);
431 456 MBC_ATTACH_MBUF(&sr->raw_data, top);
432 457 break;
433 458
434 459 default:
435 460 rc = EACCES;
436 461 break;
437 462 }
438 463
439 464 param->rw_count -= vdb->vdb_uio.uio_resid;
440 465
441 466 if (rc != 0)
442 467 return (rc);
443 468
444 469 if (param->rw_mincnt != 0 && param->rw_count < param->rw_mincnt) {
445 470 /*
446 471 * mincnt is only used by read-raw and is typically
447 472 * zero. If mincnt is greater than zero and the
448 473 * number of bytes read is less than mincnt, tell
449 474 * the client that we read nothing.
450 475 */
451 476 param->rw_count = 0;
452 477 }
453 478
454 479 param->rw_offset += param->rw_count;
455 480 mutex_enter(&sr->fid_ofile->f_mutex);
456 481 ofile->f_seek_pos = param->rw_offset;
457 482 mutex_exit(&sr->fid_ofile->f_mutex);
458 483 return (rc);
459 484 }
|
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX