2017-03-16 22:18:50 -08:00
// SPDX-License-Identifier: GPL-2.0
# include "bcachefs.h"
# include "disk_groups.h"
2023-08-05 15:40:21 -04:00
# include "sb-members.h"
2017-03-16 22:18:50 -08:00
# include "super-io.h"
# include <linux/sort.h>
static int group_cmp ( const void * _l , const void * _r )
{
const struct bch_disk_group * l = _l ;
const struct bch_disk_group * r = _r ;
return ( ( BCH_GROUP_DELETED ( l ) > BCH_GROUP_DELETED ( r ) ) -
( BCH_GROUP_DELETED ( l ) < BCH_GROUP_DELETED ( r ) ) ) ? :
( ( BCH_GROUP_PARENT ( l ) > BCH_GROUP_PARENT ( r ) ) -
( BCH_GROUP_PARENT ( l ) < BCH_GROUP_PARENT ( r ) ) ) ? :
strncmp ( l - > label , r - > label , sizeof ( l - > label ) ) ;
}
2022-01-03 23:38:50 -05:00
static int bch2_sb_disk_groups_validate ( struct bch_sb * sb ,
struct bch_sb_field * f ,
struct printbuf * err )
2017-03-16 22:18:50 -08:00
{
struct bch_sb_field_disk_groups * groups =
field_to_type ( f , disk_groups ) ;
struct bch_disk_group * g , * sorted = NULL ;
2022-01-03 23:38:50 -05:00
unsigned nr_groups = disk_groups_nr ( groups ) ;
unsigned i , len ;
2022-11-19 22:39:08 -05:00
int ret = 0 ;
2022-01-03 23:38:50 -05:00
for ( i = 0 ; i < sb - > nr_devices ; i + + ) {
2023-09-24 23:55:37 -04:00
struct bch_member m = bch2_sb_member_get ( sb , i ) ;
2023-09-12 18:41:22 -04:00
unsigned group_id ;
2017-03-16 22:18:50 -08:00
2023-09-24 23:55:37 -04:00
if ( ! BCH_MEMBER_GROUP ( & m ) )
2017-03-16 22:18:50 -08:00
continue ;
2023-09-24 23:55:37 -04:00
group_id = BCH_MEMBER_GROUP ( & m ) - 1 ;
2017-03-16 22:18:50 -08:00
2023-09-12 18:41:22 -04:00
if ( group_id > = nr_groups ) {
2023-02-03 21:01:40 -05:00
prt_printf ( err , " disk %u has invalid label %u (have %u) " ,
2023-09-12 18:41:22 -04:00
i , group_id , nr_groups ) ;
2022-11-19 22:39:08 -05:00
return - BCH_ERR_invalid_sb_disk_groups ;
2022-01-03 23:38:50 -05:00
}
2023-09-12 18:41:22 -04:00
if ( BCH_GROUP_DELETED ( & groups - > entries [ group_id ] ) ) {
prt_printf ( err , " disk %u has deleted label %u " , i , group_id ) ;
2022-11-19 22:39:08 -05:00
return - BCH_ERR_invalid_sb_disk_groups ;
2022-01-03 23:38:50 -05:00
}
2017-03-16 22:18:50 -08:00
}
if ( ! nr_groups )
2022-01-03 23:38:50 -05:00
return 0 ;
for ( i = 0 ; i < nr_groups ; i + + ) {
g = groups - > entries + i ;
2017-03-16 22:18:50 -08:00
if ( BCH_GROUP_DELETED ( g ) )
continue ;
len = strnlen ( g - > label , sizeof ( g - > label ) ) ;
if ( ! len ) {
2023-02-03 21:01:40 -05:00
prt_printf ( err , " label %u empty " , i ) ;
2022-11-19 22:39:08 -05:00
return - BCH_ERR_invalid_sb_disk_groups ;
2017-03-16 22:18:50 -08:00
}
}
sorted = kmalloc_array ( nr_groups , sizeof ( * sorted ) , GFP_KERNEL ) ;
if ( ! sorted )
2023-03-14 15:35:57 -04:00
return - BCH_ERR_ENOMEM_disk_groups_validate ;
2017-03-16 22:18:50 -08:00
memcpy ( sorted , groups - > entries , nr_groups * sizeof ( * sorted ) ) ;
sort ( sorted , nr_groups , sizeof ( * sorted ) , group_cmp , NULL ) ;
2022-01-03 23:38:50 -05:00
for ( g = sorted ; g + 1 < sorted + nr_groups ; g + + )
if ( ! BCH_GROUP_DELETED ( g ) & &
! group_cmp ( & g [ 0 ] , & g [ 1 ] ) ) {
2023-02-03 21:01:40 -05:00
prt_printf ( err , " duplicate label %llu.%.*s " ,
2022-02-20 04:52:44 -05:00
BCH_GROUP_PARENT ( g ) ,
( int ) sizeof ( g - > label ) , g - > label ) ;
2022-11-19 22:39:08 -05:00
ret = - BCH_ERR_invalid_sb_disk_groups ;
2017-03-16 22:18:50 -08:00
goto err ;
}
err :
kfree ( sorted ) ;
2022-11-19 22:39:08 -05:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2023-05-30 14:41:50 -04:00
void bch2_disk_groups_to_text ( struct printbuf * out , struct bch_fs * c )
{
out - > atomic + + ;
rcu_read_lock ( ) ;
2023-12-17 02:34:05 -05:00
struct bch_disk_groups_cpu * g = rcu_dereference ( c - > disk_groups ) ;
2023-05-30 14:41:50 -04:00
if ( ! g )
goto out ;
2023-12-17 02:34:05 -05:00
for ( unsigned i = 0 ; i < g - > nr ; i + + ) {
2023-05-30 14:41:50 -04:00
if ( i )
prt_printf ( out , " " ) ;
if ( g - > entries [ i ] . deleted ) {
prt_printf ( out , " [deleted] " ) ;
continue ;
}
prt_printf ( out , " [parent %d devs " , g - > entries [ i ] . parent ) ;
2023-12-17 02:34:05 -05:00
for_each_member_device_rcu ( c , ca , & g - > entries [ i ] . devs )
2023-05-30 14:41:50 -04:00
prt_printf ( out , " %s " , ca - > name ) ;
prt_printf ( out , " ] " ) ;
}
out :
rcu_read_unlock ( ) ;
out - > atomic - - ;
}
2018-11-09 01:24:07 -05:00
static void bch2_sb_disk_groups_to_text ( struct printbuf * out ,
2017-03-16 22:18:50 -08:00
struct bch_sb * sb ,
struct bch_sb_field * f )
{
struct bch_sb_field_disk_groups * groups =
field_to_type ( f , disk_groups ) ;
struct bch_disk_group * g ;
unsigned nr_groups = disk_groups_nr ( groups ) ;
for ( g = groups - > entries ;
g < groups - > entries + nr_groups ;
g + + ) {
if ( g ! = groups - > entries )
2023-02-03 21:01:40 -05:00
prt_printf ( out , " " ) ;
2017-03-16 22:18:50 -08:00
if ( BCH_GROUP_DELETED ( g ) )
2023-02-03 21:01:40 -05:00
prt_printf ( out , " [deleted] " ) ;
2017-03-16 22:18:50 -08:00
else
2023-02-03 21:01:40 -05:00
prt_printf ( out , " [parent %llu name %s] " ,
2018-11-09 01:24:07 -05:00
BCH_GROUP_PARENT ( g ) , g - > label ) ;
2017-03-16 22:18:50 -08:00
}
}
const struct bch_sb_field_ops bch_sb_field_ops_disk_groups = {
. validate = bch2_sb_disk_groups_validate ,
. to_text = bch2_sb_disk_groups_to_text
} ;
int bch2_sb_disk_groups_to_cpu ( struct bch_fs * c )
{
struct bch_sb_field_disk_groups * groups ;
struct bch_disk_groups_cpu * cpu_g , * old_g ;
unsigned i , g , nr_groups ;
lockdep_assert_held ( & c - > sb_lock ) ;
2023-09-26 17:49:34 -04:00
groups = bch2_sb_field_get ( c - > disk_sb . sb , disk_groups ) ;
2017-03-16 22:18:50 -08:00
nr_groups = disk_groups_nr ( groups ) ;
if ( ! groups )
return 0 ;
2023-10-01 09:13:54 +02:00
cpu_g = kzalloc ( struct_size ( cpu_g , entries , nr_groups ) , GFP_KERNEL ) ;
2017-03-16 22:18:50 -08:00
if ( ! cpu_g )
2023-03-14 15:35:57 -04:00
return - BCH_ERR_ENOMEM_disk_groups_to_cpu ;
2017-03-16 22:18:50 -08:00
cpu_g - > nr = nr_groups ;
for ( i = 0 ; i < nr_groups ; i + + ) {
struct bch_disk_group * src = & groups - > entries [ i ] ;
struct bch_disk_group_cpu * dst = & cpu_g - > entries [ i ] ;
dst - > deleted = BCH_GROUP_DELETED ( src ) ;
dst - > parent = BCH_GROUP_PARENT ( src ) ;
2023-10-22 11:12:14 -04:00
memcpy ( dst - > label , src - > label , sizeof ( dst - > label ) ) ;
2017-03-16 22:18:50 -08:00
}
for ( i = 0 ; i < c - > disk_sb . sb - > nr_devices ; i + + ) {
2023-09-24 23:55:37 -04:00
struct bch_member m = bch2_sb_member_get ( c - > disk_sb . sb , i ) ;
2023-09-12 13:37:41 +01:00
struct bch_disk_group_cpu * dst ;
2017-03-16 22:18:50 -08:00
2023-09-24 23:55:37 -04:00
if ( ! bch2_member_exists ( & m ) )
2017-03-16 22:18:50 -08:00
continue ;
2023-09-24 23:55:37 -04:00
g = BCH_MEMBER_GROUP ( & m ) ;
2017-03-16 22:18:50 -08:00
while ( g ) {
dst = & cpu_g - > entries [ g - 1 ] ;
__set_bit ( i , dst - > devs . d ) ;
g = dst - > parent ;
}
}
old_g = rcu_dereference_protected ( c - > disk_groups ,
lockdep_is_held ( & c - > sb_lock ) ) ;
rcu_assign_pointer ( c - > disk_groups , cpu_g ) ;
if ( old_g )
kfree_rcu ( old_g , rcu ) ;
return 0 ;
}
const struct bch_devs_mask * bch2_target_to_mask ( struct bch_fs * c , unsigned target )
{
struct target t = target_decode ( target ) ;
2023-05-30 14:48:58 -04:00
struct bch_devs_mask * devs ;
rcu_read_lock ( ) ;
2017-03-16 22:18:50 -08:00
switch ( t . type ) {
case TARGET_NULL :
2023-05-30 14:48:58 -04:00
devs = NULL ;
break ;
2017-03-16 22:18:50 -08:00
case TARGET_DEV : {
struct bch_dev * ca = t . dev < c - > sb . nr_devices
? rcu_dereference ( c - > devs [ t . dev ] )
: NULL ;
2023-05-30 14:48:58 -04:00
devs = ca ? & ca - > self : NULL ;
break ;
2017-03-16 22:18:50 -08:00
}
case TARGET_GROUP : {
struct bch_disk_groups_cpu * g = rcu_dereference ( c - > disk_groups ) ;
2023-05-30 14:48:58 -04:00
devs = g & & t . group < g - > nr & & ! g - > entries [ t . group ] . deleted
2017-03-16 22:18:50 -08:00
? & g - > entries [ t . group ] . devs
: NULL ;
2023-05-30 14:48:58 -04:00
break ;
2017-03-16 22:18:50 -08:00
}
default :
BUG ( ) ;
}
2023-05-30 14:48:58 -04:00
rcu_read_unlock ( ) ;
return devs ;
2017-03-16 22:18:50 -08:00
}
bool bch2_dev_in_target ( struct bch_fs * c , unsigned dev , unsigned target )
{
struct target t = target_decode ( target ) ;
switch ( t . type ) {
case TARGET_NULL :
return false ;
case TARGET_DEV :
return dev = = t . dev ;
case TARGET_GROUP : {
struct bch_disk_groups_cpu * g ;
const struct bch_devs_mask * m ;
bool ret ;
rcu_read_lock ( ) ;
g = rcu_dereference ( c - > disk_groups ) ;
2020-08-06 15:22:24 -04:00
m = g & & t . group < g - > nr & & ! g - > entries [ t . group ] . deleted
2017-03-16 22:18:50 -08:00
? & g - > entries [ t . group ] . devs
: NULL ;
ret = m ? test_bit ( dev , m - > d ) : false ;
rcu_read_unlock ( ) ;
return ret ;
}
default :
BUG ( ) ;
}
}
static int __bch2_disk_group_find ( struct bch_sb_field_disk_groups * groups ,
unsigned parent ,
const char * name , unsigned namelen )
{
unsigned i , nr_groups = disk_groups_nr ( groups ) ;
if ( ! namelen | | namelen > BCH_SB_LABEL_SIZE )
return - EINVAL ;
for ( i = 0 ; i < nr_groups ; i + + ) {
struct bch_disk_group * g = groups - > entries + i ;
if ( BCH_GROUP_DELETED ( g ) )
continue ;
if ( ! BCH_GROUP_DELETED ( g ) & &
BCH_GROUP_PARENT ( g ) = = parent & &
strnlen ( g - > label , sizeof ( g - > label ) ) = = namelen & &
! memcmp ( name , g - > label , namelen ) )
return i ;
}
return - 1 ;
}
static int __bch2_disk_group_add ( struct bch_sb_handle * sb , unsigned parent ,
const char * name , unsigned namelen )
{
struct bch_sb_field_disk_groups * groups =
2023-09-26 17:49:34 -04:00
bch2_sb_field_get ( sb - > sb , disk_groups ) ;
2017-03-16 22:18:50 -08:00
unsigned i , nr_groups = disk_groups_nr ( groups ) ;
struct bch_disk_group * g ;
if ( ! namelen | | namelen > BCH_SB_LABEL_SIZE )
return - EINVAL ;
for ( i = 0 ;
i < nr_groups & & ! BCH_GROUP_DELETED ( & groups - > entries [ i ] ) ;
i + + )
;
if ( i = = nr_groups ) {
unsigned u64s =
( sizeof ( struct bch_sb_field_disk_groups ) +
sizeof ( struct bch_disk_group ) * ( nr_groups + 1 ) ) /
sizeof ( u64 ) ;
2023-09-26 17:49:34 -04:00
groups = bch2_sb_field_resize ( sb , disk_groups , u64s ) ;
2017-03-16 22:18:50 -08:00
if ( ! groups )
2022-09-18 17:10:33 -04:00
return - BCH_ERR_ENOSPC_disk_label_add ;
2017-03-16 22:18:50 -08:00
nr_groups = disk_groups_nr ( groups ) ;
}
BUG_ON ( i > = nr_groups ) ;
g = & groups - > entries [ i ] ;
memcpy ( g - > label , name , namelen ) ;
if ( namelen < sizeof ( g - > label ) )
g - > label [ namelen ] = ' \0 ' ;
SET_BCH_GROUP_DELETED ( g , 0 ) ;
SET_BCH_GROUP_PARENT ( g , parent ) ;
SET_BCH_GROUP_DATA_ALLOWED ( g , ~ 0 ) ;
return i ;
}
int bch2_disk_path_find ( struct bch_sb_handle * sb , const char * name )
{
struct bch_sb_field_disk_groups * groups =
2023-09-26 17:49:34 -04:00
bch2_sb_field_get ( sb - > sb , disk_groups ) ;
2017-03-16 22:18:50 -08:00
int v = - 1 ;
do {
const char * next = strchrnul ( name , ' . ' ) ;
unsigned len = next - name ;
if ( * next = = ' . ' )
next + + ;
v = __bch2_disk_group_find ( groups , v + 1 , name , len ) ;
name = next ;
} while ( * name & & v > = 0 ) ;
return v ;
}
int bch2_disk_path_find_or_create ( struct bch_sb_handle * sb , const char * name )
{
struct bch_sb_field_disk_groups * groups ;
unsigned parent = 0 ;
int v = - 1 ;
do {
const char * next = strchrnul ( name , ' . ' ) ;
unsigned len = next - name ;
if ( * next = = ' . ' )
next + + ;
2023-09-26 17:49:34 -04:00
groups = bch2_sb_field_get ( sb - > sb , disk_groups ) ;
2017-03-16 22:18:50 -08:00
v = __bch2_disk_group_find ( groups , parent , name , len ) ;
if ( v < 0 )
v = __bch2_disk_group_add ( sb , parent , name , len ) ;
if ( v < 0 )
return v ;
parent = v + 1 ;
name = next ;
} while ( * name & & v > = 0 ) ;
return v ;
}
2023-10-22 11:12:14 -04:00
void bch2_disk_path_to_text ( struct printbuf * out , struct bch_fs * c , unsigned v )
{
struct bch_disk_groups_cpu * groups ;
struct bch_disk_group_cpu * g ;
unsigned nr = 0 ;
u16 path [ 32 ] ;
out - > atomic + + ;
rcu_read_lock ( ) ;
groups = rcu_dereference ( c - > disk_groups ) ;
if ( ! groups )
goto invalid ;
while ( 1 ) {
if ( nr = = ARRAY_SIZE ( path ) )
goto invalid ;
if ( v > = groups - > nr )
goto invalid ;
g = groups - > entries + v ;
if ( g - > deleted )
goto invalid ;
path [ nr + + ] = v ;
if ( ! g - > parent )
break ;
v = g - > parent - 1 ;
}
while ( nr ) {
v = path [ - - nr ] ;
g = groups - > entries + v ;
prt_printf ( out , " %.*s " , ( int ) sizeof ( g - > label ) , g - > label ) ;
if ( nr )
prt_printf ( out , " . " ) ;
}
out :
rcu_read_unlock ( ) ;
out - > atomic - - ;
return ;
invalid :
prt_printf ( out , " invalid label %u " , v ) ;
goto out ;
}
void bch2_disk_path_to_text_sb ( struct printbuf * out , struct bch_sb * sb , unsigned v )
2017-03-16 22:18:50 -08:00
{
struct bch_sb_field_disk_groups * groups =
2023-09-26 17:49:34 -04:00
bch2_sb_field_get ( sb , disk_groups ) ;
2017-03-16 22:18:50 -08:00
struct bch_disk_group * g ;
unsigned nr = 0 ;
u16 path [ 32 ] ;
while ( 1 ) {
if ( nr = = ARRAY_SIZE ( path ) )
goto inval ;
if ( v > = disk_groups_nr ( groups ) )
goto inval ;
g = groups - > entries + v ;
if ( BCH_GROUP_DELETED ( g ) )
goto inval ;
path [ nr + + ] = v ;
if ( ! BCH_GROUP_PARENT ( g ) )
break ;
v = BCH_GROUP_PARENT ( g ) - 1 ;
}
while ( nr ) {
v = path [ - - nr ] ;
g = groups - > entries + v ;
2023-02-03 21:01:40 -05:00
prt_printf ( out , " %.*s " , ( int ) sizeof ( g - > label ) , g - > label ) ;
2017-03-16 22:18:50 -08:00
if ( nr )
2023-02-03 21:01:40 -05:00
prt_printf ( out , " . " ) ;
2017-03-16 22:18:50 -08:00
}
2018-11-09 01:24:07 -05:00
return ;
2017-03-16 22:18:50 -08:00
inval :
2023-02-03 21:01:40 -05:00
prt_printf ( out , " invalid label %u " , v ) ;
2017-03-16 22:18:50 -08:00
}
2022-08-18 17:57:24 -04:00
int __bch2_dev_group_set ( struct bch_fs * c , struct bch_dev * ca , const char * name )
2017-03-16 22:18:50 -08:00
{
struct bch_member * mi ;
2022-08-18 17:57:24 -04:00
int ret , v = - 1 ;
2017-03-16 22:18:50 -08:00
if ( ! strlen ( name ) | | ! strcmp ( name , " none " ) )
2022-08-18 17:57:24 -04:00
return 0 ;
2017-03-16 22:18:50 -08:00
v = bch2_disk_path_find_or_create ( & c - > disk_sb , name ) ;
2022-08-18 17:57:24 -04:00
if ( v < 0 )
2017-03-16 22:18:50 -08:00
return v ;
2020-08-12 15:00:08 -04:00
ret = bch2_sb_disk_groups_to_cpu ( c ) ;
if ( ret )
2022-08-18 17:57:24 -04:00
return ret ;
2023-09-25 00:02:56 -04:00
mi = bch2_members_v2_get_mut ( c - > disk_sb . sb , ca - > dev_idx ) ;
2017-03-16 22:18:50 -08:00
SET_BCH_MEMBER_GROUP ( mi , v + 1 ) ;
2022-08-18 17:57:24 -04:00
return 0 ;
}
2017-03-16 22:18:50 -08:00
2022-08-18 17:57:24 -04:00
int bch2_dev_group_set ( struct bch_fs * c , struct bch_dev * ca , const char * name )
{
int ret ;
mutex_lock ( & c - > sb_lock ) ;
ret = __bch2_dev_group_set ( c , ca , name ) ? :
bch2_write_super ( c ) ;
2017-03-16 22:18:50 -08:00
mutex_unlock ( & c - > sb_lock ) ;
2020-08-12 15:00:08 -04:00
return ret ;
2017-03-16 22:18:50 -08:00
}
2023-07-12 21:48:32 -04:00
int bch2_opt_target_parse ( struct bch_fs * c , const char * val , u64 * res ,
struct printbuf * err )
2017-03-16 22:18:50 -08:00
{
struct bch_dev * ca ;
int g ;
2023-07-12 21:48:32 -04:00
if ( ! val )
return - EINVAL ;
if ( ! c )
return 0 ;
if ( ! strlen ( val ) | | ! strcmp ( val , " none " ) ) {
* res = 0 ;
2017-03-16 22:18:50 -08:00
return 0 ;
}
/* Is it a device? */
2023-07-12 21:48:32 -04:00
ca = bch2_dev_lookup ( c , val ) ;
2017-03-16 22:18:50 -08:00
if ( ! IS_ERR ( ca ) ) {
2023-07-12 21:48:32 -04:00
* res = dev_to_target ( ca - > dev_idx ) ;
2017-03-16 22:18:50 -08:00
percpu_ref_put ( & ca - > ref ) ;
return 0 ;
}
mutex_lock ( & c - > sb_lock ) ;
2023-07-12 21:48:32 -04:00
g = bch2_disk_path_find ( & c - > disk_sb , val ) ;
2017-03-16 22:18:50 -08:00
mutex_unlock ( & c - > sb_lock ) ;
if ( g > = 0 ) {
2023-07-12 21:48:32 -04:00
* res = group_to_target ( g ) ;
2017-03-16 22:18:50 -08:00
return 0 ;
}
return - EINVAL ;
}
2023-10-22 10:54:24 -04:00
void bch2_target_to_text ( struct printbuf * out , struct bch_fs * c , unsigned v )
2022-02-20 05:00:45 -05:00
{
struct target t = target_decode ( v ) ;
switch ( t . type ) {
case TARGET_NULL :
2023-02-03 21:01:40 -05:00
prt_printf ( out , " none " ) ;
2022-02-20 05:00:45 -05:00
break ;
2023-10-22 10:54:24 -04:00
case TARGET_DEV : {
struct bch_dev * ca ;
2023-11-12 00:38:41 +00:00
out - > atomic + + ;
2023-10-22 10:54:24 -04:00
rcu_read_lock ( ) ;
ca = t . dev < c - > sb . nr_devices
? rcu_dereference ( c - > devs [ t . dev ] )
: NULL ;
if ( ca & & percpu_ref_tryget ( & ca - > io_ref ) ) {
prt_printf ( out , " /dev/%pg " , ca - > disk_sb . bdev ) ;
percpu_ref_put ( & ca - > io_ref ) ;
} else if ( ca ) {
prt_printf ( out , " offline device %u " , t . dev ) ;
2022-02-20 05:00:45 -05:00
} else {
2023-10-22 10:54:24 -04:00
prt_printf ( out , " invalid device %u " , t . dev ) ;
2022-02-20 05:00:45 -05:00
}
2023-10-22 10:54:24 -04:00
rcu_read_unlock ( ) ;
2023-11-12 00:38:41 +00:00
out - > atomic - - ;
2022-02-20 05:00:45 -05:00
break ;
2023-10-22 10:54:24 -04:00
}
2022-02-20 05:00:45 -05:00
case TARGET_GROUP :
2023-10-22 11:12:14 -04:00
bch2_disk_path_to_text ( out , c , t . group ) ;
2023-10-22 10:54:24 -04:00
break ;
default :
BUG ( ) ;
}
}
2023-11-06 10:34:01 +08:00
static void bch2_target_to_text_sb ( struct printbuf * out , struct bch_sb * sb , unsigned v )
2023-10-22 10:54:24 -04:00
{
struct target t = target_decode ( v ) ;
switch ( t . type ) {
case TARGET_NULL :
prt_printf ( out , " none " ) ;
break ;
case TARGET_DEV : {
struct bch_member m = bch2_sb_member_get ( sb , t . dev ) ;
if ( bch2_dev_exists ( sb , t . dev ) ) {
prt_printf ( out , " Device " ) ;
pr_uuid ( out , m . uuid . b ) ;
prt_printf ( out , " (%u) " , t . dev ) ;
2017-03-16 22:18:50 -08:00
} else {
2023-10-22 10:54:24 -04:00
prt_printf ( out , " Bad device %u " , t . dev ) ;
2017-03-16 22:18:50 -08:00
}
break ;
2023-10-22 10:54:24 -04:00
}
case TARGET_GROUP :
2023-10-22 11:12:14 -04:00
bch2_disk_path_to_text_sb ( out , sb , t . group ) ;
2023-10-22 10:54:24 -04:00
break ;
2017-03-16 22:18:50 -08:00
default :
BUG ( ) ;
}
}
2023-10-22 10:54:24 -04:00
void bch2_opt_target_to_text ( struct printbuf * out ,
struct bch_fs * c ,
struct bch_sb * sb ,
u64 v )
{
if ( c )
bch2_target_to_text ( out , c , v ) ;
else
bch2_target_to_text_sb ( out , sb , v ) ;
}