Print this page
NEX-15555 SMB2 async redesign
NEX-15061 smtorture smb2.lock.cancel.cancel is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Also follow-up change to:
NEX-1643 dtrace provider for smbsrv (remove "done2" probes,
which don't make sense with the new async design)
NEX-15555 SMB2 async redesign
NEX-15061 smtorture smb2.lock.cancel.cancel is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Also follow-up change to:
NEX-1643 dtrace provider for smbsrv (remove "done2" probes,
which don't make sense with the new async design)
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6402 SMB2 change notify response wrong when STATUS_NOTIFY_ENUM_DIR
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
NEX-3906 Prefer that SMB change notify not tie up a worker thread
NEX-5278 SMB notify should buffer per file handle
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3310 smbstat misreports change notify
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
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)
re #13470 rb4432 Sync some SMB differences from illumos
re #11215 rb3676 sesctl to SGI JBOD hangs in biowait() with a command stuck in mptsas driver
re #10734 NT Trans. Notify returning too quickly
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.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 2015 Nexenta Systems, Inc. All rights reserved.
24 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * File Change Notification (FCN)
29 29 * SMB1 specific part.
30 30 */
31 31
32 32 /*
33 33 * SMB: nt_transact_notify_change
34 34 *
35 35 * Client Setup Words Description
36 36 * ================================== =================================
37 37 *
38 38 * ULONG CompletionFilter; Specifies operation to monitor
39 39 * USHORT Fid; Fid of directory to monitor
40 40 * BOOLEAN WatchTree; TRUE = watch all subdirectories too
41 41 * UCHAR Reserved; MBZ
42 42 *
43 43 * This command notifies the client when the directory specified by Fid is
44 44 * modified. See smb_notify.c for details.
45 45 *
46 46 * The MaxParameterCount field in the NT transact header determines
47 47 * the size of the buffer used to return change information:
48 48 *
49 49 * Server Response Description
50 50 * ================================== ================================
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
51 51 * ParameterCount # of bytes of change data
52 52 * Parameters[ ParameterCount ] FILE_NOTIFY_INFORMATION
53 53 * structures
54 54 *
55 55 * See smb_notify.c for details of FILE_NOTIFY_INFORMATION
56 56 */
57 57
58 58 #include <smbsrv/smb_kproto.h>
59 59
60 60 /*
61 - * We add this flag to the CompletionFilter (see above) when the
62 - * client sets WatchTree. Must not overlap FILE_NOTIFY_VALID_MASK.
63 - */
64 -#define NODE_FLAGS_WATCH_TREE 0x10000000
65 -#if (NODE_FLAGS_WATCH_TREE & FILE_NOTIFY_VALID_MASK)
66 -#error "NODE_FLAGS_WATCH_TREE"
67 -#endif
68 -
69 -/*
70 61 * smb_nt_transact_notify_change
71 62 *
72 63 * Handle and SMB NT transact NOTIFY CHANGE request.
73 64 * Basically, wait until "something has changed", and either
74 65 * return information about what changed, or return a special
75 66 * error telling the client "many things changed".
76 67 *
77 68 * The implementation uses a per-node list of waiting notify
78 69 * requests like this one, each with a blocked worker thead.
79 70 * Later, FEM and/or smbsrv events wake these threads, which
80 71 * then send the reply to the client.
81 72 */
82 73 smb_sdrc_t
83 74 smb_nt_transact_notify_change(smb_request_t *sr, struct smb_xa *xa)
84 75 {
76 + mbuf_chain_t tmp_mbc;
77 + uint32_t oBufSize;
85 78 uint32_t CompletionFilter;
86 79 unsigned char WatchTree;
87 80 uint32_t status;
88 - hrtime_t t1, t2;
89 81
90 82 if (smb_mbc_decodef(&xa->req_setup_mb, "lwb",
91 83 &CompletionFilter, &sr->smb_fid, &WatchTree) != 0) {
92 84 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
93 85 return (SDRC_ERROR);
94 86 }
95 - CompletionFilter &= FILE_NOTIFY_VALID_MASK;
96 - if (WatchTree)
97 - CompletionFilter |= NODE_FLAGS_WATCH_TREE;
98 87
99 88 smbsr_lookup_file(sr);
89 + if (sr->fid_ofile == NULL) {
90 + smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
91 + return (SDRC_ERROR);
92 + }
100 93
101 - t1 = gethrtime();
102 - status = smb_notify_common(sr, &xa->rep_data_mb, CompletionFilter);
103 - t2 = gethrtime();
94 + oBufSize = xa->rep_param_mb.max_bytes;
95 + CompletionFilter &= FILE_NOTIFY_VALID_MASK;
96 + if (WatchTree)
97 + CompletionFilter |= FILE_NOTIFY_CHANGE_EV_SUBDIR;
104 98
105 99 /*
106 - * We don't want to include the (indefinite) wait time of the
107 - * smb_notify_common() call in the SMB1 transact latency.
108 - * The easiest way to do that, without adding special case
109 - * logic to the common SMB1 dispatch handler is to adjust the
110 - * start time of this request to effectively subtract out the
111 - * time we were blocked in smb_notify_common().
100 + * Check for events and consume, non-blocking.
101 + * Special return STATUS_PENDING means:
102 + * No events; caller must call "act2" next.
112 103 */
113 - sr->sr_time_start += (t2 - t1);
104 + status = smb_notify_act1(sr, oBufSize, CompletionFilter);
105 + if (status == NT_STATUS_PENDING) {
106 + status = smb_notify_act2(sr);
107 + if (status == NT_STATUS_PENDING) {
108 + /* See: smb_nt_transact_notify_finish */
109 + return (SDRC_SR_KEPT);
110 + }
111 + /* else: some other error, or even success */
112 + }
114 113
115 - if (status != 0)
116 - smbsr_error(sr, status, 0, 0);
114 + /*
115 + * SMB1 expects an empty trans response after the
116 + * FID we're watching is closed.
117 + */
118 + if (status == NT_STATUS_NOTIFY_CLEANUP) {
119 + status = 0;
120 + MBC_FLUSH(&sr->raw_data);
121 + }
117 122
123 + if (status != 0) {
124 + smbsr_status(sr, status, 0, 0);
125 + if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
126 + return (SDRC_ERROR);
127 + /* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
128 + }
129 +
130 + /*
131 + * The nt_trans call expects the output in rep_param_mb,
132 + * but our common code puts it in raw_data. Move it
133 + * where the caller expects it via swaping the two,
134 + * which lets the normal cleanup take care of both.
135 + */
136 + tmp_mbc = xa->rep_param_mb;
137 + xa->rep_param_mb = sr->raw_data;
138 + sr->raw_data = tmp_mbc;
139 +
118 140 return (SDRC_SUCCESS);
141 +}
142 +
143 +/*
144 + * This is called via taskq_dispatch in smb_notify.c
145 + * to finish up an NT transact notify change request.
146 + */
147 +void
148 +smb_nt_transact_notify_finish(void *arg)
149 +{
150 + smb_request_t *sr = arg;
151 + struct smb_xa *xa;
152 + smb_disp_stats_t *sds;
153 + int total_bytes, n_setup, n_param, n_data;
154 + int param_off, param_pad, data_off, data_pad;
155 + uint32_t status;
156 +
157 + SMB_REQ_VALID(sr);
158 +
159 + /*
160 + * Common part of notify, puts data in sr->raw_data
161 + */
162 + status = smb_notify_act3(sr);
163 +
164 + /*
165 + * SMB1 expects an empty trans response after the
166 + * FID we're watching is closed.
167 + */
168 + if (status == NT_STATUS_NOTIFY_CLEANUP) {
169 + status = 0;
170 + MBC_FLUSH(&sr->raw_data);
171 + }
172 +
173 + if (status != 0) {
174 + smbsr_status(sr, status, 0, 0);
175 + if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) {
176 + (void) smb_mbc_encodef(&sr->reply, "bwbw",
177 + (short)0, 0L, (short)0, 0L);
178 + goto sendit;
179 + }
180 + /* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
181 + }
182 +
183 + /*
184 + * setup the NT transact reply
185 + *
186 + * Note that this is a copy/paste of code from
187 + * smb_nt_trans_dispatch(), with minor changes.
188 + * Intentionally keeping this similar to the
189 + * original rather than hand-optimizing.
190 + *
191 + * The "setup" and "data" parts of this trans reply
192 + * (n_setup, n_data, rep_setup_mb, rep_data_mb) are
193 + * always empty. sr->raw_data replaces rep_param_mb.
194 + */
195 + xa = sr->r_xa;
196 + n_setup = MBC_LENGTH(&xa->rep_setup_mb);
197 + n_param = MBC_LENGTH(&sr->raw_data);
198 + n_data = MBC_LENGTH(&xa->rep_data_mb);
199 +
200 + n_setup = (n_setup + 1) / 2; /* Convert to setup words */
201 + param_pad = 1; /* must be one */
202 + param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
203 + /* Pad to 4 bytes */
204 + data_pad = (4 - ((param_off + n_param) & 3)) % 4;
205 + /* Param off from hdr */
206 + data_off = param_off + n_param + data_pad;
207 + total_bytes = param_pad + n_param + data_pad + n_data;
208 +
209 + (void) smbsr_encode_result(sr, 18+n_setup, total_bytes,
210 + "b3.llllllllbCw#.C#.C",
211 + 18 + n_setup, /* wct */
212 + n_param, /* Total Parameter Bytes */
213 + n_data, /* Total Data Bytes */
214 + n_param, /* Total Parameter Bytes this buffer */
215 + param_off, /* Param offset from header start */
216 + 0, /* Param displacement */
217 + n_data, /* Total Data Bytes this buffer */
218 + data_off, /* Data offset from header start */
219 + 0, /* Data displacement */
220 + n_setup, /* suwcnt */
221 + &xa->rep_setup_mb, /* setup[] */
222 + total_bytes, /* Total data bytes */
223 + param_pad,
224 + &sr->raw_data, /* output mbc */
225 + data_pad,
226 + &xa->rep_data_mb);
227 +
228 +sendit:
229 + /*
230 + * When smb_nt_transact_notify_change returned SDRC_SR_KEPT
231 + * the dispatcher skipped the "done" probe, so do it now.
232 + * Note: Don't use this probe in response time statistics.
233 + */
234 + DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr);
235 +
236 + sds = &sr->sr_server->sv_disp_stats1[sr->smb_com];
237 + atomic_add_64(&sds->sdt_txb, (int64_t)sr->reply.chain_offset);
238 +
239 + smbsr_send_reply(sr); /* also puts the SMB header. */
240 + smbsr_cleanup(sr);
241 +
242 + mutex_enter(&sr->sr_mutex);
243 + sr->sr_state = SMB_REQ_STATE_COMPLETED;
244 + mutex_exit(&sr->sr_mutex);
245 +
246 + smb_request_free(sr);
119 247 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX