Revert "vm_phys_enqueue_contig: handle npages==0"

This reverts commit 1a7fcf6d51.

Peter Holm reported a problem, so I'm reverting now and looking for
the problem later.
This commit is contained in:
Doug Moore
2023-08-02 04:32:08 -05:00
parent 11892bc710
commit b7370efade
+37 -33
View File
@@ -72,8 +72,6 @@ __FBSDID("$FreeBSD$");
_Static_assert(sizeof(long) * NBBY >= VM_PHYSSEG_MAX, _Static_assert(sizeof(long) * NBBY >= VM_PHYSSEG_MAX,
"Too many physsegs."); "Too many physsegs.");
_Static_assert(sizeof(long long) >= sizeof(vm_paddr_t),
"vm_paddr_t too big for ffsll, flsll.");
#ifdef NUMA #ifdef NUMA
struct mem_affinity __read_mostly *mem_affinity; struct mem_affinity __read_mostly *mem_affinity;
@@ -692,16 +690,18 @@ vm_phys_split_pages(vm_page_t m, int oind, struct vm_freelist *fl, int order,
* *
* The physical page m's buddy must not be free. * The physical page m's buddy must not be free.
*/ */
static vm_page_t static void
vm_phys_enq_range(vm_page_t m, u_int npages, struct vm_freelist *fl, int tail) vm_phys_enq_range(vm_page_t m, u_int npages, struct vm_freelist *fl, int tail)
{ {
u_int n;
int order; int order;
KASSERT(npages > 0, ("vm_phys_enq_range: npages is 0"));
KASSERT(((VM_PAGE_TO_PHYS(m) + npages * PAGE_SIZE) & KASSERT(((VM_PAGE_TO_PHYS(m) + npages * PAGE_SIZE) &
((PAGE_SIZE << (fls(npages) - 1)) - 1)) == 0, ((PAGE_SIZE << (fls(npages) - 1)) - 1)) == 0,
("vm_phys_enq_range: page %p and npages %u are misaligned", ("vm_phys_enq_range: page %p and npages %u are misaligned",
m, npages)); m, npages));
while (npages > 0) { do {
KASSERT(m->order == VM_NFREEORDER, KASSERT(m->order == VM_NFREEORDER,
("vm_phys_enq_range: page %p has unexpected order %d", ("vm_phys_enq_range: page %p has unexpected order %d",
m, m->order)); m, m->order));
@@ -709,10 +709,10 @@ vm_phys_enq_range(vm_page_t m, u_int npages, struct vm_freelist *fl, int tail)
KASSERT(order < VM_NFREEORDER, KASSERT(order < VM_NFREEORDER,
("vm_phys_enq_range: order %d is out of range", order)); ("vm_phys_enq_range: order %d is out of range", order));
vm_freelist_add(fl, m, order, tail); vm_freelist_add(fl, m, order, tail);
m += 1 << order; n = 1 << order;
npages -= 1 << order; m += n;
} npages -= n;
return (m); } while (npages > 0);
} }
/* /*
@@ -744,7 +744,7 @@ vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[])
{ {
struct vm_freelist *alt, *fl; struct vm_freelist *alt, *fl;
vm_page_t m; vm_page_t m;
int avail, end, flind, freelist, i, oind, pind; int avail, end, flind, freelist, i, need, oind, pind;
KASSERT(domain >= 0 && domain < vm_ndomains, KASSERT(domain >= 0 && domain < vm_ndomains,
("vm_phys_alloc_npages: domain %d is out of range", domain)); ("vm_phys_alloc_npages: domain %d is out of range", domain));
@@ -762,18 +762,20 @@ vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[])
for (oind = 0; oind < VM_NFREEORDER; oind++) { for (oind = 0; oind < VM_NFREEORDER; oind++) {
while ((m = TAILQ_FIRST(&fl[oind].pl)) != NULL) { while ((m = TAILQ_FIRST(&fl[oind].pl)) != NULL) {
vm_freelist_rem(fl, m, oind); vm_freelist_rem(fl, m, oind);
avail = i + (1 << oind); avail = 1 << oind;
end = imin(npages, avail); need = imin(npages - i, avail);
while (i < end) for (end = i + need; i < end;)
ma[i++] = m++; ma[i++] = m++;
if (i == npages) { if (need < avail) {
/* /*
* Return excess pages to fl. Its order * Return excess pages to fl. Its
* [0, oind) queues are empty. * order [0, oind) queues are empty.
*/ */
vm_phys_enq_range(m, avail - i, fl, 1); vm_phys_enq_range(m, avail - need, fl,
1);
return (npages);
} else if (i == npages)
return (npages); return (npages);
}
} }
} }
for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) { for (oind = VM_NFREEORDER - 1; oind >= 0; oind--) {
@@ -783,20 +785,21 @@ vm_phys_alloc_npages(int domain, int pool, int npages, vm_page_t ma[])
NULL) { NULL) {
vm_freelist_rem(alt, m, oind); vm_freelist_rem(alt, m, oind);
vm_phys_set_pool(pool, m, oind); vm_phys_set_pool(pool, m, oind);
avail = i + (1 << oind); avail = 1 << oind;
end = imin(npages, avail); need = imin(npages - i, avail);
while (i < end) for (end = i + need; i < end;)
ma[i++] = m++; ma[i++] = m++;
if (i == npages) { if (need < avail) {
/* /*
* Return excess pages to fl. * Return excess pages to fl.
* Its order [0, oind) queues * Its order [0, oind) queues
* are empty. * are empty.
*/ */
vm_phys_enq_range(m, avail - i, vm_phys_enq_range(m, avail -
fl, 1); need, fl, 1);
return (npages);
} else if (i == npages)
return (npages); return (npages);
}
} }
} }
} }
@@ -1143,7 +1146,7 @@ max_order(vm_page_t m)
* because the size of a physical address exceeds the size of * because the size of a physical address exceeds the size of
* a long. * a long.
*/ */
return (min(ffsll(VM_PAGE_TO_PHYS(m) >> PAGE_SHIFT) - 1, return (min(ffsl(VM_PAGE_TO_PHYS(m) >> PAGE_SHIFT) - 1,
VM_NFREEORDER - 1)); VM_NFREEORDER - 1));
} }
@@ -1159,7 +1162,6 @@ vm_phys_enqueue_contig(vm_page_t m, u_long npages)
struct vm_freelist *fl; struct vm_freelist *fl;
struct vm_phys_seg *seg; struct vm_phys_seg *seg;
vm_page_t m_end; vm_page_t m_end;
vm_paddr_t diff, lo;
int order; int order;
/* /*
@@ -1171,15 +1173,15 @@ vm_phys_enqueue_contig(vm_page_t m, u_long npages)
fl = (*seg->free_queues)[m->pool]; fl = (*seg->free_queues)[m->pool];
m_end = m + npages; m_end = m + npages;
/* Free blocks of increasing size. */ /* Free blocks of increasing size. */
lo = VM_PAGE_TO_PHYS(m) >> PAGE_SHIFT; while ((order = max_order(m)) < VM_NFREEORDER - 1 &&
if (m < m_end && m + (1 << order) <= m_end) {
(diff = lo ^ (lo + npages - 1)) != 0) { KASSERT(seg == &vm_phys_segs[m->segind],
order = min(flsll(diff) - 1, VM_NFREEORDER - 1); ("%s: page range [%p,%p) spans multiple segments",
m = vm_phys_enq_range(m, roundup2(-lo, 1 << order), fl, 1); __func__, m_end - npages, m));
vm_freelist_add(fl, m, order, 1);
m += 1 << order;
} }
/* Free blocks of maximum size. */ /* Free blocks of maximum size. */
order = VM_NFREEORDER - 1;
while (m + (1 << order) <= m_end) { while (m + (1 << order) <= m_end) {
KASSERT(seg == &vm_phys_segs[m->segind], KASSERT(seg == &vm_phys_segs[m->segind],
("%s: page range [%p,%p) spans multiple segments", ("%s: page range [%p,%p) spans multiple segments",
@@ -1558,8 +1560,10 @@ vm_phys_alloc_contig(int domain, u_long npages, vm_paddr_t low, vm_paddr_t high,
vm_phys_set_pool(VM_FREEPOOL_DEFAULT, m, oind); vm_phys_set_pool(VM_FREEPOOL_DEFAULT, m, oind);
} }
/* Return excess pages to the free lists. */ /* Return excess pages to the free lists. */
if (&m_run[npages] < m) {
fl = (*queues)[VM_FREEPOOL_DEFAULT]; fl = (*queues)[VM_FREEPOOL_DEFAULT];
vm_phys_enq_range(&m_run[npages], m - &m_run[npages], fl, 0); vm_phys_enq_range(&m_run[npages], m - &m_run[npages], fl, 0);
}
return (m_run); return (m_run);
} }