From a4c45b75a12e644e10c8d93e5053d221582921ac Mon Sep 17 00:00:00 2001 From: Martin Renters Date: Sun, 23 Oct 1994 00:41:17 +0000 Subject: [PATCH] Fixed panic when unmounting floppy msdos filesystems. Problem was we weren't flushing dirty buffers. Fix stolen from ffs_fsync() --- sys/fs/msdosfs/msdosfs_vnops.c | 37 +++++++++++++++++++++++++++------- sys/msdosfs/msdosfs_vnops.c | 37 +++++++++++++++++++++++++++------- 2 files changed, 60 insertions(+), 14 deletions(-) diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 864981741bc..7773f598154 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.4 1994/09/28 16:45:14 dfr Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.5 1994/10/06 21:06:53 davidg Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */ /*- @@ -787,20 +787,43 @@ msdosfs_fsync(ap) struct proc *a_p; } */ *ap; { - struct vnode *vp = ap->a_vp; + register struct vnode *vp = ap->a_vp; + register struct buf *bp; int wait = ap->a_waitfor == MNT_WAIT; struct timespec ts; + struct buf *nbp; + int s; TIMEVAL_TO_TIMESPEC(&time, &ts); -#if 0 /* - * Does this call to vflushbuf() do anything? I can find no code - * anywhere that sets v_dirtyblkhd in the vnode, which vflushbuf() - * seems to depend upon. + * Flush all dirty buffers associated with a vnode. */ - vflushbuf(vp, wait ? B_SYNC : 0); +loop: + s = splbio(); + for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { + nbp = bp->b_vnbufs.le_next; + if ((bp->b_flags & B_BUSY)) + continue; + if ((bp->b_flags & B_DELWRI) == 0) + panic("msdosfs_fsync: not dirty"); + bremfree(bp); + bp->b_flags |= B_BUSY; + splx(s); + (void) bwrite(bp); + goto loop; + } + while (vp->v_numoutput) { + vp->v_flag |= VBWAIT; + (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "msdosfsn", 0); + } +#ifdef DIAGNOSTIC + if (vp->v_dirtyblkhd.lh_first) { + vprint("msdosfs_fsync: dirty", vp); + goto loop; + } #endif + splx(s); return deupdat(VTODE(vp), &ts, wait); } diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 864981741bc..7773f598154 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.4 1994/09/28 16:45:14 dfr Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.5 1994/10/06 21:06:53 davidg Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */ /*- @@ -787,20 +787,43 @@ msdosfs_fsync(ap) struct proc *a_p; } */ *ap; { - struct vnode *vp = ap->a_vp; + register struct vnode *vp = ap->a_vp; + register struct buf *bp; int wait = ap->a_waitfor == MNT_WAIT; struct timespec ts; + struct buf *nbp; + int s; TIMEVAL_TO_TIMESPEC(&time, &ts); -#if 0 /* - * Does this call to vflushbuf() do anything? I can find no code - * anywhere that sets v_dirtyblkhd in the vnode, which vflushbuf() - * seems to depend upon. + * Flush all dirty buffers associated with a vnode. */ - vflushbuf(vp, wait ? B_SYNC : 0); +loop: + s = splbio(); + for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { + nbp = bp->b_vnbufs.le_next; + if ((bp->b_flags & B_BUSY)) + continue; + if ((bp->b_flags & B_DELWRI) == 0) + panic("msdosfs_fsync: not dirty"); + bremfree(bp); + bp->b_flags |= B_BUSY; + splx(s); + (void) bwrite(bp); + goto loop; + } + while (vp->v_numoutput) { + vp->v_flag |= VBWAIT; + (void) tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "msdosfsn", 0); + } +#ifdef DIAGNOSTIC + if (vp->v_dirtyblkhd.lh_first) { + vprint("msdosfs_fsync: dirty", vp); + goto loop; + } #endif + splx(s); return deupdat(VTODE(vp), &ts, wait); }