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