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)
*** 32,41 ****
--- 32,43 ----
* $Id: smb_conn.c,v 1.27.166.1 2005/05/27 02:35:29 lindak Exp $
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Connection engine.
*/
*** 59,68 ****
--- 61,71 ----
#include <sys/u8_textprep.h>
#include <netsmb/smb_osdep.h>
#include <netsmb/smb.h>
+ #include <netsmb/smb2.h>
#include <netsmb/smb_conn.h>
#include <netsmb/smb_subr.h>
#include <netsmb/smb_tran.h>
#include <netsmb/smb_pass.h>
*** 78,87 ****
--- 81,93 ----
static void smb_vc_gone(struct smb_connobj *cp);
static void smb_share_free(struct smb_connobj *cp);
static void smb_share_gone(struct smb_connobj *cp);
+ static void smb_fh_free(struct smb_connobj *cp);
+ static void smb_fh_gone(struct smb_connobj *cp);
+
int
smb_sm_init(void)
{
smb_co_init(&smb_vclist, SMBL_SM, "smbsm");
return (0);
*** 103,113 ****
void
smb_sm_done(void)
{
/*
! * XXX Q4BP why are we not iterating on smb_vclist here?
* Because the caller has just called smb_sm_idle() to
* make sure we have no VCs before calling this.
*/
smb_co_done(&smb_vclist);
}
--- 109,119 ----
void
smb_sm_done(void)
{
/*
! * Why are we not iterating on smb_vclist here?
* Because the caller has just called smb_sm_idle() to
* make sure we have no VCs before calling this.
*/
smb_co_done(&smb_vclist);
}
*** 179,188 ****
--- 185,204 ----
{
struct smb_connobj *parent;
int old_flags;
SMB_CO_LOCK(co);
+
+ /*
+ * When VC usecount goes from 2 to 1, signal the iod_idle CV.
+ * It's unfortunate to have object type-specific logic here,
+ * but it's hard to do this anywhere else.
+ */
+ if (co->co_level == SMBL_VC && co->co_usecount == 2) {
+ smb_vc_t *vcp = CPTOVC(co);
+ cv_signal(&vcp->iod_idle);
+ }
if (co->co_usecount > 1) {
co->co_usecount--;
SMB_CO_UNLOCK(co);
return;
}
*** 363,376 ****
iconv_close(vcp->vc_toserver);
#endif
if (vcp->vc_mackey != NULL)
kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
cv_destroy(&vcp->iod_idle);
rw_destroy(&vcp->iod_rqlock);
- sema_destroy(&vcp->vc_sendlock);
cv_destroy(&vcp->vc_statechg);
smb_co_done(VCTOCP(vcp));
kmem_free(vcp, sizeof (*vcp));
}
--- 379,394 ----
iconv_close(vcp->vc_toserver);
#endif
if (vcp->vc_mackey != NULL)
kmem_free(vcp->vc_mackey, vcp->vc_mackeylen);
+ if (vcp->vc_ssnkey != NULL)
+ kmem_free(vcp->vc_ssnkey, vcp->vc_ssnkeylen);
+ cv_destroy(&vcp->iod_muxwait);
cv_destroy(&vcp->iod_idle);
rw_destroy(&vcp->iod_rqlock);
cv_destroy(&vcp->vc_statechg);
smb_co_done(VCTOCP(vcp));
kmem_free(vcp, sizeof (*vcp));
}
*** 390,407 ****
smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
vcp->vc_co.co_free = smb_vc_free;
vcp->vc_co.co_gone = smb_vc_gone;
cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
- sema_init(&vcp->vc_sendlock, 1, objtype, SEMA_DRIVER, NULL);
rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
/* Expanded TAILQ_HEAD_INITIALIZER */
vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
! vcp->vc_state = SMBIOD_ST_IDLE;
/*
* These identify the connection.
*/
vcp->vc_zoneid = getzoneid();
--- 408,426 ----
smb_co_init(VCTOCP(vcp), SMBL_VC, objtype);
vcp->vc_co.co_free = smb_vc_free;
vcp->vc_co.co_gone = smb_vc_gone;
cv_init(&vcp->vc_statechg, objtype, CV_DRIVER, NULL);
rw_init(&vcp->iod_rqlock, objtype, RW_DRIVER, NULL);
cv_init(&vcp->iod_idle, objtype, CV_DRIVER, NULL);
+ cv_init(&vcp->iod_muxwait, objtype, CV_DRIVER, NULL);
/* Expanded TAILQ_HEAD_INITIALIZER */
vcp->iod_rqlist.tqh_last = &vcp->iod_rqlist.tqh_first;
! /* A brand new VC should connect. */
! vcp->vc_state = SMBIOD_ST_RECONNECT;
/*
* These identify the connection.
*/
vcp->vc_zoneid = getzoneid();
*** 610,622 ****
--- 629,645 ----
static void
smb_share_gone(struct smb_connobj *cp)
{
struct smb_cred scred;
struct smb_share *ssp = CPTOSS(cp);
+ smb_vc_t *vcp = SSTOVC(ssp);
smb_credinit(&scred, NULL);
smb_iod_shutdown_share(ssp);
+ if (vcp->vc_flags & SMBV_SMB2)
+ (void) smb2_smb_treedisconnect(ssp, &scred);
+ else
(void) smb_smb_treedisconnect(ssp, &scred);
smb_credrele(&scred);
}
/*
*** 653,662 ****
--- 676,686 ----
ssp->ss_co.co_free = smb_share_free;
ssp->ss_co.co_gone = smb_share_gone;
cv_init(&ssp->ss_conn_done, objtype, CV_DRIVER, NULL);
ssp->ss_tid = SMB_TID_UNKNOWN;
+ ssp->ss2_tree_id = SMB2_TID_UNKNOWN;
bcopy(&tcon->tc_sh, &ssp->ss_ioc,
sizeof (smbioc_oshare_t));
smb_co_addchild(VCTOCP(vcp), SSTOCP(ssp));
*** 768,777 ****
--- 792,802 ----
* and called by smb_rq_enqueue() for reconnect.
*/
int
smb_share_tcon(smb_share_t *ssp, smb_cred_t *scred)
{
+ smb_vc_t *vcp = SSTOVC(ssp);
clock_t tmo;
int error;
SMB_SS_LOCK(ssp);
*** 811,820 ****
--- 836,848 ----
* Drop the lock while doing the TCON.
* On success, sets ss_tid, ss_vcgenid,
* and ss_flags |= SMBS_CONNECTED;
*/
SMB_SS_UNLOCK(ssp);
+ if (vcp->vc_flags & SMBV_SMB2)
+ error = smb2_smb_treeconnect(ssp, scred);
+ else
error = smb_smb_treeconnect(ssp, scred);
SMB_SS_LOCK(ssp);
ssp->ss_flags &= ~SMBS_RECONNECTING;
*** 827,836 ****
--- 855,972 ----
return (error);
}
/*
+ * File handle level functions
+ */
+
+ void
+ smb_fh_hold(struct smb_fh *fhp)
+ {
+ smb_co_hold(FHTOCP(fhp));
+ }
+
+ void
+ smb_fh_rele(struct smb_fh *fhp)
+ {
+ smb_co_rele(FHTOCP(fhp));
+ }
+
+ void
+ smb_fh_close(struct smb_fh *fhp)
+ {
+ smb_co_kill(FHTOCP(fhp));
+ }
+
+ /*
+ * Normally called via smb_fh_rele()
+ * after co_usecount drops to zero.
+ * Also called via: smb_fh_kill()
+ */
+ static void
+ smb_fh_gone(struct smb_connobj *cp)
+ {
+ struct smb_cred scred;
+ struct smb_fh *fhp = CPTOFH(cp);
+ smb_share_t *ssp = FHTOSS(fhp);
+ int err;
+
+ if ((fhp->fh_flags & SMBFH_VALID) == 0)
+ return;
+
+ /*
+ * We have no durable handles (yet) so if there has been a
+ * reconnect, don't bother to close this handle.
+ */
+ if (fhp->fh_vcgenid != ssp->ss_vcgenid)
+ return;
+
+ smb_credinit(&scred, NULL);
+ err = smb_smb_close(ssp, fhp, &scred);
+ smb_credrele(&scred);
+ if (err) {
+ SMBSDEBUG("close err=%d\n", err);
+ }
+ }
+
+ /*
+ * Normally called via smb_fh_rele()
+ * after co_usecount drops to zero.
+ */
+ static void
+ smb_fh_free(struct smb_connobj *cp)
+ {
+ struct smb_fh *fhp = CPTOFH(cp);
+
+ smb_co_done(FHTOCP(fhp));
+ kmem_free(fhp, sizeof (*fhp));
+ }
+
+ /*
+ * Allocate fh structure and attach it to the given share.
+ * Share expected to be locked on entry.
+ */
+ /*ARGSUSED*/
+ int
+ smb_fh_create(smb_share_t *ssp, struct smb_fh **fhpp)
+ {
+ static char objtype[] = "smb_fh";
+ struct smb_fh *fhp;
+
+ fhp = kmem_zalloc(sizeof (struct smb_fh), KM_SLEEP);
+ smb_co_init(FHTOCP(fhp), SMBL_FH, objtype);
+ fhp->fh_co.co_free = smb_fh_free;
+ fhp->fh_co.co_gone = smb_fh_gone;
+
+ SMB_SS_LOCK(ssp);
+ if ((ssp->ss_flags & SMBS_GONE) != 0) {
+ SMB_SS_UNLOCK(ssp);
+ smb_fh_free(FHTOCP(fhp));
+ return (ENOTCONN);
+ }
+
+ smb_co_addchild(SSTOCP(ssp), FHTOCP(fhp));
+ *fhpp = fhp;
+ SMB_SS_UNLOCK(ssp);
+
+ return (0);
+ }
+
+ void
+ smb_fh_opened(struct smb_fh *fhp)
+ {
+ smb_share_t *ssp = FHTOSS(fhp);
+
+ SMB_FH_LOCK(fhp);
+ fhp->fh_vcgenid = ssp->ss_vcgenid;
+ fhp->fh_flags |= SMBFH_VALID;
+ SMB_FH_UNLOCK(fhp);
+ }
+
+
+ /*
* Solaris zones support
*/
/*ARGSUSED*/
void
lingering_vc(struct smb_vc *vc)