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)