Print this page
NEX-4820 intended nbmand locking functionality is confused
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@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-9808 SMB3 persistent handles
Reviewed by: Matt Barden <matt.barden@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-3620 need upstream cleanups for smbsrv
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
NEX-2485 SMB authentication flood handled poorly
SUP-866 smbd lwps stuck in libsocket recv() for no apparent reason
SMB-74 Process oplock breaks as session requests
SMB-69 read-raw, write-raw are dead code
SMB-50 User-mode SMB server
Includes work by these authors:
Thomas Keiser <thomas.keiser@nexenta.com>
Albert Lee <trisk@nexenta.com>
SUP-694 panic on bad mutex in smb_event_wait() - nits
SMB-65 SMB server in non-global zones (kmem_caches)
common kmem_cache instances across zones
separate GZ-only init from NGZ init
SMB-64 smbsrv workers run at excessively high priority
re #6811 rb1752 backport illumos 1603 smbsrv raw mode is ill-advised
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_init.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_init.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 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
24 24 * Copyright 2017 Joyent, Inc.
25 25 */
26 26
27 27 #include <sys/types.h>
28 28 #include <sys/conf.h>
29 29 #include <sys/ddi.h>
30 30 #include <sys/modctl.h>
31 31 #include <sys/cred.h>
32 32 #include <sys/disp.h>
33 33 #include <sys/ioccom.h>
34 34 #include <sys/policy.h>
35 35 #include <sys/cmn_err.h>
36 36 #include <smbsrv/smb_kproto.h>
37 37 #include <smbsrv/smb_ioctl.h>
38 38
39 39 #ifdef _FAKE_KERNEL
40 40 #error "See libfksmbsrv"
41 41 #endif /* _FAKE_KERNEL */
42 42
43 43 static int smb_drv_open(dev_t *, int, int, cred_t *);
44 44 static int smb_drv_close(dev_t, int, int, cred_t *);
45 45 static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
46 46 static int smb_drv_attach(dev_info_t *, ddi_attach_cmd_t);
47 47 static int smb_drv_detach(dev_info_t *, ddi_detach_cmd_t);
48 48 static int smb_drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
49 49
50 50 /*
51 51 * *****************************************************************************
52 52 * ****************************** Global Variables *****************************
53 53 * *****************************************************************************
54 54 *
55 55 * These variables can only be changed through the /etc/system file.
56 56 */
|
↓ open down ↓ |
56 lines elided |
↑ open up ↑ |
57 57
58 58 /*
59 59 * Maximum buffer size for NT: configurable based on the client environment.
60 60 * IR104720 Experiments with Windows 2000 indicate that we achieve better
61 61 * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used
62 62 * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory
63 63 * listing problems so this buffer size is configurable based on the end-user
64 64 * environment. When in doubt use 37KB.
65 65 */
66 66 int smb_maxbufsize = SMB_NT_MAXBUF;
67 -int smb_oplock_levelII = 1;
68 -int smb_oplock_timeout = OPLOCK_STD_TIMEOUT;
69 -int smb_oplock_min_timeout = OPLOCK_MIN_TIMEOUT;
70 67 int smb_flush_required = 1;
71 68 int smb_dirsymlink_enable = 1;
72 69 int smb_sign_debug = 0;
73 70 int smb_shortnames = 1;
74 71 uint_t smb_audit_flags =
75 72 #ifdef DEBUG
76 73 SMB_AUDIT_NODE;
77 74 #else
78 75 0;
79 76 #endif
80 77
78 +int smb_allow_advisory_locks = 0; /* See smb_vops.c */
79 +
81 80 /*
82 81 * Maximum number of simultaneous authentication, share mapping, pipe open
83 82 * requests to be processed.
84 83 */
85 84 int smb_ssetup_threshold = SMB_AUTHSVC_MAXTHREAD;
86 85 int smb_tcon_threshold = 1024;
87 86 int smb_opipe_threshold = 1024;
88 87
89 88 /*
90 89 * Number of milliseconds that a request will be stalled if it comes in after
91 90 * the maximum number of inflight operations are being proccessed.
92 91 */
93 92 int smb_ssetup_timeout = (30 * 1000);
94 93 int smb_tcon_timeout = (30 * 1000);
95 94 int smb_opipe_timeout = (30 * 1000);
96 95
97 96 /*
98 97 * Thread priorities used in smbsrv. Our threads spend most of their time
99 98 * blocked on various conditions. However, if the system gets heavy load,
100 99 * the scheduler has to choose an order to run these. We want the order:
101 100 * (a) timers, (b) notifications, (c) workers, (d) receivers (and etc.)
102 101 * where notifications are oplock and change notify work. Aside from this
103 102 * relative ordering, smbsrv threads should run with a priority close to
104 103 * that of normal user-space threads (thus minclsyspri below), just like
105 104 * NFS and other "file service" kinds of processing.
106 105 */
107 106 int smbsrv_base_pri = MINCLSYSPRI;
108 107 int smbsrv_listen_pri = MINCLSYSPRI;
109 108 int smbsrv_receive_pri = MINCLSYSPRI;
110 109 int smbsrv_worker_pri = MINCLSYSPRI + 1;
111 110 int smbsrv_notify_pri = MINCLSYSPRI + 2;
112 111 int smbsrv_timer_pri = MINCLSYSPRI + 5;
113 112
114 113
115 114 /*
116 115 * *****************************************************************************
117 116 * ********************** Static Variables / Module Linkage ********************
118 117 * *****************************************************************************
119 118 */
120 119
121 120 static struct cb_ops cbops = {
122 121 smb_drv_open, /* cb_open */
123 122 smb_drv_close, /* cb_close */
124 123 nodev, /* cb_strategy */
125 124 nodev, /* cb_print */
126 125 nodev, /* cb_dump */
127 126 nodev, /* cb_read */
128 127 nodev, /* cb_write */
129 128 smb_drv_ioctl, /* cb_ioctl */
130 129 nodev, /* cb_devmap */
131 130 nodev, /* cb_mmap */
132 131 nodev, /* cb_segmap */
133 132 nochpoll, /* cb_chpoll */
134 133 ddi_prop_op, /* cb_prop_op */
135 134 NULL, /* cb_streamtab */
136 135 D_MP, /* cb_flag */
137 136 CB_REV, /* cb_rev */
138 137 nodev, /* cb_aread */
139 138 nodev, /* cb_awrite */
140 139 };
141 140
142 141 static struct dev_ops devops = {
143 142 DEVO_REV, /* devo_rev */
144 143 0, /* devo_refcnt */
145 144 smb_drv_getinfo, /* devo_getinfo */
146 145 nulldev, /* devo_identify */
147 146 nulldev, /* devo_probe */
148 147 smb_drv_attach, /* devo_attach */
149 148 smb_drv_detach, /* devo_detach */
150 149 nodev, /* devo_reset */
151 150 &cbops, /* devo_cb_ops */
152 151 NULL, /* devo_bus_ops */
153 152 NULL, /* devo_power */
154 153 ddi_quiesce_not_needed, /* devo_quiesce */
155 154 };
156 155
157 156 static struct modldrv modldrv = {
158 157 &mod_driverops, /* drv_modops */
159 158 "CIFS Server Protocol", /* drv_linkinfo */
160 159 &devops,
161 160 };
162 161
163 162 static struct modlinkage modlinkage = {
164 163 MODREV_1, /* revision of the module, must be: MODREV_1 */
165 164 &modldrv, /* ptr to linkage structures */
166 165 NULL,
167 166 };
168 167
169 168 static dev_info_t *smb_drv_dip = NULL;
170 169
171 170 /*
172 171 * ****************************************************************************
173 172 * Module Interface
174 173 * ****************************************************************************
175 174 */
176 175
177 176 int
178 177 _init(void)
179 178 {
180 179 int rc;
181 180
182 181 if ((rc = smb_server_g_init()) != 0) {
183 182 return (rc);
184 183 }
185 184
186 185 if ((rc = mod_install(&modlinkage)) != 0) {
187 186 smb_server_g_fini();
188 187 }
189 188
190 189 return (rc);
191 190 }
192 191
193 192 int
194 193 _info(struct modinfo *modinfop)
195 194 {
196 195 return (mod_info(&modlinkage, modinfop));
197 196 }
198 197
199 198 int
200 199 _fini(void)
201 200 {
202 201 int rc;
203 202
204 203 if (smb_server_get_count() != 0)
205 204 return (EBUSY);
206 205
207 206 if ((rc = mod_remove(&modlinkage)) == 0) {
208 207 smb_server_g_fini();
209 208 }
210 209
211 210 return (rc);
212 211 }
213 212
214 213 /*
215 214 * ****************************************************************************
216 215 * Pseudo Device Entry Points
217 216 * ****************************************************************************
218 217 */
219 218 /* ARGSUSED */
220 219 static int
221 220 smb_drv_open(dev_t *devp, int flag, int otyp, cred_t *cr)
222 221 {
223 222 zoneid_t zid;
224 223
225 224 /*
226 225 * Check caller's privileges.
227 226 */
228 227 if (secpolicy_smb(cr) != 0)
229 228 return (EPERM);
230 229
231 230 /*
232 231 * We need a unique minor per zone otherwise an smbd in any other
233 232 * zone will keep this minor open and we won't get a close call.
234 233 * The zone ID is good enough as a minor number.
235 234 */
236 235 zid = crgetzoneid(cr);
237 236 if (zid < 0)
238 237 return (ENODEV);
239 238 *devp = makedevice(getmajor(*devp), zid);
240 239
|
↓ open down ↓ |
150 lines elided |
↑ open up ↑ |
241 240 /*
242 241 * Start SMB service state machine
243 242 */
244 243 return (smb_server_create());
245 244 }
246 245
247 246 /* ARGSUSED */
248 247 static int
249 248 smb_drv_close(dev_t dev, int flag, int otyp, cred_t *credp)
250 249 {
251 - return (smb_server_delete());
250 + smb_server_t *sv;
251 + int rc;
252 +
253 + rc = smb_server_lookup(&sv);
254 + if (rc == 0)
255 + rc = smb_server_delete(sv);
256 +
257 + return (rc);
252 258 }
253 259
254 260 /* ARGSUSED */
255 261 static int
256 262 smb_drv_ioctl(dev_t drv, int cmd, intptr_t argp, int flags, cred_t *cred,
257 263 int *retval)
258 264 {
259 265 smb_ioc_t *ioc;
260 266 smb_ioc_header_t ioc_hdr;
261 267 uint32_t crc;
262 268 boolean_t copyout = B_FALSE;
263 269 int rc = 0;
264 270 size_t alloclen;
265 271
266 272 if (ddi_copyin((void *)argp, &ioc_hdr, sizeof (ioc_hdr), flags))
267 273 return (EFAULT);
268 274
269 275 /*
270 276 * Check version and length.
271 277 *
272 278 * Note that some ioctls (i.e. SMB_IOC_SVCENUM) have payload
273 279 * data after the ioctl struct, in which case they specify a
274 280 * length much larger than sizeof smb_ioc_t. The theoretical
275 281 * largest ioctl data is therefore the size of the union plus
276 282 * the max size of the payload (which is SMB_IOC_DATA_SIZE).
277 283 */
278 284 if (ioc_hdr.version != SMB_IOC_VERSION ||
279 285 ioc_hdr.len < sizeof (ioc_hdr) ||
280 286 ioc_hdr.len > (sizeof (*ioc) + SMB_IOC_DATA_SIZE))
281 287 return (EINVAL);
282 288
283 289 crc = ioc_hdr.crc;
284 290 ioc_hdr.crc = 0;
285 291 if (smb_crc_gen((uint8_t *)&ioc_hdr, sizeof (ioc_hdr)) != crc)
286 292 return (EINVAL);
287 293
288 294 /*
289 295 * Note that smb_ioc_t is a union, and callers set ioc_hdr.len
290 296 * to the size of the actual union arm. If some caller were to
291 297 * set that size too small, we could end up passing under-sized
292 298 * memory to one of the type-specific handler functions. Avoid
293 299 * that problem by allocating at least the size of the union,
294 300 * (zeroed out) and then copy in the caller specified length.
295 301 */
296 302 alloclen = MAX(ioc_hdr.len, sizeof (*ioc));
297 303 ioc = kmem_zalloc(alloclen, KM_SLEEP);
298 304 if (ddi_copyin((void *)argp, ioc, ioc_hdr.len, flags)) {
299 305 kmem_free(ioc, alloclen);
300 306 return (EFAULT);
301 307 }
302 308
303 309 switch (cmd) {
304 310 case SMB_IOC_CONFIG:
305 311 rc = smb_server_configure(&ioc->ioc_cfg);
306 312 break;
307 313 case SMB_IOC_START:
308 314 rc = smb_server_start(&ioc->ioc_start);
309 315 break;
310 316 case SMB_IOC_STOP:
311 317 rc = smb_server_stop();
312 318 break;
313 319 case SMB_IOC_EVENT:
314 320 rc = smb_server_notify_event(&ioc->ioc_event);
315 321 break;
316 322 case SMB_IOC_GMTOFF:
317 323 rc = smb_server_set_gmtoff(&ioc->ioc_gmt);
318 324 break;
319 325 case SMB_IOC_SHARE:
320 326 rc = smb_kshare_export_list(&ioc->ioc_share);
321 327 break;
322 328 case SMB_IOC_UNSHARE:
323 329 rc = smb_kshare_unexport_list(&ioc->ioc_share);
324 330 break;
325 331 case SMB_IOC_SHAREINFO:
326 332 rc = smb_kshare_info(&ioc->ioc_shareinfo);
327 333 copyout = B_TRUE;
328 334 break;
329 335 case SMB_IOC_NUMOPEN:
330 336 rc = smb_server_numopen(&ioc->ioc_opennum);
331 337 copyout = B_TRUE;
332 338 break;
333 339 case SMB_IOC_SVCENUM:
334 340 rc = smb_server_enum(&ioc->ioc_svcenum);
335 341 copyout = B_TRUE;
336 342 break;
337 343 case SMB_IOC_SESSION_CLOSE:
338 344 rc = smb_server_session_close(&ioc->ioc_session);
339 345 break;
340 346 case SMB_IOC_FILE_CLOSE:
341 347 rc = smb_server_file_close(&ioc->ioc_fileid);
342 348 break;
343 349 case SMB_IOC_SPOOLDOC:
344 350 rc = smb_server_spooldoc(&ioc->ioc_spooldoc);
345 351 copyout = B_TRUE;
346 352 break;
347 353 default:
348 354 rc = ENOTTY;
349 355 break;
350 356 }
351 357 if ((rc == 0) && copyout) {
352 358 if (ddi_copyout(ioc, (void *)argp, ioc_hdr.len, flags))
353 359 rc = EFAULT;
354 360 }
355 361 kmem_free(ioc, alloclen);
356 362 return (rc);
357 363 }
358 364
359 365 /*
360 366 * ****************************************************************************
361 367 * Pseudo Device Operations
362 368 * ****************************************************************************
363 369 */
364 370 static int
365 371 smb_drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
366 372 {
367 373 if (cmd == DDI_ATTACH) {
368 374 /* we only allow instance 0 to attach */
369 375 if (ddi_get_instance(dip) == 0) {
370 376 /* create the minor node */
371 377 if (ddi_create_minor_node(dip, "smbsrv", S_IFCHR, 0,
372 378 DDI_PSEUDO, 0) == DDI_SUCCESS) {
373 379 smb_drv_dip = dip;
374 380 return (DDI_SUCCESS);
375 381 } else {
376 382 cmn_err(CE_WARN, "smb_drv_attach:"
377 383 " failed creating minor node");
378 384 }
379 385 }
380 386 }
381 387 return (DDI_FAILURE);
382 388 }
383 389
384 390 static int
385 391 smb_drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
386 392 {
387 393 if (cmd == DDI_DETACH) {
388 394 ASSERT(dip == smb_drv_dip);
389 395 ddi_remove_minor_node(dip, NULL);
390 396 smb_drv_dip = NULL;
391 397 return (DDI_SUCCESS);
392 398 }
393 399 return (DDI_FAILURE);
394 400 }
395 401
396 402 /* ARGSUSED */
397 403 static int
398 404 smb_drv_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
399 405 {
400 406 ulong_t instance = getminor((dev_t)arg);
401 407
402 408 switch (cmd) {
403 409 case DDI_INFO_DEVT2DEVINFO:
404 410 *result = smb_drv_dip;
405 411 return (DDI_SUCCESS);
406 412
407 413 case DDI_INFO_DEVT2INSTANCE:
408 414 *result = (void *)instance;
409 415 return (DDI_SUCCESS);
410 416
411 417 default:
412 418 break;
413 419 }
414 420
415 421 return (DDI_FAILURE);
416 422 }
|
↓ open down ↓ |
155 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX