This is an additional and hopefully final fix for bug report 230962.

This bug was introduced with the change to use softdep_bp_to_mp()
in January 2018 changes -r327723 and -r327821. The softdep_bp_to_mp()
function failed to include VSOCK as one of the valid cases.

Although local-domain sockets do not allocate blocks in the filesystem,
they will allocate blocks if they use extended attributes (such as
ACLs). Thus, softdep_bp_to_mp() needs to return a non-NULL mount
pointer when presented with a socket vnode so that the soft updates
write complete will properly process the soft updates structures
associated with the extended attribute blocks. It was the failure
to process these soft updates structures, thus leaving them hanging
off the buffer, which lead to the "panic: softdep_deallocate_dependencies:
dangling deps" when trying to clean up the buffer after it was written.

PR:           230962
Reported by:  2t8mr7kx9f@protonmail.com
Reviewed by:  kib
Tested by:    Peter Holm
MFC after:    1 week
Sponsored by: Netflix
This commit is contained in:
Kirk McKusick 2019-03-20 23:11:05 +00:00
parent 0a0369387e
commit 69166928c7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345352

View File

@ -13970,6 +13970,8 @@ softdep_bp_to_mp(bp)
if (LIST_EMPTY(&bp->b_dep))
return (NULL);
vp = bp->b_vp;
KASSERT(vp != NULL,
("%s, buffer with dependencies lacks vnode", __func__));
/*
* The ump mount point is stable after we get a correct
@ -13979,17 +13981,33 @@ softdep_bp_to_mp(bp)
* workitem might be freed while dereferenced.
*/
retry:
if (vp->v_type == VCHR) {
switch (vp->v_type) {
case VCHR:
VI_LOCK(vp);
mp = vp->v_type == VCHR ? vp->v_rdev->si_mountpt : NULL;
VI_UNLOCK(vp);
if (mp == NULL)
goto retry;
} else if (vp->v_type == VREG || vp->v_type == VDIR ||
vp->v_type == VLNK || vp->v_type == VFIFO) {
break;
case VREG:
case VDIR:
case VLNK:
case VFIFO:
case VSOCK:
mp = vp->v_mount;
} else {
return (NULL);
break;
case VBLK:
vn_printf(vp, "softdep_bp_to_mp: unexpected block device\n");
/* FALLTHROUGH */
case VNON:
case VBAD:
case VMARKER:
mp = NULL;
break;
default:
vn_printf(vp, "unknown vnode type");
mp = NULL;
break;
}
return (VFSTOUFS(mp));
}