diff options
author | daichi <daichi@FreeBSD.org> | 2007-10-14 13:49:30 +0000 |
---|---|---|
committer | daichi <daichi@FreeBSD.org> | 2007-10-14 13:49:30 +0000 |
commit | bf7aeca620ccf8e886a32e2f04f82d808264471f (patch) | |
tree | 0e057f152fb098b47a9543b6a6b50ffc36a53de1 | |
parent | f3fd8ae96cc6ea54734a56aada5cca712888788e (diff) | |
download | FreeBSD-src-bf7aeca620ccf8e886a32e2f04f82d808264471f.zip FreeBSD-src-bf7aeca620ccf8e886a32e2f04f82d808264471f.tar.gz |
- It has been become MPSAFE.
- Fixed lock panic issue under MPSAFE.
- Fixed panic issue whenever it locks vnode with reclaim.
- Fixed lock implementations not conforming to vnode_if.src style.
Submitted by: Masanori Ozawa <ozawa@ongs.co.jp> (unionfs developer)
Reviewed by: jeff, kensmith
Approved by: re (kensmith)
MFC after: 1 week
-rw-r--r-- | sys/fs/unionfs/union_vfsops.c | 5 | ||||
-rw-r--r-- | sys/fs/unionfs/union_vnops.c | 68 |
2 files changed, 51 insertions, 22 deletions
diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c index cb7b504..34e3900 100644 --- a/sys/fs/unionfs/union_vfsops.c +++ b/sys/fs/unionfs/union_vfsops.c @@ -287,6 +287,11 @@ unionfs_domount(struct mount *mp, struct thread *td) ump->um_ufile = ufile; ump->um_copymode = copymode; + MNT_ILOCK(mp); + if ((lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE) && + (upperrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE)) + mp->mnt_kern_flag |= MNTK_MPSAFE; + MNT_IUNLOCK(mp); mp->mnt_data = (qaddr_t)ump; /* diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index b14acbf..d3b2684 100644 --- a/sys/fs/unionfs/union_vnops.c +++ b/sys/fs/unionfs/union_vnops.c @@ -1647,6 +1647,7 @@ unionfs_lock(struct vop_lock1_args *ap) int flags; int revlock; int uhold; + struct mount *mp; struct unionfs_mount *ump; struct unionfs_node *unp; struct vnode *vp; @@ -1666,16 +1667,24 @@ unionfs_lock(struct vop_lock1_args *ap) if ((revlock = unionfs_get_llt_revlock(flags)) == 0) panic("unknown lock type: 0x%x", flags & LK_TYPE_MASK); - if (!(flags & LK_INTERLOCK)) + if ((flags & LK_INTERLOCK) == 0) VI_LOCK(vp); - ump = MOUNTTOUNIONFSMOUNT(vp->v_mount); + mp = vp->v_mount; + if (mp == NULL) + goto unionfs_lock_null_vnode; + + ump = MOUNTTOUNIONFSMOUNT(mp); unp = VTOUNIONFS(vp); - if (NULL == unp) + if (ump == NULL || unp == NULL) goto unionfs_lock_null_vnode; lvp = unp->un_lowervp; uvp = unp->un_uppervp; + if ((mp->mnt_kern_flag & MNTK_MPSAFE) != 0 && + (vp->v_iflag & VI_OWEINACT) != 0) + flags |= LK_NOWAIT; + /* * Sometimes, lower or upper is already exclusive locked. * (ex. vfs_domount: mounted vnode is already locked.) @@ -1697,9 +1706,9 @@ unionfs_lock(struct vop_lock1_args *ap) VI_LOCK(vp); unp = VTOUNIONFS(vp); if (unp == NULL) { - if (error == 0) - VOP_UNLOCK(lvp, 0, td); VI_UNLOCK(vp); + if (error == 0) + VOP_UNLOCK(lvp, 0, td); vdrop(lvp); return (vop_stdlock(ap)); } @@ -1719,23 +1728,30 @@ unionfs_lock(struct vop_lock1_args *ap) VI_LOCK(vp); unp = VTOUNIONFS(vp); if (unp == NULL) { + VI_UNLOCK(vp); if (error == 0) { VOP_UNLOCK(uvp, 0, td); if (lvp != NULLVP) VOP_UNLOCK(lvp, 0, td); } - VI_UNLOCK(vp); if (lvp != NULLVP) vdrop(lvp); vdrop(uvp); return (vop_stdlock(ap)); } - if (error != 0 && lvp != NULLVP) - vn_lock(lvp, revlock | LK_RETRY, td); + if (error != 0 && lvp != NULLVP) { + VI_UNLOCK(vp); + if ((revlock & LK_TYPE_MASK) == LK_RELEASE) + VOP_UNLOCK(lvp, revlock, td); + else + vn_lock(lvp, revlock | LK_RETRY, td); + goto unionfs_lock_abort; + } } VI_UNLOCK(vp); +unionfs_lock_abort: if (lvp != NULLVP) vdrop(lvp); if (uhold != 0) @@ -1766,7 +1782,7 @@ unionfs_unlock(struct vop_unlock_args *ap) flags = ap->a_flags | LK_RELEASE; vp = ap->a_vp; - if (flags & LK_INTERLOCK) + if ((flags & LK_INTERLOCK) != 0) mtxlkflag = 1; else if (mtx_owned(VI_MTX(vp)) == 0) { VI_LOCK(vp); @@ -1988,21 +2004,25 @@ unionfs_openextattr(struct vop_openextattr_args *ap) int error; struct unionfs_node *unp; struct vnode *vp; + struct vnode *tvp; - unp = VTOUNIONFS(ap->a_vp); - vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); + vp = ap->a_vp; + unp = VTOUNIONFS(vp); + tvp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp); - if ((vp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) || - (vp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL))) + if ((tvp == unp->un_uppervp && (unp->un_flag & UNIONFS_OPENEXTU)) || + (tvp == unp->un_lowervp && (unp->un_flag & UNIONFS_OPENEXTL))) return (EBUSY); - error = VOP_OPENEXTATTR(vp, ap->a_cred, ap->a_td); + error = VOP_OPENEXTATTR(tvp, ap->a_cred, ap->a_td); if (error == 0) { - if (vp == unp->un_uppervp) + vn_lock(vp, LK_UPGRADE | LK_RETRY, ap->a_td); + if (tvp == unp->un_uppervp) unp->un_flag |= UNIONFS_OPENEXTU; else unp->un_flag |= UNIONFS_OPENEXTL; + vn_lock(vp, LK_DOWNGRADE | LK_RETRY, ap->a_td); } return (error); @@ -2014,25 +2034,29 @@ unionfs_closeextattr(struct vop_closeextattr_args *ap) int error; struct unionfs_node *unp; struct vnode *vp; + struct vnode *tvp; - unp = VTOUNIONFS(ap->a_vp); - vp = NULLVP; + vp = ap->a_vp; + unp = VTOUNIONFS(vp); + tvp = NULLVP; if (unp->un_flag & UNIONFS_OPENEXTU) - vp = unp->un_uppervp; + tvp = unp->un_uppervp; else if (unp->un_flag & UNIONFS_OPENEXTL) - vp = unp->un_lowervp; + tvp = unp->un_lowervp; - if (vp == NULLVP) + if (tvp == NULLVP) return (EOPNOTSUPP); - error = VOP_CLOSEEXTATTR(vp, ap->a_commit, ap->a_cred, ap->a_td); + error = VOP_CLOSEEXTATTR(tvp, ap->a_commit, ap->a_cred, ap->a_td); if (error == 0) { - if (vp == unp->un_uppervp) + vn_lock(vp, LK_UPGRADE | LK_RETRY, ap->a_td); + if (tvp == unp->un_uppervp) unp->un_flag &= ~UNIONFS_OPENEXTU; else unp->un_flag &= ~UNIONFS_OPENEXTL; + vn_lock(vp, LK_DOWNGRADE | LK_RETRY, ap->a_td); } return (error); |