2017-03-16 22:18:50 -08:00
// SPDX-License-Identifier: GPL-2.0
# ifdef CONFIG_BCACHEFS_TESTS
# include "bcachefs.h"
# include "btree_update.h"
# include "journal_reclaim.h"
# include "tests.h"
# include "linux/kthread.h"
# include "linux/random.h"
static void delete_test_keys ( struct bch_fs * c )
{
int ret ;
2021-02-20 19:27:37 -05:00
ret = bch2_btree_delete_range ( c , BTREE_ID_extents ,
2021-12-15 20:38:56 -05:00
SPOS ( 0 , 0 , U32_MAX ) ,
SPOS ( 0 , U64_MAX , U32_MAX ) ,
2018-08-08 19:53:30 -04:00
NULL ) ;
2017-03-16 22:18:50 -08:00
BUG_ON ( ret ) ;
2021-02-20 19:27:37 -05:00
ret = bch2_btree_delete_range ( c , BTREE_ID_xattrs ,
2021-12-15 20:38:56 -05:00
SPOS ( 0 , 0 , U32_MAX ) ,
SPOS ( 0 , U64_MAX , U32_MAX ) ,
2018-08-08 19:53:30 -04:00
NULL ) ;
2017-03-16 22:18:50 -08:00
BUG_ON ( ret ) ;
}
/* unit tests */
2020-12-01 12:23:55 -05:00
static int test_delete ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-13 20:49:16 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2017-03-16 22:18:50 -08:00
struct bkey_i_cookie k ;
int ret ;
bkey_cookie_init ( & k . k_i ) ;
2021-07-14 21:25:55 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2021-08-30 15:18:31 -04:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_xattrs , k . k . p ,
BTREE_ITER_INTENT ) ;
2017-03-16 22:18:50 -08:00
2020-02-26 15:39:46 -05:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_trans_update ( & trans , & iter , & k . k_i , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " update error in test_delete: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
pr_info ( " deleting once " ) ;
2021-06-14 16:35:03 -04:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_btree_delete_at ( & trans , & iter , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " delete error (first) in test_delete: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
pr_info ( " deleting twice " ) ;
2021-06-14 16:35:03 -04:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_btree_delete_at ( & trans , & iter , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " delete error (second) in test_delete: %i " , ret ) ;
goto err ;
}
err :
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-13 20:49:16 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int test_delete_written ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-13 20:49:16 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2017-03-16 22:18:50 -08:00
struct bkey_i_cookie k ;
int ret ;
bkey_cookie_init ( & k . k_i ) ;
2021-07-14 21:25:55 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-13 20:49:16 -04:00
2021-08-30 15:18:31 -04:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_xattrs , k . k . p ,
BTREE_ITER_INTENT ) ;
2017-03-16 22:18:50 -08:00
2020-02-26 15:39:46 -05:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_trans_update ( & trans , & iter , & k . k_i , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " update error in test_delete_written: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
2021-07-14 21:25:55 -04:00
bch2_trans_unlock ( & trans ) ;
2017-03-16 22:18:50 -08:00
bch2_journal_flush_all_pins ( & c - > journal ) ;
2021-06-14 16:35:03 -04:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_btree_delete_at ( & trans , & iter , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " delete error in test_delete_written: %i " , ret ) ;
goto err ;
}
err :
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-13 20:49:16 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int test_iterate ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter = { NULL } ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
u64 i ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-25 15:10:15 -04:00
2017-03-16 22:18:50 -08:00
delete_test_keys ( c ) ;
pr_info ( " inserting test keys " ) ;
for ( i = 0 ; i < nr ; i + + ) {
struct bkey_i_cookie k ;
bkey_cookie_init ( & k . k_i ) ;
k . k . p . offset = i ;
2021-07-14 21:25:55 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
2021-02-20 19:27:37 -05:00
ret = bch2_btree_insert ( c , BTREE_ID_xattrs , & k . k_i ,
2018-08-08 19:53:30 -04:00
NULL , NULL , 0 ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " insert error in test_iterate: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
}
pr_info ( " iterating forwards " ) ;
i = 0 ;
2021-02-20 19:27:37 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_xattrs ,
2021-12-15 20:38:56 -05:00
SPOS ( 0 , 0 , U32_MAX ) , 0 , k , ret ) {
2020-03-02 13:38:19 -05:00
if ( k . k - > p . inode )
break ;
2017-03-16 22:18:50 -08:00
BUG_ON ( k . k - > p . offset ! = i + + ) ;
2020-03-02 13:38:19 -05:00
}
2017-03-16 22:18:50 -08:00
BUG_ON ( i ! = nr ) ;
pr_info ( " iterating backwards " ) ;
2021-08-30 15:18:31 -04:00
while ( ! IS_ERR_OR_NULL ( ( k = bch2_btree_iter_prev ( & iter ) ) . k ) )
2017-03-16 22:18:50 -08:00
BUG_ON ( k . k - > p . offset ! = - - i ) ;
BUG_ON ( i ) ;
2020-12-01 12:23:55 -05:00
err :
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int test_iterate_extents ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter = { NULL } ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
u64 i ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-25 15:10:15 -04:00
2017-03-16 22:18:50 -08:00
delete_test_keys ( c ) ;
pr_info ( " inserting test extents " ) ;
for ( i = 0 ; i < nr ; i + = 8 ) {
struct bkey_i_cookie k ;
bkey_cookie_init ( & k . k_i ) ;
k . k . p . offset = i + 8 ;
2021-07-14 21:25:55 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
k . k . size = 8 ;
2021-02-20 19:27:37 -05:00
ret = bch2_btree_insert ( c , BTREE_ID_extents , & k . k_i ,
2018-08-08 19:53:30 -04:00
NULL , NULL , 0 ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " insert error in test_iterate_extents: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
}
pr_info ( " iterating forwards " ) ;
i = 0 ;
2021-02-20 19:27:37 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_extents ,
2021-12-15 20:38:56 -05:00
SPOS ( 0 , 0 , U32_MAX ) , 0 , k , ret ) {
2017-03-16 22:18:50 -08:00
BUG_ON ( bkey_start_offset ( k . k ) ! = i ) ;
i = k . k - > p . offset ;
}
BUG_ON ( i ! = nr ) ;
pr_info ( " iterating backwards " ) ;
2021-08-30 15:18:31 -04:00
while ( ! IS_ERR_OR_NULL ( ( k = bch2_btree_iter_prev ( & iter ) ) . k ) ) {
2017-03-16 22:18:50 -08:00
BUG_ON ( k . k - > p . offset ! = i ) ;
i = bkey_start_offset ( k . k ) ;
}
BUG_ON ( i ) ;
2020-12-01 12:23:55 -05:00
err :
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int test_iterate_slots ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter = { NULL } ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
u64 i ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-25 15:10:15 -04:00
2017-03-16 22:18:50 -08:00
delete_test_keys ( c ) ;
pr_info ( " inserting test keys " ) ;
for ( i = 0 ; i < nr ; i + + ) {
struct bkey_i_cookie k ;
bkey_cookie_init ( & k . k_i ) ;
k . k . p . offset = i * 2 ;
2021-07-14 21:25:55 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
2021-02-20 19:27:37 -05:00
ret = bch2_btree_insert ( c , BTREE_ID_xattrs , & k . k_i ,
2018-08-08 19:53:30 -04:00
NULL , NULL , 0 ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " insert error in test_iterate_slots: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
}
pr_info ( " iterating forwards " ) ;
i = 0 ;
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) , 0 , k , ret ) {
2020-03-02 13:38:19 -05:00
if ( k . k - > p . inode )
break ;
2017-03-16 22:18:50 -08:00
BUG_ON ( k . k - > p . offset ! = i ) ;
i + = 2 ;
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2017-03-16 22:18:50 -08:00
BUG_ON ( i ! = nr * 2 ) ;
pr_info ( " iterating forwards by slots " ) ;
i = 0 ;
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) ,
2019-04-17 15:49:28 -04:00
BTREE_ITER_SLOTS , k , ret ) {
2020-03-02 13:38:19 -05:00
BUG_ON ( k . k - > p . offset ! = i ) ;
2017-03-16 22:18:50 -08:00
BUG_ON ( bkey_deleted ( k . k ) ! = ( i & 1 ) ) ;
2020-03-02 13:38:19 -05:00
i + + ;
2017-03-16 22:18:50 -08:00
if ( i = = nr * 2 )
break ;
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2020-12-01 12:23:55 -05:00
err :
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int test_iterate_slots_extents ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter = { NULL } ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
u64 i ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-25 15:10:15 -04:00
2017-03-16 22:18:50 -08:00
delete_test_keys ( c ) ;
pr_info ( " inserting test keys " ) ;
for ( i = 0 ; i < nr ; i + = 16 ) {
struct bkey_i_cookie k ;
bkey_cookie_init ( & k . k_i ) ;
k . k . p . offset = i + 16 ;
2021-07-14 21:25:55 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
k . k . size = 8 ;
2021-02-20 19:27:37 -05:00
ret = bch2_btree_insert ( c , BTREE_ID_extents , & k . k_i ,
2018-08-08 19:53:30 -04:00
NULL , NULL , 0 ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " insert error in test_iterate_slots_extents: %i " , ret ) ;
goto err ;
}
2017-03-16 22:18:50 -08:00
}
pr_info ( " iterating forwards " ) ;
i = 0 ;
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_extents ,
SPOS ( 0 , 0 , U32_MAX ) , 0 , k , ret ) {
2017-03-16 22:18:50 -08:00
BUG_ON ( bkey_start_offset ( k . k ) ! = i + 8 ) ;
BUG_ON ( k . k - > size ! = 8 ) ;
i + = 16 ;
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2017-03-16 22:18:50 -08:00
BUG_ON ( i ! = nr ) ;
pr_info ( " iterating forwards by slots " ) ;
i = 0 ;
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_extents ,
SPOS ( 0 , 0 , U32_MAX ) ,
2019-04-17 15:49:28 -04:00
BTREE_ITER_SLOTS , k , ret ) {
2017-03-16 22:18:50 -08:00
BUG_ON ( bkey_deleted ( k . k ) ! = ! ( i % 16 ) ) ;
BUG_ON ( bkey_start_offset ( k . k ) ! = i ) ;
BUG_ON ( k . k - > size ! = 8 ) ;
i = k . k - > p . offset ;
if ( i = = nr )
break ;
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2020-12-01 12:23:55 -05:00
err :
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return 0 ;
2017-03-16 22:18:50 -08:00
}
2018-08-21 16:30:14 -04:00
/*
* XXX : we really want to make sure we ' ve got a btree with depth > 0 for these
* tests
*/
2020-12-01 12:23:55 -05:00
static int test_peek_end ( struct bch_fs * c , u64 nr )
2018-08-21 16:30:14 -04:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2018-08-21 16:30:14 -04:00
struct bkey_s_c k ;
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2021-12-15 20:38:56 -05:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) , 0 ) ;
2019-03-25 15:10:15 -04:00
2021-08-30 15:18:31 -04:00
k = bch2_btree_iter_peek ( & iter ) ;
2018-08-21 16:30:14 -04:00
BUG_ON ( k . k ) ;
2021-08-30 15:18:31 -04:00
k = bch2_btree_iter_peek ( & iter ) ;
2018-08-21 16:30:14 -04:00
BUG_ON ( k . k ) ;
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return 0 ;
2018-08-21 16:30:14 -04:00
}
2020-12-01 12:23:55 -05:00
static int test_peek_end_extents ( struct bch_fs * c , u64 nr )
2018-08-21 16:30:14 -04:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2018-08-21 16:30:14 -04:00
struct bkey_s_c k ;
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2021-12-15 20:38:56 -05:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_extents ,
SPOS ( 0 , 0 , U32_MAX ) , 0 ) ;
2019-03-25 15:10:15 -04:00
2021-08-30 15:18:31 -04:00
k = bch2_btree_iter_peek ( & iter ) ;
2018-08-21 16:30:14 -04:00
BUG_ON ( k . k ) ;
2021-08-30 15:18:31 -04:00
k = bch2_btree_iter_peek ( & iter ) ;
2018-08-21 16:30:14 -04:00
BUG_ON ( k . k ) ;
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return 0 ;
2018-08-21 16:30:14 -04:00
}
2018-08-01 23:03:41 -04:00
/* extent unit tests */
u64 test_version ;
2020-12-01 12:23:55 -05:00
static int insert_test_extent ( struct bch_fs * c ,
u64 start , u64 end )
2018-08-01 23:03:41 -04:00
{
struct bkey_i_cookie k ;
int ret ;
bkey_cookie_init ( & k . k_i ) ;
k . k_i . k . p . offset = end ;
2021-07-14 21:25:55 -04:00
k . k_i . k . p . snapshot = U32_MAX ;
2018-08-01 23:03:41 -04:00
k . k_i . k . size = end - start ;
k . k_i . k . version . lo = test_version + + ;
2021-02-20 19:27:37 -05:00
ret = bch2_btree_insert ( c , BTREE_ID_extents , & k . k_i ,
2018-08-08 19:53:30 -04:00
NULL , NULL , 0 ) ;
2020-12-01 12:23:55 -05:00
if ( ret )
bch_err ( c , " insert error in insert_test_extent: %i " , ret ) ;
return ret ;
2018-08-01 23:03:41 -04:00
}
2020-12-01 12:23:55 -05:00
static int __test_extent_overwrite ( struct bch_fs * c ,
2018-08-01 23:03:41 -04:00
u64 e1_start , u64 e1_end ,
u64 e2_start , u64 e2_end )
{
2020-12-01 12:23:55 -05:00
int ret ;
ret = insert_test_extent ( c , e1_start , e1_end ) ? :
insert_test_extent ( c , e2_start , e2_end ) ;
2018-08-01 23:03:41 -04:00
delete_test_keys ( c ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2018-08-01 23:03:41 -04:00
}
2020-12-01 12:23:55 -05:00
static int test_extent_overwrite_front ( struct bch_fs * c , u64 nr )
2018-08-01 23:03:41 -04:00
{
2020-12-01 12:23:55 -05:00
return __test_extent_overwrite ( c , 0 , 64 , 0 , 32 ) ? :
__test_extent_overwrite ( c , 8 , 64 , 0 , 32 ) ;
2018-08-01 23:03:41 -04:00
}
2020-12-01 12:23:55 -05:00
static int test_extent_overwrite_back ( struct bch_fs * c , u64 nr )
2018-08-01 23:03:41 -04:00
{
2020-12-01 12:23:55 -05:00
return __test_extent_overwrite ( c , 0 , 64 , 32 , 64 ) ? :
__test_extent_overwrite ( c , 0 , 64 , 32 , 72 ) ;
2018-08-01 23:03:41 -04:00
}
2020-12-01 12:23:55 -05:00
static int test_extent_overwrite_middle ( struct bch_fs * c , u64 nr )
2018-08-01 23:03:41 -04:00
{
2020-12-01 12:23:55 -05:00
return __test_extent_overwrite ( c , 0 , 64 , 32 , 40 ) ;
2018-08-01 23:03:41 -04:00
}
2020-12-01 12:23:55 -05:00
static int test_extent_overwrite_all ( struct bch_fs * c , u64 nr )
2018-08-01 23:03:41 -04:00
{
2020-12-01 12:23:55 -05:00
return __test_extent_overwrite ( c , 32 , 64 , 0 , 64 ) ? :
__test_extent_overwrite ( c , 32 , 64 , 0 , 128 ) ? :
__test_extent_overwrite ( c , 32 , 64 , 32 , 64 ) ? :
__test_extent_overwrite ( c , 32 , 64 , 32 , 128 ) ;
2018-08-01 23:03:41 -04:00
}
2017-03-16 22:18:50 -08:00
/* perf tests */
static u64 test_rand ( void )
{
u64 v ;
#if 0
v = prandom_u32_max ( U32_MAX ) ;
# else
get_random_bytes ( & v , sizeof ( v ) ) ;
# endif
return v ;
}
2020-12-01 12:23:55 -05:00
static int rand_insert ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2020-02-26 15:39:46 -05:00
struct btree_trans trans ;
2017-03-16 22:18:50 -08:00
struct bkey_i_cookie k ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
u64 i ;
2020-02-26 15:39:46 -05:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2017-03-16 22:18:50 -08:00
for ( i = 0 ; i < nr ; i + + ) {
bkey_cookie_init ( & k . k_i ) ;
k . k . p . offset = test_rand ( ) ;
bcachefs: Start using bpos.snapshot field
This patch starts treating the bpos.snapshot field like part of the key
in the btree code:
* bpos_successor() and bpos_predecessor() now include the snapshot field
* Keys in btrees that will be using snapshots (extents, inodes, dirents
and xattrs) now always have their snapshot field set to U32_MAX
The btree iterator code gets a new flag, BTREE_ITER_ALL_SNAPSHOTS, that
determines whether we're iterating over keys in all snapshots or not -
internally, this controlls whether bkey_(successor|predecessor)
increment/decrement the snapshot field, or only the higher bits of the
key.
We add a new member to struct btree_iter, iter->snapshot: when
BTREE_ITER_ALL_SNAPSHOTS is not set, iter->pos.snapshot should always
equal iter->snapshot, which will be 0 for btrees that don't use
snapshots, and alsways U32_MAX for btrees that will use snapshots
(until we enable snapshot creation).
This patch also introduces a new metadata version number, and compat
code for reading from/writing to older versions - this isn't a forced
upgrade (yet).
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
2021-03-24 18:02:16 -04:00
k . k . p . snapshot = U32_MAX ;
2017-03-16 22:18:50 -08:00
2020-02-26 15:39:46 -05:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-02-20 19:27:37 -05:00
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k . k_i ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " error in rand_insert: %i " , ret ) ;
break ;
}
2017-03-16 22:18:50 -08:00
}
2020-02-26 15:39:46 -05:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2021-04-14 12:10:17 -04:00
static int rand_insert_multi ( struct bch_fs * c , u64 nr )
{
struct btree_trans trans ;
struct bkey_i_cookie k [ 8 ] ;
int ret = 0 ;
unsigned j ;
u64 i ;
bch2_trans_init ( & trans , c , 0 , 0 ) ;
for ( i = 0 ; i < nr ; i + = ARRAY_SIZE ( k ) ) {
for ( j = 0 ; j < ARRAY_SIZE ( k ) ; j + + ) {
bkey_cookie_init ( & k [ j ] . k_i ) ;
k [ j ] . k . p . offset = test_rand ( ) ;
k [ j ] . k . p . snapshot = U32_MAX ;
}
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 0 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 1 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 2 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 3 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 4 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 5 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 6 ] . k_i ) ? :
__bch2_btree_insert ( & trans , BTREE_ID_xattrs , & k [ 7 ] . k_i ) ) ;
if ( ret ) {
bch_err ( c , " error in rand_insert_multi: %i " , ret ) ;
break ;
}
}
bch2_trans_exit ( & trans ) ;
return ret ;
}
2020-12-01 12:23:55 -05:00
static int rand_lookup ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2019-03-25 15:10:15 -04:00
struct bkey_s_c k ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
u64 i ;
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2021-12-15 20:38:56 -05:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) , 0 ) ;
2017-03-16 22:18:50 -08:00
2019-03-25 15:10:15 -04:00
for ( i = 0 ; i < nr ; i + + ) {
2021-12-15 20:38:56 -05:00
bch2_btree_iter_set_pos ( & iter , SPOS ( 0 , test_rand ( ) , U32_MAX ) ) ;
2017-03-16 22:18:50 -08:00
2021-08-30 15:18:31 -04:00
k = bch2_btree_iter_peek ( & iter ) ;
2020-12-01 12:23:55 -05:00
ret = bkey_err ( k ) ;
if ( ret ) {
bch_err ( c , " error in rand_lookup: %i " , ret ) ;
break ;
}
2017-03-16 22:18:50 -08:00
}
2019-03-25 15:10:15 -04:00
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2021-08-30 15:18:31 -04:00
static int rand_mixed_trans ( struct btree_trans * trans ,
struct btree_iter * iter ,
struct bkey_i_cookie * cookie ,
u64 i , u64 pos )
{
struct bkey_s_c k ;
int ret ;
2021-12-15 20:38:56 -05:00
bch2_btree_iter_set_pos ( iter , SPOS ( 0 , pos , U32_MAX ) ) ;
2021-08-30 15:18:31 -04:00
k = bch2_btree_iter_peek ( iter ) ;
ret = bkey_err ( k ) ;
if ( ret & & ret ! = - EINTR )
bch_err ( trans - > c , " lookup error in rand_mixed: %i " , ret ) ;
if ( ret )
return ret ;
if ( ! ( i & 3 ) & & k . k ) {
bkey_cookie_init ( & cookie - > k_i ) ;
cookie - > k . p = iter - > pos ;
bch2_trans_update ( trans , iter , & cookie - > k_i , 0 ) ;
}
return 0 ;
}
2020-12-01 12:23:55 -05:00
static int rand_mixed ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
struct bkey_i_cookie cookie ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2021-08-30 15:18:31 -04:00
u64 i , rand ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2021-12-15 20:38:56 -05:00
bch2_trans_iter_init ( & trans , & iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) , 0 ) ;
2017-03-16 22:18:50 -08:00
2019-03-25 15:10:15 -04:00
for ( i = 0 ; i < nr ; i + + ) {
2021-08-30 15:18:31 -04:00
rand = test_rand ( ) ;
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
rand_mixed_trans ( & trans , & iter , & cookie , i , rand ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
2021-08-30 15:18:31 -04:00
bch_err ( c , " update error in rand_mixed: %i " , ret ) ;
2020-12-01 12:23:55 -05:00
break ;
}
2017-03-16 22:18:50 -08:00
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-02-26 15:39:46 -05:00
static int __do_delete ( struct btree_trans * trans , struct bpos pos )
{
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2020-02-26 15:39:46 -05:00
struct bkey_s_c k ;
int ret = 0 ;
2021-08-30 15:18:31 -04:00
bch2_trans_iter_init ( trans , & iter , BTREE_ID_xattrs , pos ,
BTREE_ITER_INTENT ) ;
k = bch2_btree_iter_peek ( & iter ) ;
2020-02-26 15:39:46 -05:00
ret = bkey_err ( k ) ;
if ( ret )
goto err ;
2020-12-07 11:44:12 -05:00
if ( ! k . k )
goto err ;
2021-12-15 20:38:56 -05:00
ret = bch2_btree_delete_at ( trans , & iter , 0 ) ;
2020-02-26 15:39:46 -05:00
err :
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( trans , & iter ) ;
2020-02-26 15:39:46 -05:00
return ret ;
}
2020-12-01 12:23:55 -05:00
static int rand_delete ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2020-02-26 15:39:46 -05:00
struct btree_trans trans ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
u64 i ;
2020-02-26 15:39:46 -05:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2017-03-16 22:18:50 -08:00
for ( i = 0 ; i < nr ; i + + ) {
2021-12-15 20:38:56 -05:00
struct bpos pos = SPOS ( 0 , test_rand ( ) , U32_MAX ) ;
2017-03-16 22:18:50 -08:00
2020-02-26 15:39:46 -05:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
__do_delete ( & trans , pos ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " error in rand_delete: %i " , ret ) ;
break ;
}
2017-03-16 22:18:50 -08:00
}
2020-02-26 15:39:46 -05:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int seq_insert ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-13 20:49:16 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
struct bkey_i_cookie insert ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
u64 i = 0 ;
bkey_cookie_init ( & insert . k_i ) ;
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-13 20:49:16 -04:00
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_xattrs , SPOS ( 0 , 0 , U32_MAX ) ,
2019-04-17 15:49:28 -04:00
BTREE_ITER_SLOTS | BTREE_ITER_INTENT , k , ret ) {
2021-08-30 15:18:31 -04:00
insert . k . p = iter . pos ;
2017-03-16 22:18:50 -08:00
2020-02-26 15:39:46 -05:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_trans_update ( & trans , & iter , & insert . k_i , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " error in seq_insert: %i " , ret ) ;
break ;
}
2017-03-16 22:18:50 -08:00
if ( + + i = = nr )
break ;
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2021-03-19 20:29:11 -04:00
2019-03-13 20:49:16 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int seq_lookup ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-25 15:10:15 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-25 15:10:15 -04:00
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) , 0 , k , ret )
2017-03-16 22:18:50 -08:00
;
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2021-03-19 20:29:11 -04:00
2019-03-25 15:10:15 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int seq_overwrite ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
2019-03-13 20:49:16 -04:00
struct btree_trans trans ;
2021-08-30 15:18:31 -04:00
struct btree_iter iter ;
2017-03-16 22:18:50 -08:00
struct bkey_s_c k ;
2020-12-01 12:23:55 -05:00
int ret = 0 ;
2017-03-16 22:18:50 -08:00
2019-05-15 10:54:43 -04:00
bch2_trans_init ( & trans , c , 0 , 0 ) ;
2019-03-13 20:49:16 -04:00
2021-12-15 20:38:56 -05:00
for_each_btree_key ( & trans , iter , BTREE_ID_xattrs ,
SPOS ( 0 , 0 , U32_MAX ) ,
2019-04-17 15:49:28 -04:00
BTREE_ITER_INTENT , k , ret ) {
2017-03-16 22:18:50 -08:00
struct bkey_i_cookie u ;
bkey_reassemble ( & u . k_i , k ) ;
2020-02-26 15:39:46 -05:00
ret = __bch2_trans_do ( & trans , NULL , NULL , 0 ,
2021-08-30 15:18:31 -04:00
bch2_btree_iter_traverse ( & iter ) ? :
bch2_trans_update ( & trans , & iter , & u . k_i , 0 ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret ) {
bch_err ( c , " error in seq_overwrite: %i " , ret ) ;
break ;
}
2017-03-16 22:18:50 -08:00
}
2021-08-30 15:18:31 -04:00
bch2_trans_iter_exit ( & trans , & iter ) ;
2021-03-19 20:29:11 -04:00
2019-03-13 20:49:16 -04:00
bch2_trans_exit ( & trans ) ;
2020-12-01 12:23:55 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
static int seq_delete ( struct bch_fs * c , u64 nr )
2017-03-16 22:18:50 -08:00
{
int ret ;
2021-02-20 19:27:37 -05:00
ret = bch2_btree_delete_range ( c , BTREE_ID_xattrs ,
2021-12-15 20:38:56 -05:00
SPOS ( 0 , 0 , U32_MAX ) , POS_MAX , NULL ) ;
2020-12-01 12:23:55 -05:00
if ( ret )
bch_err ( c , " error in seq_delete: %i " , ret ) ;
return ret ;
2017-03-16 22:18:50 -08:00
}
2020-12-01 12:23:55 -05:00
typedef int ( * perf_test_fn ) ( struct bch_fs * , u64 ) ;
2017-03-16 22:18:50 -08:00
struct test_job {
struct bch_fs * c ;
u64 nr ;
unsigned nr_threads ;
perf_test_fn fn ;
atomic_t ready ;
wait_queue_head_t ready_wait ;
atomic_t done ;
struct completion done_completion ;
u64 start ;
u64 finish ;
2020-12-01 12:23:55 -05:00
int ret ;
2017-03-16 22:18:50 -08:00
} ;
static int btree_perf_test_thread ( void * data )
{
struct test_job * j = data ;
2020-12-01 12:23:55 -05:00
int ret ;
2017-03-16 22:18:50 -08:00
if ( atomic_dec_and_test ( & j - > ready ) ) {
wake_up ( & j - > ready_wait ) ;
j - > start = sched_clock ( ) ;
} else {
wait_event ( j - > ready_wait , ! atomic_read ( & j - > ready ) ) ;
}
2021-08-17 17:14:26 -06:00
ret = j - > fn ( j - > c , div64_u64 ( j - > nr , j - > nr_threads ) ) ;
2020-12-01 12:23:55 -05:00
if ( ret )
j - > ret = ret ;
2017-03-16 22:18:50 -08:00
if ( atomic_dec_and_test ( & j - > done ) ) {
j - > finish = sched_clock ( ) ;
complete ( & j - > done_completion ) ;
}
return 0 ;
}
2020-12-01 12:23:55 -05:00
int bch2_btree_perf_test ( struct bch_fs * c , const char * testname ,
u64 nr , unsigned nr_threads )
2017-03-16 22:18:50 -08:00
{
struct test_job j = { . c = c , . nr = nr , . nr_threads = nr_threads } ;
char name_buf [ 20 ] , nr_buf [ 20 ] , per_sec_buf [ 20 ] ;
unsigned i ;
u64 time ;
atomic_set ( & j . ready , nr_threads ) ;
init_waitqueue_head ( & j . ready_wait ) ;
atomic_set ( & j . done , nr_threads ) ;
init_completion ( & j . done_completion ) ;
# define perf_test(_test) \
if ( ! strcmp ( testname , # _test ) ) j . fn = _test
perf_test ( rand_insert ) ;
2021-04-14 12:10:17 -04:00
perf_test ( rand_insert_multi ) ;
2017-03-16 22:18:50 -08:00
perf_test ( rand_lookup ) ;
perf_test ( rand_mixed ) ;
perf_test ( rand_delete ) ;
perf_test ( seq_insert ) ;
perf_test ( seq_lookup ) ;
perf_test ( seq_overwrite ) ;
perf_test ( seq_delete ) ;
/* a unit test, not a perf test: */
perf_test ( test_delete ) ;
perf_test ( test_delete_written ) ;
perf_test ( test_iterate ) ;
perf_test ( test_iterate_extents ) ;
perf_test ( test_iterate_slots ) ;
perf_test ( test_iterate_slots_extents ) ;
2018-08-21 16:30:14 -04:00
perf_test ( test_peek_end ) ;
perf_test ( test_peek_end_extents ) ;
2017-03-16 22:18:50 -08:00
2018-08-01 23:03:41 -04:00
perf_test ( test_extent_overwrite_front ) ;
perf_test ( test_extent_overwrite_back ) ;
perf_test ( test_extent_overwrite_middle ) ;
perf_test ( test_extent_overwrite_all ) ;
2017-03-16 22:18:50 -08:00
if ( ! j . fn ) {
pr_err ( " unknown test %s " , testname ) ;
2020-12-01 12:23:55 -05:00
return - EINVAL ;
2017-03-16 22:18:50 -08:00
}
//pr_info("running test %s:", testname);
if ( nr_threads = = 1 )
btree_perf_test_thread ( & j ) ;
else
for ( i = 0 ; i < nr_threads ; i + + )
kthread_run ( btree_perf_test_thread , & j ,
" bcachefs perf test[%u] " , i ) ;
while ( wait_for_completion_interruptible ( & j . done_completion ) )
;
time = j . finish - j . start ;
scnprintf ( name_buf , sizeof ( name_buf ) , " %s: " , testname ) ;
2018-12-19 12:58:56 -05:00
bch2_hprint ( & PBUF ( nr_buf ) , nr ) ;
2021-08-17 17:14:26 -06:00
bch2_hprint ( & PBUF ( per_sec_buf ) , div64_u64 ( nr * NSEC_PER_SEC , time ) ) ;
2017-03-16 22:18:50 -08:00
printk ( KERN_INFO " %-12s %s with %u threads in %5llu sec, %5llu nsec per iter, %5s per sec \n " ,
name_buf , nr_buf , nr_threads ,
2021-08-17 17:14:26 -06:00
div_u64 ( time , NSEC_PER_SEC ) ,
div_u64 ( time * nr_threads , nr ) ,
2017-03-16 22:18:50 -08:00
per_sec_buf ) ;
2020-12-01 12:23:55 -05:00
return j . ret ;
2017-03-16 22:18:50 -08:00
}
# endif /* CONFIG_BCACHEFS_TESTS */