mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 20:22:08 +02:00
btrfs: add self test for bytes_index free space cache
I noticed a few corner cases when looking at my bytes_index patch for obvious bugs, so add a bunch of tests to validate proper behavior of the bytes_index tree. A couple of basic tests to make sure it puts things in the correct order, and then more complicated tests to make sure it re-arranges bitmap entries properly and does the right thing when we try to make allocations. Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
59c7b566a3
commit
bbf27275f2
|
|
@ -824,6 +824,184 @@ test_steal_space_from_bitmap_to_extent(struct btrfs_block_group *cache,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool bytes_index_use_bitmap(struct btrfs_free_space_ctl *ctl,
|
||||
struct btrfs_free_space *info)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int test_bytes_index(struct btrfs_block_group *cache, u32 sectorsize)
|
||||
{
|
||||
const struct btrfs_free_space_op test_free_space_ops = {
|
||||
.use_bitmap = bytes_index_use_bitmap,
|
||||
};
|
||||
const struct btrfs_free_space_op *orig_free_space_ops;
|
||||
struct btrfs_free_space_ctl *ctl = cache->free_space_ctl;
|
||||
struct btrfs_free_space *entry;
|
||||
struct rb_node *node;
|
||||
u64 offset, max_extent_size, bytes;
|
||||
int ret, i;
|
||||
|
||||
test_msg("running bytes index tests");
|
||||
|
||||
/* 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->free_space_ctl);
|
||||
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->free_space_ctl);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now set a bunch of sectorsize extents in the first entry so it's
|
||||
* ->bytes is large.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now set a contiguous extent in the second bitmap so its
|
||||
* ->max_extent_size is larger than the first bitmaps.
|
||||
*/
|
||||
offset = (BITS_PER_BITMAP * sectorsize) + sectorsize;
|
||||
ret = btrfs_add_free_space(cache, offset, sectorsize);
|
||||
if (ret) {
|
||||
test_err("error adding contiguous extent %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we don't set ->max_extent_size unless we search everything
|
||||
* should be indexed on bytes.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (max_extent_size != (2 * sectorsize)) {
|
||||
test_err("got the wrong max_extent size %llu expected %llu",
|
||||
max_extent_size, (unsigned long long)(2 * sectorsize));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* The search should have re-arranged the bytes index to use the
|
||||
* ->max_extent_size, validate it's now what we expect it to be.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now make sure we find our correct entry after searching that will
|
||||
* result in a re-arranging of the tree.
|
||||
*/
|
||||
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,
|
||||
(unsigned long long)(BITS_PER_BITMAP * sectorsize));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cache->free_space_ctl->op = orig_free_space_ops;
|
||||
__btrfs_remove_free_space_cache(cache->free_space_ctl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info;
|
||||
|
|
@ -871,6 +1049,9 @@ int btrfs_test_free_space_cache(u32 sectorsize, u32 nodesize)
|
|||
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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user