Correct the condition under which we allocate a terminator node.

We will have last_block < blocks if the block count is divisible
by BLIST_BMAP_RADIX, but a terminator node is still needed if the
tree isn't balanced.  In this case we were overruning the blist
array by 16 bytes during initialization.

While here, add a check for the invalid blocks == 0 case.

PR:		231116
Reviewed by:	alc, kib (previous version), Doug Moore <dougm@rice.edu>
Approved by:	re (gjb)
MFC after:	1 week
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D17020
This commit is contained in:
Mark Johnston 2018-09-05 19:05:30 +00:00
parent ce9e223ebd
commit ce9eea6425

View File

@ -224,17 +224,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;
@ -244,7 +246,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;