Module Name: src
Committed By: bouyer
Date: Sun Jan 13 16:03:38 UTC 2013
Modified Files:
src/sys/fs/smbfs [netbsd-5]: smbfs_node.c smbfs_node.h smbfs_vnops.c
Log Message:
Pull up following revision(s) (requested by nakayama in ticket #1823):
sys/fs/smbfs/smbfs_node.h: revision 1.13 via patch
sys/fs/smbfs/smbfs_node.c: revision 1.48 via patch
sys/fs/smbfs/smbfs_node.c: revision 1.49 via patch
sys/fs/smbfs/smbfs_vnops.c: revision 1.83 via patch
sys/fs/smbfs/smbfs_vnops.c: revision 1.84 via patch
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.39.6.1 -r1.39.6.2 src/sys/fs/smbfs/smbfs_node.c
cvs rdiff -u -r1.12 -r1.12.64.1 src/sys/fs/smbfs/smbfs_node.h
cvs rdiff -u -r1.65.6.1 -r1.65.6.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.39.6.1 src/sys/fs/smbfs/smbfs_node.c:1.39.6.2
--- src/sys/fs/smbfs/smbfs_node.c:1.39.6.1 Sat Oct 3 23:05:25 2009
+++ src/sys/fs/smbfs/smbfs_node.c Sun Jan 13 16:03:38 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: smbfs_node.c,v 1.39.6.1 2009/10/03 23:05:25 snj Exp $ */
+/* $NetBSD: smbfs_node.c,v 1.39.6.2 2013/01/13 16:03:38 bouyer Exp $ */
/*
* Copyright (c) 2000-2001 Boris Popov
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_node.c,v 1.39.6.1 2009/10/03 23:05:25 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_node.c,v 1.39.6.2 2013/01/13 16:03:38 bouyer 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;
@@ -136,11 +137,26 @@ retry:
mutex_exit(&smp->sm_hashlock);
if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK) != 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, 0);
+ 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.
@@ -306,6 +322,8 @@ smbfs_inactive(v)
smbfs_attr_cacheremove(vp);
}
VOP_UNLOCK(vp, 0);
+ if (np->n_flag & NGONE)
+ vrecycle(vp, NULL, l);
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.64.1
--- src/sys/fs/smbfs/smbfs_node.h:1.12 Thu Nov 2 17:34:21 2006
+++ src/sys/fs/smbfs/smbfs_node.h Sun Jan 13 16:03:38 2013
@@ -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.64.1 2013/01/13 16:03:38 bouyer 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.65.6.1 src/sys/fs/smbfs/smbfs_vnops.c:1.65.6.2
--- src/sys/fs/smbfs/smbfs_vnops.c:1.65.6.1 Fri Feb 17 16:01:28 2012
+++ src/sys/fs/smbfs/smbfs_vnops.c Sun Jan 13 16:03:38 2013
@@ -1,4 +1,4 @@
-/* $NetBSD: smbfs_vnops.c,v 1.65.6.1 2012/02/17 16:01:28 sborrill Exp $ */
+/* $NetBSD: smbfs_vnops.c,v 1.65.6.2 2013/01/13 16:03:38 bouyer 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.65.6.1 2012/02/17 16:01:28 sborrill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.65.6.2 2013/01/13 16:03:38 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -229,9 +229,10 @@ smbfs_open(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 */
}
@@ -317,13 +318,22 @@ smbfs_close(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);
@@ -620,6 +630,8 @@ smbfs_remove(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);
@@ -698,12 +710,14 @@ smbfs_rename(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);
}
@@ -829,6 +843,8 @@ smbfs_rmdir(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);
@@ -1211,6 +1227,7 @@ smbfs_lookup(v)
struct vattr vattr;
struct vnode *newvp;
int err2;
+ bool killit = false;
if (error && error != ENOENT) {
*vpp = NULLVP;
@@ -1239,7 +1256,21 @@ smbfs_lookup(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++; */
@@ -1250,9 +1281,13 @@ smbfs_lookup(v)
}
cache_purge(newvp);
- if (newvp != dvp)
- vput(newvp);
- else
+ if (newvp != dvp) {
+ if (killit) {
+ VOP_UNLOCK(newvp, 0);
+ vgone(newvp);
+ } else
+ vput(newvp);
+ } else
vrele(newvp);
*vpp = NULLVP;
}