PR kern/37950 Unmounting psshfs immediately panics the machine
puffs_getvnode() was inserting vnodes into mnt_vnodelist without taking a reference to the mount for each. When vnodes are scrubbed, refs to the vnodes mount structure are dropped => boom.
This commit is contained in:
parent
76807ad91e
commit
ed8a08bae0
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: puffs_node.c,v 1.12 2008/03/01 14:16:51 rmind Exp $ */
|
||||
/* $NetBSD: puffs_node.c,v 1.13 2008/05/06 12:33:16 ad 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.12 2008/03/01 14:16:51 rmind Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: puffs_node.c,v 1.13 2008/05/06 12:33:16 ad Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/hash.h>
|
||||
@ -90,62 +90,17 @@ puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type,
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: there is a deadlock condition between vfs_busy() and
|
||||
* vnode locks. For an unmounting file system the mountpoint
|
||||
* is frozen, but in unmount(FORCE) vflush() wants to access all
|
||||
* of the vnodes. If we are here waiting for the mountpoint
|
||||
* lock while holding on to a vnode lock, well, we ain't
|
||||
* just pining for the fjords anymore. If we release the
|
||||
* vnode lock, we will be in the situation "mount point
|
||||
* is dying" and panic() will ensue in insmntque. So as a
|
||||
* temporary workaround, get a vnode without putting it on
|
||||
* the mount point list, check if mount point is still alive
|
||||
* and kicking and only then add the vnode to the list.
|
||||
*/
|
||||
error = getnewvnode(VT_PUFFS, NULL, puffs_vnodeop_p, &vp);
|
||||
error = getnewvnode(VT_PUFFS, mp, puffs_vnodeop_p, &vp);
|
||||
if (error)
|
||||
goto bad;
|
||||
vp->v_vnlock = NULL;
|
||||
vp->v_type = type;
|
||||
|
||||
/*
|
||||
* Check what mount point isn't going away. This will work
|
||||
* until we decide to remove biglock or make the kernel
|
||||
* preemptive. But hopefully the real problem will be fixed
|
||||
* by then.
|
||||
*
|
||||
* XXX: yes, should call vfs_busy(), but thar be rabbits with
|
||||
* vicious streaks a mile wide ...
|
||||
*
|
||||
* XXX: there is a transient failure here: if someone is unmounting
|
||||
* the file system but doesn't succeed (due to it being busy),
|
||||
* we incorrectly fail new vnode allocation. This is *very*
|
||||
* hard to fix with the current structure of file system unmounting.
|
||||
*/
|
||||
if (mp->mnt_iflag & IMNT_UNMOUNT) {
|
||||
DPRINTF(("puffs_getvnode: mp %p unmount, unable to create "
|
||||
"vnode for cookie %p\n", mp, ck));
|
||||
ungetnewvnode(vp);
|
||||
error = ENXIO;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creation should not fail after this point. Or if it does,
|
||||
* care must be taken so that VOP_INACTIVE() isn't called.
|
||||
*/
|
||||
|
||||
/* So mp is not dead yet.. good.. inform new vnode of its master */
|
||||
mutex_enter(&mntvnode_lock);
|
||||
TAILQ_INSERT_TAIL(&mp->mnt_vnodelist, vp, v_mntvnodes);
|
||||
vp->v_mount = mp;
|
||||
mutex_exit(&mntvnode_lock);
|
||||
|
||||
/*
|
||||
* clerical tasks & footwork
|
||||
*/
|
||||
|
||||
/* default size */
|
||||
uvm_vnp_setsize(vp, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user