2017-03-16 22:18:50 -08:00
// SPDX-License-Identifier: GPL-2.0
# include <linux/kernel.h>
# include "bcachefs.h"
2018-11-12 18:30:55 -05:00
# include "compress.h"
2017-03-16 22:18:50 -08:00
# include "disk_groups.h"
2023-07-11 23:47:29 -04:00
# include "error.h"
2017-03-16 22:18:50 -08:00
# include "opts.h"
2024-03-28 21:34:14 -04:00
# include "recovery_passes.h"
2017-03-16 22:18:50 -08:00
# include "super-io.h"
# include "util.h"
2023-07-21 05:38:45 -04:00
# define x(t, n, ...) [n] = #t,
2022-03-20 23:34:11 -04:00
2017-03-16 22:18:50 -08:00
const char * const bch2_error_actions [ ] = {
2021-02-20 19:47:58 -05:00
BCH_ERROR_ACTIONS ( )
2017-03-16 22:18:50 -08:00
NULL
} ;
2023-07-11 23:47:29 -04:00
const char * const bch2_fsck_fix_opts [ ] = {
BCH_FIX_ERRORS_OPTS ( )
NULL
} ;
2023-06-27 23:34:02 -04:00
const char * const bch2_version_upgrade_opts [ ] = {
BCH_VERSION_UPGRADE_OPTS ( )
NULL
} ;
2019-12-28 20:17:06 -05:00
const char * const bch2_sb_features [ ] = {
BCH_SB_FEATURES ( )
NULL
} ;
2021-04-04 21:57:35 -04:00
const char * const bch2_sb_compat [ ] = {
BCH_SB_COMPAT ( )
NULL
} ;
2023-10-19 22:49:08 -04:00
const char * const __bch2_btree_ids [ ] = {
2021-02-20 19:27:37 -05:00
BCH_BTREE_IDS ( )
NULL
} ;
2024-04-12 15:17:00 -04:00
static const char * const __bch2_csum_types [ ] = {
2021-11-11 12:11:33 -05:00
BCH_CSUM_TYPES ( )
NULL
} ;
2019-12-28 20:17:06 -05:00
const char * const bch2_csum_opts [ ] = {
2021-02-20 19:47:58 -05:00
BCH_CSUM_OPTS ( )
2017-03-16 22:18:50 -08:00
NULL
} ;
2024-04-12 15:17:00 -04:00
static const char * const __bch2_compression_types [ ] = {
2021-11-11 12:11:33 -05:00
BCH_COMPRESSION_TYPES ( )
NULL
} ;
2019-12-28 20:17:06 -05:00
const char * const bch2_compression_opts [ ] = {
BCH_COMPRESSION_OPTS ( )
2017-03-16 22:18:50 -08:00
NULL
} ;
const char * const bch2_str_hash_types [ ] = {
2021-11-11 12:11:33 -05:00
BCH_STR_HASH_TYPES ( )
NULL
} ;
const char * const bch2_str_hash_opts [ ] = {
2021-02-20 19:47:58 -05:00
BCH_STR_HASH_OPTS ( )
2017-03-16 22:18:50 -08:00
NULL
} ;
2024-01-06 20:57:43 -05:00
const char * const __bch2_data_types [ ] = {
2020-07-09 18:28:11 -04:00
BCH_DATA_TYPES ( )
2017-03-16 22:18:50 -08:00
NULL
} ;
2021-02-20 19:47:58 -05:00
const char * const bch2_member_states [ ] = {
BCH_MEMBER_STATES ( )
2017-03-16 22:18:50 -08:00
NULL
} ;
2024-04-12 15:17:00 -04:00
static const char * const __bch2_jset_entry_types [ ] = {
2021-12-31 17:06:29 -05:00
BCH_JSET_ENTRY_TYPES ( )
NULL
} ;
2024-04-12 15:17:00 -04:00
static const char * const __bch2_fs_usage_types [ ] = {
2021-12-31 17:06:29 -05:00
BCH_FS_USAGE_TYPES ( )
NULL
} ;
2021-02-20 19:47:58 -05:00
# undef x
2017-03-16 22:18:50 -08:00
2024-04-12 15:17:00 -04:00
static void prt_str_opt_boundscheck ( struct printbuf * out , const char * const opts [ ] ,
unsigned nr , const char * type , unsigned idx )
{
if ( idx < nr )
prt_str ( out , opts [ idx ] ) ;
else
prt_printf ( out , " (unknown %s %u) " , type , idx ) ;
}
# define PRT_STR_OPT_BOUNDSCHECKED(name, type) \
void bch2_prt_ # # name ( struct printbuf * out , type t ) \
{ \
prt_str_opt_boundscheck ( out , __bch2_ # # name # # s , ARRAY_SIZE ( __bch2_ # # name # # s ) - 1 , # name , t ) ; \
}
PRT_STR_OPT_BOUNDSCHECKED ( jset_entry_type , enum bch_jset_entry_type ) ;
PRT_STR_OPT_BOUNDSCHECKED ( fs_usage_type , enum bch_fs_usage_type ) ;
PRT_STR_OPT_BOUNDSCHECKED ( data_type , enum bch_data_type ) ;
PRT_STR_OPT_BOUNDSCHECKED ( csum_type , enum bch_csum_type ) ;
PRT_STR_OPT_BOUNDSCHECKED ( compression_type , enum bch_compression_type ) ;
2023-07-11 23:47:29 -04:00
static int bch2_opt_fix_errors_parse ( struct bch_fs * c , const char * val , u64 * res ,
struct printbuf * err )
{
if ( ! val ) {
* res = FSCK_FIX_yes ;
} else {
int ret = match_string ( bch2_fsck_fix_opts , - 1 , val ) ;
if ( ret < 0 & & err )
prt_str ( err , " fix_errors: invalid selection " ) ;
if ( ret < 0 )
return ret ;
* res = ret ;
}
return 0 ;
}
static void bch2_opt_fix_errors_to_text ( struct printbuf * out ,
struct bch_fs * c ,
struct bch_sb * sb ,
u64 v )
{
prt_str ( out , bch2_fsck_fix_opts [ v ] ) ;
}
2023-08-01 20:06:45 -04:00
# define bch2_opt_fix_errors (struct bch_opt_fn) { \
. parse = bch2_opt_fix_errors_parse , \
. to_text = bch2_opt_fix_errors_to_text , \
}
2023-07-11 23:47:29 -04:00
2021-03-16 00:42:25 -04:00
const char * const bch2_d_types [ BCH_DT_MAX ] = {
2021-07-05 22:18:07 -04:00
[ DT_UNKNOWN ] = " unknown " ,
[ DT_FIFO ] = " fifo " ,
[ DT_CHR ] = " chr " ,
[ DT_DIR ] = " dir " ,
[ DT_BLK ] = " blk " ,
[ DT_REG ] = " reg " ,
[ DT_LNK ] = " lnk " ,
[ DT_SOCK ] = " sock " ,
[ DT_WHT ] = " whiteout " ,
2021-03-16 00:42:25 -04:00
[ DT_SUBVOL ] = " subvol " ,
2021-07-05 22:18:07 -04:00
} ;
2022-03-05 12:01:16 -05:00
u64 BCH2_NO_SB_OPT ( const struct bch_sb * sb )
{
BUG ( ) ;
}
void SET_BCH2_NO_SB_OPT ( struct bch_sb * sb , u64 v )
{
BUG ( ) ;
}
2017-03-16 22:18:50 -08:00
void bch2_opts_apply ( struct bch_opts * dst , struct bch_opts src )
{
2018-12-19 12:58:56 -05:00
# define x(_name, ...) \
2017-03-16 22:18:50 -08:00
if ( opt_defined ( src , _name ) ) \
opt_set ( * dst , _name , src . _name ) ;
BCH_OPTS ( )
2018-12-19 12:58:56 -05:00
# undef x
2017-03-16 22:18:50 -08:00
}
bool bch2_opt_defined_by_id ( const struct bch_opts * opts , enum bch_opt_id id )
{
switch ( id ) {
2018-12-19 12:58:56 -05:00
# define x(_name, ...) \
2017-03-16 22:18:50 -08:00
case Opt_ # # _name : \
return opt_defined ( * opts , _name ) ;
BCH_OPTS ( )
2018-12-19 12:58:56 -05:00
# undef x
2017-03-16 22:18:50 -08:00
default :
BUG ( ) ;
}
}
u64 bch2_opt_get_by_id ( const struct bch_opts * opts , enum bch_opt_id id )
{
switch ( id ) {
2018-12-19 12:58:56 -05:00
# define x(_name, ...) \
2017-03-16 22:18:50 -08:00
case Opt_ # # _name : \
return opts - > _name ;
BCH_OPTS ( )
2018-12-19 12:58:56 -05:00
# undef x
2017-03-16 22:18:50 -08:00
default :
BUG ( ) ;
}
}
void bch2_opt_set_by_id ( struct bch_opts * opts , enum bch_opt_id id , u64 v )
{
switch ( id ) {
2018-12-19 12:58:56 -05:00
# define x(_name, ...) \
2017-03-16 22:18:50 -08:00
case Opt_ # # _name : \
opt_set ( * opts , _name , v ) ; \
break ;
BCH_OPTS ( )
2018-12-19 12:58:56 -05:00
# undef x
2017-03-16 22:18:50 -08:00
default :
BUG ( ) ;
}
}
const struct bch_option bch2_opt_table [ ] = {
2021-12-14 14:24:41 -05:00
# define OPT_BOOL() .type = BCH_OPT_BOOL, .min = 0, .max = 2
# define OPT_UINT(_min, _max) .type = BCH_OPT_UINT, \
. min = _min , . max = _max
# define OPT_STR(_choices) .type = BCH_OPT_STR, \
2023-07-12 21:48:32 -04:00
. min = 0 , . max = ARRAY_SIZE ( _choices ) , \
2021-12-14 14:24:41 -05:00
. choices = _choices
2024-03-28 21:34:14 -04:00
# define OPT_STR_NOLIMIT(_choices) .type = BCH_OPT_STR, \
. min = 0 , . max = U64_MAX , \
. choices = _choices
2023-07-12 21:48:32 -04:00
# define OPT_FN(_fn) .type = BCH_OPT_FN, .fn = _fn
2017-03-16 22:18:50 -08:00
2021-12-14 14:24:41 -05:00
# define x(_name, _bits, _flags, _type, _sb_opt, _default, _hint, _help) \
2017-03-16 22:18:50 -08:00
[ Opt_ # # _name ] = { \
. attr = { \
. name = # _name , \
2021-12-14 14:24:41 -05:00
. mode = ( _flags ) & OPT_RUNTIME ? 0644 : 0444 , \
2017-03-16 22:18:50 -08:00
} , \
2021-12-14 14:24:41 -05:00
. flags = _flags , \
2018-12-19 12:58:56 -05:00
. hint = _hint , \
. help = _help , \
2021-12-14 14:24:41 -05:00
. get_sb = _sb_opt , \
2017-03-16 22:18:50 -08:00
. set_sb = SET_ # # _sb_opt , \
_type \
} ,
BCH_OPTS ( )
2018-12-19 12:58:56 -05:00
# undef x
2017-03-16 22:18:50 -08:00
} ;
int bch2_opt_lookup ( const char * name )
{
const struct bch_option * i ;
for ( i = bch2_opt_table ;
i < bch2_opt_table + ARRAY_SIZE ( bch2_opt_table ) ;
i + + )
if ( ! strcmp ( name , i - > attr . name ) )
return i - bch2_opt_table ;
return - 1 ;
}
struct synonym {
const char * s1 , * s2 ;
} ;
static const struct synonym bch_opt_synonyms [ ] = {
{ " quota " , " usrquota " } ,
} ;
static int bch2_mount_opt_lookup ( const char * name )
{
const struct synonym * i ;
for ( i = bch_opt_synonyms ;
i < bch_opt_synonyms + ARRAY_SIZE ( bch_opt_synonyms ) ;
i + + )
if ( ! strcmp ( name , i - > s1 ) )
name = i - > s2 ;
return bch2_opt_lookup ( name ) ;
}
2022-03-21 00:15:38 -04:00
int bch2_opt_validate ( const struct bch_option * opt , u64 v , struct printbuf * err )
2021-12-14 14:24:41 -05:00
{
if ( v < opt - > min ) {
2022-03-21 00:15:38 -04:00
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: too small (min %llu) " ,
2022-03-21 00:15:38 -04:00
opt - > attr . name , opt - > min ) ;
2023-11-03 11:40:32 -04:00
return - BCH_ERR_ERANGE_option_too_small ;
2021-12-14 14:24:41 -05:00
}
if ( opt - > max & & v > = opt - > max ) {
2022-03-21 00:15:38 -04:00
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: too big (max %llu) " ,
2022-03-21 00:15:38 -04:00
opt - > attr . name , opt - > max ) ;
2023-11-03 11:40:32 -04:00
return - BCH_ERR_ERANGE_option_too_big ;
2021-12-14 14:24:41 -05:00
}
if ( ( opt - > flags & OPT_SB_FIELD_SECTORS ) & & ( v & 511 ) ) {
2022-03-21 00:15:38 -04:00
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: not a multiple of 512 " ,
2022-03-21 00:15:38 -04:00
opt - > attr . name ) ;
2023-12-04 13:03:24 -05:00
return - BCH_ERR_opt_parse_error ;
2021-12-14 14:24:41 -05:00
}
if ( ( opt - > flags & OPT_MUST_BE_POW_2 ) & & ! is_power_of_2 ( v ) ) {
2022-03-21 00:15:38 -04:00
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: must be a power of two " ,
2022-03-21 00:15:38 -04:00
opt - > attr . name ) ;
2023-12-04 13:03:24 -05:00
return - BCH_ERR_opt_parse_error ;
2021-12-14 14:24:41 -05:00
}
2023-10-22 18:29:54 -04:00
if ( opt - > fn . validate )
return opt - > fn . validate ( v , err ) ;
2021-12-14 14:24:41 -05:00
return 0 ;
}
2022-03-21 00:15:38 -04:00
int bch2_opt_parse ( struct bch_fs * c ,
2021-12-14 14:24:41 -05:00
const struct bch_option * opt ,
2022-03-21 00:15:38 -04:00
const char * val , u64 * res ,
struct printbuf * err )
2017-03-16 22:18:50 -08:00
{
ssize_t ret ;
switch ( opt - > type ) {
case BCH_OPT_BOOL :
2023-07-11 23:47:29 -04:00
if ( val ) {
ret = kstrtou64 ( val , 10 , res ) ;
} else {
ret = 0 ;
* res = 1 ;
}
2022-06-04 14:49:02 -04:00
if ( ret < 0 | | ( * res ! = 0 & & * res ! = 1 ) ) {
if ( err )
2023-07-11 23:47:29 -04:00
prt_printf ( err , " %s: must be bool " , opt - > attr . name ) ;
2024-03-01 14:38:33 +08:00
return ret < 0 ? ret : - BCH_ERR_option_not_bool ;
2022-06-04 14:49:02 -04:00
}
2017-03-16 22:18:50 -08:00
break ;
case BCH_OPT_UINT :
2023-07-11 23:47:29 -04:00
if ( ! val ) {
prt_printf ( err , " %s: required value " ,
opt - > attr . name ) ;
return - EINVAL ;
}
2021-12-14 14:24:41 -05:00
ret = opt - > flags & OPT_HUMAN_READABLE
? bch2_strtou64_h ( val , res )
: kstrtou64 ( val , 10 , res ) ;
2022-06-04 14:49:02 -04:00
if ( ret < 0 ) {
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: must be a number " ,
opt - > attr . name ) ;
2017-03-16 22:18:50 -08:00
return ret ;
2022-06-04 14:49:02 -04:00
}
2017-03-16 22:18:50 -08:00
break ;
case BCH_OPT_STR :
2023-07-11 23:47:29 -04:00
if ( ! val ) {
prt_printf ( err , " %s: required value " ,
opt - > attr . name ) ;
return - EINVAL ;
}
2017-03-16 22:18:50 -08:00
ret = match_string ( opt - > choices , - 1 , val ) ;
2022-06-04 14:49:02 -04:00
if ( ret < 0 ) {
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: invalid selection " ,
opt - > attr . name ) ;
2017-03-16 22:18:50 -08:00
return ret ;
2022-06-04 14:49:02 -04:00
}
2017-03-16 22:18:50 -08:00
* res = ret ;
break ;
case BCH_OPT_FN :
2023-07-12 21:48:32 -04:00
ret = opt - > fn . parse ( c , val , res , err ) ;
2022-06-04 14:49:02 -04:00
if ( ret < 0 ) {
if ( err )
2023-02-03 21:01:40 -05:00
prt_printf ( err , " %s: parse error " ,
opt - > attr . name ) ;
2021-12-14 14:24:41 -05:00
return ret ;
2022-06-04 14:49:02 -04:00
}
2017-03-16 22:18:50 -08:00
}
2022-03-21 00:15:38 -04:00
return bch2_opt_validate ( opt , * res , err ) ;
2017-03-16 22:18:50 -08:00
}
2022-03-05 12:01:16 -05:00
void bch2_opt_to_text ( struct printbuf * out ,
struct bch_fs * c , struct bch_sb * sb ,
2018-11-09 01:24:07 -05:00
const struct bch_option * opt , u64 v ,
unsigned flags )
2017-03-16 22:18:50 -08:00
{
if ( flags & OPT_SHOW_MOUNT_STYLE ) {
2018-11-09 01:24:07 -05:00
if ( opt - > type = = BCH_OPT_BOOL ) {
2023-02-03 21:01:40 -05:00
prt_printf ( out , " %s%s " ,
2018-11-09 01:24:07 -05:00
v ? " " : " no " ,
opt - > attr . name ) ;
return ;
}
2023-02-03 21:01:40 -05:00
prt_printf ( out , " %s= " , opt - > attr . name ) ;
2017-03-16 22:18:50 -08:00
}
switch ( opt - > type ) {
case BCH_OPT_BOOL :
case BCH_OPT_UINT :
2021-12-14 14:24:41 -05:00
if ( opt - > flags & OPT_HUMAN_READABLE )
2023-02-03 21:01:40 -05:00
prt_human_readable_u64 ( out , v ) ;
2021-12-14 14:24:41 -05:00
else
2023-02-03 21:01:40 -05:00
prt_printf ( out , " %lli " , v ) ;
2018-12-19 12:58:56 -05:00
break ;
2017-03-16 22:18:50 -08:00
case BCH_OPT_STR :
2018-11-09 01:24:07 -05:00
if ( flags & OPT_SHOW_FULL_LIST )
2023-02-03 21:01:40 -05:00
prt_string_option ( out , opt - > choices , v ) ;
2018-11-09 01:24:07 -05:00
else
2023-07-11 23:47:29 -04:00
prt_str ( out , opt - > choices [ v ] ) ;
2017-03-16 22:18:50 -08:00
break ;
case BCH_OPT_FN :
2023-07-12 21:48:32 -04:00
opt - > fn . to_text ( out , c , sb , v ) ;
2018-11-09 01:24:07 -05:00
break ;
2017-03-16 22:18:50 -08:00
default :
BUG ( ) ;
}
}
2018-11-12 18:30:55 -05:00
int bch2_opt_check_may_set ( struct bch_fs * c , int id , u64 v )
{
int ret = 0 ;
switch ( id ) {
case Opt_compression :
case Opt_background_compression :
ret = bch2_check_set_has_compressed_data ( c , v ) ;
break ;
2018-11-01 15:13:19 -04:00
case Opt_erasure_code :
2019-11-29 13:47:42 -05:00
if ( v )
2019-12-28 20:17:06 -05:00
bch2_check_set_feature ( c , BCH_FEATURE_ec ) ;
2018-11-01 15:13:19 -04:00
break ;
2018-11-12 18:30:55 -05:00
}
return ret ;
}
2018-11-01 15:13:19 -04:00
int bch2_opts_check_may_set ( struct bch_fs * c )
{
unsigned i ;
int ret ;
for ( i = 0 ; i < bch2_opts_nr ; i + + ) {
ret = bch2_opt_check_may_set ( c , i ,
bch2_opt_get_by_id ( & c - > opts , i ) ) ;
if ( ret )
return ret ;
}
return 0 ;
}
2020-10-23 21:07:17 -04:00
int bch2_parse_mount_opts ( struct bch_fs * c , struct bch_opts * opts ,
char * options )
2017-03-16 22:18:50 -08:00
{
2021-05-09 18:52:23 -04:00
char * copied_opts , * copied_opts_start ;
2017-03-16 22:18:50 -08:00
char * opt , * name , * val ;
int ret , id ;
2022-03-21 00:15:38 -04:00
struct printbuf err = PRINTBUF ;
2017-03-16 22:18:50 -08:00
u64 v ;
2021-05-09 18:52:23 -04:00
if ( ! options )
return 0 ;
2023-08-02 12:51:51 -04:00
/*
* sys_fsconfig ( ) is now occasionally providing us with option lists
* starting with a comma - weird .
*/
if ( * options = = ' , ' )
options + + ;
2021-05-09 18:52:23 -04:00
copied_opts = kstrdup ( options , GFP_KERNEL ) ;
if ( ! copied_opts )
2024-02-19 20:24:32 +08:00
return - ENOMEM ;
2021-05-09 18:52:23 -04:00
copied_opts_start = copied_opts ;
while ( ( opt = strsep ( & copied_opts , " , " ) ) ! = NULL ) {
2017-03-16 22:18:50 -08:00
name = strsep ( & opt , " = " ) ;
val = opt ;
2023-07-11 23:47:29 -04:00
id = bch2_mount_opt_lookup ( name ) ;
2017-03-16 22:18:50 -08:00
2023-07-11 23:47:29 -04:00
/* Check for the form "noopt", negation of a boolean opt: */
if ( id < 0 & &
! val & &
! strncmp ( " no " , name , 2 ) ) {
id = bch2_mount_opt_lookup ( name + 2 ) ;
val = " 0 " ;
2017-03-16 22:18:50 -08:00
}
2023-09-23 18:41:51 -04:00
/* Unknown options are ignored: */
2023-07-11 23:47:29 -04:00
if ( id < 0 )
2023-09-23 18:41:51 -04:00
continue ;
2023-07-11 23:47:29 -04:00
2021-12-14 14:24:41 -05:00
if ( ! ( bch2_opt_table [ id ] . flags & OPT_MOUNT ) )
2017-03-16 22:18:50 -08:00
goto bad_opt ;
if ( id = = Opt_acl & &
! IS_ENABLED ( CONFIG_BCACHEFS_POSIX_ACL ) )
goto bad_opt ;
if ( ( id = = Opt_usrquota | |
id = = Opt_grpquota ) & &
! IS_ENABLED ( CONFIG_BCACHEFS_QUOTA ) )
goto bad_opt ;
2023-07-11 23:47:29 -04:00
ret = bch2_opt_parse ( c , & bch2_opt_table [ id ] , val , & v , & err ) ;
if ( ret < 0 )
goto bad_val ;
2017-03-16 22:18:50 -08:00
bch2_opt_set_by_id ( opts , id , v ) ;
}
2021-05-09 18:52:23 -04:00
ret = 0 ;
goto out ;
2017-03-16 22:18:50 -08:00
bad_opt :
pr_err ( " Bad mount option %s " , name ) ;
2024-02-19 20:24:32 +08:00
ret = - BCH_ERR_option_name ;
2021-05-09 18:52:23 -04:00
goto out ;
2017-03-16 22:18:50 -08:00
bad_val :
2022-03-21 00:15:38 -04:00
pr_err ( " Invalid mount option %s " , err . buf ) ;
2024-02-19 20:24:32 +08:00
ret = - BCH_ERR_option_value ;
2021-05-09 18:52:23 -04:00
goto out ;
out :
kfree ( copied_opts_start ) ;
2022-03-21 00:15:38 -04:00
printbuf_exit ( & err ) ;
2021-05-09 18:52:23 -04:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2022-03-05 12:01:16 -05:00
u64 bch2_opt_from_sb ( struct bch_sb * sb , enum bch_opt_id id )
{
const struct bch_option * opt = bch2_opt_table + id ;
u64 v ;
v = opt - > get_sb ( sb ) ;
if ( opt - > flags & OPT_SB_FIELD_ILOG2 )
v = 1ULL < < v ;
if ( opt - > flags & OPT_SB_FIELD_SECTORS )
v < < = 9 ;
return v ;
}
2021-12-14 14:24:41 -05:00
/*
* Initial options from superblock - here we don ' t want any options undefined ,
* any options the superblock doesn ' t specify are set to 0 :
*/
int bch2_opts_from_sb ( struct bch_opts * opts , struct bch_sb * sb )
{
unsigned id ;
for ( id = 0 ; id < bch2_opts_nr ; id + + ) {
const struct bch_option * opt = bch2_opt_table + id ;
2022-03-05 12:01:16 -05:00
if ( opt - > get_sb = = BCH2_NO_SB_OPT )
2021-12-14 14:24:41 -05:00
continue ;
2022-03-21 00:15:38 -04:00
bch2_opt_set_by_id ( opts , id , bch2_opt_from_sb ( sb , id ) ) ;
2021-12-14 14:24:41 -05:00
}
return 0 ;
}
void __bch2_opt_set_sb ( struct bch_sb * sb , const struct bch_option * opt , u64 v )
{
2022-03-05 12:01:16 -05:00
if ( opt - > set_sb = = SET_BCH2_NO_SB_OPT )
2021-12-14 14:24:41 -05:00
return ;
if ( opt - > flags & OPT_SB_FIELD_SECTORS )
v > > = 9 ;
if ( opt - > flags & OPT_SB_FIELD_ILOG2 )
v = ilog2 ( v ) ;
opt - > set_sb ( sb , v ) ;
}
void bch2_opt_set_sb ( struct bch_fs * c , const struct bch_option * opt , u64 v )
{
2022-03-05 12:01:16 -05:00
if ( opt - > set_sb = = SET_BCH2_NO_SB_OPT )
2021-12-14 14:24:41 -05:00
return ;
mutex_lock ( & c - > sb_lock ) ;
__bch2_opt_set_sb ( c - > disk_sb . sb , opt , v ) ;
bch2_write_super ( c ) ;
mutex_unlock ( & c - > sb_lock ) ;
}
2017-03-16 22:18:50 -08:00
/* io opts: */
struct bch_io_opts bch2_opts_to_inode_opts ( struct bch_opts src )
{
2022-11-23 20:14:55 -05:00
return ( struct bch_io_opts ) {
# define x(_name, _bits) ._name = src._name,
2017-03-16 22:18:50 -08:00
BCH_INODE_OPTS ( )
2018-12-13 06:01:30 -05:00
# undef x
2022-11-23 20:14:55 -05:00
} ;
2017-03-16 22:18:50 -08:00
}
bool bch2_opt_is_inode_opt ( enum bch_opt_id id )
{
static const enum bch_opt_id inode_opt_list [ ] = {
2018-12-13 06:01:30 -05:00
# define x(_name, _bits) Opt_##_name,
2017-03-16 22:18:50 -08:00
BCH_INODE_OPTS ( )
2018-12-13 06:01:30 -05:00
# undef x
2017-03-16 22:18:50 -08:00
} ;
unsigned i ;
for ( i = 0 ; i < ARRAY_SIZE ( inode_opt_list ) ; i + + )
if ( inode_opt_list [ i ] = = id )
return true ;
return false ;
}