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
↓ 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>
↓ 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  {
↓ 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
↓ 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.
↓ 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";
↓ 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)
↓ 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  {
↓ 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  
↓ 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          }
↓ 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  
↓ open down ↓ 66 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX