Print this page
NEX-1643 dtrace provider for smbsrv
Also illumos 1841:
DTrace smb provider was mis-implemented, doesn't exist.
Add back handlers for read/write raw, so that
legacy dtrace consumers can find the probes.
Kill extra arg in smb_negotiate
Fix missing "done" probe with smb_notify
Add example consumer: smb-trace.d
fix soi_pid
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
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 24 * Copyright 2016 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 * ================================== ================================
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 61 * smb_nt_transact_notify_change
62 62 *
63 63 * Handle and SMB NT transact NOTIFY CHANGE request.
64 64 * Basically, wait until "something has changed", and either
65 65 * return information about what changed, or return a special
66 66 * error telling the client "many things changed".
67 67 *
68 68 * The implementation uses a per-node list of waiting notify
69 69 * requests like this one, each with a blocked worker thead.
70 70 * Later, FEM and/or smbsrv events wake these threads, which
71 71 * then send the reply to the client.
72 72 */
73 73 smb_sdrc_t
74 74 smb_nt_transact_notify_change(smb_request_t *sr, struct smb_xa *xa)
75 75 {
76 76 mbuf_chain_t tmp_mbc;
77 77 uint32_t oBufSize;
78 78 uint32_t CompletionFilter;
79 79 unsigned char WatchTree;
80 80 uint32_t status;
81 81
82 82 if (smb_mbc_decodef(&xa->req_setup_mb, "lwb",
83 83 &CompletionFilter, &sr->smb_fid, &WatchTree) != 0) {
84 84 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
85 85 return (SDRC_ERROR);
86 86 }
87 87
88 88 smbsr_lookup_file(sr);
89 89 if (sr->fid_ofile == NULL) {
90 90 smbsr_error(sr, NT_STATUS_INVALID_PARAMETER, 0, 0);
91 91 return (SDRC_ERROR);
92 92 }
93 93
94 94 oBufSize = xa->rep_param_mb.max_bytes;
95 95 CompletionFilter &= FILE_NOTIFY_VALID_MASK;
96 96 if (WatchTree)
97 97 CompletionFilter |= FILE_NOTIFY_CHANGE_EV_SUBDIR;
98 98
99 99 /*
100 100 * Check for events and consume, non-blocking.
101 101 * Special return STATUS_PENDING means:
102 102 * No events; caller must call "act2" next.
103 103 */
104 104 status = smb_notify_act1(sr, oBufSize, CompletionFilter);
105 105 if (status == NT_STATUS_PENDING) {
106 106 status = smb_notify_act2(sr);
107 107 if (status == NT_STATUS_PENDING) {
108 108 /* See: smb_nt_transact_notify_finish */
109 109 return (SDRC_SR_KEPT);
110 110 }
111 111 /* else: some other error, or even success */
112 112 }
113 113
114 114 /*
115 115 * SMB1 expects an empty trans response after the
116 116 * FID we're watching is closed.
117 117 */
118 118 if (status == NT_STATUS_NOTIFY_CLEANUP) {
119 119 status = 0;
120 120 MBC_FLUSH(&sr->raw_data);
121 121 }
122 122
123 123 if (status != 0) {
124 124 smbsr_status(sr, status, 0, 0);
125 125 if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR)
126 126 return (SDRC_ERROR);
127 127 /* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
128 128 }
129 129
130 130 /*
131 131 * The nt_trans call expects the output in rep_param_mb,
132 132 * but our common code puts it in raw_data. Move it
133 133 * where the caller expects it via swaping the two,
134 134 * which lets the normal cleanup take care of both.
135 135 */
136 136 tmp_mbc = xa->rep_param_mb;
137 137 xa->rep_param_mb = sr->raw_data;
138 138 sr->raw_data = tmp_mbc;
139 139
140 140 return (SDRC_SUCCESS);
141 141 }
142 142
143 143 /*
144 144 * This is called via taskq_dispatch in smb_notify.c
145 145 * to finish up an NT transact notify change request.
146 146 */
147 147 void
148 148 smb_nt_transact_notify_finish(void *arg)
149 149 {
150 150 smb_request_t *sr = arg;
151 151 struct smb_xa *xa;
152 152 smb_disp_stats_t *sds;
153 153 int total_bytes, n_setup, n_param, n_data;
154 154 int param_off, param_pad, data_off, data_pad;
155 155 uint32_t status;
156 156
157 157 SMB_REQ_VALID(sr);
158 158
159 159 /*
160 160 * Common part of notify, puts data in sr->raw_data
161 161 */
162 162 status = smb_notify_act3(sr);
163 163
164 164 /*
165 165 * SMB1 expects an empty trans response after the
166 166 * FID we're watching is closed.
167 167 */
168 168 if (status == NT_STATUS_NOTIFY_CLEANUP) {
169 169 status = 0;
170 170 MBC_FLUSH(&sr->raw_data);
171 171 }
172 172
173 173 if (status != 0) {
174 174 smbsr_status(sr, status, 0, 0);
175 175 if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) {
176 176 (void) smb_mbc_encodef(&sr->reply, "bwbw",
177 177 (short)0, 0L, (short)0, 0L);
178 178 goto sendit;
179 179 }
180 180 /* Else continue with NT_STATUS_NOTIFY_ENUM_DIR etc. */
181 181 }
182 182
183 183 /*
184 184 * setup the NT transact reply
185 185 *
186 186 * Note that this is a copy/paste of code from
187 187 * smb_nt_trans_dispatch(), with minor changes.
188 188 * Intentionally keeping this similar to the
189 189 * original rather than hand-optimizing.
190 190 *
191 191 * The "setup" and "data" parts of this trans reply
192 192 * (n_setup, n_data, rep_setup_mb, rep_data_mb) are
193 193 * always empty. sr->raw_data replaces rep_param_mb.
194 194 */
195 195 xa = sr->r_xa;
196 196 n_setup = MBC_LENGTH(&xa->rep_setup_mb);
197 197 n_param = MBC_LENGTH(&sr->raw_data);
198 198 n_data = MBC_LENGTH(&xa->rep_data_mb);
199 199
200 200 n_setup = (n_setup + 1) / 2; /* Convert to setup words */
201 201 param_pad = 1; /* must be one */
202 202 param_off = param_pad + 32 + 37 + (n_setup << 1) + 2;
203 203 /* Pad to 4 bytes */
204 204 data_pad = (4 - ((param_off + n_param) & 3)) % 4;
205 205 /* Param off from hdr */
206 206 data_off = param_off + n_param + data_pad;
207 207 total_bytes = param_pad + n_param + data_pad + n_data;
208 208
209 209 (void) smbsr_encode_result(sr, 18+n_setup, total_bytes,
210 210 "b3.llllllllbCw#.C#.C",
211 211 18 + n_setup, /* wct */
212 212 n_param, /* Total Parameter Bytes */
213 213 n_data, /* Total Data Bytes */
214 214 n_param, /* Total Parameter Bytes this buffer */
215 215 param_off, /* Param offset from header start */
216 216 0, /* Param displacement */
217 217 n_data, /* Total Data Bytes this buffer */
218 218 data_off, /* Data offset from header start */
↓ open down ↓ |
218 lines elided |
↑ open up ↑ |
219 219 0, /* Data displacement */
220 220 n_setup, /* suwcnt */
221 221 &xa->rep_setup_mb, /* setup[] */
222 222 total_bytes, /* Total data bytes */
223 223 param_pad,
224 224 &sr->raw_data, /* output mbc */
225 225 data_pad,
226 226 &xa->rep_data_mb);
227 227
228 228 sendit:
229 + DTRACE_SMB_1(op__NtTransactNotify__done2, smb_request_t *, sr);
230 +
229 231 sds = &sr->sr_server->sv_disp_stats1[sr->smb_com];
230 232 atomic_add_64(&sds->sdt_txb, (int64_t)sr->reply.chain_offset);
231 233
232 234 smbsr_send_reply(sr); /* also puts the SMB header. */
233 235 smbsr_cleanup(sr);
234 236
235 237 mutex_enter(&sr->sr_mutex);
236 238 sr->sr_state = SMB_REQ_STATE_COMPLETED;
237 239 mutex_exit(&sr->sr_mutex);
238 240
239 241 smb_request_free(sr);
240 242 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX