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.
|
||||
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user