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"
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 "str_list.h"
# include "targets.h"
# include "lvm-string.h"
2004-05-05 22:11:43 +04:00
# include "activate.h"
2005-05-03 21:28:23 +04:00
# include "pv_alloc.h"
2004-05-05 01:25:57 +04:00
2006-04-19 19:33:07 +04:00
static const char * _striped_name ( const struct lv_segment * seg )
2004-05-05 01:25:57 +04:00
{
return ( seg - > area_count = = 1 ) ? " linear " : seg - > segtype - > name ;
}
2006-04-19 19:33:07 +04:00
static void _striped_display ( const struct lv_segment * seg )
2004-05-05 01:25:57 +04:00
{
uint32_t s ;
if ( seg - > area_count = = 1 )
display_stripe ( seg , 0 , " " ) ;
else {
log_print ( " Stripes \t \t %u " , seg - > area_count ) ;
log_print ( " Stripe size \t \t %u KB " , seg - > stripe_size / 2 ) ;
for ( s = 0 ; s < seg - > area_count ; s + + ) {
log_print ( " Stripe %d: " , s ) ;
display_stripe ( seg , s , " " ) ;
}
}
log_print ( " " ) ;
}
2006-04-19 19:33:07 +04:00
static int _striped_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 , " stripe_count " , area_count ) ) {
log_error ( " Couldn't read 'stripe_count' for "
" segment '%s'. " , sn - > key ) ;
return 0 ;
}
return 1 ;
}
2006-04-19 19:33:07 +04:00
static int _striped_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
{
struct config_node * cn ;
if ( ( seg - > area_count ! = 1 ) & &
! get_config_uint32 ( sn , " stripe_size " , & seg - > stripe_size ) ) {
log_error ( " Couldn't read stripe_size for segment '%s'. " ,
sn - > key ) ;
return 0 ;
}
if ( ! ( cn = find_config_node ( sn , " stripes " ) ) ) {
log_error ( " Couldn't find stripes array for segment "
" '%s'. " , sn - > key ) ;
return 0 ;
}
seg - > area_len / = seg - > area_count ;
2005-06-03 18:49:51 +04:00
return text_import_areas ( seg , sn , cn , pv_hash , 0 ) ;
2004-05-05 01:25:57 +04:00
}
2006-04-19 19:33:07 +04:00
static int _striped_text_export ( const struct lv_segment * seg , struct formatter * f )
2004-05-05 01:25:57 +04:00
{
outf ( f , " stripe_count = %u%s " , seg - > area_count ,
( seg - > area_count = = 1 ) ? " \t # linear " : " " ) ;
if ( seg - > area_count > 1 )
out_size ( f , ( uint64_t ) seg - > stripe_size ,
" stripe_size = %u " , seg - > stripe_size ) ;
return out_areas ( f , seg , " stripe " ) ;
}
/*
* Test whether two segments could be merged by the current merging code
*/
2006-04-19 19:33:07 +04:00
static int _striped_segments_compatible ( struct lv_segment * first ,
2004-05-05 01:25:57 +04:00
struct lv_segment * second )
{
uint32_t width ;
unsigned s ;
if ( ( first - > area_count ! = second - > area_count ) | |
2005-11-09 01:52:26 +03:00
( first - > stripe_size ! = second - > stripe_size ) )
return 0 ;
2004-05-05 01:25:57 +04:00
for ( s = 0 ; s < first - > area_count ; s + + ) {
/* FIXME Relax this to first area type != second area type */
/* plus the additional AREA_LV checks needed */
2005-10-18 17:45:25 +04:00
if ( ( seg_type ( first , s ) ! = AREA_PV ) | |
( seg_type ( second , s ) ! = AREA_PV ) )
2005-06-14 21:54:48 +04:00
return 0 ;
2004-05-05 01:25:57 +04:00
width = first - > area_len ;
2005-06-01 20:51:55 +04:00
if ( ( seg_pv ( first , s ) ! =
seg_pv ( second , s ) ) | |
( seg_pe ( first , s ) + width ! =
seg_pe ( second , s ) ) )
2004-05-05 01:25:57 +04:00
return 0 ;
}
if ( ! str_list_lists_equal ( & first - > tags , & second - > tags ) )
return 0 ;
return 1 ;
}
2006-04-19 19:33:07 +04:00
static int _striped_merge_segments ( struct lv_segment * seg1 , struct lv_segment * seg2 )
2004-05-05 01:25:57 +04:00
{
2005-05-03 21:28:23 +04:00
uint32_t s ;
2006-04-19 19:33:07 +04:00
if ( ! _striped_segments_compatible ( seg1 , seg2 ) )
2004-05-05 01:25:57 +04:00
return 0 ;
seg1 - > len + = seg2 - > len ;
seg1 - > area_len + = seg2 - > area_len ;
2005-05-03 21:28:23 +04:00
for ( s = 0 ; s < seg1 - > area_count ; s + + )
2005-10-18 17:45:25 +04:00
if ( seg_type ( seg1 , s ) = = AREA_PV )
2005-06-01 20:51:55 +04:00
merge_pv_segments ( seg_pvseg ( seg1 , s ) ,
seg_pvseg ( seg2 , s ) ) ;
2005-05-03 21:28:23 +04:00
2004-05-05 01:25:57 +04:00
return 1 ;
}
# ifdef DEVMAPPER_SUPPORT
2006-05-11 21:58:58 +04:00
static int _striped_add_target_line ( struct dev_manager * dm ,
struct dm_pool * mem __attribute ( ( unused ) ) ,
struct config_tree * cft __attribute ( ( unused ) ) ,
void * * target_state __attribute ( ( unused ) ) ,
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 ,
2006-05-11 21:58:58 +04:00
uint32_t * pvmove_mirror_count __attribute ( ( unused ) ) )
2004-05-05 01:25:57 +04:00
{
2005-11-09 01:52:26 +03:00
if ( ! seg - > area_count ) {
log_error ( " Internal error: striped add_target_line called "
" with no areas for %s. " , seg - > lv - > name ) ;
2004-05-05 01:25:57 +04:00
return 0 ;
}
2005-11-09 01:52:26 +03:00
if ( seg - > area_count = = 1 ) {
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 ;
2005-11-09 16:08:41 +03:00
} else if ( ! dm_tree_node_add_striped_target ( node , len ,
2005-11-09 01:52:26 +03:00
seg - > stripe_size ) )
return_0 ;
return add_areas_line ( dm , seg , node , 0u , seg - > area_count ) ;
2004-05-05 01:25:57 +04:00
}
2004-05-05 22:11:43 +04:00
2006-04-19 19:33:07 +04:00
static int _striped_target_present ( void )
2004-05-05 22:11:43 +04:00
{
2006-04-19 19:33:07 +04:00
static int _striped_checked = 0 ;
static int _striped_present = 0 ;
2004-05-05 22:11:43 +04:00
2006-04-19 19:33:07 +04:00
if ( ! _striped_checked )
_striped_present = target_present ( " linear " , 0 ) & &
2005-11-09 01:52:26 +03:00
target_present ( " striped " , 0 ) ;
2004-05-05 22:11:43 +04:00
2006-04-19 19:33:07 +04:00
_striped_checked = 1 ;
return _striped_present ;
2004-05-05 22:11:43 +04:00
}
2004-05-05 01:25:57 +04:00
# endif
2006-04-19 19:33:07 +04:00
static void _striped_destroy ( const struct segment_type * segtype )
2004-05-05 01:25:57 +04:00
{
2006-05-11 21:58:58 +04:00
dm_free ( ( void * ) segtype ) ;
2004-05-05 01:25:57 +04:00
}
static struct segtype_handler _striped_ops = {
2006-05-10 01:23:51 +04:00
. name = _striped_name ,
. display = _striped_display ,
. text_import_area_count = _striped_text_import_area_count ,
. text_import = _striped_text_import ,
. text_export = _striped_text_export ,
. merge_segments = _striped_merge_segments ,
2004-05-05 01:25:57 +04:00
# ifdef DEVMAPPER_SUPPORT
2006-05-10 01:23:51 +04:00
. add_target_line = _striped_add_target_line ,
. target_present = _striped_target_present ,
2004-05-05 01:25:57 +04:00
# endif
2006-05-10 01:23:51 +04:00
. destroy = _striped_destroy ,
2004-05-05 01:25:57 +04:00
} ;
struct segment_type * init_striped_segtype ( struct cmd_context * cmd )
{
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 = & _striped_ops ;
segtype - > name = " striped " ;
segtype - > private = NULL ;
segtype - > flags =
SEG_CAN_SPLIT | SEG_AREAS_STRIPED | SEG_FORMAT1_SUPPORT ;
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 ;
}