- 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)
This commit is contained in:
daichi 2007-10-23 03:32:17 +00:00
parent 2dcb77bc65
commit c4a793469a
2 changed files with 51 additions and 22 deletions

View File

@ -288,6 +288,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;
/*

View File

@ -1648,6 +1648,7 @@ unionfs_lock(struct vop_lock_args *ap)
int flags;
int revlock;
int uhold;
struct mount *mp;
struct unionfs_mount *ump;
struct unionfs_node *unp;
struct vnode *vp;
@ -1667,16 +1668,24 @@ unionfs_lock(struct vop_lock_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.)
@ -1698,9 +1707,9 @@ unionfs_lock(struct vop_lock_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));
}
@ -1720,23 +1729,30 @@ unionfs_lock(struct vop_lock_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)
@ -1767,7 +1783,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);