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.
This commit is contained in:
parent
a8045334ce
commit
5dc331fb8e
|
@ -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 @@ retry:
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -206,6 +208,54 @@ out:
|
|||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -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 @@ int smbfs_loadvnode(struct mount *, struct vnode *,
|
|||
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);
|
||||
|
|
|
@ -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 @@ smbfs_lookup(void *v)
|
|||
cache_purge(newvp);
|
||||
if (newvp != dvp) {
|
||||
if (killit) {
|
||||
VOP_UNLOCK(newvp);
|
||||
vgone(newvp);
|
||||
smbfs_uncache(newvp);
|
||||
} else
|
||||
vput(newvp);
|
||||
} else
|
||||
|
|
Loading…
Reference in New Issue