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. * 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;

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. * 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);

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