2017-03-17 09:18:50 +03:00
// SPDX-License-Identifier: GPL-2.0
# include "bcachefs.h"
# include "checksum.h"
2023-07-10 20:42:26 +03:00
# include "counters.h"
2017-03-17 09:18:50 +03:00
# include "disk_groups.h"
2018-11-01 22:13:19 +03:00
# include "ec.h"
2017-03-17 09:18:50 +03:00
# include "error.h"
# include "journal.h"
2022-03-11 00:43:52 +03:00
# include "journal_sb.h"
2019-04-05 04:53:12 +03:00
# include "journal_seq_blacklist.h"
2023-07-10 20:42:26 +03:00
# include "recovery.h"
2017-03-17 09:18:50 +03:00
# include "replicas.h"
# include "quota.h"
2023-08-05 22:54:38 +03:00
# include "sb-clean.h"
2023-08-05 22:40:21 +03:00
# include "sb-members.h"
2017-03-17 09:18:50 +03:00
# include "super-io.h"
# include "super.h"
2022-04-03 22:13:20 +03:00
# include "trace.h"
2017-03-17 09:18:50 +03:00
# include "vstructs.h"
# include <linux/backing-dev.h>
# include <linux/sort.h>
static const struct blk_holder_ops bch2_sb_handle_bdev_ops = {
} ;
2023-07-10 20:42:26 +03:00
struct bch2_metadata_version {
2023-06-28 05:09:35 +03:00
u16 version ;
const char * name ;
2023-07-10 20:42:26 +03:00
u64 recovery_passes ;
2023-06-28 05:09:35 +03:00
} ;
2023-07-10 20:42:26 +03:00
static const struct bch2_metadata_version bch2_metadata_versions [ ] = {
# define x(n, v, _recovery_passes) { \
. version = v , \
. name = # n , \
. recovery_passes = _recovery_passes , \
} ,
2023-06-29 02:53:05 +03:00
BCH_METADATA_VERSIONS ( )
# undef x
} ;
void bch2_version_to_text ( struct printbuf * out , unsigned v )
{
2023-06-28 05:09:35 +03:00
const char * str = " (unknown version) " ;
for ( unsigned i = 0 ; i < ARRAY_SIZE ( bch2_metadata_versions ) ; i + + )
if ( bch2_metadata_versions [ i ] . version = = v ) {
str = bch2_metadata_versions [ i ] . name ;
break ;
}
prt_printf ( out , " %u.%u: %s " , BCH_VERSION_MAJOR ( v ) , BCH_VERSION_MINOR ( v ) , str ) ;
}
unsigned bch2_latest_compatible_version ( unsigned v )
{
if ( ! BCH_VERSION_MAJOR ( v ) )
return v ;
for ( unsigned i = 0 ; i < ARRAY_SIZE ( bch2_metadata_versions ) ; i + + )
if ( bch2_metadata_versions [ i ] . version > v & &
BCH_VERSION_MAJOR ( bch2_metadata_versions [ i ] . version ) = =
BCH_VERSION_MAJOR ( v ) )
v = bch2_metadata_versions [ i ] . version ;
2023-06-29 02:53:05 +03:00
2023-06-28 05:09:35 +03:00
return v ;
2023-06-29 02:53:05 +03:00
}
2023-07-10 20:42:26 +03:00
u64 bch2_upgrade_recovery_passes ( struct bch_fs * c ,
unsigned old_version ,
unsigned new_version )
{
u64 ret = 0 ;
for ( const struct bch2_metadata_version * i = bch2_metadata_versions ;
i < bch2_metadata_versions + ARRAY_SIZE ( bch2_metadata_versions ) ;
i + + )
if ( i - > version > old_version & & i - > version < = new_version ) {
if ( i - > recovery_passes & RECOVERY_PASS_ALL_FSCK )
ret | = bch2_fsck_recovery_passes ( ) ;
ret | = i - > recovery_passes ;
}
return ret & = ~ RECOVERY_PASS_ALL_FSCK ;
}
2017-03-17 09:18:50 +03:00
const char * const bch2_sb_fields [ ] = {
# define x(name, nr) #name,
BCH_SB_FIELDS ( )
# undef x
NULL
} ;
2022-01-04 07:38:50 +03:00
static int bch2_sb_field_validate ( struct bch_sb * , struct bch_sb_field * ,
struct printbuf * ) ;
2017-03-17 09:18:50 +03:00
2023-09-27 00:49:34 +03:00
struct bch_sb_field * bch2_sb_field_get_id ( struct bch_sb * sb ,
2017-03-17 09:18:50 +03:00
enum bch_sb_field_type type )
{
struct bch_sb_field * f ;
/* XXX: need locking around superblock to access optional fields */
vstruct_for_each ( sb , f )
if ( le32_to_cpu ( f - > type ) = = type )
return f ;
return NULL ;
}
static struct bch_sb_field * __bch2_sb_field_resize ( struct bch_sb_handle * sb ,
struct bch_sb_field * f ,
unsigned u64s )
{
unsigned old_u64s = f ? le32_to_cpu ( f - > u64s ) : 0 ;
unsigned sb_u64s = le32_to_cpu ( sb - > sb - > u64s ) + u64s - old_u64s ;
2021-04-06 21:00:56 +03:00
BUG_ON ( __vstruct_bytes ( struct bch_sb , sb_u64s ) > sb - > buffer_size ) ;
2017-03-17 09:18:50 +03:00
2019-12-19 01:34:36 +03:00
if ( ! f & & ! u64s ) {
/* nothing to do: */
} else if ( ! f ) {
2017-03-17 09:18:50 +03:00
f = vstruct_last ( sb - > sb ) ;
memset ( f , 0 , sizeof ( u64 ) * u64s ) ;
f - > u64s = cpu_to_le32 ( u64s ) ;
f - > type = 0 ;
} else {
void * src , * dst ;
src = vstruct_end ( f ) ;
2018-10-30 21:32:47 +03:00
if ( u64s ) {
f - > u64s = cpu_to_le32 ( u64s ) ;
dst = vstruct_end ( f ) ;
} else {
dst = f ;
}
2017-03-17 09:18:50 +03:00
memmove ( dst , src , vstruct_end ( sb - > sb ) - src ) ;
if ( dst > src )
memset ( src , 0 , dst - src ) ;
}
sb - > sb - > u64s = cpu_to_le32 ( sb_u64s ) ;
2018-10-30 21:32:47 +03:00
return u64s ? f : NULL ;
}
void bch2_sb_field_delete ( struct bch_sb_handle * sb ,
enum bch_sb_field_type type )
{
2023-09-27 00:49:34 +03:00
struct bch_sb_field * f = bch2_sb_field_get_id ( sb - > sb , type ) ;
2018-10-30 21:32:47 +03:00
if ( f )
__bch2_sb_field_resize ( sb , f , 0 ) ;
2017-03-17 09:18:50 +03:00
}
/* Superblock realloc/free: */
void bch2_free_super ( struct bch_sb_handle * sb )
{
2022-10-20 01:31:33 +03:00
kfree ( sb - > bio ) ;
2017-03-17 09:18:50 +03:00
if ( ! IS_ERR_OR_NULL ( sb - > bdev ) )
blkdev_put ( sb - > bdev , sb - > holder ) ;
kfree ( sb - > holder ) ;
2021-04-06 21:00:56 +03:00
kfree ( sb - > sb ) ;
2017-03-17 09:18:50 +03:00
memset ( sb , 0 , sizeof ( * sb ) ) ;
}
int bch2_sb_realloc ( struct bch_sb_handle * sb , unsigned u64s )
{
size_t new_bytes = __vstruct_bytes ( struct bch_sb , u64s ) ;
2021-04-06 21:00:56 +03:00
size_t new_buffer_size ;
2017-03-17 09:18:50 +03:00
struct bch_sb * new_sb ;
struct bio * bio ;
2021-04-06 21:00:56 +03:00
if ( sb - > bdev )
new_bytes = max_t ( size_t , new_bytes , bdev_logical_block_size ( sb - > bdev ) ) ;
new_buffer_size = roundup_pow_of_two ( new_bytes ) ;
if ( sb - > sb & & sb - > buffer_size > = new_buffer_size )
2017-03-17 09:18:50 +03:00
return 0 ;
2023-09-20 08:32:20 +03:00
if ( sb - > sb & & sb - > have_layout ) {
2017-03-17 09:18:50 +03:00
u64 max_bytes = 512 < < sb - > sb - > layout . sb_max_size_bits ;
if ( new_bytes > max_bytes ) {
pr_err ( " %pg: superblock too big: want %zu but have %llu " ,
sb - > bdev , new_bytes , max_bytes ) ;
2022-09-19 00:10:33 +03:00
return - BCH_ERR_ENOSPC_sb ;
2017-03-17 09:18:50 +03:00
}
}
2021-04-06 21:00:56 +03:00
if ( sb - > buffer_size > = new_buffer_size & & sb - > sb )
2017-03-17 09:18:50 +03:00
return 0 ;
if ( dynamic_fault ( " bcachefs:add:super_realloc " ) )
2023-03-14 22:35:57 +03:00
return - BCH_ERR_ENOMEM_sb_realloc_injected ;
2017-03-17 09:18:50 +03:00
2023-08-08 03:44:56 +03:00
new_sb = krealloc ( sb - > sb , new_buffer_size , GFP_NOFS | __GFP_ZERO ) ;
if ( ! new_sb )
return - BCH_ERR_ENOMEM_sb_buf_realloc ;
sb - > sb = new_sb ;
2017-03-17 09:18:50 +03:00
if ( sb - > have_bio ) {
2023-08-08 03:44:56 +03:00
unsigned nr_bvecs = buf_pages ( sb - > sb , new_buffer_size ) ;
2017-03-17 09:18:50 +03:00
bio = bio_kmalloc ( nr_bvecs , GFP_KERNEL ) ;
if ( ! bio )
2023-03-14 22:35:57 +03:00
return - BCH_ERR_ENOMEM_sb_bio_realloc ;
2017-03-17 09:18:50 +03:00
bio_init ( bio , NULL , bio - > bi_inline_vecs , nr_bvecs , 0 ) ;
2022-10-20 01:31:33 +03:00
kfree ( sb - > bio ) ;
2017-03-17 09:18:50 +03:00
sb - > bio = bio ;
}
2021-04-06 21:00:56 +03:00
sb - > buffer_size = new_buffer_size ;
2017-03-17 09:18:50 +03:00
return 0 ;
}
2023-09-27 00:49:34 +03:00
struct bch_sb_field * bch2_sb_field_resize_id ( struct bch_sb_handle * sb ,
2017-03-17 09:18:50 +03:00
enum bch_sb_field_type type ,
unsigned u64s )
{
2023-09-27 00:49:34 +03:00
struct bch_sb_field * f = bch2_sb_field_get_id ( sb - > sb , type ) ;
2017-03-17 09:18:50 +03:00
ssize_t old_u64s = f ? le32_to_cpu ( f - > u64s ) : 0 ;
ssize_t d = - old_u64s + u64s ;
if ( bch2_sb_realloc ( sb , le32_to_cpu ( sb - > sb - > u64s ) + d ) )
return NULL ;
if ( sb - > fs_sb ) {
struct bch_fs * c = container_of ( sb , struct bch_fs , disk_sb ) ;
struct bch_dev * ca ;
unsigned i ;
lockdep_assert_held ( & c - > sb_lock ) ;
/* XXX: we're not checking that offline device have enough space */
for_each_online_member ( ca , c , i ) {
2023-09-13 01:41:22 +03:00
struct bch_sb_handle * dev_sb = & ca - > disk_sb ;
2017-03-17 09:18:50 +03:00
2023-09-13 01:41:22 +03:00
if ( bch2_sb_realloc ( dev_sb , le32_to_cpu ( dev_sb - > sb - > u64s ) + d ) ) {
2017-03-17 09:18:50 +03:00
percpu_ref_put ( & ca - > ref ) ;
return NULL ;
}
}
}
2023-09-27 00:49:34 +03:00
f = bch2_sb_field_get_id ( sb - > sb , type ) ;
2017-03-17 09:18:50 +03:00
f = __bch2_sb_field_resize ( sb , f , u64s ) ;
2018-10-30 21:32:47 +03:00
if ( f )
f - > type = cpu_to_le32 ( type ) ;
2017-03-17 09:18:50 +03:00
return f ;
}
/* Superblock validate: */
2022-01-04 07:38:50 +03:00
static int validate_sb_layout ( struct bch_sb_layout * layout , struct printbuf * out )
2017-03-17 09:18:50 +03:00
{
u64 offset , prev_offset , max_sectors ;
unsigned i ;
2023-08-02 03:06:45 +03:00
BUILD_BUG_ON ( sizeof ( struct bch_sb_layout ) ! = 512 ) ;
2017-03-17 09:18:50 +03:00
if ( ! uuid_equal ( & layout - > magic , & BCACHE_MAGIC ) & &
2022-01-04 07:38:50 +03:00
! uuid_equal ( & layout - > magic , & BCHFS_MAGIC ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Not a bcachefs superblock layout " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_layout ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( layout - > layout_type ! = 0 ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid superblock layout type %u " ,
2022-01-04 07:38:50 +03:00
layout - > layout_type ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_layout_type ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( ! layout - > nr_superblocks ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid superblock layout: no superblocks " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_layout_nr_superblocks ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( layout - > nr_superblocks > ARRAY_SIZE ( layout - > sb_offset ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid superblock layout: too many superblocks " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_layout_nr_superblocks ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
max_sectors = 1 < < layout - > sb_max_size_bits ;
prev_offset = le64_to_cpu ( layout - > sb_offset [ 0 ] ) ;
for ( i = 1 ; i < layout - > nr_superblocks ; i + + ) {
offset = le64_to_cpu ( layout - > sb_offset [ i ] ) ;
2022-01-04 07:38:50 +03:00
if ( offset < prev_offset + max_sectors ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid superblock layout: superblocks overlap \n "
2022-01-04 07:38:50 +03:00
" (sb %u ends at %llu next starts at %llu " ,
i - 1 , prev_offset + max_sectors , offset ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_layout_superblocks_overlap ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
prev_offset = offset ;
}
2022-01-04 07:38:50 +03:00
return 0 ;
2017-03-17 09:18:50 +03:00
}
2023-06-29 03:27:07 +03:00
static int bch2_sb_compatible ( struct bch_sb * sb , struct printbuf * out )
2017-03-17 09:18:50 +03:00
{
2023-06-29 03:27:07 +03:00
u16 version = le16_to_cpu ( sb - > version ) ;
u16 version_min = le16_to_cpu ( sb - > version_min ) ;
if ( ! bch2_version_compatible ( version ) ) {
prt_str ( out , " Unsupported superblock version " ) ;
bch2_version_to_text ( out , version ) ;
prt_str ( out , " (min " ) ;
bch2_version_to_text ( out , bcachefs_metadata_version_min ) ;
prt_str ( out , " , max " ) ;
bch2_version_to_text ( out , bcachefs_metadata_version_current ) ;
prt_str ( out , " ) " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_version ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2023-06-29 03:27:07 +03:00
if ( ! bch2_version_compatible ( version_min ) ) {
prt_str ( out , " Unsupported superblock version_min " ) ;
bch2_version_to_text ( out , version_min ) ;
prt_str ( out , " (min " ) ;
bch2_version_to_text ( out , bcachefs_metadata_version_min ) ;
prt_str ( out , " , max " ) ;
bch2_version_to_text ( out , bcachefs_metadata_version_current ) ;
prt_str ( out , " ) " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_version ;
2022-01-04 07:38:50 +03:00
}
if ( version_min > version ) {
2023-06-29 03:27:07 +03:00
prt_str ( out , " Bad minimum version " ) ;
bch2_version_to_text ( out , version_min ) ;
prt_str ( out , " , greater than version field " ) ;
bch2_version_to_text ( out , version ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_version ;
2022-01-04 07:38:50 +03:00
}
2018-11-01 22:10:01 +03:00
2023-06-29 03:27:07 +03:00
return 0 ;
}
static int bch2_sb_validate ( struct bch_sb_handle * disk_sb , struct printbuf * out ,
int rw )
{
struct bch_sb * sb = disk_sb - > sb ;
struct bch_sb_field * f ;
2023-09-25 07:06:32 +03:00
struct bch_sb_field_members_v1 * mi ;
2023-06-29 03:27:07 +03:00
enum bch_opt_id opt_id ;
u16 block_size ;
int ret ;
ret = bch2_sb_compatible ( sb , out ) ;
if ( ret )
return ret ;
2018-11-13 02:30:55 +03:00
if ( sb - > features [ 1 ] | |
2022-01-04 07:38:50 +03:00
( le64_to_cpu ( sb - > features [ 0 ] ) & ( ~ 0ULL < < BCH_FEATURE_NR ) ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Filesystem has incompatible features " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_features ;
2022-01-04 07:38:50 +03:00
}
2018-11-13 02:30:55 +03:00
2017-03-17 09:18:50 +03:00
block_size = le16_to_cpu ( sb - > block_size ) ;
2022-01-04 07:38:50 +03:00
if ( block_size > PAGE_SECTORS ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Block size too big (got %u, max %u) " ,
2022-01-04 07:38:50 +03:00
block_size , PAGE_SECTORS ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_block_size ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( bch2_is_zero ( sb - > user_uuid . b , sizeof ( sb - > user_uuid ) ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Bad user UUID (got zeroes) " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_uuid ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( bch2_is_zero ( sb - > uuid . b , sizeof ( sb - > uuid ) ) ) {
2023-09-12 11:25:27 +03:00
prt_printf ( out , " Bad internal UUID (got zeroes) " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_uuid ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
if ( ! sb - > nr_devices | |
2022-01-04 07:38:50 +03:00
sb - > nr_devices > BCH_SB_MEMBERS_MAX ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Bad number of member devices %u (max %u) " ,
2022-01-04 07:38:50 +03:00
sb - > nr_devices , BCH_SB_MEMBERS_MAX ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_too_many_members ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( sb - > dev_idx > = sb - > nr_devices ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Bad dev_idx (got %u, nr_devices %u) " ,
2022-01-04 07:38:50 +03:00
sb - > dev_idx , sb - > nr_devices ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_dev_idx ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
if ( ! sb - > time_precision | |
2022-01-04 07:38:50 +03:00
le32_to_cpu ( sb - > time_precision ) > NSEC_PER_SEC ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid time precision: %u (min 1, max %lu) " ,
2022-01-04 07:38:50 +03:00
le32_to_cpu ( sb - > time_precision ) , NSEC_PER_SEC ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_time_precision ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-03-21 10:03:03 +03:00
if ( rw = = READ ) {
/*
* Been seeing a bug where these are getting inexplicably
2023-06-29 03:27:07 +03:00
* zeroed , so we ' re now validating them , but we have to be
2022-03-21 10:03:03 +03:00
* careful not to preven people ' s filesystems from mounting :
*/
if ( ! BCH_SB_JOURNAL_FLUSH_DELAY ( sb ) )
SET_BCH_SB_JOURNAL_FLUSH_DELAY ( sb , 1000 ) ;
if ( ! BCH_SB_JOURNAL_RECLAIM_DELAY ( sb ) )
SET_BCH_SB_JOURNAL_RECLAIM_DELAY ( sb , 1000 ) ;
2023-07-16 04:03:26 +03:00
if ( ! BCH_SB_VERSION_UPGRADE_COMPLETE ( sb ) )
SET_BCH_SB_VERSION_UPGRADE_COMPLETE ( sb , le16_to_cpu ( sb - > version ) ) ;
2022-03-21 10:03:03 +03:00
}
2022-03-21 07:15:38 +03:00
for ( opt_id = 0 ; opt_id < bch2_opts_nr ; opt_id + + ) {
const struct bch_option * opt = bch2_opt_table + opt_id ;
if ( opt - > get_sb ! = BCH2_NO_SB_OPT ) {
u64 v = bch2_opt_from_sb ( sb , opt_id ) ;
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid option " ) ;
2022-03-21 07:15:38 +03:00
ret = bch2_opt_validate ( opt , v , out ) ;
if ( ret )
return ret ;
printbuf_reset ( out ) ;
}
}
2017-03-17 09:18:50 +03:00
/* validate layout */
2022-01-04 07:38:50 +03:00
ret = validate_sb_layout ( & sb - > layout , out ) ;
if ( ret )
return ret ;
2017-03-17 09:18:50 +03:00
vstruct_for_each ( sb , f ) {
2022-01-04 07:38:50 +03:00
if ( ! f - > u64s ) {
2022-11-20 06:39:08 +03:00
prt_printf ( out , " Invalid superblock: optional field with size 0 (type %u) " ,
2022-01-04 07:38:50 +03:00
le32_to_cpu ( f - > type ) ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_field_size ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( vstruct_next ( f ) > vstruct_last ( sb ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid superblock: optional field extends past end of superblock (type %u) " ,
2022-01-04 07:38:50 +03:00
le32_to_cpu ( f - > type ) ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_field_size ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
}
/* members must be validated first: */
2023-09-27 00:49:34 +03:00
mi = bch2_sb_field_get ( sb , members_v1 ) ;
2022-01-04 07:38:50 +03:00
if ( ! mi ) {
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Invalid superblock: member info area missing " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_members_missing ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
ret = bch2_sb_field_validate ( sb , & mi - > field , out ) ;
if ( ret )
return ret ;
2017-03-17 09:18:50 +03:00
vstruct_for_each ( sb , f ) {
2023-09-25 07:06:32 +03:00
if ( le32_to_cpu ( f - > type ) = = BCH_SB_FIELD_members_v1 )
2017-03-17 09:18:50 +03:00
continue ;
2022-01-04 07:38:50 +03:00
ret = bch2_sb_field_validate ( sb , f , out ) ;
if ( ret )
return ret ;
2017-03-17 09:18:50 +03:00
}
2022-01-04 07:38:50 +03:00
return 0 ;
2017-03-17 09:18:50 +03:00
}
/* device open: */
static void bch2_sb_update ( struct bch_fs * c )
{
struct bch_sb * src = c - > disk_sb . sb ;
struct bch_dev * ca ;
unsigned i ;
lockdep_assert_held ( & c - > sb_lock ) ;
c - > sb . uuid = src - > uuid ;
c - > sb . user_uuid = src - > user_uuid ;
2018-11-01 22:10:01 +03:00
c - > sb . version = le16_to_cpu ( src - > version ) ;
2021-03-21 23:03:23 +03:00
c - > sb . version_min = le16_to_cpu ( src - > version_min ) ;
2023-07-16 04:03:26 +03:00
c - > sb . version_upgrade_complete = BCH_SB_VERSION_UPGRADE_COMPLETE ( src ) ;
2017-03-17 09:18:50 +03:00
c - > sb . nr_devices = src - > nr_devices ;
c - > sb . clean = BCH_SB_CLEAN ( src ) ;
c - > sb . encryption_type = BCH_SB_ENCRYPTION_TYPE ( src ) ;
2021-04-29 05:51:42 +03:00
c - > sb . nsec_per_time_unit = le32_to_cpu ( src - > time_precision ) ;
c - > sb . time_units_per_sec = NSEC_PER_SEC / c - > sb . nsec_per_time_unit ;
/* XXX this is wrong, we need a 96 or 128 bit integer type */
c - > sb . time_base_lo = div_u64 ( le64_to_cpu ( src - > time_base_lo ) ,
c - > sb . nsec_per_time_unit ) ;
2017-03-17 09:18:50 +03:00
c - > sb . time_base_hi = le32_to_cpu ( src - > time_base_hi ) ;
2021-04-29 05:51:42 +03:00
2017-03-17 09:18:50 +03:00
c - > sb . features = le64_to_cpu ( src - > features [ 0 ] ) ;
2019-02-06 19:56:51 +03:00
c - > sb . compat = le64_to_cpu ( src - > compat [ 0 ] ) ;
2017-03-17 09:18:50 +03:00
2023-09-25 06:55:37 +03:00
for_each_member_device ( ca , c , i ) {
struct bch_member m = bch2_sb_member_get ( src , i ) ;
ca - > mi = bch2_mi_to_cpu ( & m ) ;
}
2017-03-17 09:18:50 +03:00
}
2023-02-13 06:08:39 +03:00
static int __copy_super ( struct bch_sb_handle * dst_handle , struct bch_sb * src )
2017-03-17 09:18:50 +03:00
{
struct bch_sb_field * src_f , * dst_f ;
struct bch_sb * dst = dst_handle - > sb ;
2018-10-30 21:32:47 +03:00
unsigned i ;
2017-03-17 09:18:50 +03:00
dst - > version = src - > version ;
2018-11-01 22:10:01 +03:00
dst - > version_min = src - > version_min ;
2017-03-17 09:18:50 +03:00
dst - > seq = src - > seq ;
dst - > uuid = src - > uuid ;
dst - > user_uuid = src - > user_uuid ;
memcpy ( dst - > label , src - > label , sizeof ( dst - > label ) ) ;
dst - > block_size = src - > block_size ;
dst - > nr_devices = src - > nr_devices ;
dst - > time_base_lo = src - > time_base_lo ;
dst - > time_base_hi = src - > time_base_hi ;
dst - > time_precision = src - > time_precision ;
memcpy ( dst - > flags , src - > flags , sizeof ( dst - > flags ) ) ;
memcpy ( dst - > features , src - > features , sizeof ( dst - > features ) ) ;
memcpy ( dst - > compat , src - > compat , sizeof ( dst - > compat ) ) ;
2018-10-30 21:32:47 +03:00
for ( i = 0 ; i < BCH_SB_FIELD_NR ; i + + ) {
2023-02-13 06:08:39 +03:00
int d ;
2022-03-11 00:43:52 +03:00
if ( ( 1U < < i ) & BCH_SINGLE_DEVICE_SB_FIELDS )
2017-03-17 09:18:50 +03:00
continue ;
2023-09-27 00:49:34 +03:00
src_f = bch2_sb_field_get_id ( src , i ) ;
dst_f = bch2_sb_field_get_id ( dst , i ) ;
2023-02-13 06:08:39 +03:00
d = ( src_f ? le32_to_cpu ( src_f - > u64s ) : 0 ) -
( dst_f ? le32_to_cpu ( dst_f - > u64s ) : 0 ) ;
if ( d > 0 ) {
2023-08-07 19:04:05 +03:00
int ret = bch2_sb_realloc ( dst_handle ,
le32_to_cpu ( dst_handle - > sb - > u64s ) + d ) ;
2023-02-13 06:08:39 +03:00
if ( ret )
return ret ;
dst = dst_handle - > sb ;
2023-09-27 00:49:34 +03:00
dst_f = bch2_sb_field_get_id ( dst , i ) ;
2023-02-13 06:08:39 +03:00
}
2017-03-17 09:18:50 +03:00
dst_f = __bch2_sb_field_resize ( dst_handle , dst_f ,
2018-10-30 21:32:47 +03:00
src_f ? le32_to_cpu ( src_f - > u64s ) : 0 ) ;
2017-03-17 09:18:50 +03:00
2018-10-30 21:32:47 +03:00
if ( src_f )
memcpy ( dst_f , src_f , vstruct_bytes ( src_f ) ) ;
2017-03-17 09:18:50 +03:00
}
2023-02-13 06:08:39 +03:00
return 0 ;
2017-03-17 09:18:50 +03:00
}
int bch2_sb_to_fs ( struct bch_fs * c , struct bch_sb * src )
{
int ret ;
lockdep_assert_held ( & c - > sb_lock ) ;
2023-02-13 06:08:39 +03:00
ret = bch2_sb_realloc ( & c - > disk_sb , 0 ) ? :
__copy_super ( & c - > disk_sb , src ) ? :
bch2_sb_replicas_to_cpu_replicas ( c ) ? :
bch2_sb_disk_groups_to_cpu ( c ) ;
2017-03-17 09:18:50 +03:00
if ( ret )
return ret ;
bch2_sb_update ( c ) ;
return 0 ;
}
int bch2_sb_from_fs ( struct bch_fs * c , struct bch_dev * ca )
{
2023-02-13 06:08:39 +03:00
return __copy_super ( & ca - > disk_sb , c - > disk_sb . sb ) ;
2017-03-17 09:18:50 +03:00
}
/* read superblock: */
2022-01-04 07:38:50 +03:00
static int read_one_super ( struct bch_sb_handle * sb , u64 offset , struct printbuf * err )
2017-03-17 09:18:50 +03:00
{
struct bch_csum csum ;
size_t bytes ;
2022-01-04 07:38:50 +03:00
int ret ;
2017-03-17 09:18:50 +03:00
reread :
bio_reset ( sb - > bio , sb - > bdev , REQ_OP_READ | REQ_SYNC | REQ_META ) ;
sb - > bio - > bi_iter . bi_sector = offset ;
2021-04-06 21:00:56 +03:00
bch2_bio_map ( sb - > bio , sb - > sb , sb - > buffer_size ) ;
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
ret = submit_bio_wait ( sb - > bio ) ;
if ( ret ) {
2023-02-04 05:01:40 +03:00
prt_printf ( err , " IO error: %i " , ret ) ;
2022-01-04 07:38:50 +03:00
return ret ;
}
2017-03-17 09:18:50 +03:00
if ( ! uuid_equal ( & sb - > sb - > magic , & BCACHE_MAGIC ) & &
2022-01-04 07:38:50 +03:00
! uuid_equal ( & sb - > sb - > magic , & BCHFS_MAGIC ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( err , " Not a bcachefs superblock " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_magic ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2023-06-29 03:27:07 +03:00
ret = bch2_sb_compatible ( sb - > sb , err ) ;
if ( ret )
return ret ;
2017-03-17 09:18:50 +03:00
bytes = vstruct_bytes ( sb - > sb ) ;
2022-01-04 07:38:50 +03:00
if ( bytes > 512 < < sb - > sb - > layout . sb_max_size_bits ) {
2023-02-04 05:01:40 +03:00
prt_printf ( err , " Invalid superblock: too big (got %zu bytes, layout max %lu) " ,
2022-01-04 07:38:50 +03:00
bytes , 512UL < < sb - > sb - > layout . sb_max_size_bits ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_too_big ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2021-04-06 21:00:56 +03:00
if ( bytes > sb - > buffer_size ) {
2023-03-14 22:35:57 +03:00
ret = bch2_sb_realloc ( sb , le32_to_cpu ( sb - > sb - > u64s ) ) ;
if ( ret )
return ret ;
2017-03-17 09:18:50 +03:00
goto reread ;
}
2022-01-04 07:38:50 +03:00
if ( BCH_SB_CSUM_TYPE ( sb - > sb ) > = BCH_CSUM_NR ) {
2023-02-04 05:01:40 +03:00
prt_printf ( err , " unknown checksum type %llu " , BCH_SB_CSUM_TYPE ( sb - > sb ) ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_csum_type ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
/* XXX: verify MACs */
csum = csum_vstruct ( NULL , BCH_SB_CSUM_TYPE ( sb - > sb ) ,
null_nonce ( ) , sb - > sb ) ;
2022-01-04 07:38:50 +03:00
if ( bch2_crc_cmp ( csum , sb - > sb - > csum ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( err , " bad checksum " ) ;
2022-11-20 06:39:08 +03:00
return - BCH_ERR_invalid_sb_csum ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2019-03-22 06:13:46 +03:00
sb - > seq = le64_to_cpu ( sb - > sb - > seq ) ;
2022-01-04 07:38:50 +03:00
return 0 ;
2017-03-17 09:18:50 +03:00
}
int bch2_read_super ( const char * path , struct bch_opts * opts ,
struct bch_sb_handle * sb )
{
u64 offset = opt_get ( * opts , sb ) ;
struct bch_sb_layout layout ;
2022-02-25 21:18:19 +03:00
struct printbuf err = PRINTBUF ;
2017-03-17 09:18:50 +03:00
__le64 * i ;
int ret ;
2023-07-11 03:30:04 +03:00
# ifndef __KERNEL__
retry :
# endif
2017-03-17 09:18:50 +03:00
memset ( sb , 0 , sizeof ( * sb ) ) ;
sb - > mode = BLK_OPEN_READ ;
sb - > have_bio = true ;
sb - > holder = kmalloc ( 1 , GFP_KERNEL ) ;
if ( ! sb - > holder )
return - ENOMEM ;
2023-07-11 03:30:04 +03:00
# ifndef __KERNEL__
if ( opt_get ( * opts , direct_io ) = = false )
2023-09-24 02:07:16 +03:00
sb - > mode | = BLK_OPEN_BUFFERED ;
2023-07-11 03:30:04 +03:00
# endif
2017-03-17 09:18:50 +03:00
if ( ! opt_get ( * opts , noexcl ) )
sb - > mode | = BLK_OPEN_EXCL ;
if ( ! opt_get ( * opts , nochanges ) )
sb - > mode | = BLK_OPEN_WRITE ;
sb - > bdev = blkdev_get_by_path ( path , sb - > mode , sb - > holder , & bch2_sb_handle_bdev_ops ) ;
if ( IS_ERR ( sb - > bdev ) & &
PTR_ERR ( sb - > bdev ) = = - EACCES & &
opt_get ( * opts , read_only ) ) {
sb - > mode & = ~ BLK_OPEN_WRITE ;
sb - > bdev = blkdev_get_by_path ( path , sb - > mode , sb - > holder , & bch2_sb_handle_bdev_ops ) ;
if ( ! IS_ERR ( sb - > bdev ) )
opt_set ( * opts , nochanges , true ) ;
}
if ( IS_ERR ( sb - > bdev ) ) {
ret = PTR_ERR ( sb - > bdev ) ;
goto out ;
}
ret = bch2_sb_realloc ( sb , 0 ) ;
2022-01-04 07:38:50 +03:00
if ( ret ) {
2023-02-04 05:01:40 +03:00
prt_printf ( & err , " error allocating memory for superblock " ) ;
2017-03-17 09:18:50 +03:00
goto err ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
if ( bch2_fs_init_fault ( " read_super " ) ) {
2023-02-04 05:01:40 +03:00
prt_printf ( & err , " dynamic fault " ) ;
2022-01-04 07:38:50 +03:00
ret = - EFAULT ;
2017-03-17 09:18:50 +03:00
goto err ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
ret = read_one_super ( sb , offset , & err ) ;
if ( ! ret )
2017-03-17 09:18:50 +03:00
goto got_super ;
if ( opt_defined ( * opts , sb ) )
goto err ;
2022-01-04 07:38:50 +03:00
printk ( KERN_ERR " bcachefs (%s): error reading default superblock: %s " ,
2022-02-25 21:18:19 +03:00
path , err . buf ) ;
printbuf_reset ( & err ) ;
2017-03-17 09:18:50 +03:00
/*
* Error reading primary superblock - read location of backup
* superblocks :
*/
bio_reset ( sb - > bio , sb - > bdev , REQ_OP_READ | REQ_SYNC | REQ_META ) ;
sb - > bio - > bi_iter . bi_sector = BCH_SB_LAYOUT_SECTOR ;
/*
* use sb buffer to read layout , since sb buffer is page aligned but
* layout won ' t be :
*/
2019-07-04 02:27:42 +03:00
bch2_bio_map ( sb - > bio , sb - > sb , sizeof ( struct bch_sb_layout ) ) ;
2017-03-17 09:18:50 +03:00
2022-01-04 07:38:50 +03:00
ret = submit_bio_wait ( sb - > bio ) ;
if ( ret ) {
2023-02-04 05:01:40 +03:00
prt_printf ( & err , " IO error: %i " , ret ) ;
2017-03-17 09:18:50 +03:00
goto err ;
2022-01-04 07:38:50 +03:00
}
2017-03-17 09:18:50 +03:00
memcpy ( & layout , sb - > sb , sizeof ( layout ) ) ;
2022-01-04 07:38:50 +03:00
ret = validate_sb_layout ( & layout , & err ) ;
if ( ret )
2017-03-17 09:18:50 +03:00
goto err ;
for ( i = layout . sb_offset ;
i < layout . sb_offset + layout . nr_superblocks ; i + + ) {
offset = le64_to_cpu ( * i ) ;
if ( offset = = opt_get ( * opts , sb ) )
continue ;
2022-01-04 07:38:50 +03:00
ret = read_one_super ( sb , offset , & err ) ;
if ( ! ret )
2017-03-17 09:18:50 +03:00
goto got_super ;
}
goto err ;
got_super :
if ( le16_to_cpu ( sb - > sb - > block_size ) < < 9 <
2023-07-11 03:30:04 +03:00
bdev_logical_block_size ( sb - > bdev ) & &
opt_get ( * opts , direct_io ) ) {
# ifndef __KERNEL__
opt_set ( * opts , direct_io , false ) ;
bch2_free_super ( sb ) ;
goto retry ;
# endif
2023-02-04 05:01:40 +03:00
prt_printf ( & err , " block size (%u) smaller than device block size (%u) " ,
2021-12-14 22:24:41 +03:00
le16_to_cpu ( sb - > sb - > block_size ) < < 9 ,
bdev_logical_block_size ( sb - > bdev ) ) ;
2022-11-20 06:39:08 +03:00
ret = - BCH_ERR_block_size_too_small ;
2022-01-04 07:38:50 +03:00
goto err ;
2021-12-14 22:24:41 +03:00
}
2017-03-17 09:18:50 +03:00
ret = 0 ;
sb - > have_layout = true ;
2022-01-04 07:38:50 +03:00
2022-03-21 10:03:03 +03:00
ret = bch2_sb_validate ( sb , & err , READ ) ;
2022-01-04 07:38:50 +03:00
if ( ret ) {
printk ( KERN_ERR " bcachefs (%s): error validating superblock: %s " ,
2022-02-25 21:18:19 +03:00
path , err . buf ) ;
2022-01-04 07:38:50 +03:00
goto err_no_print ;
}
2017-03-17 09:18:50 +03:00
out :
2022-02-25 21:18:19 +03:00
printbuf_exit ( & err ) ;
2017-03-17 09:18:50 +03:00
return ret ;
err :
2022-01-04 07:38:50 +03:00
printk ( KERN_ERR " bcachefs (%s): error reading superblock: %s " ,
2022-02-25 21:18:19 +03:00
path , err . buf ) ;
2021-12-14 22:24:41 +03:00
err_no_print :
bch2_free_super ( sb ) ;
2017-03-17 09:18:50 +03:00
goto out ;
}
/* write superblock: */
static void write_super_endio ( struct bio * bio )
{
struct bch_dev * ca = bio - > bi_private ;
/* XXX: return errors directly */
2023-10-25 23:29:37 +03:00
if ( bch2_dev_io_err_on ( bio - > bi_status , ca ,
bio_data_dir ( bio )
? BCH_MEMBER_ERROR_write
: BCH_MEMBER_ERROR_read ,
" superblock %s error: %s " ,
bio_data_dir ( bio ) ? " write " : " read " ,
2020-07-21 20:34:22 +03:00
bch2_blk_status_to_str ( bio - > bi_status ) ) )
2017-03-17 09:18:50 +03:00
ca - > sb_write_error = 1 ;
closure_put ( & ca - > fs - > sb_write ) ;
percpu_ref_put ( & ca - > io_ref ) ;
}
2019-03-22 06:13:46 +03:00
static void read_back_super ( struct bch_fs * c , struct bch_dev * ca )
{
struct bch_sb * sb = ca - > disk_sb . sb ;
struct bio * bio = ca - > disk_sb . bio ;
bio_reset ( bio , ca - > disk_sb . bdev , REQ_OP_READ | REQ_SYNC | REQ_META ) ;
bio - > bi_iter . bi_sector = le64_to_cpu ( sb - > layout . sb_offset [ 0 ] ) ;
bio - > bi_end_io = write_super_endio ;
bio - > bi_private = ca ;
2019-07-04 02:27:42 +03:00
bch2_bio_map ( bio , ca - > sb_read_scratch , PAGE_SIZE ) ;
2019-03-22 06:13:46 +03:00
2020-07-10 01:28:11 +03:00
this_cpu_add ( ca - > io_done - > sectors [ READ ] [ BCH_DATA_sb ] ,
2019-03-22 06:13:46 +03:00
bio_sectors ( bio ) ) ;
percpu_ref_get ( & ca - > io_ref ) ;
closure_bio_submit ( bio , & c - > sb_write ) ;
}
2017-03-17 09:18:50 +03:00
static void write_one_super ( struct bch_fs * c , struct bch_dev * ca , unsigned idx )
{
struct bch_sb * sb = ca - > disk_sb . sb ;
struct bio * bio = ca - > disk_sb . bio ;
sb - > offset = sb - > layout . sb_offset [ idx ] ;
2021-06-13 23:01:08 +03:00
SET_BCH_SB_CSUM_TYPE ( sb , bch2_csum_opt_to_type ( c - > opts . metadata_checksum , false ) ) ;
2017-03-17 09:18:50 +03:00
sb - > csum = csum_vstruct ( c , BCH_SB_CSUM_TYPE ( sb ) ,
null_nonce ( ) , sb ) ;
bio_reset ( bio , ca - > disk_sb . bdev , REQ_OP_WRITE | REQ_SYNC | REQ_META ) ;
bio - > bi_iter . bi_sector = le64_to_cpu ( sb - > offset ) ;
bio - > bi_end_io = write_super_endio ;
bio - > bi_private = ca ;
2019-07-04 02:27:42 +03:00
bch2_bio_map ( bio , sb ,
roundup ( ( size_t ) vstruct_bytes ( sb ) ,
bdev_logical_block_size ( ca - > disk_sb . bdev ) ) ) ;
2017-03-17 09:18:50 +03:00
2020-07-10 01:28:11 +03:00
this_cpu_add ( ca - > io_done - > sectors [ WRITE ] [ BCH_DATA_sb ] ,
2017-03-17 09:18:50 +03:00
bio_sectors ( bio ) ) ;
percpu_ref_get ( & ca - > io_ref ) ;
closure_bio_submit ( bio , & c - > sb_write ) ;
}
2019-03-22 06:13:46 +03:00
int bch2_write_super ( struct bch_fs * c )
2017-03-17 09:18:50 +03:00
{
struct closure * cl = & c - > sb_write ;
struct bch_dev * ca ;
2022-02-25 21:18:19 +03:00
struct printbuf err = PRINTBUF ;
2017-03-17 09:18:50 +03:00
unsigned i , sb = 0 , nr_wrote ;
struct bch_devs_mask sb_written ;
bool wrote , can_mount_without_written , can_mount_with_written ;
2021-04-10 02:04:57 +03:00
unsigned degraded_flags = BCH_FORCE_IF_DEGRADED ;
2019-03-22 06:13:46 +03:00
int ret = 0 ;
2017-03-17 09:18:50 +03:00
2022-08-27 19:48:36 +03:00
trace_and_count ( c , write_super , c , _RET_IP_ ) ;
2022-04-03 22:13:20 +03:00
2021-04-10 02:04:57 +03:00
if ( c - > opts . very_degraded )
degraded_flags | = BCH_FORCE_IF_LOST ;
2017-03-17 09:18:50 +03:00
lockdep_assert_held ( & c - > sb_lock ) ;
closure_init_stack ( cl ) ;
memset ( & sb_written , 0 , sizeof ( sb_written ) ) ;
2023-06-28 05:09:35 +03:00
/* Make sure we're using the new magic numbers: */
c - > disk_sb . sb - > magic = BCHFS_MAGIC ;
c - > disk_sb . sb - > layout . magic = BCHFS_MAGIC ;
2022-12-03 03:46:49 +03:00
2017-03-17 09:18:50 +03:00
le64_add_cpu ( & c - > disk_sb . sb - > seq , 1 ) ;
2019-03-28 16:34:55 +03:00
if ( test_bit ( BCH_FS_ERROR , & c - > flags ) )
SET_BCH_SB_HAS_ERRORS ( c - > disk_sb . sb , 1 ) ;
2021-04-24 23:32:35 +03:00
if ( test_bit ( BCH_FS_TOPOLOGY_ERROR , & c - > flags ) )
SET_BCH_SB_HAS_TOPOLOGY_ERRORS ( c - > disk_sb . sb , 1 ) ;
2019-03-28 16:34:55 +03:00
2021-03-05 03:06:26 +03:00
SET_BCH_SB_BIG_ENDIAN ( c - > disk_sb . sb , CPU_BIG_ENDIAN ) ;
2022-03-15 11:36:33 +03:00
bch2_sb_counters_from_cpu ( c ) ;
2023-10-25 23:29:37 +03:00
bch2_sb_members_cpy_v2_v1 ( & c - > disk_sb ) ;
2022-03-15 11:36:33 +03:00
2017-03-17 09:18:50 +03:00
for_each_online_member ( ca , c , i )
bch2_sb_from_fs ( c , ca ) ;
for_each_online_member ( ca , c , i ) {
2022-02-25 21:18:19 +03:00
printbuf_reset ( & err ) ;
2022-01-04 07:38:50 +03:00
2022-03-21 10:03:03 +03:00
ret = bch2_sb_validate ( & ca - > disk_sb , & err , WRITE ) ;
2022-01-04 07:38:50 +03:00
if ( ret ) {
2022-02-25 21:18:19 +03:00
bch2_fs_inconsistent ( c , " sb invalid before write: %s " , err . buf ) ;
2022-01-04 07:38:50 +03:00
percpu_ref_put ( & ca - > io_ref ) ;
2017-03-17 09:18:50 +03:00
goto out ;
}
}
2019-03-28 16:34:55 +03:00
if ( c - > opts . nochanges )
2017-03-17 09:18:50 +03:00
goto out ;
2022-04-03 00:24:25 +03:00
/*
* Defer writing the superblock until filesystem initialization is
* complete - don ' t write out a partly initialized superblock :
*/
if ( ! BCH_SB_INITIALIZED ( c - > disk_sb . sb ) )
goto out ;
2017-03-17 09:18:50 +03:00
for_each_online_member ( ca , c , i ) {
__set_bit ( ca - > dev_idx , sb_written . d ) ;
ca - > sb_write_error = 0 ;
}
2019-03-22 06:13:46 +03:00
for_each_online_member ( ca , c , i )
read_back_super ( c , ca ) ;
closure_sync ( cl ) ;
for_each_online_member ( ca , c , i ) {
2022-01-02 03:04:33 +03:00
if ( ca - > sb_write_error )
continue ;
if ( le64_to_cpu ( ca - > sb_read_scratch - > seq ) < ca - > disk_sb . seq ) {
bch2_fs_fatal_error ( c ,
" Superblock write was silently dropped! (seq %llu expected %llu) " ,
le64_to_cpu ( ca - > sb_read_scratch - > seq ) ,
ca - > disk_sb . seq ) ;
percpu_ref_put ( & ca - > io_ref ) ;
2022-12-12 04:37:11 +03:00
ret = - BCH_ERR_erofs_sb_err ;
2022-01-02 03:04:33 +03:00
goto out ;
}
if ( le64_to_cpu ( ca - > sb_read_scratch - > seq ) > ca - > disk_sb . seq ) {
2019-03-22 06:13:46 +03:00
bch2_fs_fatal_error ( c ,
2022-01-02 03:04:33 +03:00
" Superblock modified by another process (seq %llu expected %llu) " ,
le64_to_cpu ( ca - > sb_read_scratch - > seq ) ,
ca - > disk_sb . seq ) ;
2019-03-22 06:13:46 +03:00
percpu_ref_put ( & ca - > io_ref ) ;
2022-12-12 04:37:11 +03:00
ret = - BCH_ERR_erofs_sb_err ;
2019-03-22 06:13:46 +03:00
goto out ;
}
}
2017-03-17 09:18:50 +03:00
do {
wrote = false ;
for_each_online_member ( ca , c , i )
2019-03-22 06:13:46 +03:00
if ( ! ca - > sb_write_error & &
sb < ca - > disk_sb . sb - > layout . nr_superblocks ) {
2017-03-17 09:18:50 +03:00
write_one_super ( c , ca , sb ) ;
wrote = true ;
}
closure_sync ( cl ) ;
sb + + ;
} while ( wrote ) ;
2019-03-22 06:13:46 +03:00
for_each_online_member ( ca , c , i ) {
2017-03-17 09:18:50 +03:00
if ( ca - > sb_write_error )
__clear_bit ( ca - > dev_idx , sb_written . d ) ;
2019-03-22 06:13:46 +03:00
else
ca - > disk_sb . seq = le64_to_cpu ( ca - > disk_sb . sb - > seq ) ;
}
2017-03-17 09:18:50 +03:00
nr_wrote = dev_mask_nr ( & sb_written ) ;
can_mount_with_written =
2021-04-10 02:04:57 +03:00
bch2_have_enough_devs ( c , sb_written , degraded_flags , false ) ;
2017-03-17 09:18:50 +03:00
for ( i = 0 ; i < ARRAY_SIZE ( sb_written . d ) ; i + + )
sb_written . d [ i ] = ~ sb_written . d [ i ] ;
can_mount_without_written =
2021-04-10 02:04:57 +03:00
bch2_have_enough_devs ( c , sb_written , degraded_flags , false ) ;
2017-03-17 09:18:50 +03:00
/*
* If we would be able to mount _without_ the devices we successfully
* wrote superblocks to , we weren ' t able to write to enough devices :
*
* Exception : if we can mount without the successes because we haven ' t
* written anything ( new filesystem ) , we continue if we ' d be able to
* mount with the devices we did successfully write to :
*/
2019-03-22 06:13:46 +03:00
if ( bch2_fs_fatal_err_on ( ! nr_wrote | |
2021-02-07 07:17:26 +03:00
! can_mount_with_written | |
2019-03-22 06:13:46 +03:00
( can_mount_without_written & &
! can_mount_with_written ) , c ,
2021-11-04 00:23:49 +03:00
" Unable to write superblock to sufficient devices (from %ps) " ,
( void * ) _RET_IP_ ) )
2019-03-22 06:13:46 +03:00
ret = - 1 ;
2017-03-17 09:18:50 +03:00
out :
/* Make new options visible after they're persistent: */
bch2_sb_update ( c ) ;
2022-02-25 21:18:19 +03:00
printbuf_exit ( & err ) ;
2019-03-22 06:13:46 +03:00
return ret ;
2017-03-17 09:18:50 +03:00
}
2019-11-29 21:47:42 +03:00
void __bch2_check_set_feature ( struct bch_fs * c , unsigned feat )
{
mutex_lock ( & c - > sb_lock ) ;
if ( ! ( c - > sb . features & ( 1ULL < < feat ) ) ) {
c - > disk_sb . sb - > features [ 0 ] | = cpu_to_le64 ( 1ULL < < feat ) ;
bch2_write_super ( c ) ;
}
mutex_unlock ( & c - > sb_lock ) ;
}
2023-07-10 19:23:01 +03:00
/* Downgrade if superblock is at a higher version than currently supported: */
void bch2_sb_maybe_downgrade ( struct bch_fs * c )
2017-03-17 09:18:50 +03:00
{
2023-07-10 19:23:01 +03:00
lockdep_assert_held ( & c - > sb_lock ) ;
2023-06-29 02:59:56 +03:00
2023-06-28 05:09:35 +03:00
/*
* Downgrade , if superblock is at a higher version than currently
* supported :
*/
2023-06-29 02:59:56 +03:00
if ( BCH_SB_VERSION_UPGRADE_COMPLETE ( c - > disk_sb . sb ) > bcachefs_metadata_version_current )
SET_BCH_SB_VERSION_UPGRADE_COMPLETE ( c - > disk_sb . sb , bcachefs_metadata_version_current ) ;
2023-06-28 05:09:35 +03:00
if ( c - > sb . version > bcachefs_metadata_version_current )
2023-06-29 02:59:56 +03:00
c - > disk_sb . sb - > version = cpu_to_le16 ( bcachefs_metadata_version_current ) ;
2023-06-28 05:09:35 +03:00
if ( c - > sb . version_min > bcachefs_metadata_version_current )
c - > disk_sb . sb - > version_min = cpu_to_le16 ( bcachefs_metadata_version_current ) ;
c - > disk_sb . sb - > compat [ 0 ] & = cpu_to_le64 ( ( 1ULL < < BCH_COMPAT_NR ) - 1 ) ;
2023-07-10 19:23:01 +03:00
}
void bch2_sb_upgrade ( struct bch_fs * c , unsigned new_version )
{
lockdep_assert_held ( & c - > sb_lock ) ;
2023-06-29 02:59:56 +03:00
2023-07-10 19:23:01 +03:00
c - > disk_sb . sb - > version = cpu_to_le16 ( new_version ) ;
c - > disk_sb . sb - > features [ 0 ] | = cpu_to_le64 ( BCH_SB_FEATURES_ALL ) ;
}
2017-03-17 09:18:50 +03:00
static const struct bch_sb_field_ops * bch2_sb_field_ops [ ] = {
# define x(f, nr) \
[ BCH_SB_FIELD_ # # f ] = & bch_sb_field_ops_ # # f ,
BCH_SB_FIELDS ( )
# undef x
} ;
2023-07-10 22:56:05 +03:00
static const struct bch_sb_field_ops bch2_sb_field_null_ops ;
2023-07-07 03:11:36 +03:00
static const struct bch_sb_field_ops * bch2_sb_field_type_ops ( unsigned type )
{
return likely ( type < ARRAY_SIZE ( bch2_sb_field_ops ) )
? bch2_sb_field_ops [ type ]
: & bch2_sb_field_null_ops ;
}
2022-01-04 07:38:50 +03:00
static int bch2_sb_field_validate ( struct bch_sb * sb , struct bch_sb_field * f ,
2022-02-27 19:57:42 +03:00
struct printbuf * err )
2017-03-17 09:18:50 +03:00
{
unsigned type = le32_to_cpu ( f - > type ) ;
2022-02-27 19:57:42 +03:00
struct printbuf field_err = PRINTBUF ;
2023-07-07 03:11:36 +03:00
const struct bch_sb_field_ops * ops = bch2_sb_field_type_ops ( type ) ;
2022-01-04 07:38:50 +03:00
int ret ;
2017-03-17 09:18:50 +03:00
2023-07-07 03:11:36 +03:00
ret = ops - > validate ? ops - > validate ( sb , f , & field_err ) : 0 ;
2022-01-04 07:38:50 +03:00
if ( ret ) {
2023-02-04 05:01:40 +03:00
prt_printf ( err , " Invalid superblock section %s: %s " ,
2023-07-07 03:11:36 +03:00
bch2_sb_fields [ type ] , field_err . buf ) ;
2023-02-04 05:01:40 +03:00
prt_newline ( err ) ;
2022-02-27 19:57:42 +03:00
bch2_sb_field_to_text ( err , sb , f ) ;
2022-01-04 07:38:50 +03:00
}
2022-02-27 19:57:42 +03:00
printbuf_exit ( & field_err ) ;
2022-01-04 07:38:50 +03:00
return ret ;
2017-03-17 09:18:50 +03:00
}
2018-11-09 09:24:07 +03:00
void bch2_sb_field_to_text ( struct printbuf * out , struct bch_sb * sb ,
struct bch_sb_field * f )
2017-03-17 09:18:50 +03:00
{
unsigned type = le32_to_cpu ( f - > type ) ;
2023-07-07 03:11:36 +03:00
const struct bch_sb_field_ops * ops = bch2_sb_field_type_ops ( type ) ;
2017-03-17 09:18:50 +03:00
2023-02-04 05:01:40 +03:00
if ( ! out - > nr_tabstops )
printbuf_tabstop_push ( out , 32 ) ;
2022-03-05 20:01:16 +03:00
2023-07-07 03:11:36 +03:00
if ( type < BCH_SB_FIELD_NR )
2023-02-04 05:01:40 +03:00
prt_printf ( out , " %s " , bch2_sb_fields [ type ] ) ;
2018-11-09 09:24:07 +03:00
else
2023-02-04 05:01:40 +03:00
prt_printf ( out , " (unknown field %u) " , type ) ;
2018-11-09 09:24:07 +03:00
2023-02-04 05:01:40 +03:00
prt_printf ( out , " (size %zu): " , vstruct_bytes ( f ) ) ;
prt_newline ( out ) ;
2017-03-17 09:18:50 +03:00
2023-07-07 03:11:36 +03:00
if ( ops - > to_text ) {
2023-02-04 05:01:40 +03:00
printbuf_indent_add ( out , 2 ) ;
2023-07-07 03:11:36 +03:00
ops - > to_text ( out , sb , f ) ;
2023-02-04 05:01:40 +03:00
printbuf_indent_sub ( out , 2 ) ;
2022-02-20 13:00:45 +03:00
}
}
void bch2_sb_layout_to_text ( struct printbuf * out , struct bch_sb_layout * l )
{
unsigned i ;
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Type: %u " , l - > layout_type ) ;
prt_newline ( out ) ;
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
prt_str ( out , " Superblock max size: " ) ;
prt_units_u64 ( out , 512 < < l - > sb_max_size_bits ) ;
prt_newline ( out ) ;
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Nr superblocks: %u " , l - > nr_superblocks ) ;
prt_newline ( out ) ;
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
prt_str ( out , " Offsets: " ) ;
2022-02-20 13:00:45 +03:00
for ( i = 0 ; i < l - > nr_superblocks ; i + + ) {
if ( i )
2023-02-04 05:01:40 +03:00
prt_str ( out , " , " ) ;
prt_printf ( out , " %llu " , le64_to_cpu ( l - > sb_offset [ i ] ) ) ;
2022-02-20 13:00:45 +03:00
}
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
2022-02-20 13:00:45 +03:00
}
void bch2_sb_to_text ( struct printbuf * out , struct bch_sb * sb ,
bool print_layout , unsigned fields )
{
struct bch_sb_field * f ;
u64 fields_have = 0 ;
unsigned nr_devices = 0 ;
2023-02-04 05:01:40 +03:00
if ( ! out - > nr_tabstops )
2022-09-17 01:39:01 +03:00
printbuf_tabstop_push ( out , 44 ) ;
2022-03-05 20:01:16 +03:00
2023-09-25 06:55:37 +03:00
for ( int i = 0 ; i < sb - > nr_devices ; i + + )
nr_devices + = bch2_dev_exists ( sb , i ) ;
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
prt_printf ( out , " External UUID: " ) ;
prt_tab ( out ) ;
2022-02-20 13:00:45 +03:00
pr_uuid ( out , sb - > user_uuid . b ) ;
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Internal UUID: " ) ;
prt_tab ( out ) ;
2022-02-20 13:00:45 +03:00
pr_uuid ( out , sb - > uuid . b ) ;
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
prt_str ( out , " Device index: " ) ;
prt_tab ( out ) ;
prt_printf ( out , " %u " , sb - > dev_idx ) ;
prt_newline ( out ) ;
prt_str ( out , " Label: " ) ;
prt_tab ( out ) ;
prt_printf ( out , " %.*s " , ( int ) sizeof ( sb - > label ) , sb - > label ) ;
prt_newline ( out ) ;
prt_str ( out , " Version: " ) ;
prt_tab ( out ) ;
2023-06-29 02:53:05 +03:00
bch2_version_to_text ( out , le16_to_cpu ( sb - > version ) ) ;
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
2023-06-29 02:59:56 +03:00
prt_str ( out , " Version upgrade complete: " ) ;
prt_tab ( out ) ;
bch2_version_to_text ( out , BCH_SB_VERSION_UPGRADE_COMPLETE ( sb ) ) ;
prt_newline ( out ) ;
2023-02-04 05:01:40 +03:00
prt_printf ( out , " Oldest version on disk: " ) ;
prt_tab ( out ) ;
2023-06-29 02:53:05 +03:00
bch2_version_to_text ( out , le16_to_cpu ( sb - > version_min ) ) ;
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
prt_printf ( out , " Created: " ) ;
prt_tab ( out ) ;
2022-02-20 13:00:45 +03:00
if ( sb - > time_base_lo )
2022-02-23 19:46:34 +03:00
pr_time ( out , div_u64 ( le64_to_cpu ( sb - > time_base_lo ) , NSEC_PER_SEC ) ) ;
2022-02-20 13:00:45 +03:00
else
2023-02-04 05:01:40 +03:00
prt_printf ( out , " (not set) " ) ;
prt_newline ( out ) ;
prt_printf ( out , " Sequence number: " ) ;
prt_tab ( out ) ;
prt_printf ( out , " %llu " , le64_to_cpu ( sb - > seq ) ) ;
prt_newline ( out ) ;
prt_printf ( out , " Superblock size: " ) ;
prt_tab ( out ) ;
prt_printf ( out , " %zu " , vstruct_bytes ( sb ) ) ;
prt_newline ( out ) ;
prt_printf ( out , " Clean: " ) ;
prt_tab ( out ) ;
prt_printf ( out , " %llu " , BCH_SB_CLEAN ( sb ) ) ;
prt_newline ( out ) ;
prt_printf ( out , " Devices: " ) ;
prt_tab ( out ) ;
prt_printf ( out , " %u " , nr_devices ) ;
prt_newline ( out ) ;
prt_printf ( out , " Sections: " ) ;
2022-03-05 20:01:16 +03:00
vstruct_for_each ( sb , f )
fields_have | = 1 < < le32_to_cpu ( f - > type ) ;
2023-02-04 05:01:40 +03:00
prt_tab ( out ) ;
prt_bitflags ( out , bch2_sb_fields , fields_have ) ;
prt_newline ( out ) ;
prt_printf ( out , " Features: " ) ;
prt_tab ( out ) ;
prt_bitflags ( out , bch2_sb_features , le64_to_cpu ( sb - > features [ 0 ] ) ) ;
prt_newline ( out ) ;
prt_printf ( out , " Compat features: " ) ;
prt_tab ( out ) ;
prt_bitflags ( out , bch2_sb_compat , le64_to_cpu ( sb - > compat [ 0 ] ) ) ;
prt_newline ( out ) ;
prt_newline ( out ) ;
prt_printf ( out , " Options: " ) ;
prt_newline ( out ) ;
printbuf_indent_add ( out , 2 ) ;
2022-03-05 20:01:16 +03:00
{
enum bch_opt_id id ;
2022-02-20 13:00:45 +03:00
2022-03-05 20:01:16 +03:00
for ( id = 0 ; id < bch2_opts_nr ; id + + ) {
const struct bch_option * opt = bch2_opt_table + id ;
2022-02-20 13:00:45 +03:00
2022-03-05 20:01:16 +03:00
if ( opt - > get_sb ! = BCH2_NO_SB_OPT ) {
u64 v = bch2_opt_from_sb ( sb , id ) ;
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
prt_printf ( out , " %s: " , opt - > attr . name ) ;
prt_tab ( out ) ;
2022-03-05 20:01:16 +03:00
bch2_opt_to_text ( out , NULL , sb , opt , v ,
OPT_HUMAN_READABLE | OPT_SHOW_FULL_LIST ) ;
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
2022-03-05 20:01:16 +03:00
}
}
}
2022-02-20 13:00:45 +03:00
2023-02-04 05:01:40 +03:00
printbuf_indent_sub ( out , 2 ) ;
2022-02-20 13:00:45 +03:00
if ( print_layout ) {
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
prt_printf ( out , " layout: " ) ;
prt_newline ( out ) ;
printbuf_indent_add ( out , 2 ) ;
2022-02-20 13:00:45 +03:00
bch2_sb_layout_to_text ( out , & sb - > layout ) ;
2023-02-04 05:01:40 +03:00
printbuf_indent_sub ( out , 2 ) ;
2022-02-20 13:00:45 +03:00
}
vstruct_for_each ( sb , f )
if ( fields & ( 1 < < le32_to_cpu ( f - > type ) ) ) {
2023-02-04 05:01:40 +03:00
prt_newline ( out ) ;
2022-02-20 13:00:45 +03:00
bch2_sb_field_to_text ( out , sb , f ) ;
}
2017-03-17 09:18:50 +03:00
}