From owner-svn-src-stable@freebsd.org Sat Oct 3 07:43:34 2015 Return-Path: Delivered-To: svn-src-stable@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 76B63A0F29E; Sat, 3 Oct 2015 07:43:34 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (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 5929E17B5; Sat, 3 Oct 2015 07:43:34 +0000 (UTC) (envelope-from alc@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t937hYPD072945; Sat, 3 Oct 2015 07:43:34 GMT (envelope-from alc@FreeBSD.org) Received: (from alc@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t937hY8Y072944; Sat, 3 Oct 2015 07:43:34 GMT (envelope-from alc@FreeBSD.org) Message-Id: <201510030743.t937hY8Y072944@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: alc set sender to alc@FreeBSD.org using -f From: Alan Cox Date: Sat, 3 Oct 2015 07:43:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r288556 - stable/10/sys/vm X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Oct 2015 07:43:34 -0000 Author: alc Date: Sat Oct 3 07:43:33 2015 New Revision: 288556 URL: https://svnweb.freebsd.org/changeset/base/288556 Log: MFC r288281 The conversion of kmem_alloc_attr() from operating on a vm map to a vmem arena in r254025 introduced a bug in the case when an allocation is only partially successful. Specifically, the vm object lock was not being acquired before freeing the allocated pages. To address this bug, replace the existing code by a call to kmem_unback(). Change the type of a variable in kmem_alloc_attr() so that an allocation of two or more gigabytes won't fail. Replace the error handling code in kmem_back() by a call to kmem_unback(). Modified: stable/10/sys/vm/vm_kern.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/vm/vm_kern.c ============================================================================== --- stable/10/sys/vm/vm_kern.c Sat Oct 3 07:35:11 2015 (r288555) +++ stable/10/sys/vm/vm_kern.c Sat Oct 3 07:43:33 2015 (r288556) @@ -159,11 +159,10 @@ kmem_alloc_attr(vmem_t *vmem, vm_size_t vm_paddr_t high, vm_memattr_t memattr) { vm_object_t object = vmem == kmem_arena ? kmem_object : kernel_object; - vm_offset_t addr; + vm_offset_t addr, i; vm_ooffset_t offset; vm_page_t m; int pflags, tries; - int i; size = round_page(size); if (vmem_alloc(vmem, size, M_BESTFIT | flags, &addr)) @@ -184,18 +183,7 @@ retry: tries++; goto retry; } - /* - * Unmap and free the pages. - */ - if (i != 0) - pmap_remove(kernel_pmap, addr, addr + i); - while (i != 0) { - i -= PAGE_SIZE; - m = vm_page_lookup(object, - OFF_TO_IDX(offset + i)); - vm_page_unwire(m, 0); - vm_page_free(m); - } + kmem_unback(object, addr, i); vmem_free(vmem, addr, size); return (0); } @@ -353,25 +341,13 @@ retry: * aren't on any queues. */ if (m == NULL) { + VM_OBJECT_WUNLOCK(object); if ((flags & M_NOWAIT) == 0) { - VM_OBJECT_WUNLOCK(object); VM_WAIT; VM_OBJECT_WLOCK(object); goto retry; } - /* - * Unmap and free the pages. - */ - if (i != 0) - pmap_remove(kernel_pmap, addr, addr + i); - while (i != 0) { - i -= PAGE_SIZE; - m = vm_page_lookup(object, - OFF_TO_IDX(offset + i)); - vm_page_unwire(m, 0); - vm_page_free(m); - } - VM_OBJECT_WUNLOCK(object); + kmem_unback(object, addr, i); return (KERN_NO_SPACE); } if (flags & M_ZERO && (m->flags & PG_ZERO) == 0) @@ -387,6 +363,15 @@ retry: return (KERN_SUCCESS); } +/* + * kmem_unback: + * + * Unmap and free the physical pages underlying the specified virtual + * address range. + * + * A physical page must exist within the specified object at each index + * that is being unmapped. + */ void kmem_unback(vm_object_t object, vm_offset_t addr, vm_size_t size) {