2022-03-15 11:36:33 +03:00
// SPDX-License-Identifier: GPL-2.0
# include "bcachefs.h"
# include "super-io.h"
2024-01-21 07:46:35 +03:00
# include "sb-counters.h"
2022-03-15 11:36:33 +03:00
/* BCH_SB_FIELD_counters */
2023-07-07 05:47:42 +03:00
static const char * const bch2_counter_names [ ] = {
2022-03-15 11:36:33 +03:00
# define x(t, n, ...) (#t),
BCH_PERSISTENT_COUNTERS ( )
# undef x
NULL
} ;
static size_t bch2_sb_counter_nr_entries ( struct bch_sb_field_counters * ctrs )
{
if ( ! ctrs )
return 0 ;
return ( __le64 * ) vstruct_end ( & ctrs - > field ) - & ctrs - > d [ 0 ] ;
} ;
static int bch2_sb_counters_validate ( struct bch_sb * sb ,
struct bch_sb_field * f ,
struct printbuf * err )
{
return 0 ;
} ;
2023-07-07 05:47:42 +03:00
static void bch2_sb_counters_to_text ( struct printbuf * out , struct bch_sb * sb ,
2022-03-15 11:36:33 +03:00
struct bch_sb_field * f )
{
struct bch_sb_field_counters * ctrs = field_to_type ( f , counters ) ;
unsigned int nr = bch2_sb_counter_nr_entries ( ctrs ) ;
2024-04-10 23:08:24 +03:00
for ( unsigned i = 0 ; i < nr ; i + + )
prt_printf ( out , " %s \t %llu \n " ,
i < BCH_COUNTER_NR ? bch2_counter_names [ i ] : " (unknown) " ,
le64_to_cpu ( ctrs - > d [ i ] ) ) ;
2022-03-15 11:36:33 +03:00
} ;
int bch2_sb_counters_to_cpu ( struct bch_fs * c )
{
2023-09-27 00:49:34 +03:00
struct bch_sb_field_counters * ctrs = bch2_sb_field_get ( c - > disk_sb . sb , counters ) ;
2022-03-15 11:36:33 +03:00
unsigned int i ;
unsigned int nr = bch2_sb_counter_nr_entries ( ctrs ) ;
u64 val = 0 ;
for ( i = 0 ; i < BCH_COUNTER_NR ; i + + )
c - > counters_on_mount [ i ] = 0 ;
for ( i = 0 ; i < min_t ( unsigned int , nr , BCH_COUNTER_NR ) ; i + + ) {
val = le64_to_cpu ( ctrs - > d [ i ] ) ;
percpu_u64_set ( & c - > counters [ i ] , val ) ;
c - > counters_on_mount [ i ] = val ;
}
return 0 ;
} ;
int bch2_sb_counters_from_cpu ( struct bch_fs * c )
{
2023-09-27 00:49:34 +03:00
struct bch_sb_field_counters * ctrs = bch2_sb_field_get ( c - > disk_sb . sb , counters ) ;
2022-03-15 11:36:33 +03:00
struct bch_sb_field_counters * ret ;
unsigned int i ;
unsigned int nr = bch2_sb_counter_nr_entries ( ctrs ) ;
if ( nr < BCH_COUNTER_NR ) {
2023-09-27 00:49:34 +03:00
ret = bch2_sb_field_resize ( & c - > disk_sb , counters ,
2022-03-15 11:36:33 +03:00
sizeof ( * ctrs ) / sizeof ( u64 ) + BCH_COUNTER_NR ) ;
if ( ret ) {
ctrs = ret ;
nr = bch2_sb_counter_nr_entries ( ctrs ) ;
}
}
for ( i = 0 ; i < min_t ( unsigned int , nr , BCH_COUNTER_NR ) ; i + + )
ctrs - > d [ i ] = cpu_to_le64 ( percpu_u64_get ( & c - > counters [ i ] ) ) ;
return 0 ;
}
void bch2_fs_counters_exit ( struct bch_fs * c )
{
free_percpu ( c - > counters ) ;
}
int bch2_fs_counters_init ( struct bch_fs * c )
{
c - > counters = __alloc_percpu ( sizeof ( u64 ) * BCH_COUNTER_NR , sizeof ( u64 ) ) ;
if ( ! c - > counters )
2023-03-14 22:35:57 +03:00
return - BCH_ERR_ENOMEM_fs_counters_init ;
2022-03-15 11:36:33 +03:00
return bch2_sb_counters_to_cpu ( c ) ;
}
const struct bch_sb_field_ops bch_sb_field_ops_counters = {
. validate = bch2_sb_counters_validate ,
. to_text = bch2_sb_counters_to_text ,
} ;