summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/kern/subr_blist.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/kern/subr_blist.c')
-rw-r--r--freebsd/sys/kern/subr_blist.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/freebsd/sys/kern/subr_blist.c b/freebsd/sys/kern/subr_blist.c
index a7d78d86..e5b40e62 100644
--- a/freebsd/sys/kern/subr_blist.c
+++ b/freebsd/sys/kern/subr_blist.c
@@ -226,17 +226,19 @@ blist_create(daddr_t blocks, int flags)
u_daddr_t nodes, radix, skip;
int digit;
+ if (blocks == 0)
+ panic("invalid block count");
+
/*
- * Calculate the radix and node count used for scanning. Find the last
- * block that is followed by a terminator.
+ * Calculate the radix and node count used for scanning.
*/
last_block = blocks - 1;
radix = BLIST_BMAP_RADIX;
while (radix < blocks) {
if (((last_block / radix + 1) & BLIST_META_MASK) != 0)
/*
- * A terminator will be added. Update last_block to the
- * position just before that terminator.
+ * We must widen the blist to avoid partially
+ * filled nodes.
*/
last_block |= radix - 1;
radix *= BLIST_META_RADIX;
@@ -246,7 +248,9 @@ blist_create(daddr_t blocks, int flags)
* Count the meta-nodes in the expanded tree, including the final
* terminator, from the bottom level up to the root.
*/
- nodes = (last_block >= blocks) ? 2 : 1;
+ nodes = 1;
+ if (radix - blocks >= BLIST_BMAP_RADIX)
+ nodes++;
last_block /= BLIST_BMAP_RADIX;
while (last_block > 0) {
nodes += last_block + 1;