mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
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
This commit is contained in:
parent
37d4ece7c5
commit
2e57c8fde7
1 changed files with 15 additions and 5 deletions
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue