From owner-svn-src-head@freebsd.org Mon Aug 28 22:11:32 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 16CBDE14E7D; Mon, 28 Aug 2017 22:11:32 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [96.47.72.37]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id CFA0166760; Mon, 28 Aug 2017 22:11:31 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v7SMAF84068257; Mon, 28 Aug 2017 22:10:15 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v7SMAFhl068256; Mon, 28 Aug 2017 22:10:15 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201708282210.v7SMAFhl068256@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Mon, 28 Aug 2017 22:10:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r322987 - head/sys/vm X-SVN-Group: head X-SVN-Commit-Author: markj X-SVN-Commit-Paths: head/sys/vm X-SVN-Commit-Revision: 322987 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Aug 2017 22:11:32 -0000 Author: markj Date: Mon Aug 28 22:10:15 2017 New Revision: 322987 URL: https://svnweb.freebsd.org/changeset/base/322987 Log: Synchronize page laundering with pmap_extract_and_hold(). Before r207410, the hold count of a page in a page queue was protected by the queue lock, and, before laundering a page, the page daemon removed managed writeable mappings of the page before releasing the queue lock. This ensured that other threads could not concurrently create transient writeable mappings using pmap_extract_and_hold() on a user map, as is done for example by vmapbuf(). With that revision, however, a race can allow the creation of such a mapping, meaning that the page might be modified as it is being laundered, potentially resulting in it being marked clean when its contents do not match those given to the pager. Close the race by using the page lock to synchronize the hold count check in vm_pageout_cluster() with the removal of writeable managed mappings. Reported by: alc Reviewed by: alc, kib MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D12084 Modified: head/sys/vm/vm_pageout.c Modified: head/sys/vm/vm_pageout.c ============================================================================== --- head/sys/vm/vm_pageout.c Mon Aug 28 22:09:12 2017 (r322986) +++ head/sys/vm/vm_pageout.c Mon Aug 28 22:10:15 2017 (r322987) @@ -402,6 +402,8 @@ vm_pageout_cluster(vm_page_t m) */ vm_page_assert_unbusied(m); KASSERT(m->hold_count == 0, ("page %p is held", m)); + + pmap_remove_write(m); vm_page_unlock(m); mc[vm_pageout_page_count] = pb = ps = m; @@ -444,6 +446,7 @@ more: ib = 0; break; } + pmap_remove_write(p); vm_page_unlock(p); mc[--page_base] = pb = p; ++pageout_count; @@ -469,6 +472,7 @@ more: vm_page_unlock(p); break; } + pmap_remove_write(p); vm_page_unlock(p); mc[page_base + pageout_count] = ps = p; ++pageout_count; @@ -513,8 +517,8 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags, VM_OBJECT_ASSERT_WLOCKED(object); /* - * Initiate I/O. Bump the vm_page_t->busy counter and - * mark the pages read-only. + * Initiate I/O. Mark the pages busy and verify that they're valid + * and read-only. * * We do not have to fixup the clean/dirty bits here... we can * allow the pager to do it after the I/O completes. @@ -526,8 +530,9 @@ vm_pageout_flush(vm_page_t *mc, int count, int flags, KASSERT(mc[i]->valid == VM_PAGE_BITS_ALL, ("vm_pageout_flush: partially invalid page %p index %d/%d", mc[i], i, count)); + KASSERT((mc[i]->aflags & PGA_WRITEABLE) == 0, + ("vm_pageout_flush: writeable page %p", mc[i])); vm_page_sbusy(mc[i]); - pmap_remove_write(mc[i]); } vm_object_pip_add(object, count);