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 .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 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/datastruct/str_list.h"
# include "lib/activate/targets.h"
# include "lib/misc/lvm-string.h"
# include "lib/activate/activate.h"
# include "lib/metadata/pv_alloc.h"
# include "lib/metadata/metadata.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
{
2015-09-22 21:04:12 +03:00
return ( seg - > area_count = = 1 ) ? SEG_TYPE_NAME_LINEAR : seg - > segtype - > name ;
2004-05-05 01:25:57 +04:00
}
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 ) ;
2009-09-28 20:23:44 +04:00
if ( seg - > lv - > vg - > cmd - > si_unit_consistency )
log_print ( " Stripe size \t \t %s " ,
display_size ( seg - > lv - > vg - > cmd ,
( uint64_t ) seg - > stripe_size ) ) ;
else
log_print ( " Stripe size \t \t %u KB " ,
seg - > stripe_size / 2 ) ;
2004-05-05 01:25:57 +04:00
for ( s = 0 ; s < seg - > area_count ; s + + ) {
log_print ( " Stripe %d: " , s ) ;
display_stripe ( seg , s , " " ) ;
}
}
log_print ( " " ) ;
}
2011-08-30 18:55:15 +04:00
static int _striped_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 , " stripe_count " , area_count ) ) {
2004-05-05 01:25:57 +04:00
log_error ( " Couldn't read 'stripe_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 _striped_text_import ( struct lv_segment * seg , const struct dm_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
{
2011-08-31 19:19:19 +04:00
const struct dm_config_value * cv ;
2004-05-05 01:25:57 +04:00
if ( ( seg - > area_count ! = 1 ) & &
2011-08-30 18:55:15 +04:00
! dm_config_get_uint32 ( sn , " stripe_size " , & seg - > stripe_size ) ) {
2009-07-09 15:29:00 +04:00
log_error ( " Couldn't read stripe_size for segment %s "
2011-08-30 18:55:15 +04:00
" of logical volume %s. " , 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_get_list ( sn , " stripes " , & cv ) ) {
2009-07-09 15:29:00 +04:00
log_error ( " Couldn't find stripes array for segment %s "
2011-08-30 18:55:15 +04:00
" of logical volume %s. " , dm_config_parent_name ( sn ) , seg - > lv - > name ) ;
2004-05-05 01:25:57 +04:00
return 0 ;
}
seg - > area_len / = seg - > area_count ;
2011-08-31 19:19:19 +04:00
return text_import_areas ( seg , sn , cv , 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
{
2014-07-17 01:57:43 +04:00
outfc ( f , ( seg - > area_count = = 1 ) ? " # linear " : NULL ,
" stripe_count = %u " , seg - > area_count ) ;
2004-05-05 01:25:57 +04:00
if ( seg - > area_count > 1 )
2010-01-07 17:46:51 +03:00
outsize ( f , ( uint64_t ) seg - > stripe_size ,
" stripe_size = %u " , seg - > stripe_size ) ;
2004-05-05 01:25:57 +04:00
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
2016-12-01 18:09:53 +03:00
static int _striped_target_status_compatible ( const char * type )
{
return ( strcmp ( type , TARGET_NAME_LINEAR ) = = 0 ) ;
}
2006-05-11 21:58:58 +04:00
static int _striped_add_target_line ( struct dev_manager * dm ,
2010-07-09 19:34:40 +04:00
struct dm_pool * mem __attribute__ ( ( unused ) ) ,
struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
void * * target_state __attribute__ ( ( unused ) ) ,
2008-01-30 17:00:02 +03:00
struct lv_segment * seg ,
2011-06-17 18:14:19 +04:00
const struct lv_activate_opts * laopts __attribute__ ( ( unused ) ) ,
2008-01-30 17:00:02 +03:00
struct dm_tree_node * node , uint64_t len ,
2010-07-09 19:34:40 +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 ) {
2009-12-16 22:22:11 +03:00
log_error ( INTERNAL_ERROR " striped add_target_line called "
2005-11-09 01:52:26 +03:00
" 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 ) {
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 ;
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
2009-02-28 23:04:24 +03:00
static int _striped_target_present ( struct cmd_context * cmd ,
2010-07-09 19:34:40 +04:00
const struct lv_segment * seg __attribute__ ( ( unused ) ) ,
unsigned * attributes __attribute__ ( ( unused ) ) )
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
2015-12-17 14:23:33 +03:00
if ( ! activation ( ) )
return 0 ;
2004-05-05 22:11:43 +04:00
2015-12-17 14:23:33 +03:00
if ( ! _striped_checked ) {
_striped_checked = 1 ;
2016-03-22 20:46:15 +03:00
_striped_present = target_present ( cmd , TARGET_NAME_LINEAR , 0 ) & &
target_present ( cmd , TARGET_NAME_STRIPED , 0 ) ;
2015-12-17 14:23:33 +03:00
}
2006-04-19 19:33:07 +04:00
return _striped_present ;
2004-05-05 22:11:43 +04:00
}
2004-05-05 01:25:57 +04:00
# endif
2010-12-20 16:32:49 +03:00
static void _striped_destroy ( struct segment_type * segtype )
2004-05-05 01:25:57 +04:00
{
2018-06-08 15:40:53 +03:00
free ( 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
2016-12-01 18:09:53 +03:00
. target_status_compatible = _striped_target_status_compatible ,
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
} ;
2018-05-30 13:44:24 +03:00
static struct segment_type * _init_segtype ( struct cmd_context * cmd , const char * name , uint64_t target )
2004-05-05 01:25:57 +04:00
{
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 = & _striped_ops ;
2018-05-30 13:44:24 +03:00
segtype - > name = name ;
segtype - > flags = target | SEG_CAN_SPLIT | SEG_AREAS_STRIPED ;
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 ;
}
2018-05-30 13:44:24 +03:00
struct segment_type * init_striped_segtype ( struct cmd_context * cmd )
{
return _init_segtype ( cmd , SEG_TYPE_NAME_STRIPED , SEG_STRIPED_TARGET ) ;
}
struct segment_type * init_linear_segtype ( struct cmd_context * cmd )
{
return _init_segtype ( cmd , SEG_TYPE_NAME_LINEAR , SEG_LINEAR_TARGET ) ;
}