From owner-svn-src-stable-11@freebsd.org Thu Jun 21 21:21:17 2018 Return-Path: Delivered-To: svn-src-stable-11@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 569211000A51; Thu, 21 Jun 2018 21:21:17 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 0A7138F17E; Thu, 21 Jun 2018 21:21:17 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id DFB59174E0; Thu, 21 Jun 2018 21:21:16 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w5LLLGjC060356; Thu, 21 Jun 2018 21:21:16 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w5LLLG9r060355; Thu, 21 Jun 2018 21:21:16 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201806212121.w5LLLG9r060355@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 21 Jun 2018 21:21:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r335508 - stable/11/sys/vm X-SVN-Group: stable-11 X-SVN-Commit-Author: kib X-SVN-Commit-Paths: stable/11/sys/vm X-SVN-Commit-Revision: 335508 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-11@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: SVN commit messages for only the 11-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 21 Jun 2018 21:21:17 -0000 Author: kib Date: Thu Jun 21 21:21:16 2018 New Revision: 335508 URL: https://svnweb.freebsd.org/changeset/base/335508 Log: MFC r335171: Handle the race between fork/vm_object_split() and faults. Modified: stable/11/sys/vm/swap_pager.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/vm/swap_pager.c ============================================================================== --- stable/11/sys/vm/swap_pager.c Thu Jun 21 21:19:48 2018 (r335507) +++ stable/11/sys/vm/swap_pager.c Thu Jun 21 21:21:16 2018 (r335508) @@ -1096,21 +1096,24 @@ swap_pager_getpages(vm_object_t object, vm_page_t *ma, int *rahead) { struct buf *bp; - vm_page_t mpred, msucc, p; + vm_page_t bm, mpred, msucc, p; vm_pindex_t pindex; daddr_t blk; - int i, j, maxahead, maxbehind, reqcount, shift; + int i, maxahead, maxbehind, reqcount; reqcount = count; - VM_OBJECT_WUNLOCK(object); - bp = getpbuf(&nsw_rcount); - VM_OBJECT_WLOCK(object); - - if (!swap_pager_haspage(object, ma[0]->pindex, &maxbehind, &maxahead)) { - relpbuf(bp, &nsw_rcount); + /* + * Determine the final number of read-behind pages and + * allocate them BEFORE releasing the object lock. Otherwise, + * there can be a problematic race with vm_object_split(). + * Specifically, vm_object_split() might first transfer pages + * that precede ma[0] in the current object to a new object, + * and then this function incorrectly recreates those pages as + * read-behind pages in the current object. + */ + if (!swap_pager_haspage(object, ma[0]->pindex, &maxbehind, &maxahead)) return (VM_PAGER_FAIL); - } /* * Clip the readahead and readbehind ranges to exclude resident pages. @@ -1132,35 +1135,31 @@ swap_pager_getpages(vm_object_t object, vm_page_t *ma, *rbehind = pindex - mpred->pindex - 1; } + bm = ma[0]; + for (i = 0; i < count; i++) + ma[i]->oflags |= VPO_SWAPINPROG; + /* * Allocate readahead and readbehind pages. */ - shift = rbehind != NULL ? *rbehind : 0; - if (shift != 0) { - for (i = 1; i <= shift; i++) { + if (rbehind != NULL) { + for (i = 1; i <= *rbehind; i++) { p = vm_page_alloc(object, ma[0]->pindex - i, VM_ALLOC_NORMAL); - if (p == NULL) { - /* Shift allocated pages to the left. */ - for (j = 0; j < i - 1; j++) - bp->b_pages[j] = - bp->b_pages[j + shift - i + 1]; + if (p == NULL) break; - } - bp->b_pages[shift - i] = p; + p->oflags |= VPO_SWAPINPROG; + bm = p; } - shift = i - 1; - *rbehind = shift; + *rbehind = i - 1; } - for (i = 0; i < reqcount; i++) - bp->b_pages[i + shift] = ma[i]; if (rahead != NULL) { for (i = 0; i < *rahead; i++) { p = vm_page_alloc(object, ma[reqcount - 1]->pindex + i + 1, VM_ALLOC_NORMAL); if (p == NULL) break; - bp->b_pages[shift + reqcount + i] = p; + p->oflags |= VPO_SWAPINPROG; } *rahead = i; } @@ -1171,15 +1170,18 @@ swap_pager_getpages(vm_object_t object, vm_page_t *ma, vm_object_pip_add(object, count); - for (i = 0; i < count; i++) - bp->b_pages[i]->oflags |= VPO_SWAPINPROG; - - pindex = bp->b_pages[0]->pindex; + pindex = bm->pindex; blk = swp_pager_meta_ctl(object, pindex, 0); KASSERT(blk != SWAPBLK_NONE, ("no swap blocking containing %p(%jx)", object, (uintmax_t)pindex)); VM_OBJECT_WUNLOCK(object); + bp = getpbuf(&nsw_rcount); + /* Pages cannot leave the object while busy. */ + for (i = 0, p = bm; i < count; i++, p = TAILQ_NEXT(p, listq)) { + MPASS(p->pindex == bm->pindex + i); + bp->b_pages[i] = p; + } bp->b_flags |= B_PAGING; bp->b_iocmd = BIO_READ;