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
This commit is contained in:
Mark Johnston 2017-09-13 15:44:54 +00:00
parent 19ebd288fb
commit 2934eb8a22
2 changed files with 13 additions and 7 deletions

View File

@ -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)
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) &&

View File

@ -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;