Terminate a blist_alloc search when a blst_meta_alloc call fails with

cursor == 0.

Every call to blst_meta_alloc but the one at the root is made only when the
meta-node is known to include a free block, so that either the allocation
will succeed, the node hint will be updated, or the last block of the meta-
node range is, and remains, free.  But the call at the root is made without
checking that there is a free block, so in the case that every block is
allocated, there is no hint update to prevent the current code from looping
forever.

Submitted by:	Doug Moore <dougm@rice.edu>
Reported by:	pho
Reviewed by:	pho
Tested by:	pho
X-MFC with:	r340402
Differential Revision:	https://reviews.freebsd.org/D17999
This commit is contained in:
Alan Cox 2018-12-05 18:26:40 +00:00
parent 5e97950ded
commit 749cdf6f3b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=341602

View File

@ -295,9 +295,9 @@ blist_alloc(blist_t bl, daddr_t count)
* This loop iterates at most twice. An allocation failure in the
* first iteration leads to a second iteration only if the cursor was
* non-zero. When the cursor is zero, an allocation failure will
* reduce the hint, stopping further iterations.
* stop further iterations.
*/
while (count <= bl->bl_root->bm_bighint) {
for (;;) {
blk = blst_meta_alloc(bl->bl_root, bl->bl_cursor, count,
bl->bl_radix);
if (blk != SWAPBLK_NONE) {
@ -306,10 +306,10 @@ blist_alloc(blist_t bl, daddr_t count)
if (bl->bl_cursor == bl->bl_blocks)
bl->bl_cursor = 0;
return (blk);
}
} else if (bl->bl_cursor == 0)
return (SWAPBLK_NONE);
bl->bl_cursor = 0;
}
return (SWAPBLK_NONE);
}
/*