* fix a race i introduced almost two years ago in rev 1.116:
operations creating a node cannot be considered outgoing operations, since after return from userspace they modify file system state by creating a new node. if we do not protect the file system by holding the directory lock, a lookup operation might race us into the kernel and create the node earlier. * remove pnode from hashlish before sending the reclaim faf off to userspace. also, hold pmp_lock while frobbing the list.
This commit is contained in:
parent
db5a8e6176
commit
ce467a3bc2
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: puffs_node.c,v 1.13 2008/05/06 12:33:16 ad Exp $ */
|
||||
/* $NetBSD: puffs_node.c,v 1.14 2009/09/30 18:19:17 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.13 2008/05/06 12:33:16 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.14 2009/09/30 18:19:17 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/hash.h>
|
||||
@ -223,7 +223,7 @@ puffs_newnode(struct mount *mp, struct vnode *dvp, struct vnode **vpp,
|
||||
if (pnc->pnc_cookie == ck) {
|
||||
mutex_exit(&pmp->pmp_lock);
|
||||
puffs_senderr(pmp, PUFFS_ERR_MAKENODE, EEXIST,
|
||||
"cookie exists", ck);
|
||||
"newcookie exists", ck);
|
||||
return EPROTO;
|
||||
}
|
||||
}
|
||||
@ -260,7 +260,6 @@ puffs_putvnode(struct vnode *vp)
|
||||
panic("puffs_putvnode: %p not a puffs vnode", vp);
|
||||
#endif
|
||||
|
||||
LIST_REMOVE(pnode, pn_hashent);
|
||||
genfs_node_destroy(vp);
|
||||
puffs_releasenode(pnode);
|
||||
vp->v_data = NULL;
|
||||
@ -336,6 +335,9 @@ puffs_makeroot(struct puffs_mount *pmp)
|
||||
*/
|
||||
mutex_enter(&pmp->pmp_lock);
|
||||
if (pmp->pmp_root) {
|
||||
struct puffs_node *pnode = vp->v_data;
|
||||
|
||||
LIST_REMOVE(pnode, pn_hashent);
|
||||
mutex_exit(&pmp->pmp_lock);
|
||||
puffs_putvnode(vp);
|
||||
goto retry;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: puffs_vnops.c,v 1.133 2009/09/19 11:44:19 pooka Exp $ */
|
||||
/* $NetBSD: puffs_vnops.c,v 1.134 2009/09/30 18:19:17 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2006, 2007 Antti Kantee. All Rights Reserved.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.133 2009/09/19 11:44:19 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.134 2009/09/30 18:19:17 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/buf.h>
|
||||
@ -645,16 +645,7 @@ puffs_vnop_create(void *v)
|
||||
create_msg->pvnr_va = *ap->a_vap;
|
||||
puffs_msg_setinfo(park_create, PUFFSOP_VN,
|
||||
PUFFS_VN_CREATE, VPTOPNC(dvp));
|
||||
|
||||
/*
|
||||
* Do the dance:
|
||||
* + insert into queue ("interlock")
|
||||
* + unlock vnode
|
||||
* + wait for response
|
||||
*/
|
||||
puffs_msg_enqueue(pmp, park_create);
|
||||
REFPN_AND_UNLOCKVP(dvp, dpn);
|
||||
error = puffs_msg_wait2(pmp, park_create, dpn, NULL);
|
||||
PUFFS_MSG_ENQUEUEWAIT2(pmp, park_create, dvp->v_data, NULL, error);
|
||||
|
||||
error = checkerr(pmp, error, __func__);
|
||||
if (error)
|
||||
@ -667,10 +658,10 @@ puffs_vnop_create(void *v)
|
||||
create_msg->pvnr_newnode, cnp);
|
||||
|
||||
out:
|
||||
vput(dvp);
|
||||
if (error || (cnp->cn_flags & SAVESTART) == 0)
|
||||
PNBUF_PUT(cnp->cn_pnbuf);
|
||||
|
||||
RELEPN_AND_VP(dvp, dpn);
|
||||
DPRINTF(("puffs_create: return %d\n", error));
|
||||
PUFFS_MSG_RELEASE(create);
|
||||
return error;
|
||||
@ -701,9 +692,7 @@ puffs_vnop_mknod(void *v)
|
||||
puffs_msg_setinfo(park_mknod, PUFFSOP_VN,
|
||||
PUFFS_VN_MKNOD, VPTOPNC(dvp));
|
||||
|
||||
puffs_msg_enqueue(pmp, park_mknod);
|
||||
REFPN_AND_UNLOCKVP(dvp, dpn);
|
||||
error = puffs_msg_wait2(pmp, park_mknod, dpn, NULL);
|
||||
PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mknod, dvp->v_data, NULL, error);
|
||||
|
||||
error = checkerr(pmp, error, __func__);
|
||||
if (error)
|
||||
@ -717,10 +706,10 @@ puffs_vnop_mknod(void *v)
|
||||
mknod_msg->pvnr_newnode, cnp);
|
||||
|
||||
out:
|
||||
vput(dvp);
|
||||
PUFFS_MSG_RELEASE(mknod);
|
||||
if (error || (cnp->cn_flags & SAVESTART) == 0)
|
||||
PNBUF_PUT(cnp->cn_pnbuf);
|
||||
RELEPN_AND_VP(dvp, dpn);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1074,6 +1063,8 @@ puffs_vnop_reclaim(void *v)
|
||||
} */ *ap = v;
|
||||
struct vnode *vp = ap->a_vp;
|
||||
struct puffs_mount *pmp = MPTOPUFFSMP(vp->v_mount);
|
||||
struct puffs_node *pnode = vp->v_data;
|
||||
bool notifyserver = true;
|
||||
|
||||
/*
|
||||
* first things first: check if someone is trying to reclaim the
|
||||
@ -1086,14 +1077,23 @@ puffs_vnop_reclaim(void *v)
|
||||
KASSERT(pmp->pmp_root != NULL);
|
||||
pmp->pmp_root = NULL;
|
||||
mutex_exit(&pmp->pmp_lock);
|
||||
goto out;
|
||||
notifyserver = false;
|
||||
}
|
||||
|
||||
callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp));
|
||||
|
||||
out:
|
||||
/*
|
||||
* purge info from kernel before issueing FAF, since we
|
||||
* don't really know when we'll get around to it after
|
||||
* that and someone might race us into node creation
|
||||
*/
|
||||
mutex_enter(&pmp->pmp_lock);
|
||||
LIST_REMOVE(pnode, pn_hashent);
|
||||
mutex_exit(&pmp->pmp_lock);
|
||||
if (PUFFS_USE_NAMECACHE(pmp))
|
||||
cache_purge(vp);
|
||||
|
||||
if (notifyserver)
|
||||
callreclaim(MPTOPUFFSMP(vp->v_mount), VPTOPNC(vp));
|
||||
|
||||
puffs_putvnode(vp);
|
||||
|
||||
return 0;
|
||||
@ -1476,9 +1476,7 @@ puffs_vnop_mkdir(void *v)
|
||||
puffs_msg_setinfo(park_mkdir, PUFFSOP_VN,
|
||||
PUFFS_VN_MKDIR, VPTOPNC(dvp));
|
||||
|
||||
puffs_msg_enqueue(pmp, park_mkdir);
|
||||
REFPN_AND_UNLOCKVP(dvp, dpn);
|
||||
error = puffs_msg_wait2(pmp, park_mkdir, dpn, NULL);
|
||||
PUFFS_MSG_ENQUEUEWAIT2(pmp, park_mkdir, dvp->v_data, NULL, error);
|
||||
|
||||
error = checkerr(pmp, error, __func__);
|
||||
if (error)
|
||||
@ -1491,10 +1489,10 @@ puffs_vnop_mkdir(void *v)
|
||||
mkdir_msg->pvnr_newnode, cnp);
|
||||
|
||||
out:
|
||||
vput(dvp);
|
||||
PUFFS_MSG_RELEASE(mkdir);
|
||||
if (error || (cnp->cn_flags & SAVESTART) == 0)
|
||||
PNBUF_PUT(cnp->cn_pnbuf);
|
||||
RELEPN_AND_VP(dvp, dpn);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1637,9 +1635,7 @@ puffs_vnop_symlink(void *v)
|
||||
puffs_msg_setinfo(park_symlink, PUFFSOP_VN,
|
||||
PUFFS_VN_SYMLINK, VPTOPNC(dvp));
|
||||
|
||||
puffs_msg_enqueue(pmp, park_symlink);
|
||||
REFPN_AND_UNLOCKVP(dvp, dpn);
|
||||
error = puffs_msg_wait2(pmp, park_symlink, dpn, NULL);
|
||||
PUFFS_MSG_ENQUEUEWAIT2(pmp, park_symlink, dvp->v_data, NULL, error);
|
||||
|
||||
error = checkerr(pmp, error, __func__);
|
||||
if (error)
|
||||
@ -1652,10 +1648,10 @@ puffs_vnop_symlink(void *v)
|
||||
symlink_msg->pvnr_newnode, cnp);
|
||||
|
||||
out:
|
||||
vput(dvp);
|
||||
PUFFS_MSG_RELEASE(symlink);
|
||||
if (error || (cnp->cn_flags & SAVESTART) == 0)
|
||||
PNBUF_PUT(cnp->cn_pnbuf);
|
||||
RELEPN_AND_VP(dvp, dpn);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user