diff options
author | kato <kato@FreeBSD.org> | 1997-04-19 06:04:13 +0000 |
---|---|---|
committer | kato <kato@FreeBSD.org> | 1997-04-19 06:04:13 +0000 |
commit | 47e567e3df0f8ce73fc3fcffe9410b8ddbf6ea66 (patch) | |
tree | 1465ef8a781a2f54f6be61af6d13d4e7692e8895 /sys/miscfs/nullfs | |
parent | 5678742cc6736e572768d3cff00c1190bfe666fc (diff) | |
download | FreeBSD-src-47e567e3df0f8ce73fc3fcffe9410b8ddbf6ea66.zip FreeBSD-src-47e567e3df0f8ce73fc3fcffe9410b8ddbf6ea66.tar.gz |
Avoid `lock against myself' panic by following operation:
# mount -t union (or null) dir1 dir2
# mount -t union (or null) dir2 dir1
The function namei in union_mount calls union_root. The upper vnode
has been already locked and vn_lock in union_root causes above panic.
Add printf's included in `#ifdef DIAGNOSTIC' for EDEADLK cases.
Diffstat (limited to 'sys/miscfs/nullfs')
-rw-r--r-- | sys/miscfs/nullfs/null_vfsops.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/sys/miscfs/nullfs/null_vfsops.c b/sys/miscfs/nullfs/null_vfsops.c index 10791f8..8f3ca4d 100644 --- a/sys/miscfs/nullfs/null_vfsops.c +++ b/sys/miscfs/nullfs/null_vfsops.c @@ -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.15 1997/04/17 11:17:29 kato Exp $ + * $Id: null_vfsops.c,v 1.16 1997/04/17 11:24:57 kato Exp $ */ /* @@ -149,8 +149,10 @@ nullfs_mount(mp, path, data, ndp, p) * Check multi null mount to avoid `lock against myself' panic. */ if (lowerrootvp == VTONULL(mp->mnt_vnodecovered)->null_lowervp) { - error = EDEADLK; - return (error); +#ifdef DIAGNOSTIC + printf("nullfs_mount: multi null mount?\n"); +#endif + return (EDEADLK); } xmp = (struct null_mount *) malloc(sizeof(struct null_mount), @@ -293,7 +295,18 @@ nullfs_root(mp, vpp) */ vp = MOUNTTONULLMOUNT(mp)->nullm_rootvp; VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); + if (VOP_ISLOCKED(vp)) { + /* + * XXX + * Should we check type of node? + */ +#ifdef DIAGNOSTIC + printf("nullfs_root: multi null mount?\n"); +#endif + vrele(vp); + return (EDEADLK); + } else + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); *vpp = vp; return 0; } |