From f85e8fc5ca2828207b777bd8dff8191941dd241a Mon Sep 17 00:00:00 2001 From: KATO Takenori Date: Thu, 17 Apr 1997 11:24:57 +0000 Subject: [PATCH] Fix `locking against myself' panic by multi nullfs mount of same directory pair. --- sys/fs/nullfs/null_vfsops.c | 26 +++++++++++++++++++++++++- sys/miscfs/nullfs/null_vfsops.c | 26 +++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c index a62b5e8ae978..10791f8128bf 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); @@ -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 */ diff --git a/sys/miscfs/nullfs/null_vfsops.c b/sys/miscfs/nullfs/null_vfsops.c index a62b5e8ae978..10791f8128bf 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.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 */