Correct a bug in the management of the population map on big-endian

machines.  Specifically, there was a mismatch between how the routine
allocation and deallocation operations accessed the population map
and how the aggressively optimized reservation-breaking operation
accessed it.  So, problems only occurred when reservations were broken.
This change makes the routine operations access the population map in
the same way as the reservation breaking operation.

This bug was introduced in r259999.

PR:		187080
Tested by:	jmg (on an "armeb" machine)
Sponsored by:	EMC / Isilon Storage Division
This commit is contained in:
Alan Cox 2014-06-11 16:11:12 +00:00
parent 068d8643ad
commit 3180f7573a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=267364

View File

@ -107,6 +107,46 @@ typedef u_long popmap_t;
*/
#define NPOPMAP howmany(VM_LEVEL_0_NPAGES, NBPOPMAP)
/*
* Clear a bit in the population map.
*/
static __inline void
popmap_clear(popmap_t popmap[], int i)
{
popmap[i / NBPOPMAP] &= ~(1UL << (i % NBPOPMAP));
}
/*
* Set a bit in the population map.
*/
static __inline void
popmap_set(popmap_t popmap[], int i)
{
popmap[i / NBPOPMAP] |= 1UL << (i % NBPOPMAP);
}
/*
* Is a bit in the population map clear?
*/
static __inline boolean_t
popmap_is_clear(popmap_t popmap[], int i)
{
return ((popmap[i / NBPOPMAP] & (1UL << (i % NBPOPMAP))) == 0);
}
/*
* Is a bit in the population map set?
*/
static __inline boolean_t
popmap_is_set(popmap_t popmap[], int i)
{
return ((popmap[i / NBPOPMAP] & (1UL << (i % NBPOPMAP))) != 0);
}
/*
* The reservation structure
*
@ -241,7 +281,7 @@ vm_reserv_depopulate(vm_reserv_t rv, int index)
mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
KASSERT(rv->object != NULL,
("vm_reserv_depopulate: reserv %p is free", rv));
KASSERT(isset(rv->popmap, index),
KASSERT(popmap_is_set(rv->popmap, index),
("vm_reserv_depopulate: reserv %p's popmap[%d] is clear", rv,
index));
KASSERT(rv->popcnt > 0,
@ -255,7 +295,7 @@ vm_reserv_depopulate(vm_reserv_t rv, int index)
rv));
rv->pages->psind = 0;
}
clrbit(rv->popmap, index);
popmap_clear(rv->popmap, index);
rv->popcnt--;
if (rv->popcnt == 0) {
LIST_REMOVE(rv, objq);
@ -302,7 +342,7 @@ vm_reserv_populate(vm_reserv_t rv, int index)
mtx_assert(&vm_page_queue_free_mtx, MA_OWNED);
KASSERT(rv->object != NULL,
("vm_reserv_populate: reserv %p is free", rv));
KASSERT(isclr(rv->popmap, index),
KASSERT(popmap_is_clear(rv->popmap, index),
("vm_reserv_populate: reserv %p's popmap[%d] is set", rv,
index));
KASSERT(rv->popcnt < VM_LEVEL_0_NPAGES,
@ -313,7 +353,7 @@ vm_reserv_populate(vm_reserv_t rv, int index)
TAILQ_REMOVE(&vm_rvq_partpop, rv, partpopq);
rv->inpartpopq = FALSE;
}
setbit(rv->popmap, index);
popmap_set(rv->popmap, index);
rv->popcnt++;
if (rv->popcnt < VM_LEVEL_0_NPAGES) {
rv->inpartpopq = TRUE;
@ -503,7 +543,7 @@ vm_reserv_alloc_contig(vm_object_t object, vm_pindex_t pindex, u_long npages,
return (NULL);
/* Handle vm_page_rename(m, new_object, ...). */
for (i = 0; i < npages; i++)
if (isset(rv->popmap, index + i))
if (popmap_is_set(rv->popmap, index + i))
return (NULL);
for (i = 0; i < npages; i++)
vm_reserv_populate(rv, index + i);
@ -628,7 +668,7 @@ vm_reserv_alloc_page(vm_object_t object, vm_pindex_t pindex, vm_page_t mpred)
index = VM_RESERV_INDEX(object, pindex);
m = &rv->pages[index];
/* Handle vm_page_rename(m, new_object, ...). */
if (isset(rv->popmap, index))
if (popmap_is_set(rv->popmap, index))
return (NULL);
vm_reserv_populate(rv, index);
return (m);
@ -662,9 +702,9 @@ vm_reserv_break(vm_reserv_t rv, vm_page_t m)
* to the physical memory allocator.
*/
i = m - rv->pages;
KASSERT(isclr(rv->popmap, i),
KASSERT(popmap_is_clear(rv->popmap, i),
("vm_reserv_break: reserv %p's popmap is corrupted", rv));
setbit(rv->popmap, i);
popmap_set(rv->popmap, i);
rv->popcnt++;
}
i = hi = 0;