From 30d57414a00cd482cea7fb03f23132397b4bbeb0 Mon Sep 17 00:00:00 2001
From: Konstantin Belousov <kib@FreeBSD.org>
Date: Fri, 5 Dec 2014 15:02:30 +0000
Subject: [PATCH] When the last reference on the vnode' vm object is dropped,
 read the vp->v_vflag without taking vnode lock and without bypass.  We do
 know that vp is the lowest level in the stack, since the pointer is obtained
 from the object' handle.  Stale VV_TEXT flag read can only happen if parallel
 execve() is performed and not yet activated the image, since process takes
 reference for text mapping.  In this case, the execve() code manages the
 VV_TEXT flag on its own already.

It was observed that otherwise read-only sendfile(2) requires
exclusive vnode lock and contending on it on some loads for VV_TEXT
handling.

Reported by:	glebius, scottl
Tested by:	glebius, pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
---
 sys/vm/vm_object.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index c3af9d760698..21c15dc86671 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -468,7 +468,12 @@ vm_object_vndeallocate(vm_object_t object)
 	}
 #endif
 
-	if (object->ref_count > 1) {
+	/*
+	 * The test for text of vp vnode does not need a bypass to
+	 * reach right VV_TEXT there, since it is obtained from
+	 * object->handle.
+	 */
+	if (object->ref_count > 1 || (vp->v_vflag & VV_TEXT) == 0) {
 		object->ref_count--;
 		VM_OBJECT_WUNLOCK(object);
 		/* vrele may need the vnode lock. */