/* *Thistestjustdoesbasicsanitychecking,makingsurewecanaddanextent *entryandremovespacefromeitherendandthemiddle,andmakesurewecan *removespacethatcoversadjacentextententries.
*/ staticint test_extents(struct btrfs_block_group *cache)
{ int ret = 0;
test_msg("running extent only tests");
/* First just make sure we can remove an entire entry */
ret = btrfs_add_free_space(cache, 0, SZ_4M); if (ret) {
test_err("error adding initial extents %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, 0, SZ_4M); if (ret) {
test_err("error removing extent %d", ret); return ret;
}
if (test_check_exists(cache, 0, SZ_4M)) {
test_err("full remove left some lingering space"); return -1;
}
/* Ok edge and middle cases now */
ret = btrfs_add_free_space(cache, 0, SZ_4M); if (ret) {
test_err("error adding half extent %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, 3 * SZ_1M, SZ_1M); if (ret) {
test_err("error removing tail end %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, 0, SZ_1M); if (ret) {
test_err("error removing front end %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, SZ_2M, 4096); if (ret) {
test_err("error removing middle piece %d", ret); return ret;
}
if (test_check_exists(cache, 0, SZ_1M)) {
test_err("still have space at the front"); return -1;
}
if (test_check_exists(cache, SZ_2M, 4096)) {
test_err("still have space in the middle"); return -1;
}
if (test_check_exists(cache, 3 * SZ_1M, SZ_1M)) {
test_err("still have space at the end"); return -1;
}
/* Test a bit straddling two bitmaps */
ret = test_add_free_space_entry(cache, next_bitmap_offset - SZ_2M,
SZ_4M, 1); if (ret) {
test_err("couldn't add space that straddles two bitmaps %d",
ret); return ret;
}
ret = btrfs_remove_free_space(cache, next_bitmap_offset - SZ_1M, SZ_2M); if (ret) {
test_err("couldn't remove overlapping space %d", ret); return ret;
}
if (test_check_exists(cache, next_bitmap_offset - SZ_1M, SZ_2M)) {
test_err("left some space when removing overlapping"); return -1;
}
btrfs_remove_free_space_cache(cache);
return0;
}
/* This is the high grade jackassery */ staticint test_bitmaps_and_extents(struct btrfs_block_group *cache,
u32 sectorsize)
{
u64 bitmap_offset = (u64)(BITS_PER_BITMAP * sectorsize); int ret;
ret = test_add_free_space_entry(cache, 0, SZ_1M, 0); if (ret) {
test_err("couldn't add extent entry %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, 0, SZ_1M); if (ret) {
test_err("couldn't remove extent entry %d", ret); return ret;
}
if (test_check_exists(cache, 0, SZ_1M)) {
test_err("left remnants after our remove"); return -1;
}
/* Now to add back the extent entry and remove from the bitmap */
ret = test_add_free_space_entry(cache, 0, SZ_1M, 0); if (ret) {
test_err("couldn't re-add extent entry %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, SZ_4M, SZ_1M); if (ret) {
test_err("couldn't remove from bitmap %d", ret); return ret;
}
if (test_check_exists(cache, SZ_4M, SZ_1M)) {
test_err("left remnants in the bitmap"); return -1;
}
/* *Oksoalittlemoreevil,extententryandbitmapatthesameoffset, *removinganoverlappingchunk.
*/
ret = test_add_free_space_entry(cache, SZ_1M, SZ_4M, 1); if (ret) {
test_err("couldn't add to a bitmap %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, SZ_512K, 3 * SZ_1M); if (ret) {
test_err("couldn't remove overlapping space %d", ret); return ret;
}
if (test_check_exists(cache, SZ_512K, 3 * SZ_1M)) {
test_err("left over pieces after removing overlapping"); return -1;
}
btrfs_remove_free_space_cache(cache);
/* Now with the extent entry offset into the bitmap */
ret = test_add_free_space_entry(cache, SZ_4M, SZ_4M, 1); if (ret) {
test_err("couldn't add space to the bitmap %d", ret); return ret;
}
ret = test_add_free_space_entry(cache, SZ_2M, SZ_2M, 0); if (ret) {
test_err("couldn't add extent to the cache %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, 3 * SZ_1M, SZ_4M); if (ret) {
test_err("problem removing overlapping space %d", ret); return ret;
}
if (test_check_exists(cache, 3 * SZ_1M, SZ_4M)) {
test_err("left something behind when removing space"); return -1;
}
ret = test_add_free_space_entry(cache, 3 * SZ_1M, SZ_1M, 0); if (ret) {
test_err("couldn't add extent entry %d", ret); return ret;
}
ret = btrfs_remove_free_space(cache, SZ_1M, 3 * SZ_1M); if (ret) {
test_err("error removing bitmap and extent overlapping %d", ret); return ret;
}
btrfs_remove_free_space_cache(cache); return0;
}
/* Used by test_steal_space_from_bitmap_to_extent(). */ staticbool test_use_bitmap(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info)
{ return ctl->free_extents > 0;
}
/* Used by test_steal_space_from_bitmap_to_extent(). */ staticint
check_num_extents_and_bitmaps(conststruct btrfs_block_group *cache, constint num_extents, constint num_bitmaps)
{ if (cache->free_space_ctl->free_extents != num_extents) {
test_err( "incorrect # of extent entries in the cache: %d, expected %d",
cache->free_space_ctl->free_extents, num_extents); return -EINVAL;
} if (cache->free_space_ctl->total_bitmaps != num_bitmaps) {
test_err( "incorrect # of extent entries in the cache: %d, expected %d",
cache->free_space_ctl->total_bitmaps, num_bitmaps); return -EINVAL;
} return0;
}
/* Used by test_steal_space_from_bitmap_to_extent(). */ staticint check_cache_empty(struct btrfs_block_group *cache)
{
u64 offset;
u64 max_extent_size;
/* *Nowletsconfirmthatthere'sabsolutelynofreespaceleftto *allocate.
*/ if (cache->free_space_ctl->free_space != 0) {
test_err("cache free space is not 0"); return -EINVAL;
}
/* And any allocation request, no matter how small, should fail now. */
offset = btrfs_find_space_for_alloc(cache, 0, 4096, 0,
&max_extent_size); if (offset != 0) {
test_err("space allocation did not fail, returned offset: %llu",
offset); return -EINVAL;
}
/* And no extent nor bitmap entries in the cache anymore. */ return check_num_extents_and_bitmaps(cache, 0, 0);
}
/* Bitmap entry covering free space range [128Mb + 512Kb, 256Mb[ */
ret = test_add_free_space_entry(cache, SZ_128M + SZ_512K,
SZ_128M - SZ_512K, 1); if (ret) {
test_err("couldn't add bitmap entry %d", ret); return ret;
}
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Nowmakeonlythefirst256Kbofthebitmapmarkedasfree,sothat *weendupwithonlythefollowingrangesmarkedasfreespace: * *[128Mb-256Kb,128Mb-128Kb[ *[128Mb+512Kb,128Mb+768Kb[
*/
ret = btrfs_remove_free_space(cache,
SZ_128M + 768 * SZ_1K,
SZ_128M - 768 * SZ_1K); if (ret) {
test_err("failed to free part of bitmap space %d", ret); return ret;
}
/* Confirm that only those 2 ranges are marked as free. */ if (!test_check_exists(cache, SZ_128M - SZ_256K, SZ_128K)) {
test_err("free space range missing"); return -ENOENT;
} if (!test_check_exists(cache, SZ_128M + SZ_512K, SZ_256K)) {
test_err("free space range missing"); return -ENOENT;
}
/* *Confirmthatthebitmaprange[128Mb+768Kb,256Mb[isn'tmarked *asfreeanymore.
*/ if (test_check_exists(cache, SZ_128M + 768 * SZ_1K,
SZ_128M - 768 * SZ_1K)) {
test_err("bitmap region not removed from space cache"); return -EINVAL;
}
/* *Confirmthattheregion[128Mb+256Kb,128Mb+512Kb[,whichis *coveredbythebitmap,isn'tmarkedasfree.
*/ if (test_check_exists(cache, SZ_128M + SZ_256K, SZ_256K)) {
test_err("invalid bitmap region marked as free"); return -EINVAL;
}
/* *Confirmthattheregion[128Mb,128Mb+256Kb[,whichiscovered *bythebitmaptoo,isn'tmarkedasfreeeither.
*/ if (test_check_exists(cache, SZ_128M, SZ_256K)) {
test_err("invalid bitmap region marked as free"); return -EINVAL;
}
/* *Nowletsmarktheregion[128Mb,128Mb+512Kb[asfreetoo.But, *letsmakesurethefreespacecachemarksitasfreeinthebitmap, *anddoesn'tinsertanewextententrytorepresentthisregion.
*/
ret = btrfs_add_free_space(cache, SZ_128M, SZ_512K); if (ret) {
test_err("error adding free space: %d", ret); return ret;
} /* Confirm the region is marked as free. */ if (!test_check_exists(cache, SZ_128M, SZ_512K)) {
test_err("bitmap region not marked as free"); return -ENOENT;
}
/* *Confirmthatnonewextententriesorbitmapentrieswereaddedto *thecacheafteraddingthatfreespaceregion.
*/
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Confirmthatnonewextententriesorbitmapentrieswereaddedto *thecacheafteraddingthatfreespaceregion.
*/
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Nowmarktheregion[128Mb-128Kb,128Mb[asfreetoo.Thiswill *expandtherangecoveredbytheexistingextententrythatrepresents *thefreespace[128Mb-256Kb,128Mb-128Kb[.
*/
ret = btrfs_add_free_space(cache, SZ_128M - SZ_128K, SZ_128K); if (ret) {
test_err("error adding free space: %d", ret); return ret;
} /* Confirm the region is marked as free. */ if (!test_check_exists(cache, SZ_128M - SZ_128K, SZ_128K)) {
test_err("extent region not marked as free"); return -ENOENT;
}
/* *Confirmthatourextententrydidn'tstoleallfreespacefromthe *bitmap,becauseofthesmall4Kbfreespaceregion.
*/
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Sonowwehavetherange[128Mb-256Kb,128Mb+768Kb[asfree *space.Withoutstealingbitmapfreespaceintoextententryspace, *wewouldhaveallthisfreespacerepresentedby2entriesinthe *cache: * *extententrycoveringrange:[128Mb-256Kb,128Mb[ *bitmapentrycoveringrange:[128Mb,128Mb+768Kb[ * *Attemptingtoallocatethewholefreespace(1Mb)wouldfail,because *wecan'tallocatefrommultipleentries. *Withthebitmapfreespacestealing,wegetasingleextententry *thatrepresentsthe1Mbfreespace,andthereforewe'reableto *allocatethewholefreespaceatonce.
*/ if (!test_check_exists(cache, SZ_128M - SZ_256K, SZ_1M)) {
test_err("expected region not marked as free"); return -ENOENT;
}
if (cache->free_space_ctl->free_space != (SZ_1M + sectorsize)) {
test_err("cache free space is not 1Mb + %u", sectorsize); return -EINVAL;
}
offset = btrfs_find_space_for_alloc(cache, 0, SZ_1M, 0,
&max_extent_size); if (offset != (SZ_128M - SZ_256K)) {
test_err( "failed to allocate 1Mb from space cache, returned offset is: %llu",
offset); return -EINVAL;
}
/* *Allthatremainsisasectorsizefreespaceregioninabitmap. *Confirm.
*/
ret = check_num_extents_and_bitmaps(cache, 1, 1); if (ret) return ret;
if (cache->free_space_ctl->free_space != sectorsize) {
test_err("cache free space is not %u", sectorsize); return -EINVAL;
}
offset = btrfs_find_space_for_alloc(cache, 0, sectorsize, 0,
&max_extent_size); if (offset != (SZ_128M + SZ_16M)) {
test_err("failed to allocate %u, returned offset : %llu",
sectorsize, offset); return -EINVAL;
}
ret = check_cache_empty(cache); if (ret) return ret;
/* Bitmap entry covering free space range [0, 128Mb - 512Kb[ */
ret = test_add_free_space_entry(cache, 0, SZ_128M - SZ_512K, 1); if (ret) {
test_err("couldn't add bitmap entry %d", ret); return ret;
}
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Nowmakeonlythelast256Kbofthebitmapmarkedasfree,sothat *weendupwithonlythefollowingrangesmarkedasfreespace: * *[128Mb+128b,128Mb+256Kb[ *[128Mb-768Kb,128Mb-512Kb[
*/
ret = btrfs_remove_free_space(cache, 0, SZ_128M - 768 * SZ_1K); if (ret) {
test_err("failed to free part of bitmap space %d", ret); return ret;
}
/* Confirm that only those 2 ranges are marked as free. */ if (!test_check_exists(cache, SZ_128M + SZ_128K, SZ_128K)) {
test_err("free space range missing"); return -ENOENT;
} if (!test_check_exists(cache, SZ_128M - 768 * SZ_1K, SZ_256K)) {
test_err("free space range missing"); return -ENOENT;
}
/* *Confirmthatthebitmaprange[0,128Mb-768Kb[isn'tmarked *asfreeanymore.
*/ if (test_check_exists(cache, 0, SZ_128M - 768 * SZ_1K)) {
test_err("bitmap region not removed from space cache"); return -EINVAL;
}
/* *Confirmthattheregion[128Mb-512Kb,128Mb[,whichis *coveredbythebitmap,isn'tmarkedasfree.
*/ if (test_check_exists(cache, SZ_128M - SZ_512K, SZ_512K)) {
test_err("invalid bitmap region marked as free"); return -EINVAL;
}
/* *Nowletsmarktheregion[128Mb-512Kb,128Mb[asfreetoo.But, *letsmakesurethefreespacecachemarksitasfreeinthebitmap, *anddoesn'tinsertanewextententrytorepresentthisregion.
*/
ret = btrfs_add_free_space(cache, SZ_128M - SZ_512K, SZ_512K); if (ret) {
test_err("error adding free space: %d", ret); return ret;
} /* Confirm the region is marked as free. */ if (!test_check_exists(cache, SZ_128M - SZ_512K, SZ_512K)) {
test_err("bitmap region not marked as free"); return -ENOENT;
}
/* *Confirmthatnonewextententriesorbitmapentrieswereaddedto *thecacheafteraddingthatfreespaceregion.
*/
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Nowmarktheregion[128Mb,128Mb+128Kb[asfreetoo.Thiswill *expandtherangecoveredbytheexistingextententrythatrepresents *thefreespace[128Mb+128Kb,128Mb+256Kb[.
*/
ret = btrfs_add_free_space(cache, SZ_128M, SZ_128K); if (ret) {
test_err("error adding free space: %d", ret); return ret;
} /* Confirm the region is marked as free. */ if (!test_check_exists(cache, SZ_128M, SZ_128K)) {
test_err("extent region not marked as free"); return -ENOENT;
}
/* *Confirmthatourextententrydidn'tstoleallfreespacefromthe *bitmap,becauseofthesmall2*sectorsizefreespaceregion.
*/
ret = check_num_extents_and_bitmaps(cache, 2, 1); if (ret) return ret;
/* *Sonowwehavetherange[128Mb-768Kb,128Mb+256Kb[asfree *space.Withoutstealingbitmapfreespaceintoextententryspace, *wewouldhaveallthisfreespacerepresentedby2entriesinthe *cache: * *extententrycoveringrange:[128Mb,128Mb+256Kb[ *bitmapentrycoveringrange:[128Mb-768Kb,128Mb[ * *Attemptingtoallocatethewholefreespace(1Mb)wouldfail,because *wecan'tallocatefrommultipleentries. *Withthebitmapfreespacestealing,wegetasingleextententry *thatrepresentsthe1Mbfreespace,andthereforewe'reableto *allocatethewholefreespaceatonce.
*/ if (!test_check_exists(cache, SZ_128M - 768 * SZ_1K, SZ_1M)) {
test_err("expected region not marked as free"); return -ENOENT;
}
if (cache->free_space_ctl->free_space != (SZ_1M + 2 * sectorsize)) {
test_err("cache free space is not 1Mb + %u", 2 * sectorsize); return -EINVAL;
}
offset = btrfs_find_space_for_alloc(cache, 0, SZ_1M, 0,
&max_extent_size); if (offset != (SZ_128M - 768 * SZ_1K)) {
test_err( "failed to allocate 1Mb from space cache, returned offset is: %llu",
offset); return -EINVAL;
}
/* *Allthatremainsis2*sectorsizefreespaceregion *inabitmap.Confirm.
*/
ret = check_num_extents_and_bitmaps(cache, 1, 1); if (ret) return ret;
if (cache->free_space_ctl->free_space != 2 * sectorsize) {
test_err("cache free space is not %u", 2 * sectorsize); return -EINVAL;
}
/* First just validate that it does everything in order. */
offset = 0; for (i = 0; i < 10; i++) {
bytes = (i + 1) * SZ_1M;
ret = test_add_free_space_entry(cache, offset, bytes, 0); if (ret) {
test_err("couldn't add extent entry %d\n", ret); return ret;
}
offset += bytes + sectorsize;
}
for (node = rb_first_cached(&ctl->free_space_bytes), i = 9; node;
node = rb_next(node), i--) {
entry = rb_entry(node, struct btrfs_free_space, bytes_index);
bytes = (i + 1) * SZ_1M; if (entry->bytes != bytes) {
test_err("invalid bytes index order, found %llu expected %llu",
entry->bytes, bytes); return -EINVAL;
}
}
/* Now validate bitmaps do the correct thing. */
btrfs_remove_free_space_cache(cache); for (i = 0; i < 2; i++) {
offset = i * BITS_PER_BITMAP * sectorsize;
bytes = (i + 1) * SZ_1M;
ret = test_add_free_space_entry(cache, offset, bytes, 1); if (ret) {
test_err("couldn't add bitmap entry"); return ret;
}
}
for (node = rb_first_cached(&ctl->free_space_bytes), i = 1; node;
node = rb_next(node), i--) {
entry = rb_entry(node, struct btrfs_free_space, bytes_index);
bytes = (i + 1) * SZ_1M; if (entry->bytes != bytes) {
test_err("invalid bytes index order, found %llu expected %llu",
entry->bytes, bytes); return -EINVAL;
}
}
/* Now validate bitmaps with different ->max_extent_size. */
btrfs_remove_free_space_cache(cache);
orig_free_space_ops = cache->free_space_ctl->op;
cache->free_space_ctl->op = &test_free_space_ops;
ret = test_add_free_space_entry(cache, 0, sectorsize, 1); if (ret) {
test_err("couldn't add bitmap entry"); return ret;
}
offset = BITS_PER_BITMAP * sectorsize;
ret = test_add_free_space_entry(cache, offset, sectorsize, 1); if (ret) {
test_err("couldn't add bitmap_entry"); return ret;
}
/* *Nowsetabunchofsectorsizeextentsinthefirstentrysoit's *->bytesislarge.
*/ for (i = 2; i < 20; i += 2) {
offset = sectorsize * i;
ret = btrfs_add_free_space(cache, offset, sectorsize); if (ret) {
test_err("error populating sparse bitmap %d", ret); return ret;
}
}
/* *Sincewedon'tset->max_extent_sizeunlesswesearcheverything *shouldbeindexedonbytes.
*/
entry = rb_entry(rb_first_cached(&ctl->free_space_bytes), struct btrfs_free_space, bytes_index); if (entry->bytes != (10 * sectorsize)) {
test_err("error, wrong entry in the first slot in bytes_index"); return -EINVAL;
}
max_extent_size = 0;
offset = btrfs_find_space_for_alloc(cache, cache->start, sectorsize * 3, 0, &max_extent_size); if (offset != 0) {
test_err("found space to alloc even though we don't have enough space"); return -EINVAL;
}
/* *Thesearchshouldhavere-arrangedthebytesindextousethe *->max_extent_size,validateit'snowwhatweexpectittobe.
*/
entry = rb_entry(rb_first_cached(&ctl->free_space_bytes), struct btrfs_free_space, bytes_index); if (entry->bytes != (2 * sectorsize)) {
test_err("error, the bytes index wasn't recalculated properly"); return -EINVAL;
}
/* Add another sectorsize to re-arrange the tree back to ->bytes. */
offset = (BITS_PER_BITMAP * sectorsize) - sectorsize;
ret = btrfs_add_free_space(cache, offset, sectorsize); if (ret) {
test_err("error adding extent to the sparse entry %d", ret); return ret;
}
entry = rb_entry(rb_first_cached(&ctl->free_space_bytes), struct btrfs_free_space, bytes_index); if (entry->bytes != (11 * sectorsize)) {
test_err("error, wrong entry in the first slot in bytes_index"); return -EINVAL;
}
/* *Nowmakesurewefindourcorrectentryaftersearchingthatwill *resultinare-arrangingofthetree.
*/
max_extent_size = 0;
offset = btrfs_find_space_for_alloc(cache, cache->start, sectorsize * 2, 0, &max_extent_size); if (offset != (BITS_PER_BITMAP * sectorsize)) {
test_err("error, found %llu instead of %llu for our alloc",
offset,
(unsignedlonglong)(BITS_PER_BITMAP * sectorsize)); return -EINVAL;
}
ret = test_extents(cache); if (ret) goto out;
ret = test_bitmaps(cache, sectorsize); if (ret) goto out;
ret = test_bitmaps_and_extents(cache, sectorsize); if (ret) goto out;
ret = test_steal_space_from_bitmap_to_extent(cache, sectorsize); if (ret) goto out;
ret = test_bytes_index(cache, sectorsize);
out:
btrfs_free_dummy_block_group(cache);
btrfs_free_dummy_root(root);
btrfs_free_dummy_fs_info(fs_info); return ret;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-09-30)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.