2004-05-05 01:25:57 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2003 - 2004 Sistina Software , Inc . All rights reserved .
2015-11-30 23:17:25 +03:00
* Copyright ( C ) 2004 - 2015 Red Hat , Inc . All rights reserved .
2004-05-05 01:25:57 +04:00
*
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
2007-08-21 00:55:30 +04:00
* of the GNU Lesser General Public License v .2 .1 .
2004-05-05 01:25:57 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-05-05 01:25:57 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
2016-01-21 13:49:46 +03:00
* Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
2004-05-05 01:25:57 +04:00
*/
2018-06-08 15:40:53 +03:00
# include "base/memory/zalloc.h"
2018-05-14 12:30:20 +03:00
# include "lib/misc/lib.h"
# include "lib/commands/toolcontext.h"
# include "lib/metadata/segtype.h"
# include "lib/display/display.h"
# include "lib/format_text/text_export.h"
# include "lib/format_text/text_import.h"
# include "lib/config/config.h"
# include "lib/misc/lvm-string.h"
# include "lib/activate/targets.h"
# include "lib/activate/activate.h"
# include "lib/datastruct/str_list.h"
2005-12-21 22:45:16 +03:00
2010-05-24 21:46:47 +04:00
# include <sys/utsname.h>
2004-05-05 01:25:57 +04:00
enum {
MIRR_DISABLED ,
MIRR_RUNNING ,
MIRR_COMPLETED
} ;
struct mirror_state {
2005-06-01 20:51:55 +04:00
uint32_t default_region_size ;
2004-05-05 01:25:57 +04:00
} ;
2006-04-19 19:33:07 +04:00
static void _mirrored_display ( const struct lv_segment * seg )
2004-05-05 01:25:57 +04:00
{
2005-06-01 20:51:55 +04:00
const char * size ;
2005-10-26 20:12:36 +04:00
uint32_t s ;
2005-06-01 20:51:55 +04:00
2004-05-05 01:25:57 +04:00
log_print ( " Mirrors \t \t %u " , seg - > area_count ) ;
log_print ( " Mirror size \t \t %u " , seg - > area_len ) ;
2005-06-01 20:51:55 +04:00
if ( seg - > log_lv )
log_print ( " Mirror log volume \t %s " , seg - > log_lv - > name ) ;
if ( seg - > region_size ) {
size = display_size ( seg - > lv - > vg - > cmd ,
2006-05-10 01:23:51 +04:00
( uint64_t ) seg - > region_size ) ;
2005-06-01 20:51:55 +04:00
log_print ( " Mirror region size \t %s " , size ) ;
}
2004-05-05 01:25:57 +04:00
log_print ( " Mirror original: " ) ;
display_stripe ( seg , 0 , " " ) ;
2005-10-26 20:12:36 +04:00
log_print ( " Mirror destinations: " ) ;
for ( s = 1 ; s < seg - > area_count ; s + + )
display_stripe ( seg , s , " " ) ;
2004-05-05 01:25:57 +04:00
log_print ( " " ) ;
}
2011-08-30 18:55:15 +04:00
static int _mirrored_text_import_area_count ( const struct dm_config_node * sn , uint32_t * area_count )
2004-05-05 01:25:57 +04:00
{
2011-08-30 18:55:15 +04:00
if ( ! dm_config_get_uint32 ( sn , " mirror_count " , area_count ) ) {
2004-05-05 01:25:57 +04:00
log_error ( " Couldn't read 'mirror_count' for "
2011-08-30 18:55:15 +04:00
" segment '%s'. " , dm_config_parent_name ( sn ) ) ;
2004-05-05 01:25:57 +04:00
return 0 ;
}
return 1 ;
}
2011-08-30 18:55:15 +04:00
static int _mirrored_text_import ( struct lv_segment * seg , const struct dm_config_node * sn ,
2024-09-10 19:51:15 +03:00
struct dm_hash_table * pv_hash ,
struct dm_hash_table * lv_hash )
2004-05-05 01:25:57 +04:00
{
2011-08-31 19:19:19 +04:00
const struct dm_config_value * cv ;
2010-12-20 16:12:55 +03:00
const char * logname = NULL ;
2004-05-05 01:25:57 +04:00
2011-08-31 19:19:19 +04:00
if ( dm_config_has_node ( sn , " extents_moved " ) ) {
2011-08-30 18:55:15 +04:00
if ( dm_config_get_uint32 ( sn , " extents_moved " ,
2004-05-05 21:56:20 +04:00
& seg - > extents_copied ) )
2004-05-05 01:25:57 +04:00
seg - > status | = PVMOVE ;
else {
log_error ( " Couldn't read 'extents_moved' for "
2009-07-09 15:29:00 +04:00
" segment %s of logical volume %s. " ,
2011-08-30 18:55:15 +04:00
dm_config_parent_name ( sn ) , seg - > lv - > name ) ;
2004-05-05 01:25:57 +04:00
return 0 ;
}
}
2011-08-31 19:19:19 +04:00
if ( dm_config_has_node ( sn , " region_size " ) ) {
2011-08-30 18:55:15 +04:00
if ( ! dm_config_get_uint32 ( sn , " region_size " ,
2005-06-01 20:51:55 +04:00
& seg - > region_size ) ) {
log_error ( " Couldn't read 'region_size' for "
2009-07-09 15:29:00 +04:00
" segment %s of logical volume %s. " ,
2011-08-30 18:55:15 +04:00
dm_config_parent_name ( sn ) , seg - > lv - > name ) ;
2005-06-01 20:51:55 +04:00
return 0 ;
}
}
2011-08-31 19:19:19 +04:00
if ( dm_config_get_str ( sn , " mirror_log " , & logname ) ) {
2024-09-10 19:51:15 +03:00
if ( ! ( seg - > log_lv = dm_hash_lookup ( lv_hash , logname ) ) ) {
2009-07-09 15:29:00 +04:00
log_error ( " Unrecognised mirror log in "
" segment %s of logical volume %s. " ,
2011-08-30 18:55:15 +04:00
dm_config_parent_name ( sn ) , seg - > lv - > name ) ;
2005-06-01 20:51:55 +04:00
return 0 ;
}
seg - > log_lv - > status | = MIRROR_LOG ;
2008-01-30 17:00:02 +03:00
}
2005-06-01 20:51:55 +04:00
if ( logname & & ! seg - > region_size ) {
2009-07-09 15:29:00 +04:00
log_error ( " Missing region size for mirror log for "
" segment %s of logical volume %s. " ,
2011-08-30 18:55:15 +04:00
dm_config_parent_name ( sn ) , seg - > lv - > name ) ;
2005-06-01 20:51:55 +04:00
return 0 ;
}
2011-08-31 19:19:19 +04:00
if ( ! dm_config_get_list ( sn , " mirrors " , & cv ) ) {
2009-07-09 15:29:00 +04:00
log_error ( " Couldn't find mirrors array for "
" segment %s of logical volume %s. " ,
2011-08-30 18:55:15 +04:00
dm_config_parent_name ( sn ) , seg - > lv - > name ) ;
2004-05-05 01:25:57 +04:00
return 0 ;
}
2011-08-31 19:19:19 +04:00
return text_import_areas ( seg , sn , cv , pv_hash , MIRROR_IMAGE ) ;
2004-05-05 01:25:57 +04:00
}
2006-04-19 19:33:07 +04:00
static int _mirrored_text_export ( const struct lv_segment * seg , struct formatter * f )
2004-05-05 01:25:57 +04:00
{
outf ( f , " mirror_count = %u " , seg - > area_count ) ;
if ( seg - > status & PVMOVE )
2010-01-07 17:46:51 +03:00
outsize ( f , ( uint64_t ) seg - > extents_copied * seg - > lv - > vg - > extent_size ,
" extents_moved = % " PRIu32 , seg - > extents_copied ) ;
2005-06-01 20:51:55 +04:00
if ( seg - > log_lv )
outf ( f , " mirror_log = \" %s \" " , seg - > log_lv - > name ) ;
if ( seg - > region_size )
outf ( f , " region_size = % " PRIu32 , seg - > region_size ) ;
2004-05-05 01:25:57 +04:00
return out_areas ( f , seg , " mirror " ) ;
}
# ifdef DEVMAPPER_SUPPORT
2011-02-18 17:29:39 +03:00
static int _block_on_error_available = 0 ;
2006-04-19 19:33:07 +04:00
static struct mirror_state * _mirrored_init_target ( struct dm_pool * mem ,
2006-05-16 20:48:31 +04:00
struct cmd_context * cmd )
2004-05-05 01:25:57 +04:00
{
struct mirror_state * mirr_state ;
2005-10-17 03:03:59 +04:00
if ( ! ( mirr_state = dm_pool_alloc ( mem , sizeof ( * mirr_state ) ) ) ) {
2004-05-05 01:25:57 +04:00
log_error ( " struct mirr_state allocation failed " ) ;
return NULL ;
}
2013-02-21 00:40:17 +04:00
mirr_state - > default_region_size = get_default_region_size ( cmd ) ;
2004-05-05 01:25:57 +04:00
return mirr_state ;
}
2009-10-01 04:35:29 +04:00
static int _mirrored_target_percent ( void * * target_state ,
2014-06-09 14:08:27 +04:00
dm_percent_t * percent ,
2009-10-01 04:35:29 +04:00
struct dm_pool * mem ,
struct cmd_context * cmd ,
struct lv_segment * seg , char * params ,
uint64_t * total_numerator ,
uint64_t * total_denominator )
2004-05-05 01:25:57 +04:00
{
2015-11-30 23:17:25 +03:00
struct dm_status_mirror * sm ;
2004-05-05 01:25:57 +04:00
if ( ! * target_state )
2006-05-16 20:48:31 +04:00
* target_state = _mirrored_init_target ( mem , cmd ) ;
2004-05-05 01:25:57 +04:00
2015-11-30 23:17:25 +03:00
if ( ! dm_get_status_mirror ( mem , params , & sm ) )
return_0 ;
2005-09-02 20:59:46 +04:00
2015-11-30 23:17:25 +03:00
* total_numerator + = sm - > insync_regions ;
* total_denominator + = sm - > total_regions ;
2004-05-05 01:25:57 +04:00
2004-05-05 21:56:20 +04:00
if ( seg )
2015-11-30 23:17:25 +03:00
seg - > extents_copied = seg - > area_len * sm - > insync_regions / sm - > total_regions ;
* percent = dm_make_percent ( sm - > insync_regions , sm - > total_regions ) ;
2004-05-05 01:25:57 +04:00
2015-11-30 23:17:25 +03:00
dm_pool_free ( mem , sm ) ;
2009-10-01 04:35:29 +04:00
2004-05-05 01:25:57 +04:00
return 1 ;
}
2004-05-05 22:11:43 +04:00
2015-11-30 23:24:31 +03:00
static int _mirrored_transient_status ( struct dm_pool * mem , struct lv_segment * seg , char * params )
2010-05-24 19:32:20 +04:00
{
2015-11-30 23:17:25 +03:00
struct dm_status_mirror * sm ;
struct logical_volume * log ;
2010-05-24 19:32:20 +04:00
struct logical_volume * lv = seg - > lv ;
2015-11-30 23:17:25 +03:00
int failed = 0 , r = 0 ;
unsigned i , j ;
2010-05-24 19:32:20 +04:00
struct lvinfo info ;
2010-08-04 19:55:03 +04:00
log_very_verbose ( " Mirrored transient status: \" %s \" " , params ) ;
2010-05-24 19:32:20 +04:00
2015-11-30 23:17:25 +03:00
if ( ! dm_get_status_mirror ( mem , params , & sm ) )
2010-05-24 19:32:20 +04:00
return_0 ;
2015-11-30 23:17:25 +03:00
if ( sm - > dev_count ! = seg - > area_count ) {
2010-05-24 19:32:20 +04:00
log_error ( " Active mirror has a wrong number of mirror images! " ) ;
2015-11-30 23:17:25 +03:00
log_error ( " Metadata says %u, kernel says %u. " ,
seg - > area_count , sm - > dev_count ) ;
goto out ;
2010-05-24 19:32:20 +04:00
}
2015-11-30 23:17:25 +03:00
if ( ! strcmp ( sm - > log_type , " disk " ) ) {
2010-05-24 19:32:20 +04:00
log = first_seg ( lv ) - > log_lv ;
2021-03-11 22:38:51 +03:00
if ( ! lv_info ( lv - > vg - > cmd , log , 0 , & info , 0 , 0 ) | | ! info . exists ) {
2010-12-01 16:01:36 +03:00
log_error ( " Check for existence of mirror log %s failed. " ,
2015-11-30 23:17:25 +03:00
display_lvname ( log ) ) ;
goto out ;
2010-12-01 16:01:36 +03:00
}
2013-01-08 02:30:29 +04:00
log_debug_activation ( " Found mirror log at %d:%d " , info . major , info . minor ) ;
2015-11-30 23:17:25 +03:00
if ( info . major ! = ( int ) sm - > logs [ 0 ] . major | |
info . minor ! = ( int ) sm - > logs [ 0 ] . minor ) {
log_error ( " Mirror log mismatch. Metadata says %d:%d, kernel says %u:%u. " ,
info . major , info . minor ,
sm - > logs [ 0 ] . major , sm - > logs [ 0 ] . minor ) ;
goto out ;
2010-05-24 19:32:20 +04:00
}
2015-11-30 23:17:25 +03:00
log_very_verbose ( " Status of log (%d:%d): %c. " ,
info . major , info . minor ,
sm - > logs [ 0 ] . health ) ;
if ( sm - > logs [ 0 ] . health ! = DM_STATUS_MIRROR_ALIVE ) {
2010-05-24 19:32:20 +04:00
log - > status | = PARTIAL_LV ;
+ + failed ;
}
}
for ( i = 0 ; i < seg - > area_count ; + + i ) {
2021-03-11 22:38:51 +03:00
if ( ! lv_info ( lv - > vg - > cmd , seg_lv ( seg , i ) , 0 , & info , 0 , 0 ) | | ! info . exists ) {
2010-12-01 16:01:36 +03:00
log_error ( " Check for existence of mirror image %s failed. " ,
seg_lv ( seg , i ) - > name ) ;
2015-11-30 23:17:25 +03:00
goto out ;
2010-12-01 16:01:36 +03:00
}
2013-01-08 02:30:29 +04:00
log_debug_activation ( " Found mirror image at %d:%d " , info . major , info . minor ) ;
2015-11-30 23:17:25 +03:00
for ( j = 0 ; j < sm - > dev_count ; + + j )
if ( info . major = = ( int ) sm - > devs [ j ] . major & &
info . minor = = ( int ) sm - > devs [ j ] . minor ) {
log_very_verbose ( " Status of image %d: %c. " ,
i , sm - > devs [ j ] . health ) ;
if ( sm - > devs [ j ] . health ! = DM_STATUS_MIRROR_ALIVE ) {
seg_lv ( seg , i ) - > status | = PARTIAL_LV ;
+ + failed ;
}
break ;
2010-05-24 19:32:20 +04:00
}
2015-11-30 23:17:25 +03:00
if ( j = = sm - > dev_count ) {
log_error ( " Failed to find image %d (%d:%d). " ,
i , info . major , info . minor ) ;
goto out ;
2010-05-24 19:32:20 +04:00
}
}
/* update PARTIAL_LV flags across the VG */
if ( failed )
2011-05-07 17:32:05 +04:00
vg_mark_partial_lvs ( lv - > vg , 0 ) ;
2010-05-24 19:32:20 +04:00
2015-11-30 23:17:25 +03:00
r = 1 ;
out :
dm_pool_free ( mem , sm ) ;
return r ;
2010-05-24 19:32:20 +04:00
}
2010-04-14 17:01:38 +04:00
static int _add_log ( struct dm_pool * mem , struct lv_segment * seg ,
2011-06-17 18:14:19 +04:00
const struct lv_activate_opts * laopts ,
2005-11-09 16:08:41 +03:00
struct dm_tree_node * node , uint32_t area_count , uint32_t region_size )
2005-11-09 01:52:26 +03:00
{
unsigned clustered = 0 ;
char * log_dlid = NULL ;
2005-12-13 18:57:32 +03:00
uint32_t log_flags = 0 ;
2005-11-09 01:52:26 +03:00
2006-05-11 23:47:53 +04:00
if ( seg - > log_lv ) {
/* If disk log, use its UUID */
2014-03-11 20:13:47 +04:00
if ( ! ( log_dlid = build_dm_uuid ( mem , seg - > log_lv , NULL ) ) ) {
2006-05-11 23:47:53 +04:00
log_error ( " Failed to build uuid for log LV %s. " ,
seg - > log_lv - > name ) ;
return 0 ;
}
} else {
/* If core log, use mirror's UUID and set DM_CORELOG flag */
2017-11-26 02:28:33 +03:00
if ( ! ( log_dlid = build_dm_uuid ( mem , seg - > lv , lv_is_pvmove ( seg - > lv ) ? " pvmove " : NULL ) ) ) {
2006-05-11 23:47:53 +04:00
log_error ( " Failed to build uuid for mirror LV %s. " ,
seg - > lv - > name ) ;
return 0 ;
}
log_flags | = DM_CORELOG ;
2005-11-09 01:52:26 +03:00
}
2006-05-11 22:39:24 +04:00
if ( mirror_in_sync ( ) & & ! ( seg - > status & PVMOVE ) )
log_flags | = DM_NOSYNC ;
2018-03-29 22:10:58 +03:00
if ( _block_on_error_available & & ! ( seg - > status & PVMOVE ) ) {
2018-04-28 23:14:47 +03:00
if ( dmeventd_monitor_mode ( ) = = 0 ) {
log_warn_suppress ( seg - > lv - > vg - > cmd - > mirror_warn_printed ,
" WARNING: Mirror %s without monitoring will not react on failures. " ,
display_lvname ( seg - > lv ) ) ;
seg - > lv - > vg - > cmd - > mirror_warn_printed = 1 ; /* Do not print this more then once */
} else
2018-03-29 22:10:58 +03:00
log_flags | = DM_BLOCK_ON_ERROR ;
}
2005-12-13 18:57:32 +03:00
2005-12-20 00:01:39 +03:00
return dm_tree_node_add_mirror_target_log ( node , region_size , clustered , log_dlid , area_count , log_flags ) ;
2005-11-09 01:52:26 +03:00
}
2006-04-19 19:33:07 +04:00
static int _mirrored_add_target_line ( struct dev_manager * dm , struct dm_pool * mem ,
2011-06-17 18:14:19 +04:00
struct cmd_context * cmd , void * * target_state ,
struct lv_segment * seg ,
const struct lv_activate_opts * laopts ,
struct dm_tree_node * node , uint64_t len ,
uint32_t * pvmove_mirror_count )
2005-11-09 01:52:26 +03:00
{
struct mirror_state * mirr_state ;
uint32_t area_count = seg - > area_count ;
2006-05-10 01:23:51 +04:00
unsigned start_area = 0u ;
2005-11-09 01:52:26 +03:00
int mirror_status = MIRR_RUNNING ;
2009-11-18 19:48:10 +03:00
uint32_t region_size ;
2005-11-09 01:52:26 +03:00
int r ;
2012-02-13 15:07:55 +04:00
if ( ! * target_state & &
! ( * target_state = _mirrored_init_target ( mem , cmd ) ) )
return_0 ;
2005-11-09 01:52:26 +03:00
mirr_state = * target_state ;
2008-01-17 20:17:09 +03:00
/*
* Mirror segment could have only 1 area temporarily
* if the segment is under conversion .
*/
2008-01-16 22:18:51 +03:00
if ( seg - > area_count = = 1 )
mirror_status = MIRR_DISABLED ;
2005-11-09 01:52:26 +03:00
/*
* For pvmove , only have one mirror segment RUNNING at once .
* Segments before this are COMPLETED and use 2 nd area .
* Segments after this are DISABLED and use 1 st area .
*/
if ( seg - > status & PVMOVE ) {
if ( seg - > extents_copied = = seg - > area_len ) {
mirror_status = MIRR_COMPLETED ;
start_area = 1 ;
} else if ( ( * pvmove_mirror_count ) + + ) {
mirror_status = MIRR_DISABLED ;
area_count = 1 ;
}
/* else MIRR_RUNNING */
}
if ( mirror_status ! = MIRR_RUNNING ) {
2011-11-29 00:37:51 +04:00
if ( ! add_linear_area_to_dtree ( node , len , seg - > lv - > vg - > extent_size ,
cmd - > use_linear_target ,
seg - > lv - > vg - > name , seg - > lv - > name ) )
2005-11-09 01:52:26 +03:00
return_0 ;
goto done ;
}
if ( ! ( seg - > status & PVMOVE ) ) {
if ( ! seg - > region_size ) {
log_error ( " Missing region size for mirror segment. " ) ;
return 0 ;
}
region_size = seg - > region_size ;
2009-11-18 19:48:10 +03:00
2018-04-20 11:07:42 +03:00
} else if ( ! ( region_size = adjusted_mirror_region_size ( cmd ,
seg - > lv - > vg - > extent_size ,
seg - > area_len ,
mirr_state - > default_region_size , 1 ,
vg_is_clustered ( seg - > lv - > vg ) ) ) )
return_0 ;
2005-11-09 01:52:26 +03:00
2005-11-09 16:08:41 +03:00
if ( ! dm_tree_node_add_mirror_target ( node , len ) )
2005-11-09 01:52:26 +03:00
return_0 ;
2011-06-17 18:14:19 +04:00
if ( ( r = _add_log ( mem , seg , laopts , node , area_count , region_size ) ) < = 0 ) {
2005-11-09 01:52:26 +03:00
stack ;
return r ;
}
done :
2005-11-10 17:45:39 +03:00
return add_areas_line ( dm , seg , node , start_area , area_count ) ;
2005-11-09 01:52:26 +03:00
}
2009-02-28 23:04:24 +03:00
static int _mirrored_target_present ( struct cmd_context * cmd ,
const struct lv_segment * seg ,
2008-04-07 14:23:47 +04:00
unsigned * attributes )
2004-05-05 22:11:43 +04:00
{
2006-04-19 19:33:07 +04:00
static int _mirrored_checked = 0 ;
static int _mirrored_present = 0 ;
2014-02-24 17:18:26 +04:00
static unsigned _mirror_attributes = 0 ;
2005-12-20 00:01:39 +03:00
uint32_t maj , min , patchlevel ;
2006-01-04 21:09:52 +03:00
unsigned maj2 , min2 , patchlevel2 ;
2008-01-30 17:00:02 +03:00
char vsn [ 80 ] ;
2004-05-05 22:11:43 +04:00
2015-12-17 14:23:33 +03:00
if ( ! activation ( ) )
return 0 ;
2006-04-19 19:33:07 +04:00
if ( ! _mirrored_checked ) {
2014-02-24 17:18:26 +04:00
_mirrored_checked = 1 ;
2015-12-17 14:23:33 +03:00
2021-02-07 23:48:18 +03:00
if ( ! ( _mirrored_present = target_present_version ( cmd , TARGET_NAME_MIRROR , 1 ,
& maj , & min , & patchlevel ) ) )
2015-12-17 14:23:33 +03:00
return 0 ;
2004-05-05 22:11:43 +04:00
2005-12-20 00:01:39 +03:00
/*
2009-08-13 23:36:04 +04:00
* block_on_error available as " block_on_error " log
* argument with mirror target > = 1.1 and < = 1.11
2005-12-20 00:01:39 +03:00
* or with 1.0 in RHEL4U3 driver > = 4.5
2009-08-13 23:36:04 +04:00
*
* block_on_error available as " handle_errors " mirror
* argument with mirror target > = 1.12 .
*
* libdm - deptree . c is smart enough to handle the differences
* between block_on_error and handle_errors for all
* mirror target versions > = 1.1
2005-12-20 00:01:39 +03:00
*/
2005-12-20 01:36:04 +03:00
/* FIXME Move this into libdevmapper */
2005-12-20 00:01:39 +03:00
2024-05-20 15:46:20 +03:00
if ( maj = = 1 & &
2009-08-13 23:36:04 +04:00
( ( min > = 1 ) | |
2005-12-20 00:01:39 +03:00
( min = = 0 & & driver_version ( vsn , sizeof ( vsn ) ) & &
2006-01-04 21:09:52 +03:00
sscanf ( vsn , " %u.%u.%u " , & maj2 , & min2 , & patchlevel2 ) = = 3 & &
maj2 = = 4 & & min2 = = 5 & & patchlevel2 = = 0 ) ) ) /* RHEL4U3 */
2005-12-20 00:01:39 +03:00
_block_on_error_available = 1 ;
2008-04-07 14:23:47 +04:00
}
2014-02-24 17:18:26 +04:00
/*
2024-08-30 00:05:41 +03:00
* Check only for modules if attributes requested and no previous check .
2014-02-24 17:18:26 +04:00
*/
if ( attributes )
* attributes = _mirror_attributes ;
2004-05-05 22:11:43 +04:00
2006-04-19 19:33:07 +04:00
return _mirrored_present ;
2004-05-05 22:11:43 +04:00
}
2005-12-02 23:35:07 +03:00
2014-04-30 01:41:17 +04:00
# ifdef DMEVENTD
2010-08-17 05:16:41 +04:00
/* FIXME Cache this */
2018-01-29 18:28:57 +03:00
static int _target_registered ( struct lv_segment * seg , int * pending , int * monitored )
2007-01-17 18:00:57 +03:00
{
2018-02-10 01:40:37 +03:00
return target_registered_with_dmeventd ( seg - > lv - > vg - > cmd , seg - > segtype - > dso ,
2018-01-29 18:28:57 +03:00
seg - > lv , pending , monitored ) ;
2007-01-12 23:38:30 +03:00
}
2005-12-02 23:35:07 +03:00
/* FIXME This gets run while suspended and performs banned operations. */
2010-08-17 02:54:35 +04:00
static int _target_set_events ( struct lv_segment * seg , int evmask , int set )
2005-12-02 23:35:07 +03:00
{
2018-02-10 01:40:37 +03:00
return target_register_events ( seg - > lv - > vg - > cmd , seg - > segtype - > dso ,
2010-08-17 05:16:41 +04:00
seg - > lv , evmask , set , 0 ) ;
2005-12-02 23:35:07 +03:00
}
2007-01-24 19:51:24 +03:00
static int _target_monitor_events ( struct lv_segment * seg , int events )
2005-12-02 23:35:07 +03:00
{
2007-01-24 19:51:24 +03:00
return _target_set_events ( seg , events , 1 ) ;
2007-01-17 18:00:57 +03:00
}
2005-12-02 23:35:07 +03:00
2007-01-24 19:51:24 +03:00
static int _target_unmonitor_events ( struct lv_segment * seg , int events )
2007-01-17 18:00:57 +03:00
{
2007-01-24 19:51:24 +03:00
return _target_set_events ( seg , events , 0 ) ;
2005-12-02 23:35:07 +03:00
}
2014-04-30 01:41:17 +04:00
# endif /* DMEVENTD */
2004-05-05 01:25:57 +04:00
2006-10-03 21:55:20 +04:00
static int _mirrored_modules_needed ( struct dm_pool * mem ,
const struct lv_segment * seg ,
2008-11-04 01:14:30 +03:00
struct dm_list * modules )
2006-10-03 21:55:20 +04:00
{
if ( seg - > log_lv & &
! list_segment_modules ( mem , first_seg ( seg - > log_lv ) , modules ) )
return_0 ;
2016-03-22 20:46:15 +03:00
if ( ! str_list_add ( mem , modules , MODULE_NAME_MIRROR ) ) {
2006-10-03 21:55:20 +04:00
log_error ( " mirror string list allocation failed " ) ;
return 0 ;
}
return 1 ;
}
2014-04-30 01:41:17 +04:00
# endif /* DEVMAPPER_SUPPORT */
2006-10-03 21:55:20 +04:00
2010-12-20 16:32:49 +03:00
static void _mirrored_destroy ( struct segment_type * segtype )
2004-05-05 01:25:57 +04:00
{
2018-06-08 15:40:53 +03:00
free ( ( void * ) segtype - > dso ) ;
free ( segtype ) ;
2004-05-05 01:25:57 +04:00
}
2024-05-03 12:59:05 +03:00
static const struct segtype_handler _mirrored_ops = {
2006-05-10 01:23:51 +04:00
. display = _mirrored_display ,
. text_import_area_count = _mirrored_text_import_area_count ,
. text_import = _mirrored_text_import ,
. text_export = _mirrored_text_export ,
2004-05-05 01:25:57 +04:00
# ifdef DEVMAPPER_SUPPORT
2006-05-10 01:23:51 +04:00
. add_target_line = _mirrored_add_target_line ,
. target_percent = _mirrored_target_percent ,
. target_present = _mirrored_target_present ,
2010-05-24 19:32:20 +04:00
. check_transient_status = _mirrored_transient_status ,
2014-04-30 01:41:17 +04:00
. modules_needed = _mirrored_modules_needed ,
2011-04-29 04:21:13 +04:00
# ifdef DMEVENTD
2010-08-17 02:54:35 +04:00
. target_monitored = _target_registered ,
2007-01-20 01:21:45 +03:00
. target_monitor_events = _target_monitor_events ,
. target_unmonitor_events = _target_unmonitor_events ,
2011-04-29 04:21:13 +04:00
# endif /* DMEVENTD */
2004-05-05 01:25:57 +04:00
# endif
2006-05-10 01:23:51 +04:00
. destroy = _mirrored_destroy ,
2004-05-05 01:25:57 +04:00
} ;
# ifdef MIRRORED_INTERNAL
struct segment_type * init_mirrored_segtype ( struct cmd_context * cmd )
# else /* Shared */
struct segment_type * init_segtype ( struct cmd_context * cmd ) ;
struct segment_type * init_segtype ( struct cmd_context * cmd )
# endif
{
2018-06-08 15:40:53 +03:00
struct segment_type * segtype = zalloc ( sizeof ( * segtype ) ) ;
2004-05-05 01:25:57 +04:00
2008-01-30 16:19:47 +03:00
if ( ! segtype )
return_NULL ;
2004-05-05 01:25:57 +04:00
segtype - > ops = & _mirrored_ops ;
2015-09-22 21:04:12 +03:00
segtype - > name = SEG_TYPE_NAME_MIRROR ;
2014-09-16 03:13:46 +04:00
segtype - > flags = SEG_MIRROR | SEG_AREAS_MIRRORED ;
2010-08-17 02:54:35 +04:00
2011-02-18 17:29:39 +03:00
# ifdef DEVMAPPER_SUPPORT
2011-04-29 04:21:13 +04:00
# ifdef DMEVENTD
2018-02-10 22:22:32 +03:00
segtype - > dso = get_monitor_dso_path ( cmd , dmeventd_mirror_library_CFG ) ;
2018-02-10 01:40:37 +03:00
if ( segtype - > dso )
2010-08-17 02:54:35 +04:00
segtype - > flags | = SEG_MONITORED ;
2011-04-29 04:21:13 +04:00
# endif /* DMEVENTD */
2010-08-17 02:54:35 +04:00
# endif
2004-05-05 01:25:57 +04:00
2004-09-14 21:37:51 +04:00
log_very_verbose ( " Initialised segtype: %s " , segtype - > name ) ;
2004-05-05 01:25:57 +04:00
return segtype ;
}