On Mon, May 07, 2018 at 05:21:19PM +0200, Alexander Bluhm wrote:
> panic: vinvalbuf: dirty bufs

At least I know what is going on here.

vinvalbuf() calls ffs_fsync() to write all dirty buffers of the
mount point to disk.

                        if ((error = VOP_FSYNC(vp, cred, MNT_WAIT, p)) != 0)
                                return (error);

ffs_fsync() does this successfully and verifies that there are no
dirty blocks left.

                if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {

But then it calls ufs_update() to write the inode to disk.  It waits
until the disk operation has finished.

        return (UFS_UPDATE(VTOI(vp), ap->a_waitfor == MNT_WAIT));

My test is still running a cp -r and rm -rf operating on the file
system.  While bread() or bwrite() sleeps in the unmount process,
the rm process inserts a new dirty block into the vnode's list.
bdwrite() calls reassignbuf() to do that.

        if (!ISSET(bp->b_flags, B_DELWRI)) {
                SET(bp->b_flags, B_DELWRI);
                s = splbio();
                buf_flip_dma(bp);
                reassignbuf(bp);
                splx(s);
                curproc->p_ru.ru_oublock++;             /* XXX */
        }

After the wakeup, vinvalbuf() checks that ffs_fsync() has really
flushed all dirty blocks.  There it panics due to the newly added
block.

                        if (vp->v_numoutput > 0 ||
                            !LIST_EMPTY(&vp->v_dirtyblkhd))
                                panic("%s: dirty bufs, vp %p", __func__, vp);

bluhm

Reply via email to