Address problems in blist_alloc introduced in r349777. The swap block allocator could become corrupted

if a retry to allocate swap space, after a larger allocation attempt failed, allocated a smaller set of free blocks
that ended on a 32- or 64-block boundary.

Add tests to detect this kind of failure-to-extend-at-boundary and prevent the associated accounting screwup.

Reported by: pho
Tested by: pho
Reviewed by: alc
Approved by: markj (mentor)
Discussed with: kib
Differential Revision: https://reviews.freebsd.org/D20893
This commit is contained in:
dougm 2019-07-11 20:52:39 +00:00
parent 6186c641de
commit a9f5b306a6

View File

@ -639,15 +639,27 @@ blst_next_leaf_alloc(blmeta_t *scan, daddr_t start, int count, int maxcount)
* bitpos() returns zero here.
*/
avail = blk - start + bitpos(~scan->bm_bitmap);
if (avail < count) {
if (avail < count || avail == 0) {
/*
* There isn't a next leaf with enough free
* blocks at its beginning to complete the
* spanning allocation.
* blocks at its beginning to bother
* allocating.
*/
return (avail);
}
maxcount = imin(avail, maxcount);
if (maxcount % BLIST_BMAP_RADIX == 0) {
/*
* There was no next leaf. Back scan up to
* last leaf.
*/
--scan;
while (radix != BLIST_BMAP_RADIX) {
radix /= BLIST_META_RADIX;
--scan;
}
blk -= BLIST_BMAP_RADIX;
}
}
}