Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)
NEX-16824 SMB client connection setup rework
NEX-17232 SMB client reconnect failures
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (improve debug)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
+++ new/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.c
1 1 /*
2 2 * Copyright (c) 2000-2001 Boris Popov
3 3 * All rights reserved.
4 4 *
5 5 * Redistribution and use in source and binary forms, with or without
6 6 * modification, are permitted provided that the following conditions
7 7 * are met:
8 8 * 1. Redistributions of source code must retain the above copyright
9 9 * notice, this list of conditions and the following disclaimer.
10 10 * 2. Redistributions in binary form must reproduce the above copyright
11 11 * notice, this list of conditions and the following disclaimer in the
12 12 * documentation and/or other materials provided with the distribution.
13 13 * 3. All advertising materials mentioning features or use of this software
14 14 * must display the following acknowledgement:
15 15 * This product includes software developed by Boris Popov.
16 16 * 4. Neither the name of the author nor the names of any co-contributors
17 17 * may be used to endorse or promote products derived from this software
18 18 * without specific prior written permission.
19 19 *
20 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
27 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 30 * SUCH DAMAGE.
31 31 *
32 32 * $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
33 33 */
34 34 /*
35 35 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
36 36 * Use is subject to license terms.
37 + *
38 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
37 39 */
38 40
39 41 /*
40 42 * Connection engine.
41 43 */
42 44
43 45 #include <sys/param.h>
44 46 #include <sys/systm.h>
45 47 #include <sys/kmem.h>
46 48 #include <sys/proc.h>
47 49 #include <sys/lock.h>
48 50 #include <sys/vnode.h>
49 51 #include <sys/stream.h>
50 52 #include <sys/stropts.h>
51 53 #include <sys/socketvar.h>
52 54 #include <sys/cred.h>
53 55 #include <netinet/in.h>
|
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
54 56 #include <inet/ip.h>
55 57 #include <inet/ip6.h>
56 58 #include <sys/cmn_err.h>
57 59 #include <sys/thread.h>
58 60 #include <sys/atomic.h>
59 61 #include <sys/u8_textprep.h>
60 62
61 63 #include <netsmb/smb_osdep.h>
62 64
63 65 #include <netsmb/smb.h>
66 +#include <netsmb/smb2.h>
64 67 #include <netsmb/smb_conn.h>
65 68 #include <netsmb/smb_subr.h>
66 69 #include <netsmb/smb_tran.h>
67 70 #include <netsmb/smb_pass.h>
68 71
69 72 static struct smb_connobj smb_vclist;
70 73
71 74 void smb_co_init(struct smb_connobj *cp, int level, char *objname);
72 75 void smb_co_done(struct smb_connobj *cp);
73 76 void smb_co_hold(struct smb_connobj *cp);
74 77 void smb_co_rele(struct smb_connobj *cp);
75 78 void smb_co_kill(struct smb_connobj *cp);
76 79
77 80 static void smb_vc_free(struct smb_connobj *cp);
78 81 static void smb_vc_gone(struct smb_connobj *cp);
79 82
80 83 static void smb_share_free(struct smb_connobj *cp);
81 84 static void smb_share_gone(struct smb_connobj *cp);
82 85
86 +static void smb_fh_free(struct smb_connobj *cp);
87 +static void smb_fh_gone(struct smb_connobj *cp);
88 +
83 89 int
84 90 smb_sm_init(void)
85 91 {
86 92 smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
87 93 return (0);
88 94 }
89 95
90 96 int
91 97 smb_sm_idle(void)
92 98 {
93 99 int error = 0;
94 100 SMB_CO_LOCK(&smb_vclist);
95 101 if (smb_vclist.co_usecount > 1) {
96 102 SMBSDEBUG("%d connections still active\n",
97 103 smb_vclist.co_usecount - 1);
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
98 104 error = EBUSY;
99 105 }
100 106 SMB_CO_UNLOCK(&smb_vclist);
101 107 return (error);
102 108 }
103 109
104 110 void
105 111 smb_sm_done(void)
106 112 {
107 113 /*
108 - * XXX Q4BP why are we not iterating on smb_vclist here?
114 + * Why are we not iterating on smb_vclist here?
109 115 * Because the caller has just called smb_sm_idle() to
110 116 * make sure we have no VCs before calling this.
111 117 */
112 118 smb_co_done(&smb_vclist);
113 119 }
114 120
115 121
116 122
117 123 /*
118 124 * Common code for connection object
119 125 */
120 126 /*ARGSUSED*/
121 127 void
122 128 smb_co_init(struct smb_connobj *cp, int level, char *objname)
123 129 {
124 130
125 131 mutex_init(&cp->co_lock, objname, MUTEX_DRIVER, NULL);
126 132
127 133 cp->co_level = level;
128 134 cp->co_usecount = 1;
129 135 SLIST_INIT(&cp->co_children);
130 136 }
131 137
132 138 /*
133 139 * Called just before free of an object
134 140 * of which smb_connobj is a part, i.e.
135 141 * _vc_free, _share_free, also sm_done.
136 142 */
137 143 void
138 144 smb_co_done(struct smb_connobj *cp)
139 145 {
140 146 ASSERT(SLIST_EMPTY(&cp->co_children));
141 147 mutex_destroy(&cp->co_lock);
142 148 }
143 149
144 150 static void
145 151 smb_co_addchild(
146 152 struct smb_connobj *parent,
147 153 struct smb_connobj *child)
148 154 {
149 155
150 156 /*
151 157 * Set the child's pointer to the parent.
152 158 * No references yet, so no need to lock.
153 159 */
154 160 ASSERT(child->co_usecount == 1);
155 161 child->co_parent = parent;
156 162
157 163 /*
158 164 * Add the child to the parent's list of
159 165 * children, and in-line smb_co_hold
160 166 */
161 167 ASSERT(MUTEX_HELD(&parent->co_lock));
162 168 parent->co_usecount++;
163 169 SLIST_INSERT_HEAD(&parent->co_children, child, co_next);
164 170 }
165 171
166 172 void
167 173 smb_co_hold(struct smb_connobj *cp)
168 174 {
169 175 SMB_CO_LOCK(cp);
170 176 cp->co_usecount++;
171 177 SMB_CO_UNLOCK(cp);
172 178 }
173 179
|
↓ open down ↓ |
55 lines elided |
↑ open up ↑ |
174 180 /*
175 181 * Called via smb_vc_rele, smb_share_rele
176 182 */
177 183 void
178 184 smb_co_rele(struct smb_connobj *co)
179 185 {
180 186 struct smb_connobj *parent;
181 187 int old_flags;
182 188
183 189 SMB_CO_LOCK(co);
190 +
191 + /*
192 + * When VC usecount goes from 2 to 1, signal the iod_idle CV.
193 + * It's unfortunate to have object type-specific logic here,
194 + * but it's hard to do this anywhere else.
195 + */
196 + if (co->co_level == SMBL_VC && co->co_usecount == 2) {
197 + smb_vc_t *vcp = CPTOVC(co);
198 + cv_signal(&vcp->iod_idle);
199 + }
184 200 if (co->co_usecount > 1) {
185 201 co->co_usecount--;
186 202 SMB_CO_UNLOCK(co);
187 203 return;
188 204 }
189 205 ASSERT(co->co_usecount == 1);
190 206 co->co_usecount = 0;
191 207
192 208 /*
193 209 * This list of children should be empty now.
194 210 * Check this while we're still linked, so
195 211 * we have a better chance of debugging.
196 212 */
197 213 ASSERT(SLIST_EMPTY(&co->co_children));
198 214
199 215 /*
200 216 * OK, this element is going away.
201 217 *
202 218 * We need to drop the lock on this CO so we can take the
203 219 * parent CO lock. The _GONE flag prevents this CO from
204 220 * getting new references before we can unlink it from the
205 221 * parent list.
206 222 *
207 223 * The _GONE flag is also used to ensure that the co_gone
208 224 * function is called only once. Note that smb_co_kill may
209 225 * do this before we get here. If we find that the _GONE
210 226 * flag was not already set, then call the co_gone hook
211 227 * (smb_share_gone, smb_vc_gone) which will disconnect
212 228 * the share or the VC, respectively.
213 229 *
214 230 * Note the old: smb_co_gone(co, scred);
215 231 * is now in-line here.
216 232 */
217 233 old_flags = co->co_flags;
218 234 co->co_flags |= SMBO_GONE;
219 235 SMB_CO_UNLOCK(co);
220 236
221 237 if ((old_flags & SMBO_GONE) == 0 && co->co_gone)
222 238 co->co_gone(co);
223 239
224 240 /*
225 241 * If we have a parent (only smb_vclist does not)
226 242 * then unlink from parent's list of children.
227 243 * We have the only reference to the child.
228 244 */
229 245 parent = co->co_parent;
230 246 if (parent) {
231 247 SMB_CO_LOCK(parent);
232 248 ASSERT(SLIST_FIRST(&parent->co_children));
233 249 if (SLIST_FIRST(&parent->co_children)) {
234 250 SLIST_REMOVE(&parent->co_children, co,
235 251 smb_connobj, co_next);
236 252 }
237 253 SMB_CO_UNLOCK(parent);
238 254 }
239 255
240 256 /*
241 257 * Now it's safe to free the CO
242 258 */
243 259 if (co->co_free) {
244 260 co->co_free(co);
245 261 }
246 262
247 263 /*
248 264 * Finally, if the CO had a parent, decrement
249 265 * the parent's hold count for the lost child.
250 266 */
251 267 if (parent) {
252 268 /*
253 269 * Recursive call here (easier for debugging).
254 270 * Can only go two levels.
255 271 */
256 272 smb_co_rele(parent);
257 273 }
258 274 }
259 275
260 276 /*
261 277 * Do just the first part of what co_gone does,
262 278 * i.e. tree disconnect, or disconnect a VC.
263 279 * This is used to forcibly close things.
264 280 */
265 281 void
266 282 smb_co_kill(struct smb_connobj *co)
267 283 {
268 284 int old_flags;
269 285
270 286 SMB_CO_LOCK(co);
271 287 old_flags = co->co_flags;
272 288 co->co_flags |= SMBO_GONE;
273 289 SMB_CO_UNLOCK(co);
274 290
275 291 /*
276 292 * Do the same "call only once" logic here as in
277 293 * smb_co_rele, though it's probably not possible
278 294 * for this to be called after smb_co_rele.
279 295 */
280 296 if ((old_flags & SMBO_GONE) == 0 && co->co_gone)
281 297 co->co_gone(co);
282 298
283 299 /* XXX: Walk list of children and kill those too? */
284 300 }
285 301
286 302
287 303 /*
288 304 * Session objects, which are referred to as "VC" for
289 305 * "virtual cirtuit". This has nothing to do with the
290 306 * CIFS notion of a "virtual cirtuit". See smb_conn.h
291 307 */
292 308
293 309 void
294 310 smb_vc_hold(struct smb_vc *vcp)
295 311 {
296 312 smb_co_hold(VCTOCP(vcp));
297 313 }
298 314
299 315 void
300 316 smb_vc_rele(struct smb_vc *vcp)
301 317 {
302 318 smb_co_rele(VCTOCP(vcp));
303 319 }
304 320
305 321 void
306 322 smb_vc_kill(struct smb_vc *vcp)
307 323 {
308 324 smb_co_kill(VCTOCP(vcp));
309 325 }
310 326
311 327 /*
312 328 * Normally called via smb_vc_rele()
313 329 * after co_usecount drops to zero.
314 330 * Also called via: smb_vc_kill()
315 331 *
316 332 * Shutdown the VC to this server,
317 333 * invalidate shares linked with it.
318 334 */
319 335 /*ARGSUSED*/
320 336 static void
321 337 smb_vc_gone(struct smb_connobj *cp)
322 338 {
323 339 struct smb_vc *vcp = CPTOVC(cp);
324 340
325 341 /*
326 342 * Was smb_vc_disconnect(vcp);
327 343 */
328 344 smb_iod_disconnect(vcp);
329 345 }
330 346
331 347 /*
332 348 * The VC has no more references. Free it.
333 349 * No locks needed here.
334 350 */
335 351 static void
336 352 smb_vc_free(struct smb_connobj *cp)
337 353 {
338 354 struct smb_vc *vcp = CPTOVC(cp);
339 355
340 356 /*
341 357 * The _gone call should have emptied the request list,
342 358 * but let's make sure, as requests may have references
343 359 * to this VC without taking a hold. (The hold is the
344 360 * responsibility of threads placing requests.)
345 361 */
346 362 ASSERT(vcp->iod_rqlist.tqh_first == NULL);
347 363
348 364 if (vcp->vc_tdata)
349 365 SMB_TRAN_DONE(vcp);
350 366
351 367 /*
352 368 * We are not using the iconv routines here. So commenting them for now.
353 369 * REVISIT.
354 370 */
355 371 #ifdef NOTYETDEFINED
356 372 if (vcp->vc_tolower)
357 373 iconv_close(vcp->vc_tolower);
|
↓ open down ↓ |
164 lines elided |
↑ open up ↑ |
358 374 if (vcp->vc_toupper)
359 375 iconv_close(vcp->vc_toupper);
360 376 if (vcp->vc_tolocal)
361 377 iconv_close(vcp->vc_tolocal);
362 378 if (vcp->vc_toserver)
363 379 iconv_close(vcp->vc_toserver);
364 380 #endif
365 381
366 382 if (vcp->vc_mackey != NULL)
367 383 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
384 + if (vcp->vc_ssnkey != NULL)
385 + kmem_free(vcp->vc_ssnkey, vcp->vc_ssnkeylen);
368 386
387 + cv_destroy(&vcp->iod_muxwait);
369 388 cv_destroy(&vcp->iod_idle);
370 389 rw_destroy(&vcp->iod_rqlock);
371 - sema_destroy(&vcp->vc_sendlock);
372 390 cv_destroy(&vcp->vc_statechg);
373 391 smb_co_done(VCTOCP(vcp));
374 392 kmem_free(vcp, sizeof (*vcp));
375 393 }
376 394
377 395 /*ARGSUSED*/
378 396 int
379 397 smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
380 398 {
381 399 static char objtype[] = "smb_vc";
382 400 cred_t *cr = scred->scr_cred;
383 401 struct smb_vc *vcp;
384 402 int error = 0;
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
385 403
386 404 ASSERT(MUTEX_HELD(&smb_vclist.co_lock));
387 405
388 406 vcp = kmem_zalloc(sizeof (struct smb_vc), KM_SLEEP);
389 407
390 408 smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
391 409 vcp->vc_co.co_free = smb_vc_free;
392 410 vcp->vc_co.co_gone = smb_vc_gone;
393 411
394 412 cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
395 - sema_init(&vcp->vc_sendlock, 1, objtype, SEMA_DRIVER, NULL);
396 413 rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
397 414 cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
415 + cv_init(&vcp->iod_muxwait, objtype, CV_DRIVER, NULL);
398 416
399 417 /* Expanded TAILQ_HEAD_INITIALIZER */
400 418 vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
401 419
402 - vcp->vc_state = SMBIOD_ST_IDLE;
420 + /* A brand new VC should connect. */
421 + vcp->vc_state = SMBIOD_ST_RECONNECT;
403 422
404 423 /*
405 424 * These identify the connection.
406 425 */
407 426 vcp->vc_zoneid = getzoneid();
408 427 bcopy(ossn, &vcp->vc_ssn, sizeof (*ossn));
409 428
410 429 /* This fills in vcp->vc_tdata */
411 430 vcp->vc_tdesc = &smb_tran_nbtcp_desc;
412 431 if ((error = SMB_TRAN_CREATE(vcp, cr)) != 0)
413 432 goto errout;
414 433
415 434 /* Success! */
416 435 smb_co_addchild(&smb_vclist, VCTOCP(vcp));
417 436 *vcpp = vcp;
418 437 return (0);
419 438
420 439 errout:
421 440 /*
422 441 * This will destroy the new vc.
423 442 * See: smb_vc_free
424 443 */
425 444 smb_vc_rele(vcp);
426 445 return (error);
427 446 }
428 447
429 448 /*
430 449 * Find or create a VC identified by the info in ossn
431 450 * and return it with a "hold", but not locked.
432 451 */
433 452 /*ARGSUSED*/
434 453 int
435 454 smb_vc_findcreate(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
436 455 {
437 456 struct smb_connobj *co;
438 457 struct smb_vc *vcp;
439 458 smbioc_ssn_ident_t *vc_id;
440 459 int error;
441 460 zoneid_t zoneid = getzoneid();
442 461
443 462 *vcpp = vcp = NULL;
444 463
445 464 SMB_CO_LOCK(&smb_vclist);
446 465
447 466 /* var, head, next_field */
448 467 SLIST_FOREACH(co, &smb_vclist.co_children, co_next) {
449 468 vcp = CPTOVC(co);
450 469
451 470 /*
452 471 * Some things we can check without
453 472 * holding the lock (those that are
454 473 * set at creation and never change).
455 474 */
456 475
457 476 /* VCs in other zones are invisibile. */
458 477 if (vcp->vc_zoneid != zoneid)
459 478 continue;
460 479
461 480 /* Also segregate by Unix owner. */
462 481 if (vcp->vc_owner != ossn->ssn_owner)
463 482 continue;
464 483
465 484 /*
466 485 * Compare identifying info:
467 486 * server address, user, domain
468 487 * names are case-insensitive
469 488 */
470 489 vc_id = &vcp->vc_ssn.ssn_id;
471 490 if (bcmp(&vc_id->id_srvaddr,
472 491 &ossn->ssn_id.id_srvaddr,
473 492 sizeof (vc_id->id_srvaddr)))
474 493 continue;
475 494 if (u8_strcmp(vc_id->id_user, ossn->ssn_id.id_user, 0,
476 495 U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error))
477 496 continue;
478 497 if (u8_strcmp(vc_id->id_domain, ossn->ssn_id.id_domain, 0,
479 498 U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error))
480 499 continue;
481 500
482 501 /*
483 502 * We have a match, but still have to check
484 503 * the _GONE flag, and do that with a lock.
485 504 * No new references when _GONE is set.
486 505 *
487 506 * Also clear SMBVOPT_CREATE which the caller
488 507 * may check to find out if we did create.
489 508 */
490 509 SMB_VC_LOCK(vcp);
491 510 if ((vcp->vc_flags & SMBV_GONE) == 0) {
492 511 ossn->ssn_vopt &= ~SMBVOPT_CREATE;
493 512 /*
494 513 * Return it held, unlocked.
495 514 * In-line smb_vc_hold here.
496 515 */
497 516 co->co_usecount++;
498 517 SMB_VC_UNLOCK(vcp);
499 518 *vcpp = vcp;
500 519 error = 0;
501 520 goto out;
502 521 }
503 522 SMB_VC_UNLOCK(vcp);
504 523 /* keep looking. */
505 524 }
506 525 vcp = NULL;
507 526
508 527 /* Note: smb_vclist is still locked. */
509 528
510 529 if (ossn->ssn_vopt & SMBVOPT_CREATE) {
511 530 /*
512 531 * Create a new VC. It starts out with
513 532 * hold count = 1, so don't incr. here.
514 533 */
515 534 error = smb_vc_create(ossn, scred, &vcp);
516 535 if (error == 0)
517 536 *vcpp = vcp;
518 537 } else
519 538 error = ENOENT;
520 539
521 540 out:
522 541 SMB_CO_UNLOCK(&smb_vclist);
523 542 return (error);
524 543 }
525 544
526 545
527 546 /*
528 547 * Helper functions that operate on VCs
529 548 */
530 549
531 550 /*
532 551 * Get a pointer to the IP address suitable for passing to Trusted
533 552 * Extensions find_tpc() routine. Used by smbfs_mount_label_policy().
534 553 * Compare this code to nfs_mount_label_policy() if problems arise.
535 554 */
536 555 void *
537 556 smb_vc_getipaddr(struct smb_vc *vcp, int *ipvers)
538 557 {
539 558 smbioc_ssn_ident_t *id = &vcp->vc_ssn.ssn_id;
540 559 void *ret;
541 560
542 561 switch (id->id_srvaddr.sa.sa_family) {
543 562 case AF_INET:
544 563 *ipvers = IPV4_VERSION;
545 564 ret = &id->id_srvaddr.sin.sin_addr;
546 565 break;
547 566
548 567 case AF_INET6:
549 568 *ipvers = IPV6_VERSION;
550 569 ret = &id->id_srvaddr.sin6.sin6_addr;
551 570 break;
552 571 default:
553 572 SMBSDEBUG("invalid address family %d\n",
554 573 id->id_srvaddr.sa.sa_family);
555 574 *ipvers = 0;
556 575 ret = NULL;
557 576 break;
558 577 }
559 578 return (ret);
560 579 }
561 580
562 581 void
563 582 smb_vc_walkshares(struct smb_vc *vcp,
564 583 walk_share_func_t func)
565 584 {
566 585 smb_connobj_t *co;
567 586 smb_share_t *ssp;
568 587
569 588 /*
570 589 * Walk the share list calling func(ssp, arg)
571 590 */
572 591 SMB_VC_LOCK(vcp);
573 592 SLIST_FOREACH(co, &(VCTOCP(vcp)->co_children), co_next) {
574 593 ssp = CPTOSS(co);
575 594 SMB_SS_LOCK(ssp);
576 595 func(ssp);
577 596 SMB_SS_UNLOCK(ssp);
578 597 }
579 598 SMB_VC_UNLOCK(vcp);
580 599 }
581 600
582 601
583 602 /*
584 603 * Share implementation
585 604 */
586 605
587 606 void
588 607 smb_share_hold(struct smb_share *ssp)
589 608 {
590 609 smb_co_hold(SSTOCP(ssp));
591 610 }
592 611
593 612 void
594 613 smb_share_rele(struct smb_share *ssp)
595 614 {
596 615 smb_co_rele(SSTOCP(ssp));
597 616 }
598 617
599 618 void
600 619 smb_share_kill(struct smb_share *ssp)
601 620 {
602 621 smb_co_kill(SSTOCP(ssp));
603 622 }
604 623
|
↓ open down ↓ |
192 lines elided |
↑ open up ↑ |
605 624 /*
606 625 * Normally called via smb_share_rele()
607 626 * after co_usecount drops to zero.
608 627 * Also called via: smb_share_kill()
609 628 */
610 629 static void
611 630 smb_share_gone(struct smb_connobj *cp)
612 631 {
613 632 struct smb_cred scred;
614 633 struct smb_share *ssp = CPTOSS(cp);
634 + smb_vc_t *vcp = SSTOVC(ssp);
615 635
616 636 smb_credinit(&scred, NULL);
617 637 smb_iod_shutdown_share(ssp);
618 - (void) smb_smb_treedisconnect(ssp, &scred);
638 + if (vcp->vc_flags & SMBV_SMB2)
639 + (void) smb2_smb_treedisconnect(ssp, &scred);
640 + else
641 + (void) smb_smb_treedisconnect(ssp, &scred);
619 642 smb_credrele(&scred);
620 643 }
621 644
622 645 /*
623 646 * Normally called via smb_share_rele()
624 647 * after co_usecount drops to zero.
625 648 */
626 649 static void
627 650 smb_share_free(struct smb_connobj *cp)
628 651 {
629 652 struct smb_share *ssp = CPTOSS(cp);
630 653
631 654 cv_destroy(&ssp->ss_conn_done);
632 655 smb_co_done(SSTOCP(ssp));
633 656 kmem_free(ssp, sizeof (*ssp));
634 657 }
635 658
636 659 /*
637 660 * Allocate share structure and attach it to the given VC
638 661 * Connection expected to be locked on entry. Share will be returned
639 662 * in locked state.
640 663 */
641 664 /*ARGSUSED*/
642 665 int
643 666 smb_share_create(smbioc_tcon_t *tcon, struct smb_vc *vcp,
644 667 struct smb_share **sspp, struct smb_cred *scred)
645 668 {
646 669 static char objtype[] = "smb_ss";
647 670 struct smb_share *ssp;
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
648 671
649 672 ASSERT(MUTEX_HELD(&vcp->vc_lock));
650 673
651 674 ssp = kmem_zalloc(sizeof (struct smb_share), KM_SLEEP);
652 675 smb_co_init(SSTOCP(ssp), SMBL_SHARE, objtype);
653 676 ssp->ss_co.co_free = smb_share_free;
654 677 ssp->ss_co.co_gone = smb_share_gone;
655 678
656 679 cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
657 680 ssp->ss_tid = SMB_TID_UNKNOWN;
681 + ssp->ss2_tree_id = SMB2_TID_UNKNOWN;
658 682
659 683 bcopy(&tcon->tc_sh, &ssp->ss_ioc,
660 684 sizeof (smbioc_oshare_t));
661 685
662 686 smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
663 687 *sspp = ssp;
664 688
665 689 return (0);
666 690 }
667 691
668 692 /*
669 693 * Find or create a share under the given VC
670 694 * and return it with a "hold", but not locked.
671 695 */
672 696
673 697 int
674 698 smb_share_findcreate(smbioc_tcon_t *tcon, struct smb_vc *vcp,
675 699 struct smb_share **sspp, struct smb_cred *scred)
676 700 {
677 701 struct smb_connobj *co;
678 702 struct smb_share *ssp = NULL;
679 703 int error = 0;
680 704
681 705 *sspp = NULL;
682 706
683 707 SMB_VC_LOCK(vcp);
684 708
685 709 /* var, head, next_field */
686 710 SLIST_FOREACH(co, &(VCTOCP(vcp)->co_children), co_next) {
687 711 ssp = CPTOSS(co);
688 712
689 713 /* Share name */
690 714 if (u8_strcmp(ssp->ss_name, tcon->tc_sh.sh_name, 0,
691 715 U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &error))
692 716 continue;
693 717
694 718 /*
695 719 * We have a match, but still have to check
696 720 * the _GONE flag, and do that with a lock.
697 721 * No new references when _GONE is set.
698 722 *
699 723 * Also clear SMBSOPT_CREATE which the caller
700 724 * may check to find out if we did create.
701 725 */
702 726 SMB_SS_LOCK(ssp);
703 727 if ((ssp->ss_flags & SMBS_GONE) == 0) {
704 728 tcon->tc_opt &= ~SMBSOPT_CREATE;
705 729 /*
706 730 * Return it held, unlocked.
707 731 * In-line smb_share_hold here.
708 732 */
709 733 co->co_usecount++;
710 734 SMB_SS_UNLOCK(ssp);
711 735 *sspp = ssp;
712 736 error = 0;
713 737 goto out;
714 738 }
715 739 SMB_SS_UNLOCK(ssp);
716 740 /* keep looking. */
717 741 }
718 742 ssp = NULL;
719 743
720 744 /* Note: vcp (list of shares) is still locked. */
721 745
722 746 if (tcon->tc_opt & SMBSOPT_CREATE) {
723 747 /*
724 748 * Create a new share. It starts out with
725 749 * hold count = 1, so don't incr. here.
726 750 */
727 751 error = smb_share_create(tcon, vcp, &ssp, scred);
728 752 if (error == 0)
729 753 *sspp = ssp;
730 754 } else
731 755 error = ENOENT;
732 756
733 757 out:
734 758 SMB_VC_UNLOCK(vcp);
735 759 return (error);
736 760 }
737 761
738 762
739 763 /*
740 764 * Helper functions that operate on shares
741 765 */
742 766
743 767 /*
744 768 * Mark this share as invalid, so consumers will know
745 769 * their file handles have become invalid.
746 770 *
747 771 * Most share consumers store a copy of ss_vcgenid when
748 772 * opening a file handle and compare that with what's in
749 773 * the share before using a file handle. If the genid
750 774 * doesn't match, the file handle has become "stale"
751 775 * due to disconnect. Therefore, zap ss_vcgenid here.
752 776 */
753 777 void
754 778 smb_share_invalidate(struct smb_share *ssp)
755 779 {
756 780
757 781 ASSERT(MUTEX_HELD(&ssp->ss_lock));
758 782
759 783 ssp->ss_flags &= ~SMBS_CONNECTED;
760 784 ssp->ss_tid = SMB_TID_UNKNOWN;
761 785 ssp->ss_vcgenid = 0;
762 786 }
|
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
763 787
764 788 /*
765 789 * Connect (or reconnect) a share object.
766 790 *
767 791 * Called by smb_usr_get_tree() for new connections,
768 792 * and called by smb_rq_enqueue() for reconnect.
769 793 */
770 794 int
771 795 smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
772 796 {
797 + smb_vc_t *vcp = SSTOVC(ssp);
773 798 clock_t tmo;
774 799 int error;
775 800
776 801 SMB_SS_LOCK(ssp);
777 802
778 803 if (ssp->ss_flags & SMBS_CONNECTED) {
779 804 SMBIODEBUG("alread connected?");
780 805 error = 0;
781 806 goto out;
782 807 }
783 808
784 809 /*
785 810 * Wait for completion of any state changes
786 811 * that might be underway.
787 812 */
788 813 while (ssp->ss_flags & SMBS_RECONNECTING) {
789 814 ssp->ss_conn_waiters++;
790 815 tmo = cv_wait_sig(&ssp->ss_conn_done, &ssp->ss_lock);
791 816 ssp->ss_conn_waiters--;
792 817 if (tmo == 0) {
793 818 /* Interrupt! */
794 819 error = EINTR;
795 820 goto out;
796 821 }
797 822 }
798 823
799 824 /* Did someone else do it for us? */
800 825 if (ssp->ss_flags & SMBS_CONNECTED) {
801 826 error = 0;
802 827 goto out;
803 828 }
804 829
805 830 /*
|
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
806 831 * OK, we'll do the work.
807 832 */
808 833 ssp->ss_flags |= SMBS_RECONNECTING;
809 834
810 835 /*
811 836 * Drop the lock while doing the TCON.
812 837 * On success, sets ss_tid, ss_vcgenid,
813 838 * and ss_flags |= SMBS_CONNECTED;
814 839 */
815 840 SMB_SS_UNLOCK(ssp);
816 - error = smb_smb_treeconnect(ssp, scred);
841 + if (vcp->vc_flags & SMBV_SMB2)
842 + error = smb2_smb_treeconnect(ssp, scred);
843 + else
844 + error = smb_smb_treeconnect(ssp, scred);
817 845 SMB_SS_LOCK(ssp);
818 846
819 847 ssp->ss_flags &= ~SMBS_RECONNECTING;
820 848
821 849 /* They can all go ahead! */
822 850 if (ssp->ss_conn_waiters)
823 851 cv_broadcast(&ssp->ss_conn_done);
824 852
825 853 out:
826 854 SMB_SS_UNLOCK(ssp);
827 855
828 856 return (error);
829 857 }
830 858
831 859 /*
860 + * File handle level functions
861 + */
862 +
863 +void
864 +smb_fh_hold(struct smb_fh *fhp)
865 +{
866 + smb_co_hold(FHTOCP(fhp));
867 +}
868 +
869 +void
870 +smb_fh_rele(struct smb_fh *fhp)
871 +{
872 + smb_co_rele(FHTOCP(fhp));
873 +}
874 +
875 +void
876 +smb_fh_close(struct smb_fh *fhp)
877 +{
878 + smb_co_kill(FHTOCP(fhp));
879 +}
880 +
881 +/*
882 + * Normally called via smb_fh_rele()
883 + * after co_usecount drops to zero.
884 + * Also called via: smb_fh_kill()
885 + */
886 +static void
887 +smb_fh_gone(struct smb_connobj *cp)
888 +{
889 + struct smb_cred scred;
890 + struct smb_fh *fhp = CPTOFH(cp);
891 + smb_share_t *ssp = FHTOSS(fhp);
892 + int err;
893 +
894 + if ((fhp->fh_flags & SMBFH_VALID) == 0)
895 + return;
896 +
897 + /*
898 + * We have no durable handles (yet) so if there has been a
899 + * reconnect, don't bother to close this handle.
900 + */
901 + if (fhp->fh_vcgenid != ssp->ss_vcgenid)
902 + return;
903 +
904 + smb_credinit(&scred, NULL);
905 + err = smb_smb_close(ssp, fhp, &scred);
906 + smb_credrele(&scred);
907 + if (err) {
908 + SMBSDEBUG("close err=%d\n", err);
909 + }
910 +}
911 +
912 +/*
913 + * Normally called via smb_fh_rele()
914 + * after co_usecount drops to zero.
915 + */
916 +static void
917 +smb_fh_free(struct smb_connobj *cp)
918 +{
919 + struct smb_fh *fhp = CPTOFH(cp);
920 +
921 + smb_co_done(FHTOCP(fhp));
922 + kmem_free(fhp, sizeof (*fhp));
923 +}
924 +
925 +/*
926 + * Allocate fh structure and attach it to the given share.
927 + * Share expected to be locked on entry.
928 + */
929 +/*ARGSUSED*/
930 +int
931 +smb_fh_create(smb_share_t *ssp, struct smb_fh **fhpp)
932 +{
933 + static char objtype[] = "smb_fh";
934 + struct smb_fh *fhp;
935 +
936 + fhp = kmem_zalloc(sizeof (struct smb_fh), KM_SLEEP);
937 + smb_co_init(FHTOCP(fhp), SMBL_FH, objtype);
938 + fhp->fh_co.co_free = smb_fh_free;
939 + fhp->fh_co.co_gone = smb_fh_gone;
940 +
941 + SMB_SS_LOCK(ssp);
942 + if ((ssp->ss_flags & SMBS_GONE) != 0) {
943 + SMB_SS_UNLOCK(ssp);
944 + smb_fh_free(FHTOCP(fhp));
945 + return (ENOTCONN);
946 + }
947 +
948 + smb_co_addchild(SSTOCP(ssp), FHTOCP(fhp));
949 + *fhpp = fhp;
950 + SMB_SS_UNLOCK(ssp);
951 +
952 + return (0);
953 +}
954 +
955 +void
956 +smb_fh_opened(struct smb_fh *fhp)
957 +{
958 + smb_share_t *ssp = FHTOSS(fhp);
959 +
960 + SMB_FH_LOCK(fhp);
961 + fhp->fh_vcgenid = ssp->ss_vcgenid;
962 + fhp->fh_flags |= SMBFH_VALID;
963 + SMB_FH_UNLOCK(fhp);
964 +}
965 +
966 +
967 +/*
832 968 * Solaris zones support
833 969 */
834 970 /*ARGSUSED*/
835 971 void
836 972 lingering_vc(struct smb_vc *vc)
837 973 {
838 974 /* good place for a breakpoint */
839 975 DEBUG_ENTER("lingering VC");
840 976 }
841 977
842 978 /*
843 979 * On zone shutdown, kill any IOD threads still running in this zone.
844 980 */
845 981 /* ARGSUSED */
846 982 void
847 983 nsmb_zone_shutdown(zoneid_t zoneid, void *data)
848 984 {
849 985 struct smb_connobj *co;
850 986 struct smb_vc *vcp;
851 987
852 988 SMB_CO_LOCK(&smb_vclist);
853 989 SLIST_FOREACH(co, &smb_vclist.co_children, co_next) {
854 990 vcp = CPTOVC(co);
855 991
856 992 if (vcp->vc_zoneid != zoneid)
857 993 continue;
858 994
859 995 /*
860 996 * This will close the connection, and
861 997 * cause the IOD thread to terminate.
862 998 */
863 999 smb_vc_kill(vcp);
864 1000 }
865 1001 SMB_CO_UNLOCK(&smb_vclist);
866 1002 }
867 1003
868 1004 /*
869 1005 * On zone destroy, kill any IOD threads and free all resources they used.
870 1006 */
871 1007 /* ARGSUSED */
872 1008 void
873 1009 nsmb_zone_destroy(zoneid_t zoneid, void *data)
874 1010 {
875 1011 struct smb_connobj *co;
876 1012 struct smb_vc *vcp;
877 1013
878 1014 /*
879 1015 * We will repeat what should have already happened
880 1016 * in zone_shutdown to make things go away.
881 1017 *
882 1018 * There should have been an smb_vc_rele call
883 1019 * by now for all VCs in the zone. If not,
884 1020 * there's probably more we needed to do in
885 1021 * the shutdown call.
886 1022 */
887 1023
888 1024 SMB_CO_LOCK(&smb_vclist);
889 1025
890 1026 if (smb_vclist.co_usecount > 1) {
891 1027 SMBERROR("%d connections still active\n",
892 1028 smb_vclist.co_usecount - 1);
893 1029 }
894 1030
895 1031 /* var, head, next_field */
896 1032 SLIST_FOREACH(co, &smb_vclist.co_children, co_next) {
897 1033 vcp = CPTOVC(co);
898 1034
899 1035 if (vcp->vc_zoneid != zoneid)
900 1036 continue;
901 1037
902 1038 /* Debugging */
903 1039 lingering_vc(vcp);
904 1040 }
905 1041
906 1042 SMB_CO_UNLOCK(&smb_vclist);
907 1043 }
|
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX