2018-04-03 19:23:33 +02:00
// SPDX-License-Identifier: GPL-2.0
2015-09-29 20:50:36 -07:00
/*
* Copyright ( C ) 2015 Facebook . All rights reserved .
*/
2016-06-01 19:18:25 +08:00
# include <linux/types.h>
2015-09-29 20:50:36 -07:00
# include "btrfs-tests.h"
# include "../ctree.h"
# include "../disk-io.h"
# include "../free-space-tree.h"
# include "../transaction.h"
2019-06-20 15:37:44 -04:00
# include "../block-group.h"
2015-09-29 20:50:36 -07:00
struct free_space_extent {
2016-09-23 13:57:06 +02:00
u64 start ;
u64 length ;
2015-09-29 20:50:36 -07:00
} ;
static int __check_free_space_extents ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2015-09-29 20:50:36 -07:00
struct btrfs_path * path ,
2016-09-23 13:54:09 +02:00
const struct free_space_extent * const extents ,
2015-09-29 20:50:36 -07:00
unsigned int num_extents )
{
struct btrfs_free_space_info * info ;
struct btrfs_key key ;
int prev_bit = 0 , bit ;
u64 extent_start = 0 , offset , end ;
u32 flags , extent_count ;
unsigned int i ;
int ret ;
2019-03-20 14:11:21 +01:00
info = search_free_space_info ( trans , cache , path , 0 ) ;
2015-09-29 20:50:36 -07:00
if ( IS_ERR ( info ) ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not find free space info " ) ;
2015-09-29 20:50:36 -07:00
ret = PTR_ERR ( info ) ;
goto out ;
}
flags = btrfs_free_space_flags ( path - > nodes [ 0 ] , info ) ;
extent_count = btrfs_free_space_extent_count ( path - > nodes [ 0 ] , info ) ;
if ( extent_count ! = num_extents ) {
2018-05-17 00:00:42 +02:00
test_err ( " extent count is wrong " ) ;
2015-09-29 20:50:36 -07:00
ret = - EINVAL ;
goto out ;
}
if ( flags & BTRFS_FREE_SPACE_USING_BITMAPS ) {
if ( path - > slots [ 0 ] ! = 0 )
goto invalid ;
2019-10-23 18:48:22 +02:00
end = cache - > start + cache - > length ;
2015-09-29 20:50:36 -07:00
i = 0 ;
while ( + + path - > slots [ 0 ] < btrfs_header_nritems ( path - > nodes [ 0 ] ) ) {
btrfs_item_key_to_cpu ( path - > nodes [ 0 ] , & key , path - > slots [ 0 ] ) ;
if ( key . type ! = BTRFS_FREE_SPACE_BITMAP_KEY )
goto invalid ;
offset = key . objectid ;
while ( offset < key . objectid + key . offset ) {
bit = free_space_test_bit ( cache , path , offset ) ;
if ( prev_bit = = 0 & & bit = = 1 ) {
extent_start = offset ;
} else if ( prev_bit = = 1 & & bit = = 0 ) {
if ( i > = num_extents | |
extent_start ! = extents [ i ] . start | |
offset - extent_start ! = extents [ i ] . length )
goto invalid ;
i + + ;
}
prev_bit = bit ;
btrfs: remove unused sectorsize member
The sectorsize member of btrfs_block_group_cache is unused. So remove it, this
reduces the number of holes in the struct.
With patch:
/* size: 856, cachelines: 14, members: 40 */
/* sum members: 837, holes: 4, sum holes: 19 */
/* bit holes: 1, sum bit holes: 29 bits */
/* last cacheline: 24 bytes */
Without patch:
/* size: 864, cachelines: 14, members: 41 */
/* sum members: 841, holes: 5, sum holes: 23 */
/* bit holes: 1, sum bit holes: 29 bits */
/* last cacheline: 32 bytes */
Signed-off-by: Nikolay Borisov <nborisov@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
2017-06-28 11:05:22 +03:00
offset + = fs_info - > sectorsize ;
2015-09-29 20:50:36 -07:00
}
}
if ( prev_bit = = 1 ) {
if ( i > = num_extents | |
extent_start ! = extents [ i ] . start | |
end - extent_start ! = extents [ i ] . length )
goto invalid ;
i + + ;
}
if ( i ! = num_extents )
goto invalid ;
} else {
if ( btrfs_header_nritems ( path - > nodes [ 0 ] ) ! = num_extents + 1 | |
path - > slots [ 0 ] ! = 0 )
goto invalid ;
for ( i = 0 ; i < num_extents ; i + + ) {
path - > slots [ 0 ] + + ;
btrfs_item_key_to_cpu ( path - > nodes [ 0 ] , & key , path - > slots [ 0 ] ) ;
if ( key . type ! = BTRFS_FREE_SPACE_EXTENT_KEY | |
key . objectid ! = extents [ i ] . start | |
key . offset ! = extents [ i ] . length )
goto invalid ;
}
}
ret = 0 ;
out :
btrfs_release_path ( path ) ;
return ret ;
invalid :
2018-05-17 00:00:42 +02:00
test_err ( " free space tree is invalid " ) ;
2015-09-29 20:50:36 -07:00
ret = - EINVAL ;
goto out ;
}
static int check_free_space_extents ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2015-09-29 20:50:36 -07:00
struct btrfs_path * path ,
2016-09-23 13:54:09 +02:00
const struct free_space_extent * const extents ,
2015-09-29 20:50:36 -07:00
unsigned int num_extents )
{
struct btrfs_free_space_info * info ;
u32 flags ;
int ret ;
2019-03-20 14:11:21 +01:00
info = search_free_space_info ( trans , cache , path , 0 ) ;
2015-09-29 20:50:36 -07:00
if ( IS_ERR ( info ) ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not find free space info " ) ;
2015-09-29 20:50:36 -07:00
btrfs_release_path ( path ) ;
return PTR_ERR ( info ) ;
}
flags = btrfs_free_space_flags ( path - > nodes [ 0 ] , info ) ;
btrfs_release_path ( path ) ;
ret = __check_free_space_extents ( trans , fs_info , cache , path , extents ,
num_extents ) ;
if ( ret )
return ret ;
/* Flip it to the other format and check that for good measure. */
if ( flags & BTRFS_FREE_SPACE_USING_BITMAPS ) {
2018-05-10 15:44:48 +03:00
ret = convert_free_space_to_extents ( trans , cache , path ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not convert to extents " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
} else {
2018-05-10 15:44:47 +03:00
ret = convert_free_space_to_bitmaps ( trans , cache , path ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not convert to bitmaps " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
}
return __check_free_space_extents ( trans , fs_info , cache , path , extents ,
num_extents ) ;
}
static int test_empty_block_group ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start , cache - > length } ,
2015-09-29 20:50:36 -07:00
} ;
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_remove_all ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = { } ;
2015-09-29 20:50:36 -07:00
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start ,
cache - > length ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_remove_beginning ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start + alignment , cache - > length - alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start , alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_remove_end ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start , cache - > length - alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + cache - > length - alignment ,
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_remove_middle ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start , alignment } ,
{ cache - > start + 2 * alignment , cache - > length - 2 * alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + alignment ,
2016-09-22 17:24:24 -07:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_merge_left ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start , 2 * alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start , cache - > length ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2019-10-23 18:48:22 +02:00
ret = __add_to_free_space_tree ( trans , cache , path , cache - > start ,
2018-05-10 15:44:43 +03:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + alignment ,
2016-09-22 17:24:24 -07:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_merge_right ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start + alignment , 2 * alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start , cache - > length ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + 2 * alignment ,
2016-09-22 17:24:24 -07:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + alignment ,
2016-09-22 17:24:24 -07:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_merge_both ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start , 3 * alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start , cache - > length ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2019-10-23 18:48:22 +02:00
ret = __add_to_free_space_tree ( trans , cache , path , cache - > start ,
2018-05-10 15:44:43 +03:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + 2 * alignment , alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + alignment , alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
static int test_merge_none ( struct btrfs_trans_handle * trans ,
struct btrfs_fs_info * fs_info ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * path ,
u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-23 13:54:09 +02:00
const struct free_space_extent extents [ ] = {
2019-10-23 18:48:22 +02:00
{ cache - > start , alignment } ,
{ cache - > start + 2 * alignment , alignment } ,
{ cache - > start + 4 * alignment , alignment } ,
2015-09-29 20:50:36 -07:00
} ;
int ret ;
2018-05-10 15:44:53 +03:00
ret = __remove_from_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start , cache - > length ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2019-10-23 18:48:22 +02:00
ret = __add_to_free_space_tree ( trans , cache , path , cache - > start ,
2018-05-10 15:44:43 +03:00
alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + 4 * alignment , alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2018-05-10 15:44:43 +03:00
ret = __add_to_free_space_tree ( trans , cache , path ,
2019-10-23 18:48:22 +02:00
cache - > start + 2 * alignment , alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add free space " ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
return check_free_space_extents ( trans , fs_info , cache , path ,
extents , ARRAY_SIZE ( extents ) ) ;
}
typedef int ( * test_func_t ) ( struct btrfs_trans_handle * ,
struct btrfs_fs_info * ,
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * ,
2016-09-22 17:24:24 -07:00
struct btrfs_path * ,
u32 alignment ) ;
2015-09-29 20:50:36 -07:00
2016-09-22 17:24:24 -07:00
static int run_test ( test_func_t test_func , int bitmaps , u32 sectorsize ,
u32 nodesize , u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-06-20 14:14:09 -04:00
struct btrfs_fs_info * fs_info ;
2015-09-29 20:50:36 -07:00
struct btrfs_root * root = NULL ;
2019-10-29 19:20:18 +01:00
struct btrfs_block_group * cache = NULL ;
2015-09-29 20:50:36 -07:00
struct btrfs_trans_handle trans ;
struct btrfs_path * path = NULL ;
int ret ;
2016-06-15 09:22:56 -04:00
fs_info = btrfs_alloc_dummy_fs_info ( nodesize , sectorsize ) ;
2016-06-20 14:14:09 -04:00
if ( ! fs_info ) {
2019-03-15 17:28:46 +01:00
test_std_err ( TEST_ALLOC_FS_INFO ) ;
2016-06-20 14:14:09 -04:00
ret = - ENOMEM ;
2015-09-29 20:50:36 -07:00
goto out ;
}
2016-06-15 09:22:56 -04:00
root = btrfs_alloc_dummy_root ( fs_info ) ;
2016-06-20 14:14:09 -04:00
if ( IS_ERR ( root ) ) {
2019-03-15 17:28:46 +01:00
test_std_err ( TEST_ALLOC_ROOT ) ;
2016-06-20 14:14:09 -04:00
ret = PTR_ERR ( root ) ;
2015-09-29 20:50:36 -07:00
goto out ;
}
btrfs_set_super_compat_ro_flags ( root - > fs_info - > super_copy ,
BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE ) ;
root - > fs_info - > free_space_root = root ;
root - > fs_info - > tree_root = root ;
2016-06-15 09:22:56 -04:00
root - > node = alloc_test_extent_buffer ( root - > fs_info , nodesize ) ;
2019-12-03 14:24:58 +03:00
if ( IS_ERR ( root - > node ) ) {
2019-03-15 17:28:46 +01:00
test_std_err ( TEST_ALLOC_EXTENT_BUFFER ) ;
2019-12-03 14:24:58 +03:00
ret = PTR_ERR ( root - > node ) ;
2015-09-29 20:50:36 -07:00
goto out ;
}
btrfs_set_header_level ( root - > node , 0 ) ;
btrfs_set_header_nritems ( root - > node , 0 ) ;
2016-06-01 19:18:25 +08:00
root - > alloc_bytenr + = 2 * nodesize ;
2015-09-29 20:50:36 -07:00
2016-06-15 09:22:56 -04:00
cache = btrfs_alloc_dummy_block_group ( fs_info , 8 * alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ! cache ) {
2019-03-15 17:28:46 +01:00
test_std_err ( TEST_ALLOC_BLOCK_GROUP ) ;
2015-09-29 20:50:36 -07:00
ret = - ENOMEM ;
goto out ;
}
cache - > bitmap_low_thresh = 0 ;
cache - > bitmap_high_thresh = ( u32 ) - 1 ;
cache - > needs_free_space = 1 ;
2016-01-29 21:36:00 +08:00
cache - > fs_info = root - > fs_info ;
2015-09-29 20:50:36 -07:00
2018-05-10 15:44:40 +03:00
btrfs_init_dummy_trans ( & trans , root - > fs_info ) ;
2015-09-29 20:50:36 -07:00
path = btrfs_alloc_path ( ) ;
if ( ! path ) {
2019-03-15 17:28:46 +01:00
test_std_err ( TEST_ALLOC_ROOT ) ;
2017-09-10 13:19:38 +02:00
ret = - ENOMEM ;
goto out ;
2015-09-29 20:50:36 -07:00
}
2018-05-10 15:44:41 +03:00
ret = add_block_group_free_space ( & trans , cache ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not add block group free space " ) ;
2015-09-29 20:50:36 -07:00
goto out ;
}
if ( bitmaps ) {
2018-05-10 15:44:47 +03:00
ret = convert_free_space_to_bitmaps ( & trans , cache , path ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not convert block group to bitmaps " ) ;
2015-09-29 20:50:36 -07:00
goto out ;
}
}
2016-09-22 17:24:24 -07:00
ret = test_func ( & trans , root - > fs_info , cache , path , alignment ) ;
2015-09-29 20:50:36 -07:00
if ( ret )
goto out ;
2018-05-10 15:44:46 +03:00
ret = remove_block_group_free_space ( & trans , cache ) ;
2015-09-29 20:50:36 -07:00
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err ( " could not remove block group free space " ) ;
2015-09-29 20:50:36 -07:00
goto out ;
}
if ( btrfs_header_nritems ( root - > node ) ! = 0 ) {
2018-05-17 00:00:42 +02:00
test_err ( " free space tree has leftover items " ) ;
2015-09-29 20:50:36 -07:00
ret = - EINVAL ;
goto out ;
}
ret = 0 ;
out :
btrfs_free_path ( path ) ;
btrfs_free_dummy_block_group ( cache ) ;
btrfs_free_dummy_root ( root ) ;
2016-06-20 14:14:09 -04:00
btrfs_free_dummy_fs_info ( fs_info ) ;
2015-09-29 20:50:36 -07:00
return ret ;
}
2016-09-22 17:24:24 -07:00
static int run_test_both_formats ( test_func_t test_func , u32 sectorsize ,
u32 nodesize , u32 alignment )
2015-09-29 20:50:36 -07:00
{
2016-09-22 17:24:24 -07:00
int test_ret = 0 ;
2015-09-29 20:50:36 -07:00
int ret ;
2016-09-22 17:24:24 -07:00
ret = run_test ( test_func , 0 , sectorsize , nodesize , alignment ) ;
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err (
2019-03-25 21:32:28 +02:00
" %ps failed with extents, sectorsize=%u, nodesize=%u, alignment=%u " ,
2016-09-22 17:24:24 -07:00
test_func , sectorsize , nodesize , alignment ) ;
test_ret = ret ;
}
ret = run_test ( test_func , 1 , sectorsize , nodesize , alignment ) ;
if ( ret ) {
2018-05-17 00:00:42 +02:00
test_err (
2019-03-25 21:32:28 +02:00
" %ps failed with bitmaps, sectorsize=%u, nodesize=%u, alignment=%u " ,
2016-09-22 17:24:24 -07:00
test_func , sectorsize , nodesize , alignment ) ;
test_ret = ret ;
}
return test_ret ;
2015-09-29 20:50:36 -07:00
}
2016-06-01 19:18:25 +08:00
int btrfs_test_free_space_tree ( u32 sectorsize , u32 nodesize )
2015-09-29 20:50:36 -07:00
{
test_func_t tests [ ] = {
test_empty_block_group ,
test_remove_all ,
test_remove_beginning ,
test_remove_end ,
test_remove_middle ,
test_merge_left ,
test_merge_right ,
test_merge_both ,
test_merge_none ,
} ;
2016-09-22 17:24:24 -07:00
u32 bitmap_alignment ;
int test_ret = 0 ;
2015-09-29 20:50:36 -07:00
int i ;
2016-09-22 17:24:24 -07:00
/*
* Align some operations to a page to flush out bugs in the extent
* buffer bitmap handling of highmem .
*/
bitmap_alignment = BTRFS_FREE_SPACE_BITMAP_BITS * PAGE_SIZE ;
2018-05-17 00:00:44 +02:00
test_msg ( " running free space tree tests " ) ;
2015-09-29 20:50:36 -07:00
for ( i = 0 ; i < ARRAY_SIZE ( tests ) ; i + + ) {
2016-09-22 17:24:24 -07:00
int ret ;
ret = run_test_both_formats ( tests [ i ] , sectorsize , nodesize ,
sectorsize ) ;
if ( ret )
test_ret = ret ;
ret = run_test_both_formats ( tests [ i ] , sectorsize , nodesize ,
bitmap_alignment ) ;
if ( ret )
test_ret = ret ;
2015-09-29 20:50:36 -07:00
}
2016-09-22 17:24:24 -07:00
return test_ret ;
2015-09-29 20:50:36 -07:00
}