Reorganize how the root vnode is fetched so that it doesn't always
go through VFS_ROOT() and allow to fetch it without locking it. This allows us to call the cache flush operations also for the root vnode and most notably fixes e.g. a "No such file or directory" for a psshfs root directory ls -l when a file was locally deleted and remotely re-created. Also fix some sloppy programming in root node fetch (mostly cosmetic).
This commit is contained in:
parent
c82c323deb
commit
41df8e0fed
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: puffs_subr.c,v 1.32 2007/06/06 01:55:00 pooka Exp $ */
|
/* $NetBSD: puffs_subr.c,v 1.33 2007/06/21 14:11:34 pooka Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.32 2007/06/06 01:55:00 pooka Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.33 2007/06/21 14:11:34 pooka Exp $");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/conf.h>
|
#include <sys/conf.h>
|
||||||
@ -335,6 +335,59 @@ puffs_cookie2pnode(struct puffs_mount *pmp, void *cookie)
|
|||||||
return pnode;
|
return pnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure root vnode exists and reference it. Does NOT lock.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
puffs_makeroot(struct puffs_mount *pmp)
|
||||||
|
{
|
||||||
|
struct vnode *vp;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pmp_lock must be held if vref()'ing or vrele()'ing the
|
||||||
|
* root vnode. the latter is controlled by puffs_inactive().
|
||||||
|
*
|
||||||
|
* pmp_root is set here and cleared in puffs_reclaim().
|
||||||
|
*/
|
||||||
|
retry:
|
||||||
|
mutex_enter(&pmp->pmp_lock);
|
||||||
|
vp = pmp->pmp_root;
|
||||||
|
if (vp) {
|
||||||
|
simple_lock(&vp->v_interlock);
|
||||||
|
mutex_exit(&pmp->pmp_lock);
|
||||||
|
if (vget(vp, LK_INTERLOCK) == 0)
|
||||||
|
return 0;
|
||||||
|
} else
|
||||||
|
mutex_exit(&pmp->pmp_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* So, didn't have the magic root vnode available.
|
||||||
|
* No matter, grab another an stuff it with the cookie.
|
||||||
|
*/
|
||||||
|
if ((rv = puffs_getvnode(pmp->pmp_mp, pmp->pmp_root_cookie,
|
||||||
|
pmp->pmp_root_vtype, pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp)))
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Someone magically managed to race us into puffs_getvnode?
|
||||||
|
* Put our previous new vnode back and retry.
|
||||||
|
*/
|
||||||
|
mutex_enter(&pmp->pmp_lock);
|
||||||
|
if (pmp->pmp_root) {
|
||||||
|
mutex_exit(&pmp->pmp_lock);
|
||||||
|
puffs_putvnode(vp);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* store cache */
|
||||||
|
vp->v_flag = VROOT;
|
||||||
|
pmp->pmp_root = vp;
|
||||||
|
mutex_exit(&pmp->pmp_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Locate the in-kernel vnode based on the cookie received given
|
* Locate the in-kernel vnode based on the cookie received given
|
||||||
* from userspace. Returns a vnode, if found, NULL otherwise.
|
* from userspace. Returns a vnode, if found, NULL otherwise.
|
||||||
@ -351,17 +404,16 @@ puffs_pnode2vnode(struct puffs_mount *pmp, void *cookie, int lock)
|
|||||||
int vgetflags;
|
int vgetflags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're trying to get the root vnode, return it through
|
* Handle root in a special manner, since we want to make sure
|
||||||
* puffs_root() to get all the right things set. Lock must
|
* pmp_root is properly set.
|
||||||
* be set, since VFS_ROOT() always locks the returned vnode.
|
|
||||||
*/
|
*/
|
||||||
if (cookie == pmp->pmp_root_cookie) {
|
if (cookie == pmp->pmp_root_cookie) {
|
||||||
if (!lock)
|
if (puffs_makeroot(pmp))
|
||||||
return NULL;
|
|
||||||
if (VFS_ROOT(pmp->pmp_mp, &vp))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (lock)
|
||||||
|
vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
|
||||||
|
|
||||||
return vp;
|
return pmp->pmp_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
vgetflags = LK_INTERLOCK;
|
vgetflags = LK_INTERLOCK;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: puffs_sys.h,v 1.39 2007/06/06 01:55:00 pooka Exp $ */
|
/* $NetBSD: puffs_sys.h,v 1.40 2007/06/21 14:11:34 pooka Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||||
@ -227,6 +227,7 @@ void puffs_putvnode(struct vnode *);
|
|||||||
void puffs_releasenode(struct puffs_node *);
|
void puffs_releasenode(struct puffs_node *);
|
||||||
void puffs_referencenode(struct puffs_node *);
|
void puffs_referencenode(struct puffs_node *);
|
||||||
|
|
||||||
|
int puffs_makeroot(struct puffs_mount *);
|
||||||
struct vnode *puffs_pnode2vnode(struct puffs_mount *, void *, int);
|
struct vnode *puffs_pnode2vnode(struct puffs_mount *, void *, int);
|
||||||
void puffs_makecn(struct puffs_kcn *, const struct componentname *);
|
void puffs_makecn(struct puffs_kcn *, const struct componentname *);
|
||||||
void puffs_credcvt(struct puffs_cred *, kauth_cred_t);
|
void puffs_credcvt(struct puffs_cred *, kauth_cred_t);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: puffs_vfsops.c,v 1.43 2007/06/06 01:55:00 pooka Exp $ */
|
/* $NetBSD: puffs_vfsops.c,v 1.44 2007/06/21 14:11:34 pooka Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
* Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved.
|
||||||
@ -30,7 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.43 2007/06/06 01:55:00 pooka Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: puffs_vfsops.c,v 1.44 2007/06/21 14:11:34 pooka Exp $");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
@ -340,61 +340,16 @@ int
|
|||||||
puffs_root(struct mount *mp, struct vnode **vpp)
|
puffs_root(struct mount *mp, struct vnode **vpp)
|
||||||
{
|
{
|
||||||
struct puffs_mount *pmp;
|
struct puffs_mount *pmp;
|
||||||
struct puffs_node *pn;
|
int rv;
|
||||||
struct vnode *vp;
|
|
||||||
|
|
||||||
pmp = MPTOPUFFSMP(mp);
|
pmp = MPTOPUFFSMP(mp);
|
||||||
|
rv = puffs_makeroot(pmp);
|
||||||
|
if (rv)
|
||||||
|
return rv;
|
||||||
|
|
||||||
/*
|
|
||||||
* pmp_lock must be held if vref()'ing or vrele()'ing the
|
|
||||||
* root vnode. the latter is controlled by puffs_inactive().
|
|
||||||
*/
|
|
||||||
mutex_enter(&pmp->pmp_lock);
|
|
||||||
vp = pmp->pmp_root;
|
|
||||||
if (vp) {
|
|
||||||
simple_lock(&vp->v_interlock);
|
|
||||||
mutex_exit(&pmp->pmp_lock);
|
|
||||||
pn = VPTOPP(vp);
|
|
||||||
if (vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK))
|
|
||||||
goto grabnew;
|
|
||||||
*vpp = vp;
|
|
||||||
return 0;
|
|
||||||
} else
|
|
||||||
mutex_exit(&pmp->pmp_lock);
|
|
||||||
|
|
||||||
/* XXX: this is wrong, so FIXME */
|
|
||||||
grabnew:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* So, didn't have the magic root vnode available.
|
|
||||||
* No matter, grab another an stuff it with the cookie.
|
|
||||||
*/
|
|
||||||
if (puffs_getvnode(mp, pmp->pmp_root_cookie, pmp->pmp_root_vtype,
|
|
||||||
pmp->pmp_root_vsize, pmp->pmp_root_rdev, &vp))
|
|
||||||
panic("sloppy programming");
|
|
||||||
|
|
||||||
mutex_enter(&pmp->pmp_lock);
|
|
||||||
/*
|
|
||||||
* check if by mysterious force someone else created a root
|
|
||||||
* vnode while we were executing.
|
|
||||||
*/
|
|
||||||
if (pmp->pmp_root) {
|
|
||||||
vref(pmp->pmp_root);
|
|
||||||
mutex_exit(&pmp->pmp_lock);
|
|
||||||
puffs_putvnode(vp);
|
|
||||||
vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
|
vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
|
||||||
*vpp = pmp->pmp_root;
|
*vpp = pmp->pmp_root;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store cache */
|
|
||||||
vp->v_flag = VROOT;
|
|
||||||
pmp->pmp_root = vp;
|
|
||||||
mutex_exit(&pmp->pmp_lock);
|
|
||||||
|
|
||||||
vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
|
|
||||||
|
|
||||||
*vpp = vp;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user