diff options
author | dyson <dyson@FreeBSD.org> | 1997-02-27 02:57:03 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1997-02-27 02:57:03 +0000 |
commit | b3686e776a1bad7f229c4d07aa3828c83af2fc11 (patch) | |
tree | 7004af1c07bb192b75cbe359babfd58347c50795 | |
parent | 4815b9da378492da3eee817f136130ed28fa75fe (diff) | |
download | FreeBSD-src-b3686e776a1bad7f229c4d07aa3828c83af2fc11.zip FreeBSD-src-b3686e776a1bad7f229c4d07aa3828c83af2fc11.tar.gz |
Fix the simple_lock problem with the physical I/O buffer code, and
also fix the missing simple_unlock in vrele, and improve vrele/vput
by merging them into one routine. BDE pointed these problems out.
-rw-r--r-- | sys/kern/vfs_export.c | 68 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 68 |
2 files changed, 90 insertions, 46 deletions
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c index 7b91e63..c37b9d9 100644 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.71 1997/02/25 19:33:23 bde Exp $ + * $Id: vfs_subr.c,v 1.72 1997/02/26 15:35:42 bde Exp $ */ /* @@ -78,6 +78,8 @@ extern void printlockedvnodes __P((void)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); extern void vgonel __P((struct vnode *vp, struct proc *p)); unsigned long numvnodes; +extern void vfs_unmountroot __P((struct mount *rootfs)); +extern void vputrele __P((struct vnode *vp, int put)); enum vtype iftovt_tab[16] = { VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, @@ -627,9 +629,10 @@ pbgetvp(vp, bp) register struct vnode *vp; register struct buf *bp; { +#if defined(DIAGNOSTIC) if (bp->b_vp) panic("pbgetvp: not free"); - VHOLD(vp); +#endif bp->b_vp = vp; if (vp->v_type == VBLK || vp->v_type == VCHR) bp->b_dev = vp->v_rdev; @@ -646,12 +649,12 @@ pbrelvp(bp) { struct vnode *vp; +#if defined(DIAGNOSTIC) if (bp->b_vp == (struct vnode *) 0) panic("brelvp: NULL"); +#endif - vp = bp->b_vp; bp->b_vp = (struct vnode *) 0; - HOLDRELE(vp); } /* @@ -1000,29 +1003,19 @@ vref(vp) } /* - * vput(), just unlock and vrele() - */ -void -vput(vp) - struct vnode *vp; -{ - VOP_UNLOCK(vp, 0, curproc); - vrele(vp); -} - -/* - * Vnode release. + * Vnode put/release. * If count drops to zero, call inactive routine and return to freelist. */ void -vrele(vp) +vputrele(vp, put) struct vnode *vp; + int put; { struct proc *p = curproc; /* XXX */ #ifdef DIAGNOSTIC if (vp == NULL) - panic("vrele: null vp"); + panic("vputrele: null vp"); #endif simple_lock(&vp->v_interlock); vp->v_usecount--; @@ -1032,39 +1025,68 @@ vrele(vp) (vp->v_object->flags & OBJ_VFS_REF)) { vp->v_object->flags &= ~OBJ_VFS_REF; simple_unlock(&vp->v_interlock); + if (put) { + VOP_UNLOCK(vp, 0, p); + } vm_object_deallocate(vp->v_object); return; } if (vp->v_usecount > 0) { simple_unlock(&vp->v_interlock); + if (put) { + VOP_UNLOCK(vp, 0, p); + } return; } if (vp->v_usecount < 0) { #ifdef DIAGNOSTIC - vprint("vrele: negative ref count", vp); + vprint("vputrele: negative ref count", vp); #endif - panic("vrele: negative ref cnt"); + panic("vputrele: negative ref cnt"); } simple_lock(&vnode_free_list_slock); if (vp->v_flag & VAGE) { - if(vp->v_tag != VT_TFS) - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); vp->v_flag &= ~VAGE; vp->v_usage = 0; + if(vp->v_tag != VT_TFS) + TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } else { if(vp->v_tag != VT_TFS) TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); } simple_unlock(&vnode_free_list_slock); + simple_unlock(&vp->v_interlock); freevnodes++; - if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0) + /* + * If we are doing a vput, the node is already locked, and we must + * call VOP_INACTIVE with the node locked. So, in the case of + * vrele, we explicitly lock the vnode before calling VOP_INACTIVE. + */ + if (put || (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)) VOP_INACTIVE(vp, p); } +/* + * vput(), just unlock and vrele() + */ +void +vput(vp) + struct vnode *vp; +{ + vputrele(vp, 1); +} + +void +vrele(vp) + struct vnode *vp; +{ + vputrele(vp, 0); +} + #ifdef DIAGNOSTIC /* * Page or buffer structure gets a reference. diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 7b91e63..c37b9d9 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.71 1997/02/25 19:33:23 bde Exp $ + * $Id: vfs_subr.c,v 1.72 1997/02/26 15:35:42 bde Exp $ */ /* @@ -78,6 +78,8 @@ extern void printlockedvnodes __P((void)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); extern void vgonel __P((struct vnode *vp, struct proc *p)); unsigned long numvnodes; +extern void vfs_unmountroot __P((struct mount *rootfs)); +extern void vputrele __P((struct vnode *vp, int put)); enum vtype iftovt_tab[16] = { VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, @@ -627,9 +629,10 @@ pbgetvp(vp, bp) register struct vnode *vp; register struct buf *bp; { +#if defined(DIAGNOSTIC) if (bp->b_vp) panic("pbgetvp: not free"); - VHOLD(vp); +#endif bp->b_vp = vp; if (vp->v_type == VBLK || vp->v_type == VCHR) bp->b_dev = vp->v_rdev; @@ -646,12 +649,12 @@ pbrelvp(bp) { struct vnode *vp; +#if defined(DIAGNOSTIC) if (bp->b_vp == (struct vnode *) 0) panic("brelvp: NULL"); +#endif - vp = bp->b_vp; bp->b_vp = (struct vnode *) 0; - HOLDRELE(vp); } /* @@ -1000,29 +1003,19 @@ vref(vp) } /* - * vput(), just unlock and vrele() - */ -void -vput(vp) - struct vnode *vp; -{ - VOP_UNLOCK(vp, 0, curproc); - vrele(vp); -} - -/* - * Vnode release. + * Vnode put/release. * If count drops to zero, call inactive routine and return to freelist. */ void -vrele(vp) +vputrele(vp, put) struct vnode *vp; + int put; { struct proc *p = curproc; /* XXX */ #ifdef DIAGNOSTIC if (vp == NULL) - panic("vrele: null vp"); + panic("vputrele: null vp"); #endif simple_lock(&vp->v_interlock); vp->v_usecount--; @@ -1032,39 +1025,68 @@ vrele(vp) (vp->v_object->flags & OBJ_VFS_REF)) { vp->v_object->flags &= ~OBJ_VFS_REF; simple_unlock(&vp->v_interlock); + if (put) { + VOP_UNLOCK(vp, 0, p); + } vm_object_deallocate(vp->v_object); return; } if (vp->v_usecount > 0) { simple_unlock(&vp->v_interlock); + if (put) { + VOP_UNLOCK(vp, 0, p); + } return; } if (vp->v_usecount < 0) { #ifdef DIAGNOSTIC - vprint("vrele: negative ref count", vp); + vprint("vputrele: negative ref count", vp); #endif - panic("vrele: negative ref cnt"); + panic("vputrele: negative ref cnt"); } simple_lock(&vnode_free_list_slock); if (vp->v_flag & VAGE) { - if(vp->v_tag != VT_TFS) - TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); vp->v_flag &= ~VAGE; vp->v_usage = 0; + if(vp->v_tag != VT_TFS) + TAILQ_INSERT_HEAD(&vnode_free_list, vp, v_freelist); } else { if(vp->v_tag != VT_TFS) TAILQ_INSERT_TAIL(&vnode_free_list, vp, v_freelist); } simple_unlock(&vnode_free_list_slock); + simple_unlock(&vp->v_interlock); freevnodes++; - if (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0) + /* + * If we are doing a vput, the node is already locked, and we must + * call VOP_INACTIVE with the node locked. So, in the case of + * vrele, we explicitly lock the vnode before calling VOP_INACTIVE. + */ + if (put || (vn_lock(vp, LK_EXCLUSIVE | LK_INTERLOCK, p) == 0)) VOP_INACTIVE(vp, p); } +/* + * vput(), just unlock and vrele() + */ +void +vput(vp) + struct vnode *vp; +{ + vputrele(vp, 1); +} + +void +vrele(vp) + struct vnode *vp; +{ + vputrele(vp, 0); +} + #ifdef DIAGNOSTIC /* * Page or buffer structure gets a reference. |