Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Nov 2018 19:17:28 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r341162 - head/sys/vm
Message-ID:  <201811281917.wASJHSXP066547@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Wed Nov 28 19:17:27 2018
New Revision: 341162
URL: https://svnweb.freebsd.org/changeset/base/341162

Log:
  For not offpage zones the slab is placed at the end of page. Keg's uk_pgoff
  is calculated to guarantee that struct uma_slab is placed at pointer size
  alignment. Calculation of real struct uma_slab size is done in keg_ctor()
  and yet again in keg_large_init(), to check if we need an extra page. This
  calculation can actually be performed at compile time.
  
  - Add SIZEOF_UMA_SLAB macro to calculate size of struct uma_slab placed at
    an end of a page with alignment requirement.
  - Use SIZEOF_UMA_SLAB in keg_ctor() and in keg_large_init(). This is a not
    a functional change.
  - Use SIZEOF_UMA_SLAB in UMA_SLAB_SPACE definition and in keg_small_init().
    This is a potential bugfix, but in reality I don't think there are any
    systems affected, since compiler aligns struct uma_slab anyway.

Modified:
  head/sys/vm/uma_core.c
  head/sys/vm/uma_int.h

Modified: head/sys/vm/uma_core.c
==============================================================================
--- head/sys/vm/uma_core.c	Wed Nov 28 18:42:42 2018	(r341161)
+++ head/sys/vm/uma_core.c	Wed Nov 28 19:17:27 2018	(r341162)
@@ -1453,7 +1453,7 @@ keg_small_init(uma_keg_t keg)
 	if (keg->uk_flags & UMA_ZONE_OFFPAGE)
 		shsize = 0;
 	else 
-		shsize = sizeof(struct uma_slab);
+		shsize = SIZEOF_UMA_SLAB;
 
 	if (rsize <= slabsize - shsize)
 		keg->uk_ipers = (slabsize - shsize) / rsize;
@@ -1523,7 +1523,6 @@ keg_small_init(uma_keg_t keg)
 static void
 keg_large_init(uma_keg_t keg)
 {
-	u_int shsize;
 
 	KASSERT(keg != NULL, ("Keg is null in keg_large_init"));
 	KASSERT((keg->uk_flags & UMA_ZFLAG_CACHEONLY) == 0,
@@ -1536,23 +1535,17 @@ keg_large_init(uma_keg_t keg)
 	keg->uk_rsize = keg->uk_size;
 
 	/* Check whether we have enough space to not do OFFPAGE. */
-	if ((keg->uk_flags & UMA_ZONE_OFFPAGE) == 0) {
-		shsize = sizeof(struct uma_slab);
-		if (shsize & UMA_ALIGN_PTR)
-			shsize = (shsize & ~UMA_ALIGN_PTR) +
-			    (UMA_ALIGN_PTR + 1);
-
-		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) == 0 &&
+	    PAGE_SIZE * keg->uk_ppera - keg->uk_rsize < SIZEOF_UMA_SLAB) {
+		/*
+		 * 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) &&
@@ -1693,20 +1686,11 @@ keg_ctor(void *mem, int size, void *udata, int flags)
 
 	/*
 	 * If we're putting the slab header in the actual page we need to
-	 * figure out where in each page it goes.  This calculates a right
-	 * justified offset into the memory on an ALIGN_PTR boundary.
+	 * figure out where in each page it goes.  See SIZEOF_UMA_SLAB
+	 * macro definition.
 	 */
 	if (!(keg->uk_flags & UMA_ZONE_OFFPAGE)) {
-		u_int totsize;
-
-		/* Size of the slab struct and free list */
-		totsize = sizeof(struct uma_slab);
-
-		if (totsize & UMA_ALIGN_PTR)
-			totsize = (totsize & ~UMA_ALIGN_PTR) +
-			    (UMA_ALIGN_PTR + 1);
-		keg->uk_pgoff = (PAGE_SIZE * keg->uk_ppera) - totsize;
-
+		keg->uk_pgoff = (PAGE_SIZE * keg->uk_ppera) - SIZEOF_UMA_SLAB;
 		/*
 		 * The only way the following is possible is if with our
 		 * UMA_ALIGN_PTR adjustments we are now bigger than
@@ -1714,13 +1698,10 @@ keg_ctor(void *mem, int size, void *udata, int flags)
 		 * mathematically possible for all cases, so we make
 		 * sure here anyway.
 		 */
-		totsize = keg->uk_pgoff + sizeof(struct uma_slab);
-		if (totsize > PAGE_SIZE * keg->uk_ppera) {
-			printf("zone %s ipers %d rsize %d size %d\n",
-			    zone->uz_name, keg->uk_ipers, keg->uk_rsize,
-			    keg->uk_size);
-			panic("UMA slab won't fit.");
-		}
+		KASSERT(keg->uk_pgoff + sizeof(struct uma_slab) <=
+		    PAGE_SIZE * keg->uk_ppera,
+		    ("zone %s ipers %d rsize %d size %d slab won't fit",
+		    zone->uz_name, keg->uk_ipers, keg->uk_rsize, keg->uk_size));
 	}
 
 	if (keg->uk_flags & UMA_ZONE_HASH)

Modified: head/sys/vm/uma_int.h
==============================================================================
--- head/sys/vm/uma_int.h	Wed Nov 28 18:42:42 2018	(r341161)
+++ head/sys/vm/uma_int.h	Wed Nov 28 19:17:27 2018	(r341162)
@@ -139,9 +139,17 @@
 #define UMA_MAX_WASTE	10
 
 /*
- * Size of memory in a not offpage slab available for actual items.
+ * Actual size of uma_slab when it is placed at an end of a page
+ * with pointer sized alignment requirement.
  */
-#define	UMA_SLAB_SPACE	(UMA_SLAB_SIZE - sizeof(struct uma_slab))
+#define	SIZEOF_UMA_SLAB	((sizeof(struct uma_slab) & UMA_ALIGN_PTR) ?	  \
+			    (sizeof(struct uma_slab) & ~UMA_ALIGN_PTR) +  \
+			    (UMA_ALIGN_PTR + 1) : sizeof(struct uma_slab))
+
+/*
+ * Size of memory in a not offpage single page slab available for actual items.
+ */
+#define	UMA_SLAB_SPACE	(PAGE_SIZE - SIZEOF_UMA_SLAB)
 
 /*
  * I doubt there will be many cases where this is exceeded. This is the initial



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