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)


  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
  33  */
  34 /*
  35  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  36  * Use is subject to license terms.


  37  */
  38 
  39 /*
  40  * Connection engine.
  41  */
  42 
  43 #include <sys/param.h>
  44 #include <sys/systm.h>
  45 #include <sys/kmem.h>
  46 #include <sys/proc.h>
  47 #include <sys/lock.h>
  48 #include <sys/vnode.h>
  49 #include <sys/stream.h>
  50 #include <sys/stropts.h>
  51 #include <sys/socketvar.h>
  52 #include <sys/cred.h>
  53 #include <netinet/in.h>
  54 #include <inet/ip.h>
  55 #include <inet/ip6.h>
  56 #include <sys/cmn_err.h>
  57 #include <sys/thread.h>
  58 #include <sys/atomic.h>
  59 #include <sys/u8_textprep.h>
  60 
  61 #include <netsmb/smb_osdep.h>
  62 
  63 #include <netsmb/smb.h>

  64 #include <netsmb/smb_conn.h>
  65 #include <netsmb/smb_subr.h>
  66 #include <netsmb/smb_tran.h>
  67 #include <netsmb/smb_pass.h>
  68 
  69 static struct smb_connobj smb_vclist;
  70 
  71 void smb_co_init(struct smb_connobj *cp, int level, char *objname);
  72 void smb_co_done(struct smb_connobj *cp);
  73 void smb_co_hold(struct smb_connobj *cp);
  74 void smb_co_rele(struct smb_connobj *cp);
  75 void smb_co_kill(struct smb_connobj *cp);
  76 
  77 static void smb_vc_free(struct smb_connobj *cp);
  78 static void smb_vc_gone(struct smb_connobj *cp);
  79 
  80 static void smb_share_free(struct smb_connobj *cp);
  81 static void smb_share_gone(struct smb_connobj *cp);
  82 



  83 int
  84 smb_sm_init(void)
  85 {
  86         smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
  87         return (0);
  88 }
  89 
  90 int
  91 smb_sm_idle(void)
  92 {
  93         int error = 0;
  94         SMB_CO_LOCK(&smb_vclist);
  95         if (smb_vclist.co_usecount > 1) {
  96                 SMBSDEBUG("%d connections still active\n",
  97                     smb_vclist.co_usecount - 1);
  98                 error = EBUSY;
  99         }
 100         SMB_CO_UNLOCK(&smb_vclist);
 101         return (error);
 102 }
 103 
 104 void
 105 smb_sm_done(void)
 106 {
 107         /*
 108          * XXX Q4BP why are we not iterating on smb_vclist here?
 109          * Because the caller has just called smb_sm_idle() to
 110          * make sure we have no VCs before calling this.
 111          */
 112         smb_co_done(&smb_vclist);
 113 }
 114 
 115 
 116 
 117 /*
 118  * Common code for connection object
 119  */
 120 /*ARGSUSED*/
 121 void
 122 smb_co_init(struct smb_connobj *cp, int level, char *objname)
 123 {
 124 
 125         mutex_init(&cp->co_lock, objname,  MUTEX_DRIVER, NULL);
 126 
 127         cp->co_level = level;
 128         cp->co_usecount = 1;


 164 }
 165 
 166 void
 167 smb_co_hold(struct smb_connobj *cp)
 168 {
 169         SMB_CO_LOCK(cp);
 170         cp->co_usecount++;
 171         SMB_CO_UNLOCK(cp);
 172 }
 173 
 174 /*
 175  * Called via smb_vc_rele, smb_share_rele
 176  */
 177 void
 178 smb_co_rele(struct smb_connobj *co)
 179 {
 180         struct smb_connobj *parent;
 181         int old_flags;
 182 
 183         SMB_CO_LOCK(co);










 184         if (co->co_usecount > 1) {
 185                 co->co_usecount--;
 186                 SMB_CO_UNLOCK(co);
 187                 return;
 188         }
 189         ASSERT(co->co_usecount == 1);
 190         co->co_usecount = 0;
 191 
 192         /*
 193          * This list of children should be empty now.
 194          * Check this while we're still linked, so
 195          * we have a better chance of debugging.
 196          */
 197         ASSERT(SLIST_EMPTY(&co->co_children));
 198 
 199         /*
 200          * OK, this element is going away.
 201          *
 202          * We need to drop the lock on this CO so we can take the
 203          * parent CO lock. The _GONE flag prevents this CO from


 348         if (vcp->vc_tdata)
 349                 SMB_TRAN_DONE(vcp);
 350 
 351 /*
 352  * We are not using the iconv routines here. So commenting them for now.
 353  * REVISIT.
 354  */
 355 #ifdef NOTYETDEFINED
 356         if (vcp->vc_tolower)
 357                 iconv_close(vcp->vc_tolower);
 358         if (vcp->vc_toupper)
 359                 iconv_close(vcp->vc_toupper);
 360         if (vcp->vc_tolocal)
 361                 iconv_close(vcp->vc_tolocal);
 362         if (vcp->vc_toserver)
 363                 iconv_close(vcp->vc_toserver);
 364 #endif
 365 
 366         if (vcp->vc_mackey != NULL)
 367                 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);


 368 

 369         cv_destroy(&vcp->iod_idle);
 370         rw_destroy(&vcp->iod_rqlock);
 371         sema_destroy(&vcp->vc_sendlock);
 372         cv_destroy(&vcp->vc_statechg);
 373         smb_co_done(VCTOCP(vcp));
 374         kmem_free(vcp, sizeof (*vcp));
 375 }
 376 
 377 /*ARGSUSED*/
 378 int
 379 smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
 380 {
 381         static char objtype[] = "smb_vc";
 382         cred_t *cr = scred->scr_cred;
 383         struct smb_vc *vcp;
 384         int error = 0;
 385 
 386         ASSERT(MUTEX_HELD(&smb_vclist.co_lock));
 387 
 388         vcp = kmem_zalloc(sizeof (struct smb_vc), KM_SLEEP);
 389 
 390         smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
 391         vcp->vc_co.co_free = smb_vc_free;
 392         vcp->vc_co.co_gone = smb_vc_gone;
 393 
 394         cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
 395         sema_init(&vcp->vc_sendlock, 1, objtype, SEMA_DRIVER, NULL);
 396         rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
 397         cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);

 398 
 399         /* Expanded TAILQ_HEAD_INITIALIZER */
 400         vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
 401 
 402         vcp->vc_state = SMBIOD_ST_IDLE;

 403 
 404         /*
 405          * These identify the connection.
 406          */
 407         vcp->vc_zoneid = getzoneid();
 408         bcopy(ossn, &vcp->vc_ssn, sizeof (*ossn));
 409 
 410         /* This fills in vcp->vc_tdata */
 411         vcp->vc_tdesc = &smb_tran_nbtcp_desc;
 412         if ((error = SMB_TRAN_CREATE(vcp, cr)) != 0)
 413                 goto errout;
 414 
 415         /* Success! */
 416         smb_co_addchild(&smb_vclist, VCTOCP(vcp));
 417         *vcpp = vcp;
 418         return (0);
 419 
 420 errout:
 421         /*
 422          * This will destroy the new vc.


 595 {
 596         smb_co_rele(SSTOCP(ssp));
 597 }
 598 
 599 void
 600 smb_share_kill(struct smb_share *ssp)
 601 {
 602         smb_co_kill(SSTOCP(ssp));
 603 }
 604 
 605 /*
 606  * Normally called via smb_share_rele()
 607  * after co_usecount drops to zero.
 608  * Also called via: smb_share_kill()
 609  */
 610 static void
 611 smb_share_gone(struct smb_connobj *cp)
 612 {
 613         struct smb_cred scred;
 614         struct smb_share *ssp = CPTOSS(cp);

 615 
 616         smb_credinit(&scred, NULL);
 617         smb_iod_shutdown_share(ssp);



 618         (void) smb_smb_treedisconnect(ssp, &scred);
 619         smb_credrele(&scred);
 620 }
 621 
 622 /*
 623  * Normally called via smb_share_rele()
 624  * after co_usecount drops to zero.
 625  */
 626 static void
 627 smb_share_free(struct smb_connobj *cp)
 628 {
 629         struct smb_share *ssp = CPTOSS(cp);
 630 
 631         cv_destroy(&ssp->ss_conn_done);
 632         smb_co_done(SSTOCP(ssp));
 633         kmem_free(ssp, sizeof (*ssp));
 634 }
 635 
 636 /*
 637  * Allocate share structure and attach it to the given VC
 638  * Connection expected to be locked on entry. Share will be returned
 639  * in locked state.
 640  */
 641 /*ARGSUSED*/
 642 int
 643 smb_share_create(smbioc_tcon_t *tcon, struct smb_vc *vcp,
 644         struct smb_share **sspp, struct smb_cred *scred)
 645 {
 646         static char objtype[] = "smb_ss";
 647         struct smb_share *ssp;
 648 
 649         ASSERT(MUTEX_HELD(&vcp->vc_lock));
 650 
 651         ssp = kmem_zalloc(sizeof (struct smb_share), KM_SLEEP);
 652         smb_co_init(SSTOCP(ssp), SMBL_SHARE, objtype);
 653         ssp->ss_co.co_free = smb_share_free;
 654         ssp->ss_co.co_gone = smb_share_gone;
 655 
 656         cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
 657         ssp->ss_tid = SMB_TID_UNKNOWN;

 658 
 659         bcopy(&tcon->tc_sh, &ssp->ss_ioc,
 660             sizeof (smbioc_oshare_t));
 661 
 662         smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
 663         *sspp = ssp;
 664 
 665         return (0);
 666 }
 667 
 668 /*
 669  * Find or create a share under the given VC
 670  * and return it with a "hold", but not locked.
 671  */
 672 
 673 int
 674 smb_share_findcreate(smbioc_tcon_t *tcon, struct smb_vc *vcp,
 675         struct smb_share **sspp, struct smb_cred *scred)
 676 {
 677         struct smb_connobj *co;


 753 void
 754 smb_share_invalidate(struct smb_share *ssp)
 755 {
 756 
 757         ASSERT(MUTEX_HELD(&ssp->ss_lock));
 758 
 759         ssp->ss_flags &= ~SMBS_CONNECTED;
 760         ssp->ss_tid = SMB_TID_UNKNOWN;
 761         ssp->ss_vcgenid = 0;
 762 }
 763 
 764 /*
 765  * Connect (or reconnect) a share object.
 766  *
 767  * Called by smb_usr_get_tree() for new connections,
 768  * and called by smb_rq_enqueue() for reconnect.
 769  */
 770 int
 771 smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
 772 {

 773         clock_t tmo;
 774         int error;
 775 
 776         SMB_SS_LOCK(ssp);
 777 
 778         if (ssp->ss_flags & SMBS_CONNECTED) {
 779                 SMBIODEBUG("alread connected?");
 780                 error = 0;
 781                 goto out;
 782         }
 783 
 784         /*
 785          * Wait for completion of any state changes
 786          * that might be underway.
 787          */
 788         while (ssp->ss_flags & SMBS_RECONNECTING) {
 789                 ssp->ss_conn_waiters++;
 790                 tmo = cv_wait_sig(&ssp->ss_conn_done, &ssp->ss_lock);
 791                 ssp->ss_conn_waiters--;
 792                 if (tmo == 0) {


 796                 }
 797         }
 798 
 799         /* Did someone else do it for us? */
 800         if (ssp->ss_flags & SMBS_CONNECTED) {
 801                 error = 0;
 802                 goto out;
 803         }
 804 
 805         /*
 806          * OK, we'll do the work.
 807          */
 808         ssp->ss_flags |= SMBS_RECONNECTING;
 809 
 810         /*
 811          * Drop the lock while doing the TCON.
 812          * On success, sets ss_tid, ss_vcgenid,
 813          * and ss_flags |= SMBS_CONNECTED;
 814          */
 815         SMB_SS_UNLOCK(ssp);



 816         error = smb_smb_treeconnect(ssp, scred);
 817         SMB_SS_LOCK(ssp);
 818 
 819         ssp->ss_flags &= ~SMBS_RECONNECTING;
 820 
 821         /* They can all go ahead! */
 822         if (ssp->ss_conn_waiters)
 823                 cv_broadcast(&ssp->ss_conn_done);
 824 
 825 out:
 826         SMB_SS_UNLOCK(ssp);
 827 
 828         return (error);
 829 }
 830 
 831 /*












































































































 832  * Solaris zones support
 833  */
 834 /*ARGSUSED*/
 835 void
 836 lingering_vc(struct smb_vc *vc)
 837 {
 838         /* good place for a breakpoint */
 839         DEBUG_ENTER("lingering VC");
 840 }
 841 
 842 /*
 843  * On zone shutdown, kill any IOD threads still running in this zone.
 844  */
 845 /* ARGSUSED */
 846 void
 847 nsmb_zone_shutdown(zoneid_t zoneid, void *data)
 848 {
 849         struct smb_connobj *co;
 850         struct smb_vc *vcp;
 851 




  17  *    may be used to endorse or promote products derived from this software
  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
  33  */
  34 /*
  35  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  36  * Use is subject to license terms.
  37  *
  38  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  39  */
  40 
  41 /*
  42  * Connection engine.
  43  */
  44 
  45 #include <sys/param.h>
  46 #include <sys/systm.h>
  47 #include <sys/kmem.h>
  48 #include <sys/proc.h>
  49 #include <sys/lock.h>
  50 #include <sys/vnode.h>
  51 #include <sys/stream.h>
  52 #include <sys/stropts.h>
  53 #include <sys/socketvar.h>
  54 #include <sys/cred.h>
  55 #include <netinet/in.h>
  56 #include <inet/ip.h>
  57 #include <inet/ip6.h>
  58 #include <sys/cmn_err.h>
  59 #include <sys/thread.h>
  60 #include <sys/atomic.h>
  61 #include <sys/u8_textprep.h>
  62 
  63 #include <netsmb/smb_osdep.h>
  64 
  65 #include <netsmb/smb.h>
  66 #include <netsmb/smb2.h>
  67 #include <netsmb/smb_conn.h>
  68 #include <netsmb/smb_subr.h>
  69 #include <netsmb/smb_tran.h>
  70 #include <netsmb/smb_pass.h>
  71 
  72 static struct smb_connobj smb_vclist;
  73 
  74 void smb_co_init(struct smb_connobj *cp, int level, char *objname);
  75 void smb_co_done(struct smb_connobj *cp);
  76 void smb_co_hold(struct smb_connobj *cp);
  77 void smb_co_rele(struct smb_connobj *cp);
  78 void smb_co_kill(struct smb_connobj *cp);
  79 
  80 static void smb_vc_free(struct smb_connobj *cp);
  81 static void smb_vc_gone(struct smb_connobj *cp);
  82 
  83 static void smb_share_free(struct smb_connobj *cp);
  84 static void smb_share_gone(struct smb_connobj *cp);
  85 
  86 static void smb_fh_free(struct smb_connobj *cp);
  87 static void smb_fh_gone(struct smb_connobj *cp);
  88 
  89 int
  90 smb_sm_init(void)
  91 {
  92         smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
  93         return (0);
  94 }
  95 
  96 int
  97 smb_sm_idle(void)
  98 {
  99         int error = 0;
 100         SMB_CO_LOCK(&smb_vclist);
 101         if (smb_vclist.co_usecount > 1) {
 102                 SMBSDEBUG("%d connections still active\n",
 103                     smb_vclist.co_usecount - 1);
 104                 error = EBUSY;
 105         }
 106         SMB_CO_UNLOCK(&smb_vclist);
 107         return (error);
 108 }
 109 
 110 void
 111 smb_sm_done(void)
 112 {
 113         /*
 114          * Why are we not iterating on smb_vclist here?
 115          * Because the caller has just called smb_sm_idle() to
 116          * make sure we have no VCs before calling this.
 117          */
 118         smb_co_done(&smb_vclist);
 119 }
 120 
 121 
 122 
 123 /*
 124  * Common code for connection object
 125  */
 126 /*ARGSUSED*/
 127 void
 128 smb_co_init(struct smb_connobj *cp, int level, char *objname)
 129 {
 130 
 131         mutex_init(&cp->co_lock, objname,  MUTEX_DRIVER, NULL);
 132 
 133         cp->co_level = level;
 134         cp->co_usecount = 1;


 170 }
 171 
 172 void
 173 smb_co_hold(struct smb_connobj *cp)
 174 {
 175         SMB_CO_LOCK(cp);
 176         cp->co_usecount++;
 177         SMB_CO_UNLOCK(cp);
 178 }
 179 
 180 /*
 181  * Called via smb_vc_rele, smb_share_rele
 182  */
 183 void
 184 smb_co_rele(struct smb_connobj *co)
 185 {
 186         struct smb_connobj *parent;
 187         int old_flags;
 188 
 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         }
 200         if (co->co_usecount > 1) {
 201                 co->co_usecount--;
 202                 SMB_CO_UNLOCK(co);
 203                 return;
 204         }
 205         ASSERT(co->co_usecount == 1);
 206         co->co_usecount = 0;
 207 
 208         /*
 209          * This list of children should be empty now.
 210          * Check this while we're still linked, so
 211          * we have a better chance of debugging.
 212          */
 213         ASSERT(SLIST_EMPTY(&co->co_children));
 214 
 215         /*
 216          * OK, this element is going away.
 217          *
 218          * We need to drop the lock on this CO so we can take the
 219          * parent CO lock. The _GONE flag prevents this CO from


 364         if (vcp->vc_tdata)
 365                 SMB_TRAN_DONE(vcp);
 366 
 367 /*
 368  * We are not using the iconv routines here. So commenting them for now.
 369  * REVISIT.
 370  */
 371 #ifdef NOTYETDEFINED
 372         if (vcp->vc_tolower)
 373                 iconv_close(vcp->vc_tolower);
 374         if (vcp->vc_toupper)
 375                 iconv_close(vcp->vc_toupper);
 376         if (vcp->vc_tolocal)
 377                 iconv_close(vcp->vc_tolocal);
 378         if (vcp->vc_toserver)
 379                 iconv_close(vcp->vc_toserver);
 380 #endif
 381 
 382         if (vcp->vc_mackey != NULL)
 383                 kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
 384         if (vcp->vc_ssnkey != NULL)
 385                 kmem_free(vcp->vc_ssnkey, vcp->vc_ssnkeylen);
 386 
 387         cv_destroy(&vcp->iod_muxwait);
 388         cv_destroy(&vcp->iod_idle);
 389         rw_destroy(&vcp->iod_rqlock);

 390         cv_destroy(&vcp->vc_statechg);
 391         smb_co_done(VCTOCP(vcp));
 392         kmem_free(vcp, sizeof (*vcp));
 393 }
 394 
 395 /*ARGSUSED*/
 396 int
 397 smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp)
 398 {
 399         static char objtype[] = "smb_vc";
 400         cred_t *cr = scred->scr_cred;
 401         struct smb_vc *vcp;
 402         int error = 0;
 403 
 404         ASSERT(MUTEX_HELD(&smb_vclist.co_lock));
 405 
 406         vcp = kmem_zalloc(sizeof (struct smb_vc), KM_SLEEP);
 407 
 408         smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
 409         vcp->vc_co.co_free = smb_vc_free;
 410         vcp->vc_co.co_gone = smb_vc_gone;
 411 
 412         cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);

 413         rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
 414         cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
 415         cv_init(&vcp->iod_muxwait, objtype, CV_DRIVER, NULL);
 416 
 417         /* Expanded TAILQ_HEAD_INITIALIZER */
 418         vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
 419 
 420         /* A brand new VC should connect. */
 421         vcp->vc_state = SMBIOD_ST_RECONNECT;
 422 
 423         /*
 424          * These identify the connection.
 425          */
 426         vcp->vc_zoneid = getzoneid();
 427         bcopy(ossn, &vcp->vc_ssn, sizeof (*ossn));
 428 
 429         /* This fills in vcp->vc_tdata */
 430         vcp->vc_tdesc = &smb_tran_nbtcp_desc;
 431         if ((error = SMB_TRAN_CREATE(vcp, cr)) != 0)
 432                 goto errout;
 433 
 434         /* Success! */
 435         smb_co_addchild(&smb_vclist, VCTOCP(vcp));
 436         *vcpp = vcp;
 437         return (0);
 438 
 439 errout:
 440         /*
 441          * This will destroy the new vc.


 614 {
 615         smb_co_rele(SSTOCP(ssp));
 616 }
 617 
 618 void
 619 smb_share_kill(struct smb_share *ssp)
 620 {
 621         smb_co_kill(SSTOCP(ssp));
 622 }
 623 
 624 /*
 625  * Normally called via smb_share_rele()
 626  * after co_usecount drops to zero.
 627  * Also called via: smb_share_kill()
 628  */
 629 static void
 630 smb_share_gone(struct smb_connobj *cp)
 631 {
 632         struct smb_cred scred;
 633         struct smb_share *ssp = CPTOSS(cp);
 634         smb_vc_t *vcp = SSTOVC(ssp);
 635 
 636         smb_credinit(&scred, NULL);
 637         smb_iod_shutdown_share(ssp);
 638         if (vcp->vc_flags & SMBV_SMB2)
 639                 (void) smb2_smb_treedisconnect(ssp, &scred);
 640         else
 641                 (void) smb_smb_treedisconnect(ssp, &scred);
 642         smb_credrele(&scred);
 643 }
 644 
 645 /*
 646  * Normally called via smb_share_rele()
 647  * after co_usecount drops to zero.
 648  */
 649 static void
 650 smb_share_free(struct smb_connobj *cp)
 651 {
 652         struct smb_share *ssp = CPTOSS(cp);
 653 
 654         cv_destroy(&ssp->ss_conn_done);
 655         smb_co_done(SSTOCP(ssp));
 656         kmem_free(ssp, sizeof (*ssp));
 657 }
 658 
 659 /*
 660  * Allocate share structure and attach it to the given VC
 661  * Connection expected to be locked on entry. Share will be returned
 662  * in locked state.
 663  */
 664 /*ARGSUSED*/
 665 int
 666 smb_share_create(smbioc_tcon_t *tcon, struct smb_vc *vcp,
 667         struct smb_share **sspp, struct smb_cred *scred)
 668 {
 669         static char objtype[] = "smb_ss";
 670         struct smb_share *ssp;
 671 
 672         ASSERT(MUTEX_HELD(&vcp->vc_lock));
 673 
 674         ssp = kmem_zalloc(sizeof (struct smb_share), KM_SLEEP);
 675         smb_co_init(SSTOCP(ssp), SMBL_SHARE, objtype);
 676         ssp->ss_co.co_free = smb_share_free;
 677         ssp->ss_co.co_gone = smb_share_gone;
 678 
 679         cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
 680         ssp->ss_tid = SMB_TID_UNKNOWN;
 681         ssp->ss2_tree_id = SMB2_TID_UNKNOWN;
 682 
 683         bcopy(&tcon->tc_sh, &ssp->ss_ioc,
 684             sizeof (smbioc_oshare_t));
 685 
 686         smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
 687         *sspp = ssp;
 688 
 689         return (0);
 690 }
 691 
 692 /*
 693  * Find or create a share under the given VC
 694  * and return it with a "hold", but not locked.
 695  */
 696 
 697 int
 698 smb_share_findcreate(smbioc_tcon_t *tcon, struct smb_vc *vcp,
 699         struct smb_share **sspp, struct smb_cred *scred)
 700 {
 701         struct smb_connobj *co;


 777 void
 778 smb_share_invalidate(struct smb_share *ssp)
 779 {
 780 
 781         ASSERT(MUTEX_HELD(&ssp->ss_lock));
 782 
 783         ssp->ss_flags &= ~SMBS_CONNECTED;
 784         ssp->ss_tid = SMB_TID_UNKNOWN;
 785         ssp->ss_vcgenid = 0;
 786 }
 787 
 788 /*
 789  * Connect (or reconnect) a share object.
 790  *
 791  * Called by smb_usr_get_tree() for new connections,
 792  * and called by smb_rq_enqueue() for reconnect.
 793  */
 794 int
 795 smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
 796 {
 797         smb_vc_t *vcp = SSTOVC(ssp);
 798         clock_t tmo;
 799         int error;
 800 
 801         SMB_SS_LOCK(ssp);
 802 
 803         if (ssp->ss_flags & SMBS_CONNECTED) {
 804                 SMBIODEBUG("alread connected?");
 805                 error = 0;
 806                 goto out;
 807         }
 808 
 809         /*
 810          * Wait for completion of any state changes
 811          * that might be underway.
 812          */
 813         while (ssp->ss_flags & SMBS_RECONNECTING) {
 814                 ssp->ss_conn_waiters++;
 815                 tmo = cv_wait_sig(&ssp->ss_conn_done, &ssp->ss_lock);
 816                 ssp->ss_conn_waiters--;
 817                 if (tmo == 0) {


 821                 }
 822         }
 823 
 824         /* Did someone else do it for us? */
 825         if (ssp->ss_flags & SMBS_CONNECTED) {
 826                 error = 0;
 827                 goto out;
 828         }
 829 
 830         /*
 831          * OK, we'll do the work.
 832          */
 833         ssp->ss_flags |= SMBS_RECONNECTING;
 834 
 835         /*
 836          * Drop the lock while doing the TCON.
 837          * On success, sets ss_tid, ss_vcgenid,
 838          * and ss_flags |= SMBS_CONNECTED;
 839          */
 840         SMB_SS_UNLOCK(ssp);
 841         if (vcp->vc_flags & SMBV_SMB2)
 842                 error = smb2_smb_treeconnect(ssp, scred);
 843         else
 844                 error = smb_smb_treeconnect(ssp, scred);
 845         SMB_SS_LOCK(ssp);
 846 
 847         ssp->ss_flags &= ~SMBS_RECONNECTING;
 848 
 849         /* They can all go ahead! */
 850         if (ssp->ss_conn_waiters)
 851                 cv_broadcast(&ssp->ss_conn_done);
 852 
 853 out:
 854         SMB_SS_UNLOCK(ssp);
 855 
 856         return (error);
 857 }
 858 
 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 /*
 968  * Solaris zones support
 969  */
 970 /*ARGSUSED*/
 971 void
 972 lingering_vc(struct smb_vc *vc)
 973 {
 974         /* good place for a breakpoint */
 975         DEBUG_ENTER("lingering VC");
 976 }
 977 
 978 /*
 979  * On zone shutdown, kill any IOD threads still running in this zone.
 980  */
 981 /* ARGSUSED */
 982 void
 983 nsmb_zone_shutdown(zoneid_t zoneid, void *data)
 984 {
 985         struct smb_connobj *co;
 986         struct smb_vc *vcp;
 987