Index: sys/kern/subr_pctrie.c =================================================================== --- sys/kern/subr_pctrie.c +++ sys/kern/subr_pctrie.c @@ -630,16 +630,34 @@ base = (index + i) % PCTRIE_COUNT; if (base == 0 || parent == NULL || parent->pn_clev != 0) continue; - end = MIN(count, i + PCTRIE_COUNT - base); + + /* + * For PCTRIE_SMR, compute an upper bound on number of children + * of this parent left to examine, For PCTRIE_LOCKED, compute + * the number of non-NULL children from base up to the first + * NULL child, if any, using the fact that pn_popmap has bits + * set for only the non-NULL children. + */ + end = (access == PCTRIE_SMR) ? PCTRIE_COUNT - base : + ffs((parent->pn_popmap >> base) + 1) - 1; + end = MIN(count, i + end); while (i < end) { node = pctrie_node_load(&parent->pn_child[base++], smr, access); - if ((val = pctrie_toval(node)) == NULL) + val = pctrie_toval(node); + if (access == PCTRIE_SMR && val == NULL) break; value[i++] = val; + KASSERT(val != NULL), + ("%s: null child written to range", __func__)); + } + if (access == PCTRIE_SMR) { + if (i < end) + break; + } else { + if (base < PCTRIE_COUNT) + break; } - if (i < end) - break; } if (parent_out != NULL) *parent_out = parent;