[Midnightbsd-cvs] src [10021] trunk/sys/fs/smbfs: sync smbfs with freebsd

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sun May 27 18:08:56 EDT 2018


Revision: 10021
          http://svnweb.midnightbsd.org/src/?rev=10021
Author:   laffer1
Date:     2018-05-27 18:08:55 -0400 (Sun, 27 May 2018)
Log Message:
-----------
sync smbfs with freebsd

Modified Paths:
--------------
    trunk/sys/fs/smbfs/smbfs.h
    trunk/sys/fs/smbfs/smbfs_io.c
    trunk/sys/fs/smbfs/smbfs_node.c
    trunk/sys/fs/smbfs/smbfs_node.h
    trunk/sys/fs/smbfs/smbfs_smb.c
    trunk/sys/fs/smbfs/smbfs_subr.c
    trunk/sys/fs/smbfs/smbfs_subr.h
    trunk/sys/fs/smbfs/smbfs_vfsops.c
    trunk/sys/fs/smbfs/smbfs_vnops.c

Modified: trunk/sys/fs/smbfs/smbfs.h
===================================================================
--- trunk/sys/fs/smbfs/smbfs.h	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs.h	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs.h 250236 2013-05-04 14:03:18Z davide $
  */
 #ifndef _SMBFS_SMBFS_H_
 #define _SMBFS_SMBFS_H_
@@ -61,10 +62,6 @@
 
 #include <sys/_sx.h>
 
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_SMBFSMNT);
-#endif
-
 struct smbnode;
 struct smb_share;
 struct u_cred;
@@ -79,16 +76,13 @@
 	mode_t 			sm_dir_mode;
 	struct mount * 		sm_mp;
 	struct smbnode *	sm_root;
+	struct smb_dev *	sm_dev;
 	struct ucred *		sm_owner;
 	uint64_t		sm_flags;
 	long			sm_nextino;
 	struct smb_share * 	sm_share;
-/*	struct simplelock	sm_npslock;*/
 	struct smbnode *	sm_npstack[SMBFS_MAXPATHCOMP];
 	int			sm_caseopt;
-	struct sx		sm_hashlock;
-	LIST_HEAD(smbnode_hashhead, smbnode) *sm_hash;
-	u_long			sm_hashlen;
 	int			sm_didrele;
 };
 

Modified: trunk/sys/fs/smbfs/smbfs_io.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_io.c	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_io.c	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_io.c 250238 2013-05-04 14:27:28Z davide $
  *
  */
 #include <sys/param.h>
@@ -36,6 +37,7 @@
 #include <sys/namei.h>
 #include <sys/vnode.h>
 #include <sys/dirent.h>
+#include <sys/rwlock.h>
 #include <sys/signalvar.h>
 #include <sys/sysctl.h>
 #include <sys/vmmeter.h>
@@ -75,7 +77,7 @@
 {
 	struct dirent de;
 	struct componentname cn;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	struct smbfs_fctx *ctx;
 	struct vnode *newvp;
 	struct smbnode *np = VTOSMB(vp);
@@ -84,17 +86,20 @@
 
 	np = VTOSMB(vp);
 	SMBVDEBUG("dirname='%s'\n", np->n_name);
-	smb_makescred(&scred, uio->uio_td, cred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, uio->uio_td, cred);
 	offset = uio->uio_offset / DE_SIZE;	/* offset in the directory */
 	limit = uio->uio_resid / DE_SIZE;
-	if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0)
-		return EINVAL;
+	if (uio->uio_resid < DE_SIZE || uio->uio_offset < 0) {
+		error = EINVAL;
+		goto out;
+	}
 	while (limit && offset < 2) {
 		limit--;
 		bzero((caddr_t)&de, DE_SIZE);
 		de.d_reclen = DE_SIZE;
 		de.d_fileno = (offset == 0) ? np->n_ino :
-		    (np->n_parent ? VTOSMB(np->n_parent)->n_ino : 2);
+		    (np->n_parent ? np->n_parentino : 2);
 		if (de.d_fileno == 0)
 			de.d_fileno = 0x7ffffffd + offset;
 		de.d_namlen = offset + 1;
@@ -104,40 +109,43 @@
 		de.d_type = DT_DIR;
 		error = uiomove(&de, DE_SIZE, uio);
 		if (error)
-			return error;
+			goto out;
 		offset++;
 		uio->uio_offset += DE_SIZE;
 	}
-	if (limit == 0)
-		return 0;
+	if (limit == 0) {
+		error = 0;
+		goto out;
+	}
 	if (offset != np->n_dirofs || np->n_dirseq == NULL) {
 		SMBVDEBUG("Reopening search %ld:%ld\n", offset, np->n_dirofs);
 		if (np->n_dirseq) {
-			smbfs_findclose(np->n_dirseq, &scred);
+			smbfs_findclose(np->n_dirseq, scred);
 			np->n_dirseq = NULL;
 		}
 		np->n_dirofs = 2;
 		error = smbfs_findopen(np, "*", 1,
 		    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR,
-		    &scred, &ctx);
+		    scred, &ctx);
 		if (error) {
 			SMBVDEBUG("can not open search, error = %d", error);
-			return error;
+			goto out;
 		}
 		np->n_dirseq = ctx;
 	} else
 		ctx = np->n_dirseq;
 	while (np->n_dirofs < offset) {
-		error = smbfs_findnext(ctx, offset - np->n_dirofs++, &scred);
+		error = smbfs_findnext(ctx, offset - np->n_dirofs++, scred);
 		if (error) {
-			smbfs_findclose(np->n_dirseq, &scred);
+			smbfs_findclose(np->n_dirseq, scred);
 			np->n_dirseq = NULL;
-			return error == ENOENT ? 0 : error;
+			error = ENOENT ? 0 : error;
+			goto out;
 		}
 	}
 	error = 0;
 	for (; limit; limit--, offset++) {
-		error = smbfs_findnext(ctx, limit, &scred);
+		error = smbfs_findnext(ctx, limit, scred);
 		if (error)
 			break;
 		np->n_dirofs++;
@@ -165,6 +173,8 @@
 	if (error == ENOENT)
 		error = 0;
 	uio->uio_offset = offset * DE_SIZE;
+out:
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -175,7 +185,7 @@
 	struct smbnode *np = VTOSMB(vp);
 	struct thread *td;
 	struct vattr vattr;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	int error, lks;
 
 	/*
@@ -223,8 +233,11 @@
 			np->n_mtime.tv_sec = vattr.va_mtime.tv_sec;
 		}
 	}
-	smb_makescred(&scred, td, cred);
-	return smb_read(smp->sm_share, np->n_fid, uiop, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cred);
+	error = smb_read(smp->sm_share, np->n_fid, uiop, scred);
+	smbfs_free_scred(scred);
+	return (error);
 }
 
 int
@@ -233,7 +246,7 @@
 {
 	struct smbmount *smp = VTOSMBFS(vp);
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	struct thread *td;
 	int error = 0;
 
@@ -241,7 +254,8 @@
 		SMBERROR("vn types other than VREG unsupported !\n");
 		return EIO;
 	}
-	SMBVDEBUG("ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
+	SMBVDEBUG("ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset, 
+	    uiop->uio_resid);
 	if (uiop->uio_offset < 0)
 		return EINVAL;
 /*	if (uiop->uio_offset + uiop->uio_resid > smp->nm_maxfilesize)
@@ -271,10 +285,13 @@
 
 	if (vn_rlimit_fsize(vp, uiop, td))
 		return (EFBIG);
-
-	smb_makescred(&scred, td, cred);
-	error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
-	SMBVDEBUG("after: ofs=%d,resid=%d\n",(int)uiop->uio_offset, uiop->uio_resid);
+	
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cred);
+	error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
+	smbfs_free_scred(scred);
+	SMBVDEBUG("after: ofs=%jd,resid=%zd\n", (intmax_t)uiop->uio_offset, 
+	    uiop->uio_resid);
 	if (!error) {
 		if (uiop->uio_offset > np->n_size) {
 			np->n_size = uiop->uio_offset;
@@ -292,17 +309,19 @@
 {
 	struct smbmount *smp = VFSTOSMBFS(vp->v_mount);
 	struct smbnode *np = VTOSMB(vp);
-	struct uio uio, *uiop = &uio;
+	struct uio *uiop;
 	struct iovec io;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	int error = 0;
 
+	uiop = malloc(sizeof(struct uio), M_SMBFSDATA, M_WAITOK);
 	uiop->uio_iov = &io;
 	uiop->uio_iovcnt = 1;
 	uiop->uio_segflg = UIO_SYSSPACE;
 	uiop->uio_td = td;
 
-	smb_makescred(&scred, td, cr);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cr);
 
 	if (bp->b_iocmd == BIO_READ) {
 	    io.iov_len = uiop->uio_resid = bp->b_bcount;
@@ -311,7 +330,7 @@
 	    switch (vp->v_type) {
 	      case VREG:
 		uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
-		error = smb_read(smp->sm_share, np->n_fid, uiop, &scred);
+		error = smb_read(smp->sm_share, np->n_fid, uiop, scred);
 		if (error)
 			break;
 		if (uiop->uio_resid) {
@@ -338,7 +357,7 @@
 		uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff;
 		io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
 		uiop->uio_rw = UIO_WRITE;
-		error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
+		error = smb_write(smp->sm_share, np->n_fid, uiop, scred);
 
 		/*
 		 * For an interrupted write, the buffer is still valid
@@ -378,11 +397,15 @@
 	    } else {
 		bp->b_resid = 0;
 		bufdone(bp);
+		free(uiop, M_SMBFSDATA);
+		smbfs_free_scred(scred);
 		return 0;
 	    }
 	}
 	bp->b_resid = uiop->uio_resid;
 	bufdone(bp);
+	free(uiop, M_SMBFSDATA);
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -413,7 +436,7 @@
 	struct ucred *cred;
 	struct smbmount *smp;
 	struct smbnode *np;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	vm_object_t object;
 	vm_page_t *pages, m;
 
@@ -439,7 +462,7 @@
 	 */
 	m = pages[reqpage];
 
-	VM_OBJECT_LOCK(object);
+	VM_OBJECT_WLOCK(object);
 	if (m->valid != 0) {
 		for (i = 0; i < npages; ++i) {
 			if (i != reqpage) {
@@ -448,12 +471,13 @@
 				vm_page_unlock(pages[i]);
 			}
 		}
-		VM_OBJECT_UNLOCK(object);
+		VM_OBJECT_WUNLOCK(object);
 		return 0;
 	}
-	VM_OBJECT_UNLOCK(object);
+	VM_OBJECT_WUNLOCK(object);
 
-	smb_makescred(&scred, td, cred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cred);
 
 	bp = getpbuf(&smbfs_pbuf_freecnt);
 
@@ -472,12 +496,13 @@
 	uio.uio_rw = UIO_READ;
 	uio.uio_td = td;
 
-	error = smb_read(smp->sm_share, np->n_fid, &uio, &scred);
+	error = smb_read(smp->sm_share, np->n_fid, &uio, scred);
+	smbfs_free_scred(scred);
 	pmap_qremove(kva, npages);
 
 	relpbuf(bp, &smbfs_pbuf_freecnt);
 
-	VM_OBJECT_LOCK(object);
+	VM_OBJECT_WLOCK(object);
 	if (error && (uio.uio_resid == count)) {
 		printf("smbfs_getpages: error %d\n",error);
 		for (i = 0; i < npages; i++) {
@@ -487,7 +512,7 @@
 				vm_page_unlock(pages[i]);
 			}
 		}
-		VM_OBJECT_UNLOCK(object);
+		VM_OBJECT_WUNLOCK(object);
 		return VM_PAGER_ERROR;
 	}
 
@@ -510,7 +535,7 @@
 			 * Read operation filled a partial page.
 			 */
 			m->valid = 0;
-			vm_page_set_valid(m, 0, size - toff);
+			vm_page_set_valid_range(m, 0, size - toff);
 			KASSERT(m->dirty == 0,
 			    ("smbfs_getpages: page %p is dirty", m));
 		} else {
@@ -525,7 +550,7 @@
 		if (i != reqpage)
 			vm_page_readahead_finish(m);
 	}
-	VM_OBJECT_UNLOCK(object);
+	VM_OBJECT_WUNLOCK(object);
 	return 0;
 #endif /* SMBFS_RWGENERIC */
 }
@@ -568,7 +593,7 @@
 	int *rtvals;
 	struct smbmount *smp;
 	struct smbnode *np;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	vm_page_t *pages;
 
 	td = curthread;			/* XXX */
@@ -601,10 +626,13 @@
 	uio.uio_segflg = UIO_SYSSPACE;
 	uio.uio_rw = UIO_WRITE;
 	uio.uio_td = td;
-	SMBVDEBUG("ofs=%d,resid=%d\n",(int)uio.uio_offset, uio.uio_resid);
+	SMBVDEBUG("ofs=%jd,resid=%zd\n", (intmax_t)uio.uio_offset, 
+	    uio.uio_resid);
 
-	smb_makescred(&scred, td, cred);
-	error = smb_write(smp->sm_share, np->n_fid, &uio, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cred);
+	error = smb_write(smp->sm_share, np->n_fid, &uio, scred);
+	smbfs_free_scred(scred);
 /*	VOP_CLOSE(vp, FWRITE, cred, td);*/
 	SMBVDEBUG("paged write done: %d\n", error);
 
@@ -641,9 +669,9 @@
 	np->n_flag |= NFLUSHINPROG;
 
 	if (vp->v_bufobj.bo_object != NULL) {
-		VM_OBJECT_LOCK(vp->v_bufobj.bo_object);
+		VM_OBJECT_WLOCK(vp->v_bufobj.bo_object);
 		vm_object_page_clean(vp->v_bufobj.bo_object, 0, 0, OBJPC_SYNC);
-		VM_OBJECT_UNLOCK(vp->v_bufobj.bo_object);
+		VM_OBJECT_WUNLOCK(vp->v_bufobj.bo_object);
 	}
 
 	error = vinvalbuf(vp, V_SAVE, PCATCH, 0);

Modified: trunk/sys/fs/smbfs/smbfs_node.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_node.c	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_node.c	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,10 +24,11 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_node.c 254627 2013-08-21 23:04:48Z ken $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/fnv_hash.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -52,56 +54,17 @@
 #include <fs/smbfs/smbfs_node.h>
 #include <fs/smbfs/smbfs_subr.h>
 
-#define	SMBFS_NOHASH(smp, hval)	(&(smp)->sm_hash[(hval) & (smp)->sm_hashlen])
-#define	smbfs_hash_lock(smp)	sx_xlock(&smp->sm_hashlock)
-#define	smbfs_hash_unlock(smp)	sx_xunlock(&smp->sm_hashlock)
-
 extern struct vop_vector smbfs_vnodeops;	/* XXX -> .h file */
 
 static MALLOC_DEFINE(M_SMBNODE, "smbufs_node", "SMBFS vnode private part");
 static MALLOC_DEFINE(M_SMBNODENAME, "smbufs_nname", "SMBFS node name");
 
-int smbfs_hashprint(struct mount *mp);
-
-#if 0
-#ifdef SYSCTL_DECL
-SYSCTL_DECL(_vfs_smbfs);
-#endif
-SYSCTL_PROC(_vfs_smbfs, OID_AUTO, vnprint, CTLFLAG_WR|CTLTYPE_OPAQUE,
-	    NULL, 0, smbfs_hashprint, "S,vnlist", "vnode hash");
-#endif
-
-#define	FNV_32_PRIME ((u_int32_t) 0x01000193UL)
-#define	FNV1_32_INIT ((u_int32_t) 33554467UL)
-
-u_int32_t
+u_int32_t __inline
 smbfs_hash(const u_char *name, int nmlen)
 {
-	u_int32_t v;
-
-	for (v = FNV1_32_INIT; nmlen; name++, nmlen--) {
-		v *= FNV_32_PRIME;
-		v ^= (u_int32_t)*name;
-	}
-	return v;
+	return (fnv_32_buf(name, nmlen, FNV1_32_INIT)); 
 }
 
-int
-smbfs_hashprint(struct mount *mp)
-{
-	struct smbmount *smp = VFSTOSMBFS(mp);
-	struct smbnode_hashhead *nhpp;
-	struct smbnode *np;
-	int i;
-
-	for(i = 0; i <= smp->sm_hashlen; i++) {
-		nhpp = &smp->sm_hash[i];
-		LIST_FOREACH(np, nhpp, n_hash)
-			vprint("", SMBTOV(np));
-	}
-	return 0;
-}
-
 static char *
 smbfs_name_alloc(const u_char *name, int nmlen)
 {
@@ -108,18 +71,8 @@
 	u_char *cp;
 
 	nmlen++;
-#ifdef SMBFS_NAME_DEBUG
-	cp = malloc(nmlen + 2 + sizeof(int), M_SMBNODENAME, M_WAITOK);
-	*(int*)cp = nmlen;
-	cp += sizeof(int);
-	cp[0] = 0xfc;
-	cp++;
-	bcopy(name, cp, nmlen - 1);
-	cp[nmlen] = 0xfe;
-#else
 	cp = malloc(nmlen, M_SMBNODENAME, M_WAITOK);
 	bcopy(name, cp, nmlen - 1);
-#endif
 	cp[nmlen - 1] = 0;
 	return cp;
 }
@@ -127,42 +80,41 @@
 static void
 smbfs_name_free(u_char *name)
 {
-#ifdef SMBFS_NAME_DEBUG
-	int nmlen, slen;
-	u_char *cp;
 
-	cp = name;
-	cp--;
-	if (*cp != 0xfc)
-		panic("First byte of name entry '%s' corrupted", name);
-	cp -= sizeof(int);
-	nmlen = *(int*)cp;
-	slen = strlen(name) + 1;
-	if (nmlen != slen)
-		panic("Name length mismatch: was %d, now %d name '%s'",
-		    nmlen, slen, name);
-	if (name[nmlen] != 0xfe)
-		panic("Last byte of name entry '%s' corrupted\n", name);
-	free(cp, M_SMBNODENAME);
-#else
 	free(name, M_SMBNODENAME);
-#endif
 }
 
+static int __inline
+smbfs_vnode_cmp(struct vnode *vp, void *_sc) 
+{
+	struct smbnode *np;
+	struct smbcmp *sc;
+
+	np = (struct smbnode *) vp->v_data;
+	sc = (struct smbcmp *) _sc;
+	if (np->n_parent != sc->n_parent || np->n_nmlen != sc->n_nmlen ||
+	    bcmp(sc->n_name, np->n_name, sc->n_nmlen) != 0)
+		return 1;
+	return 0;
+}
+
 static int
-smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
-	const char *name, int nmlen, struct smbfattr *fap, struct vnode **vpp)
+smbfs_node_alloc(struct mount *mp, struct vnode *dvp, const char *dirnm, 
+	int dirlen, const char *name, int nmlen, char sep, 
+	struct smbfattr *fap, struct vnode **vpp)
 {
 	struct vattr vattr;
 	struct thread *td = curthread;	/* XXX */
 	struct smbmount *smp = VFSTOSMBFS(mp);
-	struct smbnode_hashhead *nhpp;
-	struct smbnode *np, *np2, *dnp;
-	struct vnode *vp;
-	u_long hashval;
-	int error;
+	struct smbnode *np, *dnp;
+	struct vnode *vp, *vp2;
+	struct smbcmp sc;
+	char *p, *rpath;
+	int error, rplen;
 
-	*vpp = NULL;
+	sc.n_parent = dvp;
+	sc.n_nmlen = nmlen;
+	sc.n_name = name;	
 	if (smp->sm_root != NULL && dvp == NULL) {
 		SMBERROR("do not allocate root vnode twice!\n");
 		return EINVAL;
@@ -184,22 +136,14 @@
 		vprint("smbfs_node_alloc: dead parent vnode", dvp);
 		return EINVAL;
 	}
-	hashval = smbfs_hash(name, nmlen);
-retry:
-	smbfs_hash_lock(smp);
-loop:
-	nhpp = SMBFS_NOHASH(smp, hashval);
-	LIST_FOREACH(np, nhpp, n_hash) {
-		vp = SMBTOV(np);
-		if (np->n_parent != dvp ||
-		    np->n_nmlen != nmlen || bcmp(name, np->n_name, nmlen) != 0)
-			continue;
-		VI_LOCK(vp);
-		smbfs_hash_unlock(smp);
-		if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td) != 0)
-			goto retry;
+	error = vfs_hash_get(mp, smbfs_hash(name, nmlen), LK_EXCLUSIVE, td,
+	    vpp, smbfs_vnode_cmp, &sc);
+	if (error)
+		return (error);
+	if (*vpp) {
+		np = VTOSMB(*vpp);
 		/* Force cached attributes to be refreshed if stale. */
-		(void)VOP_GETATTR(vp, &vattr, td->td_ucred);
+		(void)VOP_GETATTR(*vpp, &vattr, td->td_ucred);
 		/*
 		 * If the file type on the server is inconsistent with
 		 * what it was when we created the vnode, kill the
@@ -206,16 +150,18 @@
 		 * bogus vnode now and fall through to the code below
 		 * to create a new one with the right type.
 		 */
-		if ((vp->v_type == VDIR && (np->n_dosattr & SMB_FA_DIR) == 0) ||
-		    (vp->v_type == VREG && (np->n_dosattr & SMB_FA_DIR) != 0)) {
-			vgone(vp);
-			vput(vp);
-			break;
+		if (((*vpp)->v_type == VDIR && 
+		    (np->n_dosattr & SMB_FA_DIR) == 0) ||
+	    	    ((*vpp)->v_type == VREG && 
+		    (np->n_dosattr & SMB_FA_DIR) != 0)) {
+			vgone(*vpp);
+			vput(*vpp);
 		}
-		*vpp = vp;
-		return 0;
+		else {
+			SMBVDEBUG("vnode taken from the hashtable\n");
+			return (0);
+		}
 	}
-	smbfs_hash_unlock(smp);
 	/*
 	 * If we don't have node attributes, then it is an explicit lookup
 	 * for an existing vnode.
@@ -223,29 +169,42 @@
 	if (fap == NULL)
 		return ENOENT;
 
-	np = malloc(sizeof *np, M_SMBNODE, M_WAITOK);
-	error = getnewvnode("smbfs", mp, &smbfs_vnodeops, &vp);
-	if (error) {
-		free(np, M_SMBNODE);
-		return error;
-	}
-	error = insmntque(vp, mp);	/* XXX: Too early for mpsafe fs */
-	if (error != 0) {
-		free(np, M_SMBNODE);
+	error = getnewvnode("smbfs", mp, &smbfs_vnodeops, vpp);
+	if (error)
 		return (error);
+	vp = *vpp;
+	np = malloc(sizeof *np, M_SMBNODE, M_WAITOK | M_ZERO);
+	rplen = dirlen;
+	if (sep != '\0')
+		rplen++;
+	rplen += nmlen;
+	rpath = malloc(rplen + 1, M_SMBNODENAME, M_WAITOK);
+	p = rpath;
+	bcopy(dirnm, p, dirlen);
+	p += dirlen;
+	if (sep != '\0')
+		*p++ = sep;
+	if (name != NULL) {
+		bcopy(name, p, nmlen);
+		p += nmlen;
 	}
+	*p = '\0';
+	MPASS(p == rpath + rplen);
+	lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
+	/* Vnode initialization */
 	vp->v_type = fap->fa_attr & SMB_FA_DIR ? VDIR : VREG;
-	bzero(np, sizeof(*np));
 	vp->v_data = np;
 	np->n_vnode = vp;
 	np->n_mount = VFSTOSMBFS(mp);
+	np->n_rpath = rpath;
+	np->n_rplen = rplen;
 	np->n_nmlen = nmlen;
 	np->n_name = smbfs_name_alloc(name, nmlen);
 	np->n_ino = fap->fa_ino;
-
 	if (dvp) {
 		ASSERT_VOP_LOCKED(dvp, "smbfs_node_alloc");
 		np->n_parent = dvp;
+		np->n_parentino = VTOSMB(dvp)->n_ino;
 		if (/*vp->v_type == VDIR &&*/ (dvp->v_vflag & VV_ROOT) == 0) {
 			vref(dvp);
 			np->n_flag |= NREFPARENT;
@@ -252,24 +211,18 @@
 		}
 	} else if (vp->v_type == VREG)
 		SMBERROR("new vnode '%s' born without parent ?\n", np->n_name);
-
-	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-	VN_LOCK_AREC(vp);
-
-	smbfs_hash_lock(smp);
-	LIST_FOREACH(np2, nhpp, n_hash) {
-		if (np2->n_parent != dvp ||
-		    np2->n_nmlen != nmlen || bcmp(name, np2->n_name, nmlen) != 0)
-			continue;
-		vput(vp);
-/*		smb_name_free(np->n_name);
-		free(np, M_SMBNODE);*/
-		goto loop;
+	error = insmntque(vp, mp);
+	if (error) {
+		free(np, M_SMBNODE);
+		return (error);
 	}
-	LIST_INSERT_HEAD(nhpp, np, n_hash);
-	smbfs_hash_unlock(smp);
-	*vpp = vp;
-	return 0;
+	error = vfs_hash_insert(vp, smbfs_hash(name, nmlen), LK_EXCLUSIVE,
+	    td, &vp2, smbfs_vnode_cmp, &sc);
+	if (error) 
+		return (error);
+	if (vp2 != NULL)
+		*vpp = vp2;
+	return (0);
 }
 
 int
@@ -276,14 +229,22 @@
 smbfs_nget(struct mount *mp, struct vnode *dvp, const char *name, int nmlen,
 	struct smbfattr *fap, struct vnode **vpp)
 {
-	struct smbnode *np;
+	struct smbnode *dnp, *np;
 	struct vnode *vp;
-	int error;
+	int error, sep;
 
-	*vpp = NULL;
-	error = smbfs_node_alloc(mp, dvp, name, nmlen, fap, &vp);
+	dnp = (dvp) ? VTOSMB(dvp) : NULL;
+	sep = 0;
+	if (dnp != NULL) {
+		sep = SMBFS_DNP_SEP(dnp); 
+		error = smbfs_node_alloc(mp, dvp, dnp->n_rpath, dnp->n_rplen, 
+		    name, nmlen, sep, fap, &vp); 
+	} else
+		error = smbfs_node_alloc(mp, NULL, "\\", 1, name, nmlen, 
+		    sep, fap, &vp); 
 	if (error)
 		return error;
+	MPASS(vp != NULL);
 	np = VTOSMB(vp);
 	if (fap)
 		smbfs_attr_cacheenter(vp, fap);
@@ -310,26 +271,23 @@
 
 	KASSERT((np->n_flag & NOPEN) == 0, ("file not closed before reclaim"));
 
-	smbfs_hash_lock(smp);
 	/*
 	 * Destroy the vm object and flush associated pages.
 	 */
 	vnode_destroy_vobject(vp);
-
 	dvp = (np->n_parent && (np->n_flag & NREFPARENT)) ?
 	    np->n_parent : NULL;
-
-	if (np->n_hash.le_prev)
-		LIST_REMOVE(np, n_hash);
-	if (smp->sm_root == np) {
-		SMBVDEBUG("root vnode\n");
-		smp->sm_root = NULL;
-	}
-	vp->v_data = NULL;
-	smbfs_hash_unlock(smp);
+	
+	/*
+	 * Remove the vnode from its hash chain.
+	 */
+	vfs_hash_remove(vp);
 	if (np->n_name)
 		smbfs_name_free(np->n_name);
+	if (np->n_rpath)
+		free(np->n_rpath, M_SMBNODENAME);
 	free(np, M_SMBNODE);
+	vp->v_data = NULL;
 	if (dvp != NULL) {
 		vrele(dvp);
 		/*
@@ -352,28 +310,30 @@
 	struct ucred *cred = td->td_ucred;
 	struct vnode *vp = ap->a_vp;
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	struct vattr va;
 
 	SMBVDEBUG("%s: %d\n", VTOSMB(vp)->n_name, vrefcnt(vp));
 	if ((np->n_flag & NOPEN) != 0) {
-		smb_makescred(&scred, td, cred);
+		scred = smbfs_malloc_scred();
+		smb_makescred(scred, td, cred);
 		smbfs_vinvalbuf(vp, td);
 		if (vp->v_type == VREG) {
 			VOP_GETATTR(vp, &va, cred);
 			smbfs_smb_close(np->n_mount->sm_share, np->n_fid,
-			    &np->n_mtime, &scred);
+			    &np->n_mtime, scred);
 		} else if (vp->v_type == VDIR) {
 			if (np->n_dirseq != NULL) {
-				smbfs_findclose(np->n_dirseq, &scred);
+				smbfs_findclose(np->n_dirseq, scred);
 				np->n_dirseq = NULL;
 			}
 		}
 		np->n_flag &= ~NOPEN;
 		smbfs_attr_cacheremove(vp);
+		smbfs_free_scred(scred);
 	}
 	if (np->n_flag & NGONE)
-		vrecycle(vp, td);
+		vrecycle(vp);
 	return (0);
 }
 /*
@@ -411,10 +371,13 @@
 	if (diff > 2)	/* XXX should be configurable */
 		return ENOENT;
 	va->va_type = vp->v_type;		/* vnode type (for create) */
+	va->va_flags = 0;			/* flags defined for file */
 	if (vp->v_type == VREG) {
 		va->va_mode = smp->sm_file_mode; /* files access mode and type */
-		if (np->n_dosattr & SMB_FA_RDONLY)
+		if (np->n_dosattr & SMB_FA_RDONLY) {
 			va->va_mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
+			va->va_flags |= UF_READONLY;
+		}
 	} else if (vp->v_type == VDIR) {
 		va->va_mode = smp->sm_dir_mode;	/* files access mode and type */
 	} else
@@ -431,7 +394,15 @@
 	va->va_mtime = np->n_mtime;
 	va->va_atime = va->va_ctime = va->va_mtime;	/* time file changed */
 	va->va_gen = VNOVAL;		/* generation number of file */
-	va->va_flags = 0;		/* flags defined for file */
+	if (np->n_dosattr & SMB_FA_HIDDEN)
+		va->va_flags |= UF_HIDDEN;
+	if (np->n_dosattr & SMB_FA_SYSTEM)
+		va->va_flags |= UF_SYSTEM;
+	/*
+	 * We don't set the archive bit for directories.
+	 */
+	if ((vp->v_type != VDIR) && (np->n_dosattr & SMB_FA_ARCHIVE))
+		va->va_flags |= UF_ARCHIVE;
 	va->va_rdev = NODEV;		/* device the special file represents */
 	va->va_bytes = va->va_size;	/* bytes of disk space held by file */
 	va->va_filerev = 0;		/* file modification number */

Modified: trunk/sys/fs/smbfs/smbfs_node.h
===================================================================
--- trunk/sys/fs/smbfs/smbfs_node.h	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_node.h	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_node.h 243396 2012-11-22 08:58:29Z davide $
  */
 #ifndef _FS_SMBFS_NODE_H_
 #define _FS_SMBFS_NODE_H_
@@ -53,9 +54,12 @@
 	struct timespec		n_atime;	/* last access time */
 	u_quad_t		n_size;
 	long			n_ino;
+	long			n_parentino;	/* parent inode number */
 	int			n_dosattr;
 	u_int16_t		n_fid;		/* file handle */
 	int			n_rwstate;	/* granted access mode */
+	int			n_rplen;
+	char *			n_rpath;
 	u_char			n_nmlen;
 	u_char *		n_name;
 	struct smbfs_fctx *	n_dirseq;	/* ff context */
@@ -63,9 +67,17 @@
 	LIST_ENTRY(smbnode)	n_hash;
 };
 
+struct smbcmp {
+	struct vnode * 		n_parent;
+	int 			n_nmlen;
+	const char *		n_name;
+};
+
 #define VTOSMB(vp)	((struct smbnode *)(vp)->v_data)
 #define SMBTOV(np)	((struct vnode *)(np)->n_vnode)
 
+#define	SMBFS_DNP_SEP(dnp)	((dnp->n_rplen > 1) ? '\\' : '\0')
+
 struct vop_getpages_args;
 struct vop_inactive_args;
 struct vop_putpages_args;

Modified: trunk/sys/fs/smbfs/smbfs_smb.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_smb.c	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_smb.c	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_smb.c 294263 2016-01-18 11:47:03Z ae $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -87,7 +88,7 @@
 	struct smb_cred *scred)
 {
 	struct smb_share *ssp = np->n_mount->sm_share;
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct mbchain *mbp;
 	u_char ltype = 0;
 	int error;
@@ -94,9 +95,10 @@
 
 	if (op == SMB_LOCK_SHARED)
 		ltype |= SMB_LOCKING_ANDX_SHARED_LOCK;
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred);
+
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_LOCKING_ANDX, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_uint8(mbp, 0xff);	/* secondary command */
@@ -134,13 +136,54 @@
 		return smbfs_smb_lockandx(np, op, (uintptr_t)id, start, end, scred);
 }
 
-int
-smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp,
+static int
+smbfs_query_info_fs(struct smb_share *ssp, struct statfs *sbp,
 	struct smb_cred *scred)
 {
 	struct smb_t2rq *t2p;
 	struct mbchain *mbp;
 	struct mdchain *mdp;
+	uint32_t bsize, bpu;
+	int64_t units, funits;
+	int error;
+
+	error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_QUERY_FS_INFORMATION,
+	    scred, &t2p);
+	if (error)
+		return (error);
+	mbp = &t2p->t2_tparam;
+	mb_init(mbp);
+	mb_put_uint16le(mbp, SMB_QUERY_FS_SIZE_INFO);
+	t2p->t2_maxpcount = 2;
+	t2p->t2_maxdcount = sizeof(int64_t) * 2 + sizeof(uint32_t) * 2;
+	error = smb_t2_request(t2p);
+	if (error) {
+		smb_t2_done(t2p);
+		return (error);
+	}
+	mdp = &t2p->t2_rdata;
+	md_get_int64le(mdp, &units);
+	md_get_int64le(mdp, &funits);
+	md_get_uint32le(mdp, &bpu);
+	md_get_uint32le(mdp, &bsize);
+	sbp->f_bsize = bpu * bsize;	/* fundamental filesystem block size */
+	sbp->f_blocks= (uint64_t)units;	/* total data blocks in filesystem */
+	sbp->f_bfree = (uint64_t)funits;/* free blocks in fs */
+	sbp->f_bavail= (uint64_t)funits;/* free blocks avail to non-superuser */
+	sbp->f_files = 0xffff;		/* total file nodes in filesystem */
+	sbp->f_ffree = 0xffff;		/* free file nodes in fs */
+	smb_t2_done(t2p);
+	return (0);
+}
+
+
+static int
+smbfs_query_info_alloc(struct smb_share *ssp, struct statfs *sbp,
+	struct smb_cred *scred)
+{
+	struct smb_t2rq *t2p;
+	struct mbchain *mbp;
+	struct mdchain *mdp;
 	u_int16_t bsize;
 	u_int32_t units, bpu, funits;
 	int error;
@@ -175,18 +218,19 @@
 	return 0;
 }
 
-int
-smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
+static int
+smbfs_query_info_disk(struct smb_share *ssp, struct statfs *sbp,
 	struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct mdchain *mdp;
 	u_int16_t units, bpu, bsize, funits;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION_DISK,
+	    scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_wstart(rqp);
 	smb_rq_wend(rqp);
 	smb_rq_bstart(rqp);
@@ -211,6 +255,20 @@
 	return 0;
 }
 
+int
+smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
+	struct smb_cred *scred)
+{
+
+	if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0) {
+		if (smbfs_query_info_fs(ssp, sbp, scred) == 0)
+			return (0);
+		if (smbfs_query_info_alloc(ssp, sbp, scred) == 0)
+			return (0);
+	}
+	return (smbfs_query_info_disk(ssp, sbp, scred));
+}
+
 static int
 smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred)
 {
@@ -244,7 +302,7 @@
 smb_smb_flush(struct smbnode *np, struct smb_cred *scred)
 {
 	struct smb_share *ssp = np->n_mount->sm_share;
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct mbchain *mbp;
 	int error;
 
@@ -251,7 +309,7 @@
 	if ((np->n_flag & NOPEN) == 0 || !SMBTOV(np) ||
 	    SMBTOV(np)->v_type != VREG)
 		return 0; /* not a regular open file */
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_FLUSH, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_FLUSH, scred, &rqp);
 	if (error)
 		return (error);
 	smb_rq_getrequest(rqp, &mbp);
@@ -276,26 +334,26 @@
 }
 
 int
-smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred)
+smbfs_smb_setfsize(struct smbnode *np, int64_t newsize, struct smb_cred *scred)
 {
 	struct smb_share *ssp = np->n_mount->sm_share;
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct mbchain *mbp;
 	int error;
 
-	if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) {
+	if (!smbfs_smb_seteof(np, newsize, scred)) {
 		np->n_flag |= NFLUSHWIRE;
 		return (0);
 	}
-
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scred);
+	/* XXX: We should use SMB_COM_WRITE_ANDX to support large offsets */
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM);
 	mb_put_uint16le(mbp, 0);
-	mb_put_uint32le(mbp, newsize);
+	mb_put_uint32le(mbp, (uint32_t)newsize);
 	mb_put_uint16le(mbp, 0);
 	smb_rq_wend(rqp);
 	smb_rq_bstart(rqp);
@@ -311,7 +369,7 @@
 smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
 		     struct smbfattr *fap, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct mbchain *mbp;
 	struct mdchain *mdp;
@@ -320,9 +378,10 @@
 	u_int16_t wattr;
 	u_int32_t lint;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_QUERY_INFORMATION, scred,
+	    &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	smb_rq_wend(rqp);
@@ -367,15 +426,16 @@
 smbfs_smb_setpattr(struct smbnode *np, u_int16_t attr, struct timespec *mtime,
 	struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct mbchain *mbp;
 	u_long time;
 	int error, svtz;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_SET_INFORMATION, scred,
+	    &rqp);
 	if (error)
-		return error;
+		return (error);
 	svtz = SSTOVC(ssp)->vc_sopt.sv_tz;
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
@@ -523,15 +583,16 @@
 smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime,
 	struct timespec *atime, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct mbchain *mbp;
 	u_int16_t date, time;
 	int error, tzoff;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred,
+	    &rqp);
 	if (error)
-		return error;
+		return (error);
 	tzoff = SSTOVC(ssp)->vc_sopt.sv_tz;
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
@@ -611,7 +672,7 @@
 int
 smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct mbchain *mbp;
 	struct mdchain *mdp;
@@ -619,9 +680,9 @@
 	u_int16_t fid, wattr, grantedmode;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_OPEN, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_uint16le(mbp, accmode);
@@ -664,14 +725,14 @@
 smbfs_smb_close(struct smb_share *ssp, u_int16_t fid, struct timespec *mtime,
 	struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct mbchain *mbp;
 	u_long time;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CLOSE, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CLOSE, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM);
@@ -692,7 +753,7 @@
 smbfs_smb_create(struct smbnode *dnp, const char *name, int nmlen,
 	struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = dnp->n_mount->sm_share;
 	struct mbchain *mbp;
 	struct mdchain *mdp;
@@ -702,9 +763,9 @@
 	u_long tm;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CREATE, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_uint16le(mbp, SMB_FA_ARCHIVE);		/* attributes  */
@@ -737,14 +798,14 @@
 int
 smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct mbchain *mbp;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_DELETE, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
@@ -764,14 +825,14 @@
 smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp,
 	const char *tname, int tnmlen, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = src->n_mount->sm_share;
 	struct mbchain *mbp;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_RENAME, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_RENAME, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN);
@@ -797,14 +858,14 @@
 smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp,
 	const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = src->n_mount->sm_share;
 	struct mbchain *mbp;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_MOVE, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_MOVE, scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_uint16le(mbp, SMB_TID_UNKNOWN);
@@ -832,14 +893,15 @@
 smbfs_smb_mkdir(struct smbnode *dnp, const char *name, int len,
 	struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = dnp->n_mount->sm_share;
 	struct mbchain *mbp;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_CREATE_DIRECTORY, scred,
+	    &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	smb_rq_wend(rqp);
@@ -857,14 +919,15 @@
 int
 smbfs_smb_rmdir(struct smbnode *np, struct smb_cred *scred)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct mbchain *mbp;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred);
+	error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_DELETE_DIRECTORY, scred,
+	    &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	smb_rq_wend(rqp);
@@ -897,7 +960,7 @@
 	}
 	error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_SEARCH, ctx->f_scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	ctx->f_rq = rqp;
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
@@ -1139,13 +1202,14 @@
 static int
 smbfs_smb_findclose2(struct smbfs_fctx *ctx)
 {
-	struct smb_rq rq, *rqp = &rq;
+	struct smb_rq *rqp;
 	struct mbchain *mbp;
 	int error;
 
-	error = smb_rq_init(rqp, SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2, ctx->f_scred);
+	error = smb_rq_alloc(SSTOCP(ctx->f_ssp), SMB_COM_FIND_CLOSE2,
+	    ctx->f_scred, &rqp);
 	if (error)
-		return error;
+		return (error);
 	smb_rq_getrequest(rqp, &mbp);
 	smb_rq_wstart(rqp);
 	mb_put_mem(mbp, (caddr_t)&ctx->f_Sid, 2, MB_MSYSTEM);
@@ -1165,8 +1229,6 @@
 		ctx->f_name = malloc(SMB_MAXFNAMELEN * 2, M_SMBFSDATA, M_WAITOK);
 	} else
 		ctx->f_name = malloc(SMB_MAXFNAMELEN, M_SMBFSDATA, M_WAITOK);
-	if (ctx->f_name == NULL)
-		return ENOMEM;
 	ctx->f_infolevel = SMB_DIALECT(SSTOVC(ctx->f_ssp)) < SMB_DIALECT_NTLM0_12 ?
 	    SMB_INFO_STANDARD : SMB_FIND_FILE_DIRECTORY_INFO;
 	ctx->f_attrmask = attr;
@@ -1311,10 +1373,7 @@
 	struct smbfs_fctx *ctx;
 	int error;
 
-	ctx = malloc(sizeof(*ctx), M_SMBFSDATA, M_WAITOK);
-	if (ctx == NULL)
-		return ENOMEM;
-	bzero(ctx, sizeof(*ctx));
+	ctx = malloc(sizeof(*ctx), M_SMBFSDATA, M_WAITOK | M_ZERO);
 	ctx->f_ssp = dnp->n_mount->sm_share;
 	ctx->f_dnp = dnp;
 	ctx->f_flags = SMBFS_RDD_FINDFIRST;
@@ -1395,15 +1454,9 @@
 		fap->fa_ino = 2;
 		return 0;
 	}
-	if (nmlen == 1 && name[0] == '.') {
-		error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred);
-		return error;
-	} else if (nmlen == 2 && name[0] == '.' && name[1] == '.') {
-		error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap,
-		    scred);
-		printf("%s: knows NOTHING about '..'\n", __func__);
-		return error;
-	}
+	MPASS(!(nmlen == 2 && name[0] == '.' && name[1] == '.'));
+	MPASS(!(nmlen == 1 && name[0] == '.'));
+	ASSERT_VOP_ELOCKED(dnp->n_vnode, "smbfs_smb_lookup");
 	error = smbfs_findopen(dnp, name, nmlen,
 	    SMB_FA_SYSTEM | SMB_FA_HIDDEN | SMB_FA_DIR, scred, &ctx);
 	if (error)

Modified: trunk/sys/fs/smbfs/smbfs_subr.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_subr.c	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_subr.c	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_subr.c 278435 2015-02-09 07:45:46Z dim $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -46,6 +47,7 @@
 #include <fs/smbfs/smbfs_subr.h>
 
 MALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data");
+MALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data");
 
 void
 smb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds)
@@ -106,44 +108,6 @@
 	smb_time_server2local(tsp->tv_sec, tzoff, tsp);
 }
 
-static int
-smb_fphelp(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *np,
-	int caseopt)
-{
-	struct smbmount *smp= np->n_mount;
-	struct smbnode **npp = smp->sm_npstack;
-	int i, error = 0;
-
-/*	simple_lock(&smp->sm_npslock);*/
-	i = 0;
-	while (np->n_parent) {
-		if (i++ == SMBFS_MAXPATHCOMP) {
-/*			simple_unlock(&smp->sm_npslock);*/
-			return ENAMETOOLONG;
-		}
-		*npp++ = np;
-		if ((np->n_flag & NREFPARENT) == 0)
-			break;
-		np = VTOSMB(np->n_parent);
-	}
-/*	if (i == 0)
-		return smb_put_dmem(mbp, vcp, "\\", 2, caseopt);*/
-	while (i--) {
-		np = *--npp;
-		if (SMB_UNICODE_STRINGS(vcp))
-			error = mb_put_uint16le(mbp, '\\');
-		else
-			error = mb_put_uint8(mbp, '\\');
-		if (error)
-			break;
-		error = smb_put_dmem(mbp, vcp, np->n_name, np->n_nmlen, caseopt);
-		if (error)
-			break;
-	}
-/*	simple_unlock(&smp->sm_npslock);*/
-	return error;
-}
-
 int
 smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp,
 	const char *name, int nmlen)
@@ -159,23 +123,28 @@
 	if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0)
 		caseopt |= SMB_CS_UPPER;
 	if (dnp != NULL) {
-		error = smb_fphelp(mbp, vcp, dnp, caseopt);
+		error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, 
+		    caseopt);
 		if (error)
 			return error;
+		if (name) {
+			/* Put the separator */
+			if (SMB_UNICODE_STRINGS(vcp))
+				error = mb_put_uint16le(mbp, '\\');
+			else
+				error = mb_put_uint8(mbp, '\\');
+			if (error)
+				return error;
+			/* Put the name */
+			error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt);
+			if (error)
+				return error;
+		}
 	}
-	if (name) {
-		if (SMB_UNICODE_STRINGS(vcp))
-			error = mb_put_uint16le(mbp, '\\');
-		else
-			error = mb_put_uint8(mbp, '\\');
-		if (error)
-			return error;
-		error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt);
-		if (error)
-			return error;
-	}
-	error = mb_put_uint8(mbp, 0);
-	if (SMB_UNICODE_STRINGS(vcp) && error == 0)
+	/* Put NULL terminator. */
+	if (SMB_UNICODE_STRINGS(vcp))
+		error = mb_put_uint16le(mbp, 0);
+	else
 		error = mb_put_uint8(mbp, 0);
 	return error;
 }
@@ -202,8 +171,8 @@
 		if (error) return error;
 		*/
 
-		error = iconv_conv_case
-			(vcp->vc_tolocal, (const char **)&ibuf, &ilen, &obuf, &olen, copt);
+		error = iconv_conv_case(vcp->vc_tolocal,
+		    __DECONST(const char **, &ibuf), &ilen, &obuf, &olen, copt);
 		if (error && SMB_UNICODE_STRINGS(vcp)) {
 			/*
 			 * If using unicode, leaving a file name as it was when
@@ -222,3 +191,15 @@
 	}
 	return error;
 }
+
+void *
+smbfs_malloc_scred(void)
+{
+	return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK));
+}
+
+void
+smbfs_free_scred(void *scred)
+{
+	free(scred, M_SMBFSCRED);
+}

Modified: trunk/sys/fs/smbfs/smbfs_subr.h
===================================================================
--- trunk/sys/fs/smbfs/smbfs_subr.h	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_subr.h	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_subr.h 294263 2016-01-18 11:47:03Z ae $
  */
 #ifndef _FS_SMBFS_SMBFS_SUBR_H_
 #define _FS_SMBFS_SMBFS_SUBR_H_
@@ -30,6 +31,7 @@
 
 #ifdef MALLOC_DECLARE
 MALLOC_DECLARE(M_SMBFSDATA);
+MALLOC_DECLARE(M_SMBFSCRED);
 #endif
 
 #define SMBFSERR(format, args...) printf("%s: "format, __func__ ,## args)
@@ -125,11 +127,10 @@
  */
 int  smbfs_smb_lock(struct smbnode *np, int op, caddr_t id,
 	off_t start, off_t end,	struct smb_cred *scred);
-int  smbfs_smb_statfs2(struct smb_share *ssp, struct statfs *sbp,
-	struct smb_cred *scred);
 int  smbfs_smb_statfs(struct smb_share *ssp, struct statfs *sbp,
 	struct smb_cred *scred);
-int  smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred);
+int  smbfs_smb_setfsize(struct smbnode *np, int64_t newsize,
+	struct smb_cred *scred);
 
 int  smbfs_smb_query_info(struct smbnode *np, const char *name, int len,
 	struct smbfattr *fap, struct smb_cred *scred);
@@ -178,4 +179,6 @@
 	     u_int16_t *dtp, u_int8_t *dhp);
 void smb_dos2unixtime (u_int dd, u_int dt, u_int dh, int tzoff, struct timespec *tsp);
 
+void *smbfs_malloc_scred(void);
+void smbfs_free_scred(void *);
 #endif /* !_FS_SMBFS_SMBFS_SUBR_H_ */

Modified: trunk/sys/fs/smbfs/smbfs_vfsops.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_vfsops.c	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_vfsops.c	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_vfsops.c 276002 2014-12-21 11:33:18Z trasz $
  */
 
 #include <sys/param.h>
@@ -54,19 +55,10 @@
 
 static int smbfs_version = SMBFS_VERSION;
 
-#ifdef SMBFS_USEZONE
-#include <vm/vm.h>
-#include <vm/vm_extern.h>
-
-vm_zone_t smbfsmount_zone;
-#endif
-
 SYSCTL_NODE(_vfs, OID_AUTO, smbfs, CTLFLAG_RW, 0, "SMB/CIFS filesystem");
 SYSCTL_INT(_vfs_smbfs, OID_AUTO, version, CTLFLAG_RD, &smbfs_version, 0, "");
 SYSCTL_INT(_vfs_smbfs, OID_AUTO, debuglevel, CTLFLAG_RW, &smbfs_debuglevel, 0, "");
 
-static MALLOC_DEFINE(M_SMBFSHASH, "smbfs_hash", "SMBFS hash table");
-
 static vfs_init_t       smbfs_init;
 static vfs_uninit_t     smbfs_uninit;
 static vfs_cmount_t     smbfs_cmount;
@@ -131,7 +123,7 @@
 }
 
 static const char *smbfs_opts[] = {
-	"dev", "soft", "intr", "strong", "have_nls", "long",
+	"fd", "soft", "intr", "strong", "have_nls", "long",
 	"mountpoint", "rootpath", "uid", "gid", "file_mode", "dir_mode",
 	"caseopt", "errmsg", NULL
 };
@@ -144,10 +136,12 @@
 	struct smb_share *ssp = NULL;
 	struct vnode *vp;
 	struct thread *td;
-	struct smb_cred scred;
+	struct smb_dev *dev;
+	struct smb_cred *scred;
 	int error, v;
 	char *pc, *pe;
 
+	dev = NULL;
 	td = curthread;
 	if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
 		return EOPNOTSUPP;
@@ -157,40 +151,31 @@
 		return (EINVAL);
 	}
 
-	smb_makescred(&scred, td, td->td_ucred);
-	if (1 != vfs_scanopt(mp->mnt_optnew, "dev", "%d", &v)) {
-		vfs_mount_error(mp, "No dev option");
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, td->td_ucred);
+	
+	/* Ask userspace of `fd`, the file descriptor of this session */
+	if (1 != vfs_scanopt(mp->mnt_optnew, "fd", "%d", &v)) {
+		vfs_mount_error(mp, "No fd option");
+		smbfs_free_scred(scred);
 		return (EINVAL);
 	}
-	error = smb_dev2share(v, SMBM_EXEC, &scred, &ssp);
+	error = smb_dev2share(v, SMBM_EXEC, scred, &ssp, &dev);
+	smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK | M_ZERO);
 	if (error) {
 		printf("invalid device handle %d (%d)\n", v, error);
-		vfs_mount_error(mp, "invalid device handle %d (%d)\n", v, error);
+		vfs_mount_error(mp, "invalid device handle %d %d\n", v, error);
+		smbfs_free_scred(scred);
+		free(smp, M_SMBFSDATA);
 		return error;
 	}
 	vcp = SSTOVC(ssp);
-	smb_share_unlock(ssp, 0);
+	smb_share_unlock(ssp);
 	mp->mnt_stat.f_iosize = SSTOVC(ssp)->vc_txmax;
-
-#ifdef SMBFS_USEZONE
-	smp = zalloc(smbfsmount_zone);
-#else
-	smp = malloc(sizeof(*smp), M_SMBFSDATA, M_WAITOK);
-#endif
-        if (smp == NULL) {
-		printf("could not alloc smbmount\n");
-		vfs_mount_error(mp, "could not alloc smbmount", v, error);
-		error = ENOMEM;
-		goto bad;
-        }
-	bzero(smp, sizeof(*smp));
-        mp->mnt_data = smp;
-	smp->sm_hash = hashinit(desiredvnodes, M_SMBFSHASH, &smp->sm_hashlen);
-	if (smp->sm_hash == NULL)
-		goto bad;
-	sx_init(&smp->sm_hashlock, "smbfsh");
+	mp->mnt_data = smp;
 	smp->sm_share = ssp;
 	smp->sm_root = NULL;
+	smp->sm_dev = dev;
 	if (1 != vfs_scanopt(mp->mnt_optnew,
 	    "caseopt", "%d", &smp->sm_caseopt)) {
 		vfs_mount_error(mp, "Invalid caseopt");
@@ -228,16 +213,15 @@
 	vfs_flagopt(mp->mnt_optnew,
 	    "nolong", &smp->sm_flags, SMBFS_MOUNT_NO_LONG);
 
-/*	simple_lock_init(&smp->sm_npslock);*/
 	pc = mp->mnt_stat.f_mntfromname;
 	pe = pc + sizeof(mp->mnt_stat.f_mntfromname);
 	bzero(pc, MNAMELEN);
 	*pc++ = '/';
 	*pc++ = '/';
-	pc=index(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
+	pc = strchr(strncpy(pc, vcp->vc_username, pe - pc - 2), 0);
 	if (pc < pe-1) {
 		*(pc++) = '@';
-		pc = index(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
+		pc = strchr(strncpy(pc, vcp->vc_srvname, pe - pc - 2), 0);
 		if (pc < pe - 1) {
 			*(pc++) = '/';
 			strncpy(pc, ssp->ss_name, pe - pc - 2);
@@ -255,21 +239,20 @@
 #ifdef DIAGNOSTIC
 	SMBERROR("mp=%p\n", mp);
 #endif
+	smbfs_free_scred(scred);
 	return error;
 bad:
-        if (smp) {
-		if (smp->sm_hash)
-			free(smp->sm_hash, M_SMBFSHASH);
-		sx_destroy(&smp->sm_hashlock);
-#ifdef SMBFS_USEZONE
-		zfree(smbfsmount_zone, smp);
-#else
-		free(smp, M_SMBFSDATA);
-#endif
+	if (ssp)
+		smb_share_put(ssp, scred);
+	smbfs_free_scred(scred);	
+	SMB_LOCK();
+	if (error && smp->sm_dev == dev) {
+		smp->sm_dev = NULL;
+		sdp_trydestroy(dev);
 	}
-	if (ssp)
-		smb_share_put(ssp, &scred);
-        return error;
+	SMB_UNLOCK();
+	free(smp, M_SMBFSDATA);
+	return error;
 }
 
 /* Unmount the filesystem described by mp. */
@@ -278,7 +261,8 @@
 {
 	struct thread *td;
 	struct smbmount *smp = VFSTOSMBFS(mp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
+	struct smb_dev *dev;
 	int error, flags;
 
 	SMBVDEBUG("smbfs_unmount: flags=%04x\n", mntflags);
@@ -301,24 +285,25 @@
 	} while (error == EBUSY && smp->sm_didrele != 0);
 	if (error)
 		return error;
-	smb_makescred(&scred, td, td->td_ucred);
-	error = smb_share_lock(smp->sm_share, LK_EXCLUSIVE);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, td->td_ucred);
+	error = smb_share_lock(smp->sm_share);
 	if (error)
-		return error;
-	smb_share_put(smp->sm_share, &scred);
+		goto out;
+	smb_share_put(smp->sm_share, scred);
+	SMB_LOCK();
+	dev = smp->sm_dev;
+	if (!dev)
+		panic("No private data for mount point");
+	sdp_trydestroy(dev);
 	mp->mnt_data = NULL;
-
-	if (smp->sm_hash)
-		free(smp->sm_hash, M_SMBFSHASH);
-	sx_destroy(&smp->sm_hashlock);
-#ifdef SMBFS_USEZONE
-	zfree(smbfsmount_zone, smp);
-#else
+	SMB_UNLOCK();
 	free(smp, M_SMBFSDATA);
-#endif
 	MNT_ILOCK(mp);
 	mp->mnt_flag &= ~MNT_LOCAL;
 	MNT_IUNLOCK(mp);
+out:
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -334,34 +319,32 @@
 	struct smbfattr fattr;
 	struct thread *td;
 	struct ucred *cred;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	int error;
 
 	td = curthread;
 	cred = td->td_ucred;
 
-	if (smp == NULL) {
-		SMBERROR("smp == NULL (bug in umount)\n");
-		vfs_mount_error(mp, "smp == NULL (bug in umount)");
-		return EINVAL;
-	}
 	if (smp->sm_root) {
 		*vpp = SMBTOV(smp->sm_root);
 		return vget(*vpp, LK_EXCLUSIVE | LK_RETRY, td);
 	}
-	smb_makescred(&scred, td, cred);
-	error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cred);
+	error = smbfs_smb_lookup(NULL, NULL, 0, &fattr, scred);
 	if (error)
-		return error;
-	error = smbfs_nget(mp, NULL, "TheRooT", 7, &fattr, &vp);
+		goto out;
+	error = smbfs_nget(mp, NULL, NULL, 0, &fattr, &vp);
 	if (error)
-		return error;
+		goto out;
 	ASSERT_VOP_LOCKED(vp, "smbfs_root");
 	vp->v_vflag |= VV_ROOT;
 	np = VTOSMB(vp);
 	smp->sm_root = np;
 	*vpp = vp;
-	return 0;
+out:
+	smbfs_free_scred(scred);
+	return error;
 }
 
 /*
@@ -383,9 +366,6 @@
 int
 smbfs_init(struct vfsconf *vfsp)
 {
-#ifdef SMBFS_USEZONE
-	smbfsmount_zone = zinit("SMBFSMOUNT", sizeof(struct smbmount), 0, 0, 1);
-#endif
 	smbfs_pbuf_freecnt = nswbuf / 2 + 1;
 	SMBVDEBUG("done.\n");
 	return 0;
@@ -410,8 +390,8 @@
 	struct smbmount *smp = VFSTOSMBFS(mp);
 	struct smbnode *np = smp->sm_root;
 	struct smb_share *ssp = smp->sm_share;
-	struct smb_cred scred;
-	int error = 0;
+	struct smb_cred *scred;
+	int error;
 
 	if (np == NULL) {
 		vfs_mount_error(mp, "np == NULL");
@@ -419,14 +399,9 @@
 	}
 	
 	sbp->f_iosize = SSTOVC(ssp)->vc_txmax;		/* optimal transfer block size */
-	smb_makescred(&scred, td, td->td_ucred);
-
-	if (SMB_DIALECT(SSTOVC(ssp)) >= SMB_DIALECT_LANMAN2_0)
-		error = smbfs_smb_statfs2(ssp, sbp, &scred);
-	else
-		error = smbfs_smb_statfs(ssp, sbp, &scred);
-	if (error)
-		return error;
-	sbp->f_flags = 0;		/* copy of mount exported flags */
-	return 0;
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, td->td_ucred);
+	error = smbfs_smb_statfs(ssp, sbp, scred);
+	smbfs_free_scred(scred);
+	return (error);
 }

Modified: trunk/sys/fs/smbfs/smbfs_vnops.c
===================================================================
--- trunk/sys/fs/smbfs/smbfs_vnops.c	2018-05-27 22:08:25 UTC (rev 10020)
+++ trunk/sys/fs/smbfs/smbfs_vnops.c	2018-05-27 22:08:55 UTC (rev 10021)
@@ -1,3 +1,4 @@
+/* $MidnightBSD$ */
 /*-
  * Copyright (c) 2000-2001 Boris Popov
  * All rights reserved.
@@ -23,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $MidnightBSD$
+ * $FreeBSD: stable/10/sys/fs/smbfs/smbfs_vnops.c 294263 2016-01-18 11:47:03Z ae $
  */
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -153,7 +154,7 @@
 {
 	struct vnode *vp = ap->a_vp;
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	struct vattr vattr;
 	int mode = ap->a_mode;
 	int error, accmode;
@@ -197,14 +198,15 @@
 	accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
 	if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0)
 		accmode = SMB_SM_DENYNONE|SMB_AM_OPENRW;
-	smb_makescred(&scred, ap->a_td, ap->a_cred);
-	error = smbfs_smb_open(np, accmode, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, ap->a_td, ap->a_cred);
+	error = smbfs_smb_open(np, accmode, scred);
 	if (error) {
 		if (mode & FWRITE)
 			return EACCES;
 		else if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
 			accmode = SMB_SM_DENYNONE|SMB_AM_OPENREAD;
-			error = smbfs_smb_open(np, accmode, &scred);
+			error = smbfs_smb_open(np, accmode, scred);
 		}
 	}
 	if (error == 0) {
@@ -212,6 +214,7 @@
 		vnode_create_vobject(ap->a_vp, vattr.va_size, ap->a_td);
 	}
 	smbfs_attr_cacheremove(vp);
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -228,12 +231,14 @@
 	struct vnode *vp = ap->a_vp;
 	struct thread *td = ap->a_td;
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
 
 	if (vp->v_type == VDIR && (np->n_flag & NOPEN) != 0 &&
 	    np->n_dirseq != NULL) {
-		smb_makescred(&scred, td, ap->a_cred);
-		smbfs_findclose(np->n_dirseq, &scred);
+		scred = smbfs_malloc_scred();
+		smb_makescred(scred, td, ap->a_cred);
+		smbfs_findclose(np->n_dirseq, scred);
+		smbfs_free_scred(scred);
 		np->n_dirseq = NULL;
 	}
 	return 0;
@@ -254,7 +259,7 @@
 	struct smbnode *np = VTOSMB(vp);
 	struct vattr *va=ap->a_vap;
 	struct smbfattr fattr;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	u_quad_t oldsize;
 	int error;
 
@@ -263,11 +268,13 @@
 	if (!error)
 		return 0;
 	SMBVDEBUG("not in the cache\n");
-	smb_makescred(&scred, curthread, ap->a_cred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, curthread, ap->a_cred);
 	oldsize = np->n_size;
-	error = smbfs_smb_lookup(np, NULL, 0, &fattr, &scred);
+	error = smbfs_smb_lookup(np, NULL, 0, &fattr, scred);
 	if (error) {
 		SMBVDEBUG("error %d\n", error);
+		smbfs_free_scred(scred);
 		return error;
 	}
 	smbfs_attr_cacheenter(vp, &fattr);
@@ -274,6 +281,7 @@
 	smbfs_attr_cachelookup(vp, va);
 	if (np->n_flag & NOPEN)
 		np->n_size = oldsize;
+		smbfs_free_scred(scred);
 	return 0;
 }
 
@@ -289,7 +297,7 @@
 	struct smbnode *np = VTOSMB(vp);
 	struct vattr *vap = ap->a_vap;
 	struct timespec *mtime, *atime;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	struct smb_share *ssp = np->n_mount->sm_share;
 	struct smb_vc *vcp = SSTOVC(ssp);
 	struct thread *td = curthread;
@@ -298,8 +306,6 @@
 	int old_n_dosattr;
 
 	SMBVDEBUG("\n");
-	if (vap->va_flags != VNOVAL)
-		return EOPNOTSUPP;
 	isreadonly = (vp->v_mount->mnt_flag & MNT_RDONLY);
 	/*
 	 * Disallow write attempts if the filesystem is mounted read-only.
@@ -306,20 +312,41 @@
 	 */
   	if ((vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || 
 	     vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
-	     vap->va_mode != (mode_t)VNOVAL) && isreadonly)
+	     vap->va_mode != (mode_t)VNOVAL || vap->va_flags != VNOVAL) &&
+	     isreadonly)
 		return EROFS;
-	smb_makescred(&scred, td, ap->a_cred);
+
+	/*
+	 * We only support setting four flags.  Don't allow setting others.
+	 *
+	 * We map UF_READONLY to SMB_FA_RDONLY, unlike the MacOS X version
+	 * of this code, which maps both UF_IMMUTABLE AND SF_IMMUTABLE to
+	 * SMB_FA_RDONLY.  The immutable flags have different semantics
+	 * than readonly, which is the reason for the difference.
+	 */
+	if (vap->va_flags != VNOVAL) {
+		if (vap->va_flags & ~(UF_HIDDEN|UF_SYSTEM|UF_ARCHIVE|
+				      UF_READONLY))
+			return EINVAL;
+	}
+
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, ap->a_cred);
 	if (vap->va_size != VNOVAL) {
  		switch (vp->v_type) {
  		    case VDIR:
- 			return EISDIR;
+ 			error = EISDIR;
+			goto out;
  		    case VREG:
 			break;
  		    default:
-			return EINVAL;
+			error = EINVAL;
+			goto out;
   		};
-		if (isreadonly)
-			return EROFS;
+		if (isreadonly) {
+			error = EROFS;
+			goto out;
+		}
 		doclose = 0;
 		vnode_pager_setsize(vp, (u_long)vap->va_size);
  		tsize = np->n_size;
@@ -327,30 +354,66 @@
 		if ((np->n_flag & NOPEN) == 0) {
 			error = smbfs_smb_open(np,
 					       SMB_SM_DENYNONE|SMB_AM_OPENRW,
-					       &scred);
+					       scred);
 			if (error == 0)
 				doclose = 1;
 		}
 		if (error == 0)
-			error = smbfs_smb_setfsize(np, vap->va_size, &scred);
+			error = smbfs_smb_setfsize(np,
+			    (int64_t)vap->va_size, scred);
 		if (doclose)
-			smbfs_smb_close(ssp, np->n_fid, NULL, &scred);
+			smbfs_smb_close(ssp, np->n_fid, NULL, scred);
 		if (error) {
 			np->n_size = tsize;
 			vnode_pager_setsize(vp, (u_long)tsize);
-			return error;
+			goto out;
 		}
   	}
-	if (vap->va_mode != (mode_t)VNOVAL) {
+	if ((vap->va_flags != VNOVAL) || (vap->va_mode != (mode_t)VNOVAL)) {
 		old_n_dosattr = np->n_dosattr;
-		if (vap->va_mode & S_IWUSR)
-			np->n_dosattr &= ~SMB_FA_RDONLY;
-		else
-			np->n_dosattr |= SMB_FA_RDONLY;
+
+		if (vap->va_mode != (mode_t)VNOVAL) {
+			if (vap->va_mode & S_IWUSR)
+				np->n_dosattr &= ~SMB_FA_RDONLY;
+			else
+				np->n_dosattr |= SMB_FA_RDONLY;
+		}
+
+		if (vap->va_flags != VNOVAL) {
+			if (vap->va_flags & UF_HIDDEN)
+				np->n_dosattr |= SMB_FA_HIDDEN;
+			else
+				np->n_dosattr &= ~SMB_FA_HIDDEN;
+
+			if (vap->va_flags & UF_SYSTEM)
+				np->n_dosattr |= SMB_FA_SYSTEM;
+			else
+				np->n_dosattr &= ~SMB_FA_SYSTEM;
+
+			if (vap->va_flags & UF_ARCHIVE)
+				np->n_dosattr |= SMB_FA_ARCHIVE;
+			else
+				np->n_dosattr &= ~SMB_FA_ARCHIVE;
+
+			/*
+			 * We only support setting the immutable / readonly
+			 * bit for regular files.  According to comments in
+			 * the MacOS X version of this code, supporting the
+			 * readonly bit on directories doesn't do the same
+			 * thing in Windows as in Unix.
+			 */
+			if (vp->v_type == VREG) {
+				if (vap->va_flags & UF_READONLY)
+					np->n_dosattr |= SMB_FA_RDONLY;
+				else
+					np->n_dosattr &= ~SMB_FA_RDONLY;
+			}
+		}
+
 		if (np->n_dosattr != old_n_dosattr) {
-			error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, &scred);
+			error = smbfs_smb_setpattr(np, np->n_dosattr, NULL, scred);
 			if (error)
-				return error;
+				goto out;
 		}
 	}
 	mtime = atime = NULL;
@@ -381,7 +444,7 @@
 				    NULL);
 				if (!error) {
 /*					error = smbfs_smb_setfattrNT(np, 0,
-					    mtime, atime, &scred);
+					    mtime, atime, scred);
 					VOP_GETATTR(vp, &vattr, ap->a_cred); */
 					if (mtime)
 						np->n_mtime = *mtime;
@@ -388,18 +451,18 @@
 					VOP_CLOSE(vp, FWRITE, ap->a_cred, td);
 				}
 			} else if ((vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS)) {
-				error = smbfs_smb_setptime2(np, mtime, atime, 0, &scred);
-/*				error = smbfs_smb_setpattrNT(np, 0, mtime, atime, &scred);*/
+				error = smbfs_smb_setptime2(np, mtime, atime, 0, scred);
+/*				error = smbfs_smb_setpattrNT(np, 0, mtime, atime, scred);*/
 			} else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN2_0) {
-				error = smbfs_smb_setptime2(np, mtime, atime, 0, &scred);
+				error = smbfs_smb_setptime2(np, mtime, atime, 0, scred);
 			} else {
-				error = smbfs_smb_setpattr(np, 0, mtime, &scred);
+				error = smbfs_smb_setpattr(np, 0, mtime, scred);
 			}
 		} else {
 			if (vcp->vc_sopt.sv_caps & SMB_CAP_NT_SMBS) {
-				error = smbfs_smb_setfattrNT(np, 0, mtime, atime, &scred);
+				error = smbfs_smb_setfattrNT(np, 0, mtime, atime, scred);
 			} else if (SMB_DIALECT(vcp) >= SMB_DIALECT_LANMAN1_0) {
-				error = smbfs_smb_setftime(np, mtime, atime, &scred);
+				error = smbfs_smb_setftime(np, mtime, atime, scred);
 			} else {
 				/*
 				 * I have no idea how to handle this for core
@@ -417,6 +480,8 @@
 	smbfs_attr_cacheremove(vp);	/* invalidate cache */
 	VOP_GETATTR(vp, vap, ap->a_cred);
 	np->n_mtime.tv_sec = vap->va_mtime.tv_sec;
+out:
+	smbfs_free_scred(scred);
 	return error;
 }
 /*
@@ -452,7 +517,8 @@
 	struct vnode *vp = ap->a_vp;
 	struct uio *uio = ap->a_uio;
 
-	SMBVDEBUG("%d,ofs=%d,sz=%d\n",vp->v_type, (int)uio->uio_offset, uio->uio_resid);
+	SMBVDEBUG("%d,ofs=%jd,sz=%zd\n",vp->v_type, (intmax_t)uio->uio_offset, 
+	    uio->uio_resid);
 	if (vp->v_type != VREG)
 		return (EPERM);
 	return smbfs_writevnode(vp, uio, ap->a_cred,ap->a_ioflag);
@@ -481,7 +547,7 @@
 	struct vnode *vp;
 	struct vattr vattr;
 	struct smbfattr fattr;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	char *name = cnp->cn_nameptr;
 	int nmlen = cnp->cn_namelen;
 	int error;
@@ -493,20 +559,23 @@
 		return EOPNOTSUPP;
 	if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)))
 		return error;
-	smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
 	
-	error = smbfs_smb_create(dnp, name, nmlen, &scred);
+	error = smbfs_smb_create(dnp, name, nmlen, scred);
 	if (error)
-		return error;
-	error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, &scred);
+		goto out;
+	error = smbfs_smb_lookup(dnp, name, nmlen, &fattr, scred);
 	if (error)
-		return error;
+		goto out;
 	error = smbfs_nget(VTOVFS(dvp), dvp, name, nmlen, &fattr, &vp);
 	if (error)
-		return error;
+		goto out;
 	*vpp = vp;
 	if (cnp->cn_flags & MAKEENTRY)
 		cache_enter(dvp, vp, cnp);
+out:
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -523,16 +592,18 @@
 /*	struct vnode *dvp = ap->a_dvp;*/
 	struct componentname *cnp = ap->a_cnp;
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	int error;
 
 	if (vp->v_type == VDIR || (np->n_flag & NOPEN) != 0 || vrefcnt(vp) != 1)
 		return EPERM;
-	smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
-	error = smbfs_smb_delete(np, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
+	error = smbfs_smb_delete(np, scred);
 	if (error == 0)
 		np->n_flag |= NGONE;
 	cache_purge(vp);
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -556,10 +627,11 @@
 	struct vnode *tdvp = ap->a_tdvp;
 	struct componentname *tcnp = ap->a_tcnp;
 /*	struct componentname *fcnp = ap->a_fcnp;*/
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	u_int16_t flags = 6;
 	int error=0;
 
+	scred = NULL;
 	/* Check for cross-device rename */
 	if ((fvp->v_mount != tdvp->v_mount) ||
 	    (tvp && (fvp->v_mount != tvp->v_mount))) {
@@ -577,10 +649,10 @@
 	} else if (fvp->v_type == VREG) {
 		flags |= 1;
 	} else {
-		error = EINVAL;
-		goto out;
+		return EINVAL;
 	}
-	smb_makescred(&scred, tcnp->cn_thread, tcnp->cn_cred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, tcnp->cn_thread, tcnp->cn_cred);
 	/*
 	 * It seems that Samba doesn't implement SMB_COM_MOVE call...
 	 */
@@ -587,7 +659,7 @@
 #ifdef notnow
 	if (SMB_DIALECT(SSTOCN(smp->sm_share)) >= SMB_DIALECT_LANMAN1_0) {
 		error = smbfs_smb_move(VTOSMB(fvp), VTOSMB(tdvp),
-		    tcnp->cn_nameptr, tcnp->cn_namelen, flags, &scred);
+		    tcnp->cn_nameptr, tcnp->cn_namelen, flags, scred);
 	} else
 #endif
 	{
@@ -595,13 +667,13 @@
 		 * We have to do the work atomicaly
 		 */
 		if (tvp && tvp != fvp) {
-			error = smbfs_smb_delete(VTOSMB(tvp), &scred);
+			error = smbfs_smb_delete(VTOSMB(tvp), scred);
 			if (error)
 				goto out_cacherem;
 			VTOSMB(fvp)->n_flag |= NGONE;
 		}
 		error = smbfs_smb_rename(VTOSMB(fvp), VTOSMB(tdvp),
-		    tcnp->cn_nameptr, tcnp->cn_namelen, &scred);
+		    tcnp->cn_nameptr, tcnp->cn_namelen, scred);
 	}
 
 	if (fvp->v_type == VDIR) {
@@ -614,6 +686,7 @@
 	smbfs_attr_cacheremove(fdvp);
 	smbfs_attr_cacheremove(tdvp);
 out:
+	smbfs_free_scred(scred);
 	if (tdvp == tvp)
 		vrele(tdvp);
 	else
@@ -684,7 +757,7 @@
 	struct componentname *cnp = ap->a_cnp;
 	struct smbnode *dnp = VTOSMB(dvp);
 	struct vattr vattr;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	struct smbfattr fattr;
 	char *name = cnp->cn_nameptr;
 	int len = cnp->cn_namelen;
@@ -695,18 +768,21 @@
 	}	
 	if ((name[0] == '.') && ((len == 1) || ((len == 2) && (name[1] == '.'))))
 		return EEXIST;
-	smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
-	error = smbfs_smb_mkdir(dnp, name, len, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
+	error = smbfs_smb_mkdir(dnp, name, len, scred);
 	if (error)
-		return error;
-	error = smbfs_smb_lookup(dnp, name, len, &fattr, &scred);
+		goto out;
+	error = smbfs_smb_lookup(dnp, name, len, &fattr, scred);
 	if (error)
-		return error;
+		goto out;
 	error = smbfs_nget(VTOVFS(dvp), dvp, name, len, &fattr, &vp);
 	if (error)
-		return error;
+		goto out;
 	*ap->a_vpp = vp;
-	return 0;
+out:
+	smbfs_free_scred(scred);
+	return error;
 }
 
 /*
@@ -726,14 +802,15 @@
 /*	struct smbmount *smp = VTOSMBFS(vp);*/
 	struct smbnode *dnp = VTOSMB(dvp);
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	int error;
 
 	if (dvp == vp)
 		return EINVAL;
 
-	smb_makescred(&scred, cnp->cn_thread, cnp->cn_cred);
-	error = smbfs_smb_rmdir(np, &scred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, cnp->cn_thread, cnp->cn_cred);
+	error = smbfs_smb_rmdir(np, scred);
 	if (error == 0)
 		np->n_flag |= NGONE;
 	dnp->n_flag |= NMODIFIED;
@@ -740,6 +817,7 @@
 	smbfs_attr_cacheremove(dvp);
 /*	cache_purge(dvp);*/
 	cache_purge(vp);
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -935,7 +1013,7 @@
 	caddr_t id = (caddr_t)1 /* ap->a_id */;
 /*	int flags = ap->a_flags;*/
 	struct thread *td = curthread;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	u_quad_t size;
 	off_t start, end, oadd;
 	int error, lkop;
@@ -985,7 +1063,8 @@
 			return EOVERFLOW;
 		end = start + oadd;
 	}
-	smb_makescred(&scred, td, td->td_ucred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, td->td_ucred);
 	switch (ap->a_op) {
 	    case F_SETLK:
 		switch (fl->l_type) {
@@ -999,6 +1078,7 @@
 			lkop = SMB_LOCK_RELEASE;
 			break;
 		    default:
+			smbfs_free_scred(scred);
 			return EINVAL;
 		}
 		error = lf_advlock(ap, &vp->v_lockf, size);
@@ -1005,7 +1085,7 @@
 		if (error)
 			break;
 		lkop = SMB_LOCK_EXCL;
-		error = smbfs_smb_lock(np, lkop, id, start, end, &scred);
+		error = smbfs_smb_lock(np, lkop, id, start, end, scred);
 		if (error) {
 			int oldtype = fl->l_type;
 			fl->l_type = F_UNLCK;
@@ -1016,14 +1096,16 @@
 		break;
 	    case F_UNLCK:
 		lf_advlock(ap, &vp->v_lockf, size);
-		error = smbfs_smb_lock(np, SMB_LOCK_RELEASE, id, start, end, &scred);
+		error = smbfs_smb_lock(np, SMB_LOCK_RELEASE, id, start, end, scred);
 		break;
 	    case F_GETLK:
 		error = lf_advlock(ap, &vp->v_lockf, size);
 		break;
 	    default:
+		smbfs_free_scred(scred);
 		return EINVAL;
 	}
+	smbfs_free_scred(scred);
 	return error;
 }
 
@@ -1039,7 +1121,7 @@
 	 * Backslash characters, being a path delimiter, are prohibited
 	 * within a path component even for LOOKUP operations.
 	 */
-	if (index(name, '\\') != NULL)
+	if (strchr(name, '\\') != NULL)
 		return ENOENT;
 
 	if (nameiop == LOOKUP)
@@ -1051,20 +1133,20 @@
 		 */
 		if (nmlen > 12)
 			return ENAMETOOLONG;
-		cp = index(name, '.');
+		cp = strchr(name, '.');
 		if (cp == NULL)
 			return error;
 		if (cp == name || (cp - name) > 8)
 			return error;
-		cp = index(cp + 1, '.');
+		cp = strchr(cp + 1, '.');
 		if (cp != NULL)
 			return error;
 		for (cp = name, i = 0; i < nmlen; i++, cp++)
-			if (index(badchars83, *cp) != NULL)
+			if (strchr(badchars83, *cp) != NULL)
 				return error;
 	}
 	for (cp = name, i = 0; i < nmlen; i++, cp++)
-		if (index(badchars, *cp) != NULL)
+		if (strchr(badchars, *cp) != NULL)
 			return error;
 	return 0;
 }
@@ -1090,7 +1172,7 @@
 	struct mount *mp = dvp->v_mount;
 	struct smbnode *dnp;
 	struct smbfattr fattr, *fap;
-	struct smb_cred scred;
+	struct smb_cred *scred;
 	char *name = cnp->cn_nameptr;
 	int flags = cnp->cn_flags;
 	int nameiop = cnp->cn_nameiop;
@@ -1105,18 +1187,6 @@
 		SMBFSERR("invalid '..'\n");
 		return EIO;
 	}
-#ifdef SMB_VNODE_DEBUG
-	{
-		char *cp, c;
-
-		cp = name + nmlen;
-		c = *cp;
-		*cp = 0;
-		SMBVDEBUG("%d '%s' in '%s' id=d\n", nameiop, name, 
-			VTOSMB(dvp)->n_name);
-		*cp = c;
-	}
-#endif
 	islastcn = flags & ISLASTCN;
 	if (islastcn && (mp->mnt_flag & MNT_RDONLY) && (nameiop != LOOKUP))
 		return EROFS;
@@ -1131,7 +1201,7 @@
 	if (error) 
 		return ENOENT;
 
-	error = cache_lookup(dvp, vpp, cnp);
+	error = cache_lookup(dvp, vpp, cnp, NULL, NULL);
 	SMBVDEBUG("cache_lookup returned %d\n", error);
 	if (error > 0)
 		return error;
@@ -1181,20 +1251,28 @@
 	 */
 	error = 0;
 	*vpp = NULLVP;
-	smb_makescred(&scred, td, cnp->cn_cred);
+	scred = smbfs_malloc_scred();
+	smb_makescred(scred, td, cnp->cn_cred);
 	fap = &fattr;
 	if (flags & ISDOTDOT) {
-		error = smbfs_smb_lookup(VTOSMB(dnp->n_parent), NULL, 0, fap,
-		    &scred);
-		SMBVDEBUG("result of dotdot lookup: %d\n", error);
-	} else {
-		fap = &fattr;
-		error = smbfs_smb_lookup(dnp, name, nmlen, fap, &scred);
-/*		if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.')*/
+		/*
+		 * In the DOTDOT case, don't go over-the-wire
+		 * in order to request attributes. We already
+		 * know it's a directory and subsequent call to
+		 * smbfs_getattr() will restore consistency.
+		 *
+		 */
+		SMBVDEBUG("smbfs_smb_lookup: dotdot\n");
+	} else if (isdot) {
+		error = smbfs_smb_lookup(dnp, NULL, 0, fap, scred);
 		SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error);
 	}
+	else {
+		error = smbfs_smb_lookup(dnp, name, nmlen, fap, scred);
+		SMBVDEBUG("result of smbfs_smb_lookup: %d\n", error);
+	}
 	if (error && error != ENOENT)
-		return error;
+		goto out;
 	if (error) {			/* entry not found */
 		/*
 		 * Handle RENAME or CREATE case...
@@ -1202,11 +1280,13 @@
 		if ((nameiop == CREATE || nameiop == RENAME) && islastcn) {
 			error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
 			if (error)
-				return error;
+				goto out;
 			cnp->cn_flags |= SAVENAME;
-			return (EJUSTRETURN);
+			error = EJUSTRETURN;
+			goto out;
 		}
-		return ENOENT;
+		error = ENOENT;
+		goto out;
 	}/* else {
 		SMBVDEBUG("Found entry %s with id=%d\n", fap->entryName, fap->dirEntNum);
 	}*/
@@ -1216,38 +1296,64 @@
 	if (nameiop == DELETE && islastcn) { 	/* delete last component */
 		error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
 		if (error)
-			return error;
+			goto out;
 		if (isdot) {
 			VREF(dvp);
 			*vpp = dvp;
-			return 0;
+			goto out;
 		}
 		error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
 		if (error)
-			return error;
+			goto out;
 		*vpp = vp;
 		cnp->cn_flags |= SAVENAME;
-		return 0;
+		goto out;
 	}
 	if (nameiop == RENAME && islastcn) {
 		error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td);
 		if (error)
-			return error;
-		if (isdot)
-			return EISDIR;
+			goto out;
+		if (isdot) {
+			error = EISDIR;
+			goto out;
+		}
 		error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
 		if (error)
-			return error;
+			goto out;
 		*vpp = vp;
 		cnp->cn_flags |= SAVENAME;
-		return 0;
+		goto out;
 	}
 	if (flags & ISDOTDOT) {
+		mp = dvp->v_mount;
+		error = vfs_busy(mp, MBF_NOWAIT);
+		if (error != 0) {
+			vfs_ref(mp);
+			VOP_UNLOCK(dvp, 0);
+			error = vfs_busy(mp, 0);
+			vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+			vfs_rel(mp);
+			if (error) {
+				error = ENOENT;
+				goto out;
+			}
+			if ((dvp->v_iflag & VI_DOOMED) != 0) {
+				vfs_unbusy(mp);
+				error = ENOENT;
+				goto out;
+			}
+		}	
 		VOP_UNLOCK(dvp, 0);
 		error = smbfs_nget(mp, dvp, name, nmlen, NULL, &vp);
+		vfs_unbusy(mp);
 		vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
+		if ((dvp->v_iflag & VI_DOOMED) != 0) {
+			if (error == 0)
+				vput(vp);
+			error = ENOENT;
+		}
 		if (error)
-			return error;
+			goto out;
 		*vpp = vp;
 	} else if (isdot) {
 		vref(dvp);
@@ -1255,7 +1361,7 @@
 	} else {
 		error = smbfs_nget(mp, dvp, name, nmlen, fap, &vp);
 		if (error)
-			return error;
+			goto out;
 		*vpp = vp;
 		SMBVDEBUG("lookup: getnewvp!\n");
 	}
@@ -1263,5 +1369,7 @@
 /*		VTOSMB(*vpp)->n_ctime = VTOSMB(*vpp)->n_vattr.va_ctime.tv_sec;*/
 		cache_enter(dvp, *vpp, cnp);
 	}
-	return 0;
+out:
+	smbfs_free_scred(scred);
+	return (error);
 }



More information about the Midnightbsd-cvs mailing list