Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Sep 2017 15:44:54 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r323544 - head/sys/vm
Message-ID:  <201709131544.v8DFispa089913@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Wed Sep 13 15:44:54 2017
New Revision: 323544
URL: https://svnweb.freebsd.org/changeset/base/323544

Log:
  Fix a logic error in the item size calculation for internal UMA zones.
  
  Kegs for internal zones always keep the slab header in the slab itself.
  Therefore, when determining the allocation size, we need to take the
  slab header size into account.
  
  Reported and tested by:	ae, rakuco
  Reviewed by:	avg
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D12342

Modified:
  head/sys/vm/uma_core.c
  head/sys/vm/vm_page.c

Modified: head/sys/vm/uma_core.c
==============================================================================
--- head/sys/vm/uma_core.c	Wed Sep 13 15:17:35 2017	(r323543)
+++ head/sys/vm/uma_core.c	Wed Sep 13 15:44:54 2017	(r323544)
@@ -1306,10 +1306,6 @@ keg_large_init(uma_keg_t keg)
 	keg->uk_ipers = 1;
 	keg->uk_rsize = keg->uk_size;
 
-	/* We can't do OFFPAGE if we're internal, bail out here. */
-	if (keg->uk_flags & UMA_ZFLAG_INTERNAL)
-		return;
-
 	/* Check whether we have enough space to not do OFFPAGE. */
 	if ((keg->uk_flags & UMA_ZONE_OFFPAGE) == 0) {
 		shsize = sizeof(struct uma_slab);
@@ -1317,8 +1313,17 @@ keg_large_init(uma_keg_t keg)
 			shsize = (shsize & ~UMA_ALIGN_PTR) +
 			    (UMA_ALIGN_PTR + 1);
 
-		if ((PAGE_SIZE * keg->uk_ppera) - keg->uk_rsize < shsize)
-			keg->uk_flags |= UMA_ZONE_OFFPAGE;
+		if (PAGE_SIZE * keg->uk_ppera - keg->uk_rsize < shsize) {
+			/*
+			 * We can't do OFFPAGE if we're internal, in which case
+			 * we need an extra page per allocation to contain the
+			 * slab header.
+			 */
+			if ((keg->uk_flags & UMA_ZFLAG_INTERNAL) == 0)
+				keg->uk_flags |= UMA_ZONE_OFFPAGE;
+			else
+				keg->uk_ppera++;
+		}
 	}
 
 	if ((keg->uk_flags & UMA_ZONE_OFFPAGE) &&

Modified: head/sys/vm/vm_page.c
==============================================================================
--- head/sys/vm/vm_page.c	Wed Sep 13 15:17:35 2017	(r323543)
+++ head/sys/vm/vm_page.c	Wed Sep 13 15:44:54 2017	(r323544)
@@ -473,7 +473,8 @@ vm_page_startup(vm_offset_t vaddr)
 	 * in proportion to the zone structure size.
 	 */
 	pages_per_zone = howmany(sizeof(struct uma_zone) +
-	    sizeof(struct uma_cache) * (mp_maxid + 1), UMA_SLAB_SIZE);
+	    sizeof(struct uma_cache) * (mp_maxid + 1) +
+	    roundup2(sizeof(struct uma_slab), sizeof(void *)), UMA_SLAB_SIZE);
 	if (pages_per_zone > 1) {
 		/* Reserve more pages so that we don't run out. */
 		boot_pages = UMA_BOOT_PAGES_ZONES * pages_per_zone;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709131544.v8DFispa089913>