Date: Mon, 10 Feb 2020 22:28:55 +0000 (UTC) From: Mateusz Guzik <mjg@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357746 - head/sys/kern Message-ID: <202002102228.01AMSttn049062@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mjg Date: Mon Feb 10 22:28:54 2020 New Revision: 357746 URL: https://svnweb.freebsd.org/changeset/base/357746 Log: vfs: fix device count leak on vrele racing with vgone The race is: CPU1 CPU2 devfs_reclaim_vchr make v_usecount 0 VI_LOCK sees v_usecount == 0, no updates vp->v_rdev = NULL; ... VI_UNLOCK VI_LOCK v_decr_devcount sees v_rdev == NULL, no updates In this scenario si_devcount decrement is not performed. Note this can only happen if the vnode lock is not held. Reviewed by: kib Tested by: pho Differential Revision: https://reviews.freebsd.org/D23529 Modified: head/sys/kern/vfs_subr.c Modified: head/sys/kern/vfs_subr.c ============================================================================== --- head/sys/kern/vfs_subr.c Mon Feb 10 20:53:59 2020 (r357745) +++ head/sys/kern/vfs_subr.c Mon Feb 10 22:28:54 2020 (r357746) @@ -3192,12 +3192,22 @@ vputx(struct vnode *vp, enum vputx_op func) * count which provides liveness of the vnode, in which case we * have to vdrop. */ - if (!refcount_release(&vp->v_usecount)) { - if (func == VPUTX_VPUT) - VOP_UNLOCK(vp); - return; + if (__predict_false(vp->v_type == VCHR && func == VPUTX_VRELE)) { + if (refcount_release_if_not_last(&vp->v_usecount)) + return; + VI_LOCK(vp); + if (!refcount_release(&vp->v_usecount)) { + VI_UNLOCK(vp); + return; + } + } else { + if (!refcount_release(&vp->v_usecount)) { + if (func == VPUTX_VPUT) + VOP_UNLOCK(vp); + return; + } + VI_LOCK(vp); } - VI_LOCK(vp); v_decr_devcount(vp); /* * By the time we got here someone else might have transitioned
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202002102228.01AMSttn049062>