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; }