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:
pooka 2007-06-21 14:11:34 +00:00
parent c82c323deb
commit 41df8e0fed
3 changed files with 70 additions and 62 deletions

View File

@ -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.
@ -30,7 +30,7 @@
*/
#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/conf.h>
@ -335,6 +335,59 @@ puffs_cookie2pnode(struct puffs_mount *pmp, void *cookie)
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
* 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;
/*
* If we're trying to get the root vnode, return it through
* puffs_root() to get all the right things set. Lock must
* be set, since VFS_ROOT() always locks the returned vnode.
* Handle root in a special manner, since we want to make sure
* pmp_root is properly set.
*/
if (cookie == pmp->pmp_root_cookie) {
if (!lock)
return NULL;
if (VFS_ROOT(pmp->pmp_mp, &vp))
if (puffs_makeroot(pmp))
return NULL;
if (lock)
vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
return vp;
return pmp->pmp_root;
}
vgetflags = LK_INTERLOCK;

View File

@ -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.
@ -227,6 +227,7 @@ void puffs_putvnode(struct vnode *);
void puffs_releasenode(struct puffs_node *);
void puffs_referencenode(struct puffs_node *);
int puffs_makeroot(struct puffs_mount *);
struct vnode *puffs_pnode2vnode(struct puffs_mount *, void *, int);
void puffs_makecn(struct puffs_kcn *, const struct componentname *);
void puffs_credcvt(struct puffs_cred *, kauth_cred_t);

View File

@ -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.
@ -30,7 +30,7 @@
*/
#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/mount.h>
@ -340,61 +340,16 @@ int
puffs_root(struct mount *mp, struct vnode **vpp)
{
struct puffs_mount *pmp;
struct puffs_node *pn;
struct vnode *vp;
int rv;
pmp = MPTOPUFFSMP(mp);
/*
* 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);
*vpp = pmp->pmp_root;
return 0;
}
/* store cache */
vp->v_flag = VROOT;
pmp->pmp_root = vp;
mutex_exit(&pmp->pmp_lock);
rv = puffs_makeroot(pmp);
if (rv)
return rv;
vn_lock(pmp->pmp_root, LK_EXCLUSIVE | LK_RETRY);
*vpp = pmp->pmp_root;
*vpp = vp;
return 0;
}