2004-05-05 01:25:57 +04:00
/*
* Copyright ( C ) 2003 - 2004 Sistina Software , Inc . All rights reserved .
* Copyright ( C ) 2004 Red Hat , Inc . All rights reserved .
*
* 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
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "lib.h"
# include "toolcontext.h"
# include "metadata.h"
2004-09-16 22:40:56 +04:00
# include "segtype.h"
2004-05-05 01:25:57 +04:00
# include "display.h"
# include "text_export.h"
# include "text_import.h"
# include "config.h"
# include "defaults.h"
# include "lvm-string.h"
# include "targets.h"
2004-05-05 22:11:43 +04:00
# include "activate.h"
2006-01-27 23:13:12 +03:00
# include "sharedlib.h"
2006-10-03 21:55:20 +04:00
# include "str_list.h"
2005-12-21 22:45:16 +03:00
# ifdef DMEVENTD
# include <libdevmapper-event.h>
# endif
2004-05-05 01:25:57 +04:00
2005-12-20 00:01:39 +03:00
static int _block_on_error_available = 0 ;
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 const char * _mirrored_name ( const struct lv_segment * seg )
2004-05-05 01:25:57 +04:00
{
return seg - > segtype - > name ;
}
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 ( " " ) ;
}
2006-04-19 19:33:07 +04:00
static int _mirrored_text_import_area_count ( struct config_node * sn , uint32_t * area_count )
2004-05-05 01:25:57 +04:00
{
if ( ! get_config_uint32 ( sn , " mirror_count " , area_count ) ) {
log_error ( " Couldn't read 'mirror_count' for "
" segment '%s'. " , sn - > key ) ;
return 0 ;
}
return 1 ;
}
2006-04-19 19:33:07 +04:00
static int _mirrored_text_import ( struct lv_segment * seg , const struct config_node * sn ,
2005-10-17 03:03:59 +04:00
struct dm_hash_table * pv_hash )
2004-05-05 01:25:57 +04:00
{
const struct config_node * cn ;
2005-06-01 20:51:55 +04:00
char * logname = NULL ;
2004-05-05 01:25:57 +04:00
if ( find_config_node ( sn , " extents_moved " ) ) {
2004-05-05 21:56:20 +04:00
if ( get_config_uint32 ( sn , " extents_moved " ,
& seg - > extents_copied ) )
2004-05-05 01:25:57 +04:00
seg - > status | = PVMOVE ;
else {
log_error ( " Couldn't read 'extents_moved' for "
" segment '%s'. " , sn - > key ) ;
return 0 ;
}
}
2005-06-01 20:51:55 +04:00
if ( find_config_node ( sn , " region_size " ) ) {
if ( ! get_config_uint32 ( sn , " region_size " ,
& seg - > region_size ) ) {
log_error ( " Couldn't read 'region_size' for "
" segment '%s'. " , sn - > key ) ;
return 0 ;
}
}
if ( ( cn = find_config_node ( sn , " mirror_log " ) ) ) {
if ( ! cn - > v | | ! cn - > v - > v . str ) {
log_error ( " Mirror log type must be a string. " ) ;
return 0 ;
}
logname = cn - > v - > v . str ;
if ( ! ( seg - > log_lv = find_lv ( seg - > lv - > vg , logname ) ) ) {
log_error ( " Unrecognised mirror log in segment %s. " ,
sn - > key ) ;
return 0 ;
}
seg - > log_lv - > status | = MIRROR_LOG ;
}
if ( logname & & ! seg - > region_size ) {
log_error ( " Missing region size for mirror log for segment "
" '%s'. " , sn - > key ) ;
return 0 ;
}
2004-05-05 01:25:57 +04:00
if ( ! ( cn = find_config_node ( sn , " mirrors " ) ) ) {
log_error ( " Couldn't find mirrors array for segment "
" '%s'. " , sn - > key ) ;
return 0 ;
}
2005-06-03 18:49:51 +04:00
return text_import_areas ( seg , sn , cn , 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 )
2004-08-18 02:09:02 +04:00
out_size ( f , ( uint64_t ) seg - > extents_copied * seg - > lv - > vg - > extent_size ,
2005-06-01 20:51:55 +04:00
" extents_moved = % " PRIu32 , seg - > extents_copied ) ;
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
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 ;
}
2005-06-01 20:51:55 +04:00
mirr_state - > default_region_size = 2 *
2006-05-16 20:48:31 +04:00
find_config_tree_int ( cmd ,
2004-05-05 01:25:57 +04:00
" activation/mirror_region_size " ,
DEFAULT_MIRROR_REGION_SIZE ) ;
return mirr_state ;
}
2006-04-19 19:33:07 +04:00
static int _mirrored_target_percent ( void * * target_state , struct dm_pool * mem ,
2006-05-16 20:48:31 +04:00
struct cmd_context * cmd , struct lv_segment * seg ,
2004-05-05 01:25:57 +04:00
char * params , uint64_t * total_numerator ,
2006-05-11 21:58:58 +04:00
uint64_t * total_denominator ,
float * percent __attribute ( ( unused ) ) )
2004-05-05 01:25:57 +04:00
{
struct mirror_state * mirr_state ;
uint64_t numerator , denominator ;
2005-09-02 20:59:46 +04:00
unsigned mirror_count , m ;
int used ;
char * pos = params ;
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
mirr_state = * target_state ;
2005-09-02 20:59:46 +04:00
/* Status line: <#mirrors> (maj:min)+ <synced>/<total_regions> */
2004-05-05 01:25:57 +04:00
log_debug ( " Mirror status: %s " , params ) ;
2005-09-02 20:59:46 +04:00
2005-10-17 03:03:59 +04:00
if ( sscanf ( pos , " %u %n " , & mirror_count , & used ) ! = 1 ) {
2005-09-02 20:59:46 +04:00
log_error ( " Failure parsing mirror status mirror count: %s " ,
params ) ;
2004-05-05 01:25:57 +04:00
return 0 ;
}
2005-09-02 20:59:46 +04:00
pos + = used ;
for ( m = 0 ; m < mirror_count ; m + + ) {
if ( sscanf ( pos , " %*x:%*x %n " , & used ) ! = 0 ) {
log_error ( " Failure parsing mirror status devices: %s " ,
params ) ;
return 0 ;
}
pos + = used ;
}
if ( sscanf ( pos , " % " PRIu64 " /% " PRIu64 " %n " , & numerator , & denominator ,
& used ) ! = 2 ) {
log_error ( " Failure parsing mirror status fraction: %s " , params ) ;
return 0 ;
}
pos + = used ;
2004-05-05 01:25:57 +04:00
* total_numerator + = numerator ;
* total_denominator + = denominator ;
2004-05-05 21:56:20 +04:00
if ( seg )
2004-08-18 02:09:02 +04:00
seg - > extents_copied = seg - > area_len * numerator / denominator ;
2004-05-05 01:25:57 +04:00
return 1 ;
}
2004-05-05 22:11:43 +04:00
2005-11-09 01:52:26 +03:00
static int _add_log ( struct dev_manager * dm , struct lv_segment * seg ,
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
/*
* Use clustered mirror log for non - exclusive activation
* in clustered VG .
*/
if ( ( ! ( seg - > lv - > status & ACTIVATE_EXCL ) & &
( seg - > lv - > vg - > status & CLUSTERED ) ) )
clustered = 1 ;
2006-05-11 23:47:53 +04:00
if ( seg - > log_lv ) {
/* If disk log, use its UUID */
if ( ! ( log_dlid = build_dlid ( dm , seg - > log_lv - > lvid . s , NULL ) ) ) {
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 */
if ( ! ( log_dlid = build_dlid ( dm , seg - > lv - > lvid . s , NULL ) ) ) {
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 ;
2005-12-20 00:01:39 +03:00
if ( _block_on_error_available & & ! ( seg - > status & PVMOVE ) )
2005-12-13 18:57:32 +03:00
log_flags | = DM_BLOCK_ON_ERROR ;
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 ,
2006-05-16 20:48:31 +04:00
struct cmd_context * cmd , void * * target_state ,
2005-11-09 01:52:26 +03:00
struct lv_segment * seg ,
2005-11-09 16:08:41 +03:00
struct dm_tree_node * node , uint64_t len ,
2005-11-09 01:52:26 +03:00
uint32_t * pvmove_mirror_count )
{
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 ;
uint32_t region_size , region_max ;
int r ;
if ( ! * target_state )
2006-05-16 20:48:31 +04:00
* target_state = _mirrored_init_target ( mem , cmd ) ;
2005-11-09 01:52:26 +03:00
mirr_state = * target_state ;
/*
* 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 ) {
2005-11-09 16:08:41 +03:00
if ( ! dm_tree_node_add_linear_target ( node , len ) )
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 ;
} else {
/* Find largest power of 2 region size unit we can use */
2006-05-10 01:23:51 +04:00
region_max = ( 1 < < ( ffs ( ( int ) seg - > area_len ) - 1 ) ) *
2005-11-09 01:52:26 +03:00
seg - > lv - > vg - > extent_size ;
region_size = mirr_state - > default_region_size ;
if ( region_max < region_size ) {
region_size = region_max ;
log_verbose ( " Using reduced mirror region size of %u sectors " ,
region_size ) ;
}
}
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 ;
if ( ( r = _add_log ( dm , seg , node , area_count , region_size ) ) < = 0 ) {
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
}
2006-10-18 22:01:53 +04:00
static int _mirrored_target_present ( const struct lv_segment * seg __attribute ( ( unused ) ) )
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 ;
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 ;
2005-12-20 00:01:39 +03:00
char vsn [ 80 ] ;
2004-05-05 22:11:43 +04:00
2006-04-19 19:33:07 +04:00
if ( ! _mirrored_checked ) {
_mirrored_present = target_present ( " mirror " , 1 ) ;
2004-05-05 22:11:43 +04:00
2005-12-20 00:01:39 +03:00
/*
* block_on_error available with mirror target > = 1.1
* or with 1.0 in RHEL4U3 driver > = 4.5
*/
2005-12-20 01:36:04 +03:00
/* FIXME Move this into libdevmapper */
2005-12-20 00:01:39 +03:00
if ( target_version ( " mirror " , & maj , & min , & patchlevel ) & &
maj = = 1 & &
( min > = 1 | |
( 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 ;
}
2006-04-19 19:33:07 +04:00
_mirrored_checked = 1 ;
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
# ifdef DMEVENTD
2007-01-17 18:00:57 +03:00
static int _get_mirror_dso_path ( struct cmd_context * cmd , char * * dso )
2005-12-02 23:35:07 +03:00
{
2006-01-27 23:13:12 +03:00
char * path ;
const char * libpath ;
2007-01-12 23:38:30 +03:00
if ( ! ( path = dm_pool_alloc ( cmd - > mem , PATH_MAX ) ) ) {
2006-01-27 23:13:12 +03:00
log_error ( " Failed to allocate dmeventd library path. " ) ;
return 0 ;
}
2006-05-16 20:48:31 +04:00
libpath = find_config_tree_str ( cmd , " dmeventd/mirror_library " ,
DEFAULT_DMEVENTD_MIRROR_LIB ) ;
2006-01-27 23:13:12 +03:00
2006-05-16 20:48:31 +04:00
get_shared_library_path ( cmd , libpath , path , PATH_MAX ) ;
2006-01-27 23:13:12 +03:00
* dso = path ;
2005-12-02 23:35:07 +03:00
return 1 ;
}
2007-01-17 18:00:57 +03:00
static struct dm_event_handler * _create_dm_event_handler ( const char * dmname ,
const char * dso ,
enum dm_event_mask mask )
{
struct dm_event_handler * dmevh ;
if ( ! ( dmevh = dm_event_handler_create ( ) ) )
return_0 ;
if ( dm_event_handler_set_dso ( dmevh , dso ) )
goto fail ;
if ( dm_event_handler_set_dev_name ( dmevh , dmname ) )
goto fail ;
dm_event_handler_set_event_mask ( dmevh , mask ) ;
return dmevh ;
fail :
dm_event_handler_destroy ( dmevh ) ;
return NULL ;
}
2007-01-20 01:21:45 +03:00
static int _target_monitored ( struct lv_segment * seg , int * pending )
2007-01-12 23:38:30 +03:00
{
char * dso , * name ;
struct logical_volume * lv ;
struct volume_group * vg ;
2007-01-15 21:22:02 +03:00
enum dm_event_mask evmask = 0 ;
2007-01-17 02:05:13 +03:00
struct dm_event_handler * dmevh ;
2007-01-12 23:38:30 +03:00
lv = seg - > lv ;
vg = lv - > vg ;
* pending = 0 ;
2007-01-17 18:00:57 +03:00
if ( ! _get_mirror_dso_path ( vg - > cmd , & dso ) )
return_0 ;
2007-01-12 23:38:30 +03:00
if ( ! ( name = build_dm_name ( vg - > cmd - > mem , vg - > name , lv - > name , NULL ) ) )
return_0 ;
2007-01-17 18:00:57 +03:00
if ( ! ( dmevh = _create_dm_event_handler ( name , dso , DM_EVENT_ALL_ERRORS ) ) )
2007-01-17 02:05:13 +03:00
return_0 ;
if ( dm_event_get_registered_device ( dmevh , 0 ) ) {
dm_event_handler_destroy ( dmevh ) ;
2007-01-12 23:38:30 +03:00
return 0 ;
2007-01-17 02:05:13 +03:00
}
2007-01-12 23:38:30 +03:00
2007-01-17 02:05:13 +03:00
evmask = dm_event_handler_get_event_mask ( dmevh ) ;
2007-01-15 21:22:02 +03:00
if ( evmask & DM_EVENT_REGISTRATION_PENDING ) {
2007-01-12 23:38:30 +03:00
* pending = 1 ;
2007-01-15 21:22:02 +03:00
evmask & = ~ DM_EVENT_REGISTRATION_PENDING ;
2007-01-12 23:38:30 +03:00
}
2007-01-17 02:05:13 +03:00
dm_event_handler_destroy ( dmevh ) ;
2007-01-15 21:22:02 +03:00
return evmask ;
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. */
2007-01-24 19:51:24 +03:00
static int _target_set_events ( struct lv_segment * seg , int evmask , int set )
2005-12-02 23:35:07 +03:00
{
2006-01-27 23:13:12 +03:00
char * dso , * name ;
2005-12-02 23:35:07 +03:00
struct logical_volume * lv ;
struct volume_group * vg ;
2007-01-15 21:22:02 +03:00
struct dm_event_handler * dmevh ;
2007-01-17 18:00:57 +03:00
int r ;
2005-12-02 23:35:07 +03:00
lv = seg - > lv ;
vg = lv - > vg ;
2007-01-24 19:51:24 +03:00
if ( ! _get_mirror_dso_path ( vg - > cmd , & dso ) )
2007-01-17 18:00:57 +03:00
return_0 ;
2005-12-02 23:35:07 +03:00
2007-01-24 19:51:24 +03:00
if ( ! ( name = build_dm_name ( vg - > cmd - > mem , vg - > name , lv - > name , NULL ) ) )
2006-01-27 23:13:12 +03:00
return_0 ;
2005-12-02 23:35:07 +03:00
2007-01-17 18:00:57 +03:00
if ( ! ( dmevh = _create_dm_event_handler ( name , dso , DM_EVENT_ALL_ERRORS ) ) )
2006-01-27 23:13:12 +03:00
return_0 ;
2007-01-17 18:00:57 +03:00
r = set ? dm_event_register_handler ( dmevh ) : dm_event_unregister_handler ( dmevh ) ;
2007-01-15 21:22:02 +03:00
dm_event_handler_destroy ( dmevh ) ;
2007-01-17 18:00:57 +03:00
if ( ! r )
return_0 ;
2007-01-12 01:24:32 +03:00
2007-01-20 01:21:45 +03:00
log_info ( " %s %s for events " , set ? " Monitored " : " Unmonitored " , name ) ;
2005-12-02 23:35:07 +03:00
return 1 ;
}
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
}
# endif /* DMEVENTD */
# endif /* DEVMAPPER_SUPPORT */
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 ,
struct list * modules )
{
if ( seg - > log_lv & &
! list_segment_modules ( mem , first_seg ( seg - > log_lv ) , modules ) )
return_0 ;
if ( ( seg - > lv - > vg - > status & CLUSTERED ) & &
! str_list_add ( mem , modules , " clog " ) ) {
log_error ( " cluster log string list allocation failed " ) ;
return 0 ;
}
if ( ! str_list_add ( mem , modules , " mirror " ) ) {
log_error ( " mirror string list allocation failed " ) ;
return 0 ;
}
return 1 ;
}
2006-04-19 19:33:07 +04:00
static void _mirrored_destroy ( const struct segment_type * segtype )
2004-05-05 01:25:57 +04:00
{
2005-10-17 03:03:59 +04:00
dm_free ( ( void * ) segtype ) ;
2004-05-05 01:25:57 +04:00
}
static struct segtype_handler _mirrored_ops = {
2006-05-10 01:23:51 +04:00
. name = _mirrored_name ,
. 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 ,
2005-12-02 23:35:07 +03:00
# ifdef DMEVENTD
2007-01-20 01:21:45 +03:00
. target_monitored = _target_monitored ,
. target_monitor_events = _target_monitor_events ,
. target_unmonitor_events = _target_unmonitor_events ,
2005-12-13 16:32:19 +03:00
# endif
2004-05-05 01:25:57 +04:00
# endif
2006-10-03 21:55:20 +04:00
. modules_needed = _mirrored_modules_needed ,
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
{
2005-10-17 03:03:59 +04:00
struct segment_type * segtype = dm_malloc ( sizeof ( * segtype ) ) ;
2004-05-05 01:25:57 +04:00
if ( ! segtype ) {
stack ;
return NULL ;
}
segtype - > cmd = cmd ;
segtype - > ops = & _mirrored_ops ;
segtype - > name = " mirror " ;
segtype - > private = NULL ;
2007-01-12 23:38:30 +03:00
segtype - > flags = SEG_AREAS_MIRRORED | SEG_MONITORED ;
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 ;
}