svn commit: r357746 - head/sys/kern
Mateusz Guzik
mjg at FreeBSD.org
Mon Feb 10 22:28:55 UTC 2020
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
More information about the svn-src-head
mailing list