summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorkato <kato@FreeBSD.org>1997-04-17 11:24:57 +0000
committerkato <kato@FreeBSD.org>1997-04-17 11:24:57 +0000
commitb38f98ddc9e3efbde3bcae4c57e2c0ba21ca803e (patch)
tree1e319e07403b3d688e2e3eacd2962f764fefd2e7 /sys/fs
parent89de63b34867b051fbafa128e5f7061ddedcea93 (diff)
downloadFreeBSD-src-b38f98ddc9e3efbde3bcae4c57e2c0ba21ca803e.zip
FreeBSD-src-b38f98ddc9e3efbde3bcae4c57e2c0ba21ca803e.tar.gz
Fix `locking against myself' panic by multi nullfs mount of same
directory pair.
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nullfs/null_vfsops.c26
1 files changed, 25 insertions, 1 deletions
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index a62b5e8..10791f8 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/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.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);
@@ -113,11 +114,26 @@ nullfs_mount(mp, path, data, ndp, p)
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 */
OpenPOWER on IntegriCloud