Module Name:    src
Committed By:   riz
Date:           Mon Dec 10 21:12:51 UTC 2012

Modified Files:
        src/sys/fs/smbfs [netbsd-6]: smbfs_node.c smbfs_node.h smbfs_vnops.c

Log Message:
Pull up following revision(s) (requested by nakayama in ticket #731):
        sys/fs/smbfs/smbfs_node.h: revision 1.13
        sys/fs/smbfs/smbfs_node.c: revision 1.48
        sys/fs/smbfs/smbfs_node.c: revision 1.49
        sys/fs/smbfs/smbfs_vnops.c: revision 1.83
        sys/fs/smbfs/smbfs_vnops.c: revision 1.84
Various fixes for smbfs:
- Implement NGONE to fix caching issue described in PR kern/25070.
  Mostly taken from FreeBSD r125637.
- Revert revision 1.70 of smbfs_vnops.c to fix setattr to opened
  direcotry.  In case of SMB_CAP_NT_SMBS, NOPEN is set after
  smbfs_smb_ntcreatex() call.  If NOPEN is set in front, it will
  immediately return by condition at do_open label.
- In smbfs_close(), call smbfs_smb_close() and drop NOPEN bit in
  the case of direcotry.  Otherwise smbfs_rmdir() fails when the
  directory was opened.
- Remove redundant vput() before vgone().
- Avoid unnecessary mutex_exit() in smbfs_node_alloc().
- Set NGONE bit to from-name vnode to invalidate the smbnode cache.


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.47.8.1 src/sys/fs/smbfs/smbfs_node.c
cvs rdiff -u -r1.12 -r1.12.94.1 src/sys/fs/smbfs/smbfs_node.h
cvs rdiff -u -r1.78.2.1 -r1.78.2.2 src/sys/fs/smbfs/smbfs_vnops.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/smbfs/smbfs_node.c
diff -u src/sys/fs/smbfs/smbfs_node.c:1.47 src/sys/fs/smbfs/smbfs_node.c:1.47.8.1
--- src/sys/fs/smbfs/smbfs_node.c:1.47	Sun Jun 12 03:35:54 2011
+++ src/sys/fs/smbfs/smbfs_node.c	Mon Dec 10 21:12:51 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_node.c,v 1.47 2011/06/12 03:35:54 rmind Exp $	*/
+/*	$NetBSD: smbfs_node.c,v 1.47.8.1 2012/12/10 21:12:51 riz Exp $	*/
 
 /*
  * Copyright (c) 2000-2001 Boris Popov
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_node.c,v 1.47 2011/06/12 03:35:54 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_node.c,v 1.47.8.1 2012/12/10 21:12:51 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -96,6 +96,7 @@ static int
 smbfs_node_alloc(struct mount *mp, struct vnode *dvp,
 	const char *name, int nmlen, struct smbfattr *fap, struct vnode **vpp)
 {
+	struct vattr vattr;
 	struct smbmount *smp = VFSTOSMBFS(mp);
 	struct smbnode_hashhead *nhpp;
 	struct smbnode *np, *np2, *dnp;
@@ -139,11 +140,26 @@ retry:
 		mutex_exit(&smp->sm_hashlock);
 		if (vget(vp, LK_EXCLUSIVE) != 0)
 			goto retry;
+		/* Force cached attributes to be refreshed if stale. */
+		(void)VOP_GETATTR(vp, &vattr, curlwp->l_cred);
+		/*
+		 * If the file type on the server is inconsistent with
+		 * what it was when we created the vnode, kill the
+		 * 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)) {
+			VOP_UNLOCK(vp);
+			vgone(vp);
+			goto allocnew;
+		}
 		*vpp = vp;
 		return (0);
 	}
 	mutex_exit(&smp->sm_hashlock);
 
+allocnew:
 	/*
 	 * If we don't have node attributes, then it is an explicit lookup
 	 * for an existing vnode.
@@ -307,10 +323,9 @@ smbfs_inactive(void *v)
 		np->n_flag &= ~NOPEN;
 		smbfs_attr_cacheremove(vp);
 	}
+	*ap->a_recycle = ((np->n_flag & NGONE) != 0);
 	VOP_UNLOCK(vp);
 
-	*ap->a_recycle = false; /* XXX: should set the value properly */
-
 	return (0);
 }
 /*

Index: src/sys/fs/smbfs/smbfs_node.h
diff -u src/sys/fs/smbfs/smbfs_node.h:1.12 src/sys/fs/smbfs/smbfs_node.h:1.12.94.1
--- src/sys/fs/smbfs/smbfs_node.h:1.12	Thu Nov  2 17:34:21 2006
+++ src/sys/fs/smbfs/smbfs_node.h	Mon Dec 10 21:12:51 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_node.h,v 1.12 2006/11/02 17:34:21 jmmv Exp $	*/
+/*	$NetBSD: smbfs_node.h,v 1.12.94.1 2012/12/10 21:12:51 riz Exp $	*/
 
 /*
  * Copyright (c) 2000-2001, Boris Popov
@@ -48,6 +48,7 @@
 /*efine	NNEW			0x0008*//* smb/vnode has been allocated */
 #define	NREFPARENT		0x0010	/* node holds parent from recycling */
 #define	NOPEN			0x2000	/* file is open */
+#define	NGONE			0x4000	/* file has been removed/renamed */
 
 #define SMBFS_ATTRTIMO		5	/* Attribute cache timeout in sec */
 

Index: src/sys/fs/smbfs/smbfs_vnops.c
diff -u src/sys/fs/smbfs/smbfs_vnops.c:1.78.2.1 src/sys/fs/smbfs/smbfs_vnops.c:1.78.2.2
--- src/sys/fs/smbfs/smbfs_vnops.c:1.78.2.1	Sun Aug 12 12:59:51 2012
+++ src/sys/fs/smbfs/smbfs_vnops.c	Mon Dec 10 21:12:51 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_vnops.c,v 1.78.2.1 2012/08/12 12:59:51 martin Exp $	*/
+/*	$NetBSD: smbfs_vnops.c,v 1.78.2.2 2012/12/10 21:12:51 riz Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.78.2.1 2012/08/12 12:59:51 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.78.2.2 2012/12/10 21:12:51 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -250,9 +250,10 @@ smbfs_open(void *v)
 		return EACCES;
 	}
 	if (vp->v_type == VDIR) {
-		np->n_flag |= NOPEN;
-		if ((sv_caps & SMB_CAP_NT_SMBS) == 0)
+		if ((sv_caps & SMB_CAP_NT_SMBS) == 0) {
+			np->n_flag |= NOPEN;
 			return 0;
+		}
 		goto do_open;	/* skip 'modified' check */
 	}
 
@@ -337,13 +338,22 @@ smbfs_close(void *v)
 	 * Ideally, the lookup routines should handle such case, and
 	 * the context would be removed only in smbfs_inactive().
 	 */
-	if (vp->v_type == VDIR && (np->n_flag & NOPEN) != 0 &&
-	    np->n_dirseq != NULL) {
+	if (vp->v_type == VDIR && (np->n_flag & NOPEN) != 0) {
+		struct smb_share *ssp = np->n_mount->sm_share;
 		struct smb_cred scred;
 
 		smb_makescred(&scred, l, ap->a_cred);
-		smbfs_findclose(np->n_dirseq, &scred);
-		np->n_dirseq = NULL;
+
+		if (np->n_dirseq != NULL) {
+			smbfs_findclose(np->n_dirseq, &scred);
+			np->n_dirseq = NULL;
+		}
+
+		if (SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_NT_SMBS)
+			smbfs_smb_close(ssp, np->n_fid, &np->n_mtime, &scred);
+
+		np->n_flag &= ~NOPEN;
+		smbfs_attr_cacheremove(vp);
 	}
 
 	return (0);
@@ -624,6 +634,8 @@ smbfs_remove(void *v)
 		smb_makescred(&scred, curlwp, cnp->cn_cred);
 		error = smbfs_smb_delete(np, &scred);
 	}
+	if (error == 0)
+		np->n_flag |= NGONE;
 
 	VN_KNOTE(ap->a_vp, NOTE_DELETE);
 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
@@ -701,12 +713,14 @@ smbfs_rename(void *v)
 			error = smbfs_smb_delete(VTOSMB(tvp), &scred);
 			if (error)
 				goto out;
+			VTOSMB(tvp)->n_flag |= NGONE;
 			VN_KNOTE(tdvp, NOTE_WRITE);
 			VN_KNOTE(tvp, NOTE_DELETE);
 			cache_purge(tvp);
 		}
 		error = smbfs_smb_rename(VTOSMB(fvp), VTOSMB(tdvp),
 		    tcnp->cn_nameptr, tcnp->cn_namelen, &scred);
+		VTOSMB(fvp)->n_flag |= NGONE;
 		VN_KNOTE(fdvp, NOTE_WRITE);
 		VN_KNOTE(fvp, NOTE_RENAME);
 	}
@@ -826,6 +840,8 @@ smbfs_rmdir(void *v)
 
 	smb_makescred(&scred, curlwp, cnp->cn_cred);
 	error = smbfs_smb_rmdir(np, &scred);
+	if (error == 0)
+		np->n_flag |= NGONE;
 	dnp->n_flag |= NMODIFIED;
 	smbfs_attr_cacheremove(dvp);
 	VN_KNOTE(dvp, NOTE_WRITE | NOTE_LINK);
@@ -1202,6 +1218,7 @@ smbfs_lookup(void *v)
 		struct vattr vattr;
 		struct vnode *newvp;
 		int err2;
+		bool killit = false;
 
 		if (error && error != ENOENT) {
 			*vpp = NULLVP;
@@ -1230,7 +1247,21 @@ smbfs_lookup(void *v)
 		}
 
 		newvp = *vpp;
-		if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred)
+		error = VOP_GETATTR(newvp, &vattr, cnp->cn_cred);
+		/*
+		 * If the file type on the server is inconsistent
+		 * with what it was when we created the vnode,
+		 * kill the bogus vnode now and fall through to
+		 * the code below to create a new one with the
+		 * right type.
+		 */
+		if (error == 0 &&
+		    ((newvp->v_type == VDIR &&
+		    (VTOSMB(newvp)->n_dosattr & SMB_FA_DIR) == 0) ||
+		    (newvp->v_type == VREG &&
+		    (VTOSMB(newvp)->n_dosattr & SMB_FA_DIR) != 0)))
+			killit = true;
+		else if (error == 0
 			&& vattr.va_ctime.tv_sec == VTOSMB(newvp)->n_ctime)
 		{
 			/* nfsstats.lookupcache_hits++; */
@@ -1238,9 +1269,13 @@ smbfs_lookup(void *v)
 		}
 
 		cache_purge(newvp);
-		if (newvp != dvp)
-			vput(newvp);
-		else
+		if (newvp != dvp) {
+			if (killit) {
+				VOP_UNLOCK(newvp);
+				vgone(newvp);
+			} else
+				vput(newvp);
+		} else
 			vrele(newvp);
 		*vpp = NULLVP;
 	}

Reply via email to