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>
SMB-119 Text file contains garbage when re-opened
SMB-120 Share enumeration fails with Windows 8
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_write.c
+++ new/usr/src/uts/common/fs/smbsrv/smb2_write.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 2018 Nexenta Systems, Inc. All rights reserved.
14 14 */
15 15
16 16 /*
17 17 * Dispatch function for SMB2_WRITE
18 18 */
19 19
20 20 #include <smbsrv/smb2_kproto.h>
21 21 #include <smbsrv/smb_fsops.h>
22 22
23 +boolean_t smb_allow_unbuffered = B_TRUE;
24 +
23 25 smb_sdrc_t
24 26 smb2_write(smb_request_t *sr)
25 27 {
26 28 smb_ofile_t *of = NULL;
27 29 smb_vdb_t *vdb = NULL;
28 30 uint16_t StructSize;
29 31 uint16_t DataOff;
30 32 uint32_t Length;
31 33 uint64_t Offset;
32 34 smb2fid_t smb2fid;
33 35 uint32_t Channel;
34 36 uint32_t Remaining;
35 37 uint16_t ChanInfoOffset;
36 38 uint16_t ChanInfoLength;
37 39 uint32_t Flags;
38 40 uint32_t XferCount;
39 41 uint32_t status;
40 42 int data_chain_off, skip;
41 43 int stability = 0;
42 44 int rc = 0;
45 + boolean_t unbuffered = B_FALSE;
43 46
44 47 /*
45 - * SMB2 Write request
48 + * Decode SMB2 Write request
46 49 */
47 50 rc = smb_mbc_decodef(
48 51 &sr->smb_data,
49 52 "wwlqqqllwwl",
50 53 &StructSize, /* w */
51 54 &DataOff, /* w */
52 55 &Length, /* l */
53 56 &Offset, /* q */
54 57 &smb2fid.persistent, /* q */
55 58 &smb2fid.temporal, /* q */
56 59 &Channel, /* l */
57 60 &Remaining, /* l */
58 61 &ChanInfoOffset, /* w */
59 62 &ChanInfoLength, /* w */
60 63 &Flags); /* l */
61 64 if (rc)
62 65 return (SDRC_ERROR);
63 66 if (StructSize != 49)
64 67 return (SDRC_ERROR);
65 68
66 - status = smb2sr_lookup_fid(sr, &smb2fid);
67 - if (status) {
68 - smb2sr_put_error(sr, status);
69 - return (SDRC_SUCCESS);
70 - }
71 - of = sr->fid_ofile;
72 -
73 - if (Length > smb2_max_rwsize) {
74 - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER);
75 - return (SDRC_SUCCESS);
76 - }
77 -
78 69 /*
79 70 * Skip any padding before the write data.
80 71 */
81 72 data_chain_off = sr->smb2_cmd_hdr + DataOff;
82 73 skip = data_chain_off - sr->smb_data.chain_offset;
83 - if (skip < 0) {
84 - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER);
85 - return (SDRC_SUCCESS);
86 - }
87 - if (skip > 0) {
74 + if (skip < 0)
75 + return (SDRC_ERROR);
76 + if (skip > 0)
88 77 (void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
89 - }
90 78
91 - /* This is automatically free'd. */
79 + /*
80 + * Decode the write data (payload)
81 + * This is automatically free'd.
82 + */
83 + if (Length > smb2_max_rwsize)
84 + return (SDRC_ERROR);
92 85 vdb = smb_srm_zalloc(sr, sizeof (*vdb));
93 86 rc = smb_mbc_decodef(&sr->smb_data, "#B", Length, vdb);
94 - if (rc != 0 || vdb->vdb_len != Length) {
95 - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER);
96 - return (SDRC_SUCCESS);
97 - }
87 + if (rc != 0 || vdb->vdb_len != Length)
88 + return (SDRC_ERROR);
98 89 vdb->vdb_uio.uio_loffset = (offset_t)Offset;
99 90
91 + /*
92 + * Want FID lookup before the start probe.
93 + */
94 + status = smb2sr_lookup_fid(sr, &smb2fid);
95 + of = sr->fid_ofile;
96 +
97 + DTRACE_SMB2_START(op__Write, smb_request_t *, sr); /* arg.rw */
98 +
99 + if (status)
100 + goto errout; /* Bad FID */
101 +
102 +
100 103 XferCount = 0;
101 104 if (Length == 0)
102 - goto doreply;
105 + goto errout;
103 106
107 + /*
108 + * Unbuffered refers to the MS-FSA Write argument by the same name.
109 + * It indicates that the cache for this range should be flushed to disk,
110 + * and data written directly to disk, bypassing the cache.
111 + * We don't allow that degree of cache management.
112 + * Translate this directly as FSYNC,
113 + * which should at least flush the cache.
114 + */
115 +
116 + if (smb_allow_unbuffered &&
117 + (Flags & SMB2_WRITEFLAG_WRITE_UNBUFFERED) != 0)
118 + unbuffered = B_TRUE;
119 +
104 120 switch (of->f_tree->t_res_type & STYPE_MASK) {
105 121 case STYPE_DISKTREE:
106 122 case STYPE_PRINTQ:
107 123 if (!smb_node_is_dir(of->f_node)) {
108 124 /* Check for conflicting locks. */
109 125 rc = smb_lock_range_access(sr, of->f_node,
110 126 Offset, Length, B_TRUE);
111 127 if (rc) {
112 128 rc = ERANGE;
113 129 break;
114 130 }
115 131 }
116 - if ((Flags & SMB2_WRITEFLAG_WRITE_THROUGH) ||
117 - (of->f_node->flags & NODE_FLAGS_WRITE_THROUGH)) {
132 +
133 + if (unbuffered || (Flags & SMB2_WRITEFLAG_WRITE_THROUGH) != 0 ||
134 + (of->f_node->flags & NODE_FLAGS_WRITE_THROUGH) != 0) {
118 135 stability = FSYNC;
119 136 }
120 - rc = smb_fsop_write(sr, of->f_cr, of->f_node,
137 + rc = smb_fsop_write(sr, of->f_cr, of->f_node, of,
121 138 &vdb->vdb_uio, &XferCount, stability);
122 139 if (rc)
123 140 break;
124 141 of->f_written = B_TRUE;
125 - if (!smb_node_is_dir(of->f_node))
126 - smb_oplock_break_levelII(of->f_node);
142 + /* This revokes read cache delegations. */
143 + (void) smb_oplock_break_WRITE(of->f_node, of);
127 144 break;
128 145
129 146 case STYPE_IPC:
130 - rc = smb_opipe_write(sr, &vdb->vdb_uio);
147 + if (unbuffered || (Flags & SMB2_WRITEFLAG_WRITE_THROUGH) != 0)
148 + rc = EINVAL;
149 + else
150 + rc = smb_opipe_write(sr, &vdb->vdb_uio);
131 151 if (rc == 0)
132 152 XferCount = Length;
133 153 break;
134 154
135 155 default:
136 156 rc = EACCES;
137 157 break;
138 158 }
159 + status = smb_errno2status(rc);
139 160
140 - if (rc) {
141 - smb2sr_put_errno(sr, rc);
161 +errout:
162 + sr->smb2_status = status;
163 + DTRACE_SMB2_DONE(op__Write, smb_request_t *, sr); /* arg.rw */
164 +
165 + if (status) {
166 + smb2sr_put_error(sr, status);
142 167 return (SDRC_SUCCESS);
143 168 }
144 169
145 170 /*
146 - * SMB2 Write reply
171 + * Encode SMB2 Write reply
147 172 */
148 -doreply:
149 173 DataOff = SMB2_HDR_SIZE + 16;
150 174 rc = smb_mbc_encodef(
151 175 &sr->reply, "wwlll",
152 176 17, /* StructSize */ /* w */
153 177 0, /* reserved */ /* w */
154 178 XferCount, /* l */
155 179 0, /* DataRemaining */ /* l */
156 180 0); /* Channel Info */ /* l */
157 - if (rc)
181 + if (rc) {
182 + sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
158 183 return (SDRC_ERROR);
184 + }
159 185
160 186 mutex_enter(&of->f_mutex);
161 187 of->f_seek_pos = Offset + XferCount;
162 188 mutex_exit(&of->f_mutex);
163 189
164 190 return (SDRC_SUCCESS);
165 191 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX