Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/fs/smbfs When a vnode has an invalid type because the ty...



details:   https://anonhg.NetBSD.org/src/rev/2c7abfb58b8e
branches:  trunk
changeset: 824224:2c7abfb58b8e
user:      hannken <hannken%NetBSD.org@localhost>
date:      Sun May 28 16:36:37 2017 +0000

description:
When a vnode has an invalid type because the type changed on the
server replace vgone() with new operation smbfs_uncache() that
removes the vnode from the name cache and changes the vcache key
to an unique and illegal key to prevent further lookups.

diffstat:

 sys/fs/smbfs/smbfs_node.c  |  56 +++++++++++++++++++++++++++++++++++++++++++--
 sys/fs/smbfs/smbfs_node.h  |   3 +-
 sys/fs/smbfs/smbfs_vnops.c |   7 ++---
 3 files changed, 58 insertions(+), 8 deletions(-)

diffs (132 lines):

diff -r 3be3e45ba3a1 -r 2c7abfb58b8e sys/fs/smbfs/smbfs_node.c
--- a/sys/fs/smbfs/smbfs_node.c Sun May 28 16:35:47 2017 +0000
+++ b/sys/fs/smbfs/smbfs_node.c Sun May 28 16:36:37 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: smbfs_node.c,v 1.57 2017/05/26 14:34:20 riastradh Exp $        */
+/*     $NetBSD: smbfs_node.c,v 1.58 2017/05/28 16:36:37 hannken Exp $  */
 
 /*
  * Copyright (c) 2000-2001 Boris Popov
@@ -35,10 +35,11 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_node.c,v 1.57 2017/05/26 14:34:20 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_node.c,v 1.58 2017/05/28 16:36:37 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/atomic.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -191,7 +192,8 @@
                if ((vp->v_type == VDIR && (np->n_dosattr & SMB_FA_DIR) == 0) ||
                    (vp->v_type == VREG && (np->n_dosattr & SMB_FA_DIR) != 0)) {
                        mutex_exit(&np->n_lock);
-                       vgone(vp);
+                       vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+                       smbfs_uncache(vp);
                        goto retry;
                }
        }
@@ -207,6 +209,54 @@
 }
 
 /*
+ * Remove vnode that changed its type on the server from
+ * the vnode cache and the name cache.
+ */
+void
+smbfs_uncache(struct vnode *vp)
+{
+       static uint32_t gen = 0;
+       int error __diagused;
+       char newname[10];
+       struct mount *mp = vp->v_mount;
+       struct smbnode *np = VTOSMB(vp);
+       struct smbkey *key = np->n_key, *oldkey, *newkey;
+       int key_len = SMBFS_KEYSIZE(key->k_nmlen), newkey_len;
+
+       /* Setup old key as current key. */
+       oldkey = kmem_alloc(key_len, KM_SLEEP);
+       memcpy(oldkey, key, key_len);
+
+       /* Setup new key as unique and illegal name with colon. */
+       snprintf(newname, sizeof(newname), ":%08x", atomic_inc_uint_nv(&gen));
+       newkey = kmem_alloc(SMBFS_KEYSIZE(strlen(newname)), KM_SLEEP);
+       newkey->k_parent = NULL;
+       newkey->k_nmlen = strlen(newname);
+       memcpy(newkey->k_name, newname, newkey->k_nmlen);
+       newkey_len = SMBFS_KEYSIZE(newkey->k_nmlen);
+
+       /* Release parent and mark as gone. */
+       if (np->n_parent && (np->n_flag & NREFPARENT)) {
+               vrele(np->n_parent);
+               np->n_flag &= ~NREFPARENT;
+       }
+       np->n_flag |= NGONE;
+
+       /* Rekey the node. */
+       error = vcache_rekey_enter(mp, vp, oldkey, key_len, newkey, newkey_len);
+       KASSERT(error == 0);
+       np->n_key = newkey;
+       vcache_rekey_exit(mp, vp, oldkey, key_len, newkey, newkey_len);
+
+       /* Purge from name cache and cleanup. */
+       cache_purge(vp);
+       kmem_free(key, key_len);
+       kmem_free(oldkey, key_len);
+
+       vput(vp);
+}
+
+/*
  * Free smbnode, and give vnode back to system
  */
 int
diff -r 3be3e45ba3a1 -r 2c7abfb58b8e sys/fs/smbfs/smbfs_node.h
--- a/sys/fs/smbfs/smbfs_node.h Sun May 28 16:35:47 2017 +0000
+++ b/sys/fs/smbfs/smbfs_node.h Sun May 28 16:36:37 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: smbfs_node.h,v 1.15 2015/01/02 09:48:01 martin Exp $   */
+/*     $NetBSD: smbfs_node.h,v 1.16 2017/05/28 16:36:37 hannken Exp $  */
 
 /*
  * Copyright (c) 2000-2001, Boris Popov
@@ -97,6 +97,7 @@
     const void *, size_t, const void **);
 int smbfs_nget(struct mount *, struct vnode *, const char *, int,
     struct smbfattr *, struct vnode **);
+void smbfs_uncache(struct vnode *);
 
 int  smbfs_readvnode(struct vnode *, struct uio *, kauth_cred_t);
 int  smbfs_writevnode(struct vnode *, struct uio *, kauth_cred_t, int);
diff -r 3be3e45ba3a1 -r 2c7abfb58b8e sys/fs/smbfs/smbfs_vnops.c
--- a/sys/fs/smbfs/smbfs_vnops.c        Sun May 28 16:35:47 2017 +0000
+++ b/sys/fs/smbfs/smbfs_vnops.c        Sun May 28 16:36:37 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: smbfs_vnops.c,v 1.94 2017/04/26 03:02:48 riastradh Exp $       */
+/*     $NetBSD: smbfs_vnops.c,v 1.95 2017/05/28 16:36:37 hannken 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.94 2017/04/26 03:02:48 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.95 2017/05/28 16:36:37 hannken Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1269,8 +1269,7 @@
                cache_purge(newvp);
                if (newvp != dvp) {
                        if (killit) {
-                               VOP_UNLOCK(newvp);
-                               vgone(newvp);
+                               smbfs_uncache(newvp);
                        } else
                                vput(newvp);
                } else



Home | Main Index | Thread Index | Old Index