Alexander Bluhm <[email protected]> wrote:
> Quite often I see "panic: unmount: dangling vnode". My test
> regress/sys/kern/mount triggers it, but it also happens when rebooting
> virtual machines.
>
> The problem is, when dirty buffers are flushed to disk, the unmount
> process sleeps. If the file system is busy, other processes can
> create new dirty buffers by writing files.
>
> First I tired to block these writes. But this is very complex. A
> much simpler solution is to flush a few times. With this diff I
> could not trigger the problem anymore.
>
> Is that fix good enough?
Hmm. In Feb 2018 I added a mechanism so that suspend & hibernate
can do a better job syncronizing filesystems.
Look at vfs_stall(), can it be somewhat repurposed for reboots?
Hmm... I think I tried, but hit some problems.
> Index: kern/vfs_subr.c
> ===================================================================
> RCS file: /data/mirror/openbsd/cvs/src/sys/kern/vfs_subr.c,v
> retrieving revision 1.293
> diff -u -p -r1.293 vfs_subr.c
> --- kern/vfs_subr.c 26 Aug 2019 18:56:29 -0000 1.293
> +++ kern/vfs_subr.c 20 Nov 2019 20:50:31 -0000
> @@ -962,14 +962,20 @@ int
> vflush(struct mount *mp, struct vnode *skipvp, int flags)
> {
> struct vflush_args va;
> + int loopcnt;
> va.skipvp = skipvp;
> va.busy = 0;
> va.flags = flags;
>
> - vfs_mount_foreach_vnode(mp, vflush_vnode, &va);
> -
> - if (va.busy)
> - return (EBUSY);
> + for (loopcnt = 10; loopcnt > 0; loopcnt--) {
> + vfs_mount_foreach_vnode(mp, vflush_vnode, &va);
> + if (va.busy)
> + return (EBUSY);
> + if ((flags & FORCECLOSE) == 0)
> + break;
> + if (LIST_EMPTY(&mp->mnt_vnodelist))
> + break;
> + }
> return (0);
> }
>