Fix `locking against myself' panic by multi nullfs mount of same

directory pair.
This commit is contained in:
KATO Takenori 1997-04-17 11:24:57 +00:00
parent c5e17d9e2b
commit f85e8fc5ca
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=24988
2 changed files with 50 additions and 2 deletions

View File

@ -36,7 +36,7 @@
* @(#)null_vfsops.c 8.2 (Berkeley) 1/21/94
*
* @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
* $Id: null_vfsops.c,v 1.14 1997/02/22 09:40:21 peter Exp $
* $Id: null_vfsops.c,v 1.15 1997/04/17 11:17:29 kato Exp $
*/
/*
@ -92,6 +92,7 @@ nullfs_mount(mp, path, data, ndp, p)
struct vnode *nullm_rootvp;
struct null_mount *xmp;
u_int size;
int isvnunlocked = 0;
#ifdef NULLFS_DIAGNOSTIC
printf("nullfs_mount(mp = %x)\n", mp);
@ -112,12 +113,27 @@ nullfs_mount(mp, path, data, ndp, p)
if (error)
return (error);
/*
* Unlock lower node to avoid deadlock.
* (XXX) VOP_ISLOCKED is needed?
*/
if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) &&
VOP_ISLOCKED(mp->mnt_vnodecovered)) {
VOP_UNLOCK(mp->mnt_vnodecovered, 0, p);
isvnunlocked = 1;
}
/*
* Find lower node
*/
NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
UIO_USERSPACE, args.target, p);
error = namei(ndp);
/*
* Re-lock vnode.
*/
if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered))
vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
return (error);
@ -129,6 +145,14 @@ nullfs_mount(mp, path, data, ndp, p)
vrele(ndp->ni_dvp);
ndp->ni_dvp = NULLVP;
/*
* Check multi null mount to avoid `lock against myself' panic.
*/
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
error = EDEADLK;
return (error);
}
xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
M_UFSMNT, M_WAITOK); /* XXX */

View File

@ -36,7 +36,7 @@
* @(#)null_vfsops.c 8.2 (Berkeley) 1/21/94
*
* @(#)lofs_vfsops.c 1.2 (Berkeley) 6/18/92
* $Id: null_vfsops.c,v 1.14 1997/02/22 09:40:21 peter Exp $
* $Id: null_vfsops.c,v 1.15 1997/04/17 11:17:29 kato Exp $
*/
/*
@ -92,6 +92,7 @@ nullfs_mount(mp, path, data, ndp, p)
struct vnode *nullm_rootvp;
struct null_mount *xmp;
u_int size;
int isvnunlocked = 0;
#ifdef NULLFS_DIAGNOSTIC
printf("nullfs_mount(mp = %x)\n", mp);
@ -112,12 +113,27 @@ nullfs_mount(mp, path, data, ndp, p)
if (error)
return (error);
/*
* Unlock lower node to avoid deadlock.
* (XXX) VOP_ISLOCKED is needed?
*/
if ((mp->mnt_vnodecovered->v_op == null_vnodeop_p) &&
VOP_ISLOCKED(mp->mnt_vnodecovered)) {
VOP_UNLOCK(mp->mnt_vnodecovered, 0, p);
isvnunlocked = 1;
}
/*
* Find lower node
*/
NDINIT(ndp, LOOKUP, FOLLOW|WANTPARENT|LOCKLEAF,
UIO_USERSPACE, args.target, p);
error = namei(ndp);
/*
* Re-lock vnode.
*/
if (isvnunlocked && !VOP_ISLOCKED(mp->mnt_vnodecovered))
vn_lock(mp->mnt_vnodecovered, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
return (error);
@ -129,6 +145,14 @@ nullfs_mount(mp, path, data, ndp, p)
vrele(ndp->ni_dvp);
ndp->ni_dvp = NULLVP;
/*
* Check multi null mount to avoid `lock against myself' panic.
*/
if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) {
error = EDEADLK;
return (error);
}
xmp = (struct null_mount *) malloc(sizeof(struct null_mount),
M_UFSMNT, M_WAITOK); /* XXX */