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