2001-11-13 17:17:50 +03:00
/*
2004-05-11 20:01:58 +04:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2013-06-11 15:45:49 +04:00
* Copyright ( C ) 2004 - 2013 Red Hat , Inc . All rights reserved .
2001-11-13 17:17:50 +03:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
2001-11-13 17:17:50 +03:00
*
2004-03-30 23:35:44 +04:00
* 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 .
2001-11-13 17:17:50 +03:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2004-03-30 23:35:44 +04:00
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2001-11-13 17:17:50 +03:00
*/
# include "tools.h"
2004-06-15 21:23:49 +04:00
# define SIZE_BUF 128
2004-05-11 22:47:40 +04:00
struct lvresize_params {
2002-12-20 02:25:55 +03:00
const char * vg_name ;
2004-05-11 22:47:40 +04:00
const char * lv_name ;
uint32_t stripes ;
uint32_t stripe_size ;
2005-06-03 23:48:19 +04:00
uint32_t mirrors ;
2004-05-11 22:47:40 +04:00
2006-05-10 01:23:51 +04:00
const struct segment_type * segtype ;
2004-05-11 22:47:40 +04:00
/* size */
uint32_t extents ;
uint64_t size ;
2013-06-11 15:45:49 +04:00
int sizeargs ;
2004-05-11 22:47:40 +04:00
sign_t sign ;
2013-06-11 15:45:49 +04:00
uint64_t poolmetadatasize ;
sign_t poolmetadatasign ;
2010-11-30 14:53:31 +03:00
percent_type_t percent ;
2001-11-13 17:17:50 +03:00
enum {
LV_ANY = 0 ,
LV_REDUCE = 1 ,
LV_EXTEND = 2
2004-05-11 22:47:40 +04:00
} resize ;
2004-06-15 21:23:49 +04:00
int resizefs ;
int nofsck ;
2004-05-11 22:47:40 +04:00
int argc ;
char * * argv ;
} ;
2009-02-28 02:40:11 +03:00
static int _validate_stripesize ( struct cmd_context * cmd ,
const struct volume_group * vg ,
struct lvresize_params * lp )
2007-09-07 01:08:16 +04:00
{
2012-02-28 18:24:57 +04:00
if ( arg_sign_value ( cmd , stripesize_ARG , SIGN_NONE ) = = SIGN_MINUS ) {
2007-09-07 01:08:16 +04:00
log_error ( " Stripesize may not be negative. " ) ;
return 0 ;
}
2011-03-02 19:56:06 +03:00
if ( arg_uint64_value ( cmd , stripesize_ARG , 0 ) > STRIPE_SIZE_LIMIT * 2 ) {
2007-09-07 01:08:16 +04:00
log_error ( " Stripe size cannot be larger than %s " ,
display_size ( cmd , ( uint64_t ) STRIPE_SIZE_LIMIT ) ) ;
return 0 ;
}
if ( ! ( vg - > fid - > fmt - > features & FMT_SEGMENTS ) )
log_warn ( " Varied stripesize not supported. Ignoring. " ) ;
2012-03-05 19:05:24 +04:00
else if ( arg_uint_value ( cmd , stripesize_ARG , 0 ) > ( uint64_t ) vg - > extent_size * 2 ) {
2007-09-07 01:08:16 +04:00
log_error ( " Reducing stripe size %s to maximum, "
" physical extent size %s " ,
display_size ( cmd ,
2007-11-14 03:08:25 +03:00
( uint64_t ) arg_uint_value ( cmd , stripesize_ARG , 0 ) ) ,
2007-09-07 01:08:16 +04:00
display_size ( cmd , ( uint64_t ) vg - > extent_size ) ) ;
lp - > stripe_size = vg - > extent_size ;
} else
2007-11-14 03:08:25 +03:00
lp - > stripe_size = arg_uint_value ( cmd , stripesize_ARG , 0 ) ;
2007-09-07 01:08:16 +04:00
if ( lp - > stripe_size & ( lp - > stripe_size - 1 ) ) {
log_error ( " Stripe size must be power of 2 " ) ;
return 0 ;
}
return 1 ;
}
2009-02-28 02:40:11 +03:00
static int _request_confirmation ( struct cmd_context * cmd ,
const struct volume_group * vg ,
const struct logical_volume * lv ,
const struct lvresize_params * lp )
2007-09-07 01:08:16 +04:00
{
2012-03-30 19:17:25 +04:00
struct lvinfo info = { 0 } ;
2007-09-07 01:08:16 +04:00
2010-08-17 20:25:32 +04:00
if ( ! lv_info ( cmd , lv , 0 , & info , 1 , 0 ) & & driver_version ( NULL , 0 ) ) {
2007-09-07 01:08:16 +04:00
log_error ( " lv_info failed: aborting " ) ;
return 0 ;
}
2009-02-28 02:40:11 +03:00
if ( lp - > resizefs ) {
if ( ! info . exists ) {
log_error ( " Logical volume %s must be activated "
" before resizing filesystem " , lp - > lv_name ) ;
return 0 ;
}
return 1 ;
2007-09-07 01:08:16 +04:00
}
2009-02-28 02:40:11 +03:00
if ( ! info . exists )
return 1 ;
2007-09-07 01:08:16 +04:00
2009-02-28 02:40:11 +03:00
log_warn ( " WARNING: Reducing active%s logical volume to %s " ,
info . open_count ? " and open " : " " ,
display_size ( cmd , ( uint64_t ) lp - > extents * vg - > extent_size ) ) ;
2007-09-07 01:08:16 +04:00
2009-02-28 02:40:11 +03:00
log_warn ( " THIS MAY DESTROY YOUR DATA (filesystem etc.) " ) ;
if ( ! arg_count ( cmd , force_ARG ) ) {
if ( yes_no_prompt ( " Do you really want to reduce %s? [y/n]: " ,
lp - > lv_name ) = = ' n ' ) {
2009-12-03 22:18:33 +03:00
log_error ( " Logical volume %s NOT reduced " , lp - > lv_name ) ;
2009-02-28 02:40:11 +03:00
return 0 ;
2007-09-07 01:08:16 +04:00
}
2009-02-28 02:40:11 +03:00
if ( sigint_caught ( ) )
return 0 ;
2007-09-07 01:08:16 +04:00
}
return 1 ;
}
2009-02-24 18:48:00 +03:00
enum fsadm_cmd_e { FSADM_CMD_CHECK , FSADM_CMD_RESIZE } ;
2009-02-28 02:40:11 +03:00
# define FSADM_CMD "fsadm"
# define FSADM_CMD_MAX_ARGS 6
2010-11-01 17:17:35 +03:00
# define FSADM_CHECK_FAILS_FOR_MOUNTED 3 /* shell exist status code */
2009-02-24 18:48:00 +03:00
2009-02-28 02:40:11 +03:00
/*
* FSADM_CMD - - dry - run - - verbose - - force check lv_path
* FSADM_CMD - - dry - run - - verbose - - force resize lv_path size
*/
2009-02-28 03:54:06 +03:00
static int _fsadm_cmd ( struct cmd_context * cmd ,
2009-02-28 02:40:11 +03:00
const struct volume_group * vg ,
const struct lvresize_params * lp ,
2010-11-01 17:17:35 +03:00
enum fsadm_cmd_e fcmd ,
int * status )
2007-09-07 01:08:16 +04:00
{
char lv_path [ PATH_MAX ] ;
char size_buf [ SIZE_BUF ] ;
2009-02-28 02:40:11 +03:00
const char * argv [ FSADM_CMD_MAX_ARGS + 2 ] ;
unsigned i = 0 ;
2009-02-24 18:48:00 +03:00
2009-02-28 02:40:11 +03:00
argv [ i + + ] = FSADM_CMD ;
2009-02-24 18:48:00 +03:00
if ( test_mode ( ) )
argv [ i + + ] = " --dry-run " ;
2009-02-28 02:40:11 +03:00
if ( verbose_level ( ) > = _LOG_NOTICE )
2009-02-24 18:48:00 +03:00
argv [ i + + ] = " --verbose " ;
if ( arg_count ( cmd , force_ARG ) )
argv [ i + + ] = " --force " ;
argv [ i + + ] = ( fcmd = = FSADM_CMD_RESIZE ) ? " resize " : " check " ;
2007-09-07 01:08:16 +04:00
2012-02-08 14:56:17 +04:00
if ( status )
* status = - 1 ;
2009-02-28 02:40:11 +03:00
if ( dm_snprintf ( lv_path , PATH_MAX , " %s%s/%s " , cmd - > dev_dir , lp - > vg_name ,
lp - > lv_name ) < 0 ) {
log_error ( " Couldn't create LV path for %s " , lp - > lv_name ) ;
2007-09-07 01:08:16 +04:00
return 0 ;
}
2009-02-24 18:48:00 +03:00
argv [ i + + ] = lv_path ;
2007-09-07 01:08:16 +04:00
2009-02-24 18:48:00 +03:00
if ( fcmd = = FSADM_CMD_RESIZE ) {
if ( dm_snprintf ( size_buf , SIZE_BUF , " % " PRIu64 " K " ,
( uint64_t ) lp - > extents * vg - > extent_size / 2 ) < 0 ) {
log_error ( " Couldn't generate new LV size string " ) ;
return 0 ;
}
2007-09-07 01:08:16 +04:00
2009-02-24 18:48:00 +03:00
argv [ i + + ] = size_buf ;
}
2007-09-07 01:08:16 +04:00
2009-02-24 18:48:00 +03:00
argv [ i ] = NULL ;
2011-01-13 17:51:32 +03:00
return exec_cmd ( cmd , argv , status , 1 ) ;
2007-09-07 01:08:16 +04:00
}
2006-04-19 19:33:07 +04:00
static int _lvresize_params ( struct cmd_context * cmd , int argc , char * * argv ,
struct lvresize_params * lp )
2004-05-11 22:47:40 +04:00
{
const char * cmd_name ;
char * st ;
2008-02-06 15:45:32 +03:00
unsigned dev_dir_found = 0 ;
2010-10-15 20:28:14 +04:00
int use_policy = arg_count ( cmd , use_policies_ARG ) ;
2004-05-11 22:47:40 +04:00
lp - > sign = SIGN_NONE ;
2013-06-11 15:45:49 +04:00
lp - > poolmetadatasign = SIGN_NONE ;
2004-05-11 22:47:40 +04:00
lp - > resize = LV_ANY ;
2001-11-13 17:17:50 +03:00
2002-02-11 23:50:53 +03:00
cmd_name = command_name ( cmd ) ;
2001-11-13 17:17:50 +03:00
if ( ! strcmp ( cmd_name , " lvreduce " ) )
2004-05-11 22:47:40 +04:00
lp - > resize = LV_REDUCE ;
2001-11-13 17:17:50 +03:00
if ( ! strcmp ( cmd_name , " lvextend " ) )
2004-05-11 22:47:40 +04:00
lp - > resize = LV_EXTEND ;
2001-11-13 17:17:50 +03:00
2010-10-15 20:28:14 +04:00
if ( use_policy ) {
/* do nothing; _lvresize will handle --use-policies itself */
lp - > extents = 0 ;
2007-09-21 01:39:08 +04:00
lp - > sign = SIGN_PLUS ;
2010-10-15 20:28:14 +04:00
lp - > percent = PERCENT_LV ;
} else {
/*
* Allow omission of extents and size if the user has given us
* one or more PVs . Most likely , the intent was " resize this
* LV the best you can with these PVs "
2013-06-11 21:46:42 +04:00
* If only - - poolmetadatasize is specified with list of PVs ,
* then metadata will be extended there .
2010-10-15 20:28:14 +04:00
*/
2013-06-11 15:45:49 +04:00
lp - > sizeargs = arg_count ( cmd , extents_ARG ) + arg_count ( cmd , size_ARG ) ;
if ( ( lp - > sizeargs = = 0 ) & & ( argc > = 2 ) ) {
2010-10-15 20:28:14 +04:00
lp - > extents = 100 ;
lp - > percent = PERCENT_PVS ;
lp - > sign = SIGN_PLUS ;
2013-06-11 21:46:42 +04:00
lp - > sizeargs = ! lp - > poolmetadatasize ? 1 : 0 ;
2013-06-11 15:45:49 +04:00
} else if ( ( lp - > sizeargs ! = 1 ) & &
( ( lp - > sizeargs = = 2 ) | |
! arg_count ( cmd , poolmetadatasize_ARG ) ) ) {
2010-10-15 20:28:14 +04:00
log_error ( " Please specify either size or extents but not "
" both. " ) ;
return 0 ;
}
2001-11-13 17:17:50 +03:00
2010-10-15 20:28:14 +04:00
if ( arg_count ( cmd , extents_ARG ) ) {
lp - > extents = arg_uint_value ( cmd , extents_ARG , 0 ) ;
lp - > sign = arg_sign_value ( cmd , extents_ARG , SIGN_NONE ) ;
lp - > percent = arg_percent_value ( cmd , extents_ARG , PERCENT_NONE ) ;
}
2001-11-13 17:17:50 +03:00
2010-10-15 20:28:14 +04:00
/* Size returned in kilobyte units; held in sectors */
if ( arg_count ( cmd , size_ARG ) ) {
lp - > size = arg_uint64_value ( cmd , size_ARG , 0 ) ;
lp - > sign = arg_sign_value ( cmd , size_ARG , SIGN_NONE ) ;
lp - > percent = PERCENT_NONE ;
}
2013-06-11 15:45:49 +04:00
if ( arg_count ( cmd , poolmetadatasize_ARG ) ) {
lp - > poolmetadatasize = arg_uint64_value ( cmd , poolmetadatasize_ARG , 0 ) ;
lp - > poolmetadatasign = arg_sign_value ( cmd , poolmetadatasize_ARG , SIGN_NONE ) ;
if ( lp - > poolmetadatasign = = SIGN_MINUS ) {
log_error ( " Can't reduce pool metadata size. " ) ;
return 0 ;
}
}
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
if ( lp - > resize = = LV_EXTEND & & lp - > sign = = SIGN_MINUS ) {
2001-11-13 17:17:50 +03:00
log_error ( " Negative argument not permitted - use lvreduce " ) ;
2004-05-11 22:47:40 +04:00
return 0 ;
2001-11-13 17:17:50 +03:00
}
2013-06-11 15:45:49 +04:00
if ( lp - > resize = = LV_REDUCE & &
( ( lp - > sign = = SIGN_PLUS ) | | ( lp - > poolmetadatasign = = SIGN_PLUS ) ) ) {
2001-11-13 17:17:50 +03:00
log_error ( " Positive sign not permitted - use lvextend " ) ;
2004-05-11 22:47:40 +04:00
return 0 ;
2001-11-13 17:17:50 +03:00
}
2009-11-03 18:50:42 +03:00
lp - > resizefs = arg_is_set ( cmd , resizefs_ARG ) ;
lp - > nofsck = arg_is_set ( cmd , nofsck_ARG ) ;
2004-06-15 21:23:49 +04:00
2001-11-13 17:17:50 +03:00
if ( ! argc ) {
log_error ( " Please provide the logical volume name " ) ;
2004-05-11 22:47:40 +04:00
return 0 ;
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
lp - > lv_name = argv [ 0 ] ;
2001-11-13 17:17:50 +03:00
argv + + ;
argc - - ;
2008-04-10 23:59:43 +04:00
if ( ! ( lp - > lv_name = skip_dev_dir ( cmd , lp - > lv_name , & dev_dir_found ) ) | |
! ( lp - > vg_name = extract_vgname ( cmd , lp - > lv_name ) ) ) {
2001-11-13 17:17:50 +03:00
log_error ( " Please provide a volume group name " ) ;
2004-05-11 22:47:40 +04:00
return 0 ;
2001-11-13 17:17:50 +03:00
}
2008-02-06 15:45:32 +03:00
2007-11-02 23:40:05 +03:00
if ( ! validate_name ( lp - > vg_name ) ) {
log_error ( " Volume group name %s has invalid characters " ,
lp - > vg_name ) ;
2007-11-12 23:02:55 +03:00
return 0 ;
2007-11-02 23:40:05 +03:00
}
2001-11-13 17:17:50 +03:00
2004-05-11 22:47:40 +04:00
if ( ( st = strrchr ( lp - > lv_name , ' / ' ) ) )
lp - > lv_name = st + 1 ;
2001-11-13 17:17:50 +03:00
2004-05-11 22:47:40 +04:00
lp - > argc = argc ;
lp - > argv = argv ;
return 1 ;
}
2002-02-11 18:42:34 +03:00
2010-10-15 20:28:14 +04:00
static int _adjust_policy_params ( struct cmd_context * cmd ,
struct logical_volume * lv , struct lvresize_params * lp )
{
2010-11-30 14:53:31 +03:00
percent_t percent ;
2010-10-15 20:28:14 +04:00
int policy_threshold , policy_amount ;
2011-12-21 17:10:52 +04:00
if ( lv_is_thin_pool ( lv ) ) {
policy_threshold =
2013-06-25 14:30:34 +04:00
find_config_tree_int ( cmd , activation_thin_pool_autoextend_threshold_CFG , NULL ) * PERCENT_1 ;
2011-12-21 17:10:52 +04:00
policy_amount =
2013-06-25 14:30:34 +04:00
find_config_tree_int ( cmd , activation_thin_pool_autoextend_percent_CFG , NULL ) ;
2012-10-14 21:43:25 +04:00
if ( ! policy_amount & & policy_threshold < PERCENT_100 )
return 0 ;
2011-12-21 17:10:52 +04:00
} else {
policy_threshold =
2013-06-25 14:30:34 +04:00
find_config_tree_int ( cmd , activation_snapshot_autoextend_threshold_CFG , NULL ) * PERCENT_1 ;
2011-12-21 17:10:52 +04:00
policy_amount =
2013-06-25 14:30:34 +04:00
find_config_tree_int ( cmd , activation_snapshot_autoextend_percent_CFG , NULL ) ;
2011-12-21 17:10:52 +04:00
}
2010-10-15 20:28:14 +04:00
2010-11-30 14:53:31 +03:00
if ( policy_threshold > = PERCENT_100 )
2010-10-15 20:28:14 +04:00
return 1 ; /* nothing to do */
2011-12-21 17:10:52 +04:00
if ( lv_is_thin_pool ( lv ) ) {
2012-01-19 19:25:37 +04:00
if ( ! lv_thin_pool_percent ( lv , 1 , & percent ) )
return_0 ;
2013-06-11 15:45:49 +04:00
if ( ( PERCENT_0 < percent & & percent < = PERCENT_100 ) & &
( percent > policy_threshold ) ) {
if ( ! pool_can_resize_metadata ( lv ) ) {
log_error_once ( " Online metadata resize for %s/%s is not supported. " ,
lp - > vg_name , lp - > lv_name ) ;
return 0 ;
}
lp - > poolmetadatasize = ( first_seg ( lv ) - > metadata_lv - > size *
policy_amount + 99 ) / 100 ;
lp - > poolmetadatasign = SIGN_PLUS ;
2012-01-19 19:25:37 +04:00
}
if ( ! lv_thin_pool_percent ( lv , 0 , & percent ) )
2011-12-21 17:10:52 +04:00
return_0 ;
if ( ! ( PERCENT_0 < percent & & percent < = PERCENT_100 ) | |
percent < = policy_threshold )
2013-06-11 15:45:49 +04:00
return 1 ;
2011-12-21 17:10:52 +04:00
} else {
if ( ! lv_snapshot_percent ( lv , & percent ) )
return_0 ;
2013-05-29 23:17:15 +04:00
if ( ! ( PERCENT_0 < percent & & percent < = PERCENT_100 ) | | percent < = policy_threshold )
2011-12-21 17:10:52 +04:00
return 1 ; /* nothing to do */
}
2010-10-15 20:28:14 +04:00
lp - > extents = policy_amount ;
2013-06-11 15:45:49 +04:00
lp - > sizeargs = ( lp - > extents ) ? 1 : 0 ;
2011-12-21 17:10:52 +04:00
2010-10-15 20:28:14 +04:00
return 1 ;
}
2011-06-09 23:38:56 +04:00
static uint32_t lvseg_get_stripes ( struct lv_segment * seg , uint32_t * stripesize )
{
uint32_t s ;
struct lv_segment * seg_mirr ;
/* If segment mirrored, check if images are striped */
if ( seg_is_mirrored ( seg ) )
for ( s = 0 ; s < seg - > area_count ; s + + ) {
if ( seg_type ( seg , s ) ! = AREA_LV )
continue ;
seg_mirr = first_seg ( seg_lv ( seg , s ) ) ;
if ( seg_is_striped ( seg_mirr ) ) {
seg = seg_mirr ;
break ;
}
}
if ( seg_is_striped ( seg ) ) {
* stripesize = seg - > stripe_size ;
return seg - > area_count ;
}
* stripesize = 0 ;
return 0 ;
}
2013-06-11 15:45:49 +04:00
static int _lvresize_poolmetadata ( struct cmd_context * cmd , struct volume_group * vg ,
struct lvresize_params * lp ,
const struct logical_volume * pool_lv ,
struct dm_list * pvh ,
alloc_policy_t alloc )
{
struct logical_volume * lv ;
struct lv_segment * mseg ;
uint32_t extents ;
uint32_t seg_mirrors ;
if ( ! pool_can_resize_metadata ( pool_lv ) ) {
log_error ( " Support for online metadata resize not detected. " ) ;
return 0 ;
}
if ( lp - > poolmetadatasize % vg - > extent_size ) {
lp - > poolmetadatasize + = vg - > extent_size -
( lp - > poolmetadatasize % vg - > extent_size ) ;
log_print_unless_silent ( " Rounding pool metadata size to boundary between physical extents: %s " ,
display_size ( cmd , lp - > poolmetadatasize ) ) ;
}
if ( ! ( extents = extents_from_size ( vg - > cmd , lp - > poolmetadatasize ,
vg - > extent_size ) ) )
return_0 ;
lv = first_seg ( pool_lv ) - > metadata_lv ;
if ( lp - > poolmetadatasign = = SIGN_PLUS ) {
if ( extents > = ( MAX_EXTENT_COUNT - lv - > le_count ) ) {
log_error ( " Unable to extend %s by %u extents, exceeds limit (%u). " ,
lv - > name , lv - > le_count , MAX_EXTENT_COUNT ) ;
return 0 ;
}
extents + = lv - > le_count ;
}
if ( extents * vg - > extent_size > DM_THIN_MAX_METADATA_SIZE ) {
log_print_unless_silent ( " Rounding size to maximum supported size 16GiB "
" for metadata volume %s. " , lv - > name ) ;
extents = ( DM_THIN_MAX_METADATA_SIZE + vg - > extent_size - 1 ) /
vg - > extent_size ;
}
if ( extents = = lv - > le_count ) {
log_print_unless_silent ( " Metadata volume %s has already %s. " ,
lv - > name , display_size ( cmd , lv - > size ) ) ;
return 2 ;
}
2013-06-11 21:46:42 +04:00
if ( ! lp - > sizeargs & & ! archive ( vg ) )
return_0 ;
2013-06-11 15:45:49 +04:00
log_print_unless_silent ( " Extending logical volume %s to %s. " ,
2013-06-11 21:46:42 +04:00
lv - > name ,
2013-06-11 15:45:49 +04:00
display_size ( cmd , ( uint64_t ) extents * vg - > extent_size ) ) ;
mseg = last_seg ( lv ) ;
seg_mirrors = lv_mirror_count ( lv ) ;
if ( ! lv_extend ( lv ,
mseg - > segtype ,
mseg - > area_count / seg_mirrors ,
mseg - > stripe_size ,
seg_mirrors ,
mseg - > region_size ,
extents - lv - > le_count , NULL ,
pvh , alloc ) )
return_0 ;
return 1 ;
}
2007-11-15 05:20:03 +03:00
static int _lvresize ( struct cmd_context * cmd , struct volume_group * vg ,
struct lvresize_params * lp )
2004-05-11 22:47:40 +04:00
{
struct logical_volume * lv ;
2012-04-11 16:30:48 +04:00
uint32_t stripesize_extents ;
uint32_t seg_stripes = 0 , seg_stripesize = 0 , seg_size ;
2005-06-03 23:48:19 +04:00
uint32_t seg_mirrors = 0 ;
2012-04-11 16:30:48 +04:00
uint32_t extents_used ;
2004-05-11 22:47:40 +04:00
uint32_t size_rest ;
2012-04-11 16:30:48 +04:00
uint32_t pv_extent_count ;
2004-05-19 02:12:53 +04:00
alloc_policy_t alloc ;
2013-06-11 16:55:32 +04:00
struct logical_volume * lock_lv = NULL ;
2004-05-11 22:47:40 +04:00
struct lv_list * lvl ;
2010-04-09 05:00:10 +04:00
struct lv_segment * seg , * uninitialized_var ( mirr_seg ) ;
2004-05-11 22:47:40 +04:00
uint32_t seg_extents ;
uint32_t sz , str ;
2010-11-01 17:17:35 +03:00
int status ;
2008-11-04 01:14:30 +03:00
struct dm_list * pvh = NULL ;
2010-10-15 20:28:14 +04:00
int use_policy = arg_count ( cmd , use_policies_ARG ) ;
2004-05-11 22:47:40 +04:00
2001-11-13 17:17:50 +03:00
/* does LV exist? */
2004-05-11 22:47:40 +04:00
if ( ! ( lvl = find_lv_in_vg ( vg , lp - > lv_name ) ) ) {
2001-11-13 17:17:50 +03:00
log_error ( " Logical volume %s not found in volume group %s " ,
2004-05-11 22:47:40 +04:00
lp - > lv_name , lp - > vg_name ) ;
2004-05-24 19:58:50 +04:00
return ECMD_FAILED ;
2001-11-13 17:17:50 +03:00
}
2013-06-05 15:28:26 +04:00
lv = lvl - > lv ;
if ( lv_is_external_origin ( lv ) ) {
2013-02-05 17:03:43 +04:00
/*
* Since external - origin can be activated read - only ,
* there is no way to use extended areas .
*/
2013-06-05 15:28:26 +04:00
log_error ( " Cannot resize external origin \" %s \" . " , lv - > name ) ;
2013-02-05 17:03:43 +04:00
return EINVALID_CMD_LINE ;
}
2013-06-05 15:28:26 +04:00
if ( lv - > status & ( RAID_IMAGE | RAID_META ) ) {
2011-12-01 04:13:16 +04:00
log_error ( " Cannot resize a RAID %s directly " ,
2013-06-05 15:28:26 +04:00
( lv - > status & RAID_IMAGE ) ? " image " :
2011-12-01 04:13:16 +04:00
" metadata area " ) ;
return ECMD_FAILED ;
}
2013-06-05 15:28:26 +04:00
if ( lv_is_raid_with_tracking ( lv ) ) {
2011-12-01 04:13:16 +04:00
log_error ( " Cannot resize %s while it is tracking a split image " ,
2013-06-05 15:28:26 +04:00
lv - > name ) ;
2011-12-01 04:13:16 +04:00
return ECMD_FAILED ;
}
2002-04-24 22:20:51 +04:00
if ( arg_count ( cmd , stripes_ARG ) ) {
if ( vg - > fid - > fmt - > features & FMT_SEGMENTS )
2004-05-11 22:47:40 +04:00
lp - > stripes = arg_uint_value ( cmd , stripes_ARG , 1 ) ;
2002-04-24 22:20:51 +04:00
else
2007-06-28 21:33:44 +04:00
log_warn ( " Varied striping not supported. Ignoring. " ) ;
2002-04-24 22:20:51 +04:00
}
2005-06-03 23:48:19 +04:00
if ( arg_count ( cmd , mirrors_ARG ) ) {
if ( vg - > fid - > fmt - > features & FMT_SEGMENTS )
lp - > mirrors = arg_uint_value ( cmd , mirrors_ARG , 1 ) + 1 ;
else
2007-06-28 21:33:44 +04:00
log_warn ( " Mirrors not supported. Ignoring. " ) ;
2012-02-28 18:24:57 +04:00
if ( arg_sign_value ( cmd , mirrors_ARG , SIGN_NONE ) = = SIGN_MINUS ) {
2005-11-29 00:00:37 +03:00
log_error ( " Mirrors argument may not be negative " ) ;
2007-09-07 01:08:16 +04:00
return EINVALID_CMD_LINE ;
2005-11-29 00:00:37 +03:00
}
2005-06-03 23:48:19 +04:00
}
2009-02-28 02:40:11 +03:00
if ( arg_count ( cmd , stripesize_ARG ) & &
! _validate_stripesize ( cmd , vg , lp ) )
return EINVALID_CMD_LINE ;
2002-04-24 22:20:51 +04:00
2010-10-15 20:28:14 +04:00
if ( use_policy ) {
2011-12-21 17:10:52 +04:00
if ( ! lv_is_cow ( lv ) & &
! lv_is_thin_pool ( lv ) ) {
log_error ( " Policy-based resize is supported only for snapshot and thin pool volumes. " ) ;
2010-10-15 20:28:14 +04:00
return ECMD_FAILED ;
}
2012-01-09 16:31:52 +04:00
if ( ! _adjust_policy_params ( cmd , lv , lp ) )
2013-07-01 13:27:22 +04:00
return_ECMD_FAILED ;
2010-10-15 20:28:14 +04:00
}
2013-06-11 15:11:54 +04:00
if ( ! lv_is_visible ( lv ) & &
! lv_is_thin_pool_metadata ( lv ) ) {
2010-03-20 06:44:04 +03:00
log_error ( " Can't resize internal logical volume %s " , lv - > name ) ;
return ECMD_FAILED ;
}
2003-05-06 16:10:18 +04:00
if ( lv - > status & LOCKED ) {
log_error ( " Can't resize locked LV %s " , lv - > name ) ;
2004-05-24 19:58:50 +04:00
return ECMD_FAILED ;
2003-05-06 16:10:18 +04:00
}
2008-09-18 22:51:58 +04:00
if ( lv - > status & CONVERTING ) {
log_error ( " Can't resize %s while lvconvert in progress " , lv - > name ) ;
return ECMD_FAILED ;
}
2012-02-28 18:24:57 +04:00
alloc = ( alloc_policy_t ) arg_uint_value ( cmd , alloc_ARG , lv - > alloc ) ;
2004-05-24 19:58:50 +04:00
2012-04-12 19:11:21 +04:00
/*
* First adjust to an exact multiple of extent size .
* When extending by a relative amount we round that amount up .
* When reducing by a relative amount we remove at most that amount .
* When changing to an absolute size , we round that size up .
*/
2004-05-11 22:47:40 +04:00
if ( lp - > size ) {
if ( lp - > size % vg - > extent_size ) {
if ( lp - > sign = = SIGN_MINUS )
lp - > size - = lp - > size % vg - > extent_size ;
2001-11-13 17:17:50 +03:00
else
2004-05-11 22:47:40 +04:00
lp - > size + = vg - > extent_size -
( lp - > size % vg - > extent_size ) ;
2001-11-13 17:17:50 +03:00
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Rounding size to boundary between physical extents: %s " ,
display_size ( cmd , lp - > size ) ) ;
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
lp - > extents = lp - > size / vg - > extent_size ;
2001-11-13 17:17:50 +03:00
}
2007-09-21 01:39:08 +04:00
if ( ! ( pvh = lp - > argc ? create_pv_list ( cmd - > mem , vg , lp - > argc ,
2013-07-01 13:27:22 +04:00
lp - > argv , 1 ) : & vg - > pvs ) )
return_ECMD_FAILED ;
2007-09-21 01:39:08 +04:00
2013-06-11 21:46:42 +04:00
if ( lp - > sizeargs ) { /* TODO: reindent or move to function */
2013-06-11 15:45:49 +04:00
2006-09-26 13:35:43 +04:00
switch ( lp - > percent ) {
case PERCENT_VG :
2012-01-05 19:38:18 +04:00
lp - > extents = percent_of_extents ( lp - > extents , vg - > extent_count ,
( lp - > sign ! = SIGN_MINUS ) ) ;
2006-09-26 13:35:43 +04:00
break ;
case PERCENT_FREE :
2012-01-05 19:38:18 +04:00
lp - > extents = percent_of_extents ( lp - > extents , vg - > free_count ,
( lp - > sign ! = SIGN_MINUS ) ) ;
2006-09-26 13:35:43 +04:00
break ;
case PERCENT_LV :
2012-01-05 19:38:18 +04:00
lp - > extents = percent_of_extents ( lp - > extents , lv - > le_count ,
( lp - > sign ! = SIGN_MINUS ) ) ;
2006-09-26 13:35:43 +04:00
break ;
2007-09-21 01:39:08 +04:00
case PERCENT_PVS :
2009-11-04 17:47:27 +03:00
if ( lp - > argc ) {
pv_extent_count = pv_list_extents_free ( pvh ) ;
2012-01-05 19:38:18 +04:00
lp - > extents = percent_of_extents ( lp - > extents , pv_extent_count ,
( lp - > sign ! = SIGN_MINUS ) ) ;
2009-11-04 17:47:27 +03:00
} else
2012-01-05 19:38:18 +04:00
lp - > extents = percent_of_extents ( lp - > extents , vg - > extent_count ,
( lp - > sign ! = SIGN_MINUS ) ) ;
2007-09-21 01:39:08 +04:00
break ;
2010-02-03 06:58:08 +03:00
case PERCENT_ORIGIN :
if ( ! lv_is_cow ( lv ) ) {
log_error ( " Specified LV does not have an origin LV. " ) ;
return EINVALID_CMD_LINE ;
}
2012-01-05 19:38:18 +04:00
lp - > extents = percent_of_extents ( lp - > extents , origin_from_cow ( lv ) - > le_count ,
( lp - > sign ! = SIGN_MINUS ) ) ;
2010-02-03 06:58:08 +03:00
break ;
2006-09-26 13:35:43 +04:00
case PERCENT_NONE :
break ;
}
2011-11-05 02:49:53 +04:00
if ( lp - > sign = = SIGN_PLUS ) {
if ( lp - > extents > = ( MAX_EXTENT_COUNT - lv - > le_count ) ) {
log_error ( " Unable to extend %s by %u extents, exceeds limit (%u). " ,
lp - > lv_name , lv - > le_count , MAX_EXTENT_COUNT ) ;
return EINVALID_CMD_LINE ;
}
2004-05-11 22:47:40 +04:00
lp - > extents + = lv - > le_count ;
2013-05-29 23:23:02 +04:00
if ( lv_is_cow ( lv ) ) {
extents_used = cow_max_extents ( origin_from_cow ( lv ) , find_cow ( lv ) - > chunk_size ) ;
if ( extents_used < lp - > extents ) {
log_print_unless_silent ( " Reached maximum COW size %s. " ,
display_size ( vg - > cmd , ( uint64_t ) vg - > extent_size * extents_used ) ) ;
lp - > extents = extents_used ;
if ( lp - > extents = = lv - > le_count )
return ECMD_PROCESSED ;
}
}
2013-06-11 15:09:11 +04:00
} else if ( lp - > sign = = SIGN_MINUS ) {
2004-05-11 22:47:40 +04:00
if ( lp - > extents > = lv - > le_count ) {
2001-11-13 17:17:50 +03:00
log_error ( " Unable to reduce %s below 1 extent " ,
2004-05-11 22:47:40 +04:00
lp - > lv_name ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
lp - > extents = lv - > le_count - lp - > extents ;
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
if ( ! lp - > extents ) {
2001-11-13 17:17:50 +03:00
log_error ( " New size of 0 not permitted " ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
if ( lp - > extents = = lv - > le_count ) {
2013-06-11 15:45:49 +04:00
/* A bit of hack - but still may resize metadata */
if ( lp - > poolmetadatasize ) {
lp - > sizeargs = 0 ;
goto metadata_resize ;
}
2010-10-15 20:28:14 +04:00
if ( use_policy )
return ECMD_PROCESSED ; /* Nothing to do. */
2009-02-24 18:48:00 +03:00
if ( ! lp - > resizefs ) {
log_error ( " New size (%d extents) matches existing size "
" (%d extents) " , lp - > extents , lv - > le_count ) ;
return EINVALID_CMD_LINE ;
}
lp - > resize = LV_EXTEND ; /* lets pretend zero size extension */
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
seg_size = lp - > extents - lv - > le_count ;
2002-04-24 22:20:51 +04:00
2004-05-11 20:01:58 +04:00
/* Use segment type of last segment */
2013-05-22 17:04:51 +04:00
lp - > segtype = last_seg ( lv ) - > segtype ;
2004-05-11 20:01:58 +04:00
/* FIXME Support LVs with mixed segment types */
2010-04-29 05:38:12 +04:00
if ( lp - > segtype ! = get_segtype_from_string ( cmd , arg_str_value ( cmd , type_ARG ,
lp - > segtype - > name ) ) ) {
2004-05-11 22:47:40 +04:00
log_error ( " VolumeType does not match (%s) " , lp - > segtype - > name ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2004-05-11 20:01:58 +04:00
}
2010-04-09 05:00:10 +04:00
/* If extending, find mirrors of last segment */
if ( ( lp - > extents > lv - > le_count ) ) {
Allow 'nosync' extension of mirrors.
This patch allows a mirror to be extended without an initial resync of the
extended portion. It compliments the existing '--nosync' option to lvcreate.
This action can be done implicitly if the mirror was created with the '--nosync'
option, or explicitly if the '--nosync' option is used when extending the device.
Here are the operational criteria:
1) A mirror created with '--nosync' should extend with 'nosync' implicitly
[EXAMPLE]# lvs vg; lvextend -L +5G vg/lv ; lvs vg
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg Mwi-a-m- 5.00g lv_mlog 100.00
Extending 2 mirror images.
Extending logical volume lv to 10.00 GiB
Logical volume lv successfully resized
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg Mwi-a-m- 10.00g lv_mlog 100.00
2) The 'M' attribute ('M' signifies a mirror created with '--nosync', while 'm'
signifies a mirror created w/o '--nosync') must be preserved when extending a
mirror created with '--nosync'. See #1 for example of 'M' attribute.
3) A mirror created without '--nosync' should extend with 'nosync' only when
'--nosync' is explicitly used when extending.
[EXAMPLE]# lvs vg; lvextend -L +5G vg/lv; lvs vg
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg mwi-a-m- 20.00m lv_mlog 100.00
Extending 2 mirror images.
Extending logical volume lv to 5.02 GiB
Logical volume lv successfully resized
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg mwi-a-m- 5.02g lv_mlog 0.39
vs.
[EXAMPLE]# lvs vg; lvextend -L +5G vg/lv --nosync; lvs vg
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg mwi-a-m- 20.00m lv_mlog 100.00
Extending 2 mirror images.
Extending logical volume lv to 5.02 GiB
Logical volume lv successfully resized
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg Mwi-a-m- 5.02g lv_mlog 100.00
4) The 'm' attribute must change to 'M' when extending a mirror created without
'--nosync' is extended with the '--nosync' option. (See #3 examples above.)
5) An inactive mirror's sync percent cannot be determined definitively, so it
must not be allowed to skip resync. Instead, the extend should ask the user if
they want to extend while performing a resync.
[EXAMPLE]# lvchange -an vg/lv
[EXAMPLE]# lvextend -L +5G vg/lv
Extending 2 mirror images.
Extending logical volume lv to 10.00 GiB
vg/lv is not active. Unable to get sync percent.
Do full resync of extended portion of vg/lv? [y/n]: y
Logical volume lv successfully resized
6) A mirror that is performing recovery (as opposed to an initial sync) - like
after a failure - is not allowed to extend with either an implicit or
explicit nosync option. [You can simulate this with a 'corelog' mirror because
when it is reactivated, it must be recovered every time.]
[EXAMPLE]# lvcreate -m1 -L 5G -n lv vg --nosync --corelog
WARNING: New mirror won't be synchronised. Don't read what you didn't write!
Logical volume "lv" created
[EXAMPLE]# lvs vg
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg Mwi-a-m- 5.00g 100.00
[EXAMPLE]# lvchange -an vg/lv; lvchange -ay vg/lv; lvs vg
LV VG Attr LSize Pool Origin Snap% Move Log Copy% Convert
lv vg Mwi-a-m- 5.00g 0.08
[EXAMPLE]# lvextend -L +5G vg/lv
Extending 2 mirror images.
Extending logical volume lv to 10.00 GiB
vg/lv cannot be extended while it is recovering.
7) If 'no' is selected in #5 or if the condition in #6 is hit, it should not
result in the mirror being resized or the 'm/M' attribute being changed.
NOTE: A mirror created with '--nosync' behaves differently than one created
without it when performing an extension. The former cannot be extended when
the mirror is recovering (unless in-active), while the latter can. This is
a reasonable thing to do since recovery of a mirror doesn't take long (at
least in the case of an on-disk log) and it would cause far more time in
degraded mode if the extension w/o '--nosync' was allowed. It might be
reasonable to add the ability to force the operation in the future. This
should /not/ force a nosync extension, but rather force a sync'ed extension.
IOW, the user would be saying, "Yes, yes... I know recovery won't take long
and that I'll be adding significantly to the time spent in degraded mode, but
I need the extra space right now!".
2011-10-06 19:32:26 +04:00
/*
* Has the user specified that they would like the additional
* extents of a mirror not to have an initial sync ?
*/
if ( seg_is_mirrored ( first_seg ( lv ) ) & & arg_count ( cmd , nosync_ARG ) )
lv - > status | = LV_NOTSYNCED ;
2010-04-09 05:00:10 +04:00
dm_list_iterate_back_items ( mirr_seg , & lv - > segments ) {
if ( seg_is_mirrored ( mirr_seg ) )
seg_mirrors = lv_mirror_count ( mirr_seg - > lv ) ;
else
seg_mirrors = 0 ;
break ;
}
2012-08-25 00:34:19 +04:00
2010-04-09 05:00:10 +04:00
if ( ! arg_count ( cmd , mirrors_ARG ) & & seg_mirrors ) {
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Extending % " PRIu32 " mirror images. " ,
seg_mirrors ) ;
2010-04-09 05:00:10 +04:00
lp - > mirrors = seg_mirrors ;
}
if ( ( arg_count ( cmd , mirrors_ARG ) | | seg_mirrors ) & &
( lp - > mirrors ! = seg_mirrors ) ) {
log_error ( " Cannot vary number of mirrors in LV yet. " ) ;
return EINVALID_CMD_LINE ;
}
2012-08-25 00:34:19 +04:00
if ( seg_mirrors & & ! strcmp ( mirr_seg - > segtype - > name , " raid10 " ) ) {
lp - > stripes = mirr_seg - > area_count / seg_mirrors ;
lp - > stripe_size = mirr_seg - > stripe_size ;
}
2010-04-09 05:00:10 +04:00
}
2001-11-27 16:42:37 +03:00
/* If extending, find stripes, stripesize & size of last segment */
2004-05-11 22:47:40 +04:00
if ( ( lp - > extents > lv - > le_count ) & &
2012-08-25 00:34:19 +04:00
! ( lp - > stripes = = 1 | | ( lp - > stripes > 1 & & lp - > stripe_size ) ) & &
strcmp ( mirr_seg - > segtype - > name , " raid10 " ) ) {
2010-04-09 05:00:10 +04:00
/* FIXME Don't assume mirror seg will always be AREA_LV */
2012-04-11 16:40:03 +04:00
/* FIXME We will need to support resize for metadata LV as well,
* and data LV could be any type ( i . e . mirror ) ) */
dm_list_iterate_items ( seg , seg_mirrors ? & seg_lv ( mirr_seg , 0 ) - > segments :
lv_is_thin_pool ( lv ) ? & seg_lv ( first_seg ( lv ) , 0 ) - > segments : & lv - > segments ) {
2012-08-25 00:34:19 +04:00
/* Allow through "striped" and RAID 4/5/6/10 */
2012-06-26 18:44:54 +04:00
if ( ! seg_is_striped ( seg ) & &
2012-08-25 00:34:19 +04:00
( ! seg_is_raid ( seg ) | | seg_is_mirrored ( seg ) ) & &
strcmp ( seg - > segtype - > name , " raid10 " ) )
2004-05-11 20:01:58 +04:00
continue ;
2003-04-25 02:23:24 +04:00
2001-11-28 16:45:50 +03:00
sz = seg - > stripe_size ;
2012-06-26 18:44:54 +04:00
str = seg - > area_count - lp - > segtype - > parity_devs ;
2001-11-27 16:42:37 +03:00
2009-02-28 02:40:11 +03:00
if ( ( seg_stripesize & & seg_stripesize ! = sz & &
2010-04-09 05:00:10 +04:00
sz & & ! lp - > stripe_size ) | |
2004-05-11 22:47:40 +04:00
( seg_stripes & & seg_stripes ! = str & & ! lp - > stripes ) ) {
2001-11-27 16:42:37 +03:00
log_error ( " Please specify number of "
" stripes (-i) and stripesize (-I) " ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2001-11-27 16:42:37 +03:00
}
seg_stripesize = sz ;
seg_stripes = str ;
}
2004-05-11 22:47:40 +04:00
if ( ! lp - > stripes )
lp - > stripes = seg_stripes ;
2012-06-26 18:44:54 +04:00
else if ( seg_is_raid ( first_seg ( lv ) ) & &
( lp - > stripes ! = seg_stripes ) ) {
2012-09-05 20:35:54 +04:00
log_error ( " Unable to extend \" %s \" segment type with different number of stripes. " , first_seg ( lv ) - > segtype - > ops - > name ( first_seg ( lv ) ) ) ;
2012-06-26 18:44:54 +04:00
return ECMD_FAILED ;
}
2001-11-27 16:42:37 +03:00
2004-05-11 22:47:40 +04:00
if ( ! lp - > stripe_size & & lp - > stripes > 1 ) {
2002-04-24 22:20:51 +04:00
if ( seg_stripesize ) {
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Using stripesize of last segment %s " ,
display_size ( cmd , ( uint64_t ) seg_stripesize ) ) ;
2004-05-11 22:47:40 +04:00
lp - > stripe_size = seg_stripesize ;
2002-04-24 22:20:51 +04:00
} else {
2004-05-24 19:58:50 +04:00
lp - > stripe_size =
2013-06-25 14:30:34 +04:00
find_config_tree_int ( cmd , metadata_stripesize_CFG , NULL ) * 2 ;
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Using default stripesize %s " ,
display_size ( cmd , ( uint64_t ) lp - > stripe_size ) ) ;
2002-04-24 22:20:51 +04:00
}
}
2001-11-27 16:42:37 +03:00
}
/* If reducing, find stripes, stripesize & size of last segment */
2004-05-11 22:47:40 +04:00
if ( lp - > extents < lv - > le_count ) {
2002-04-24 22:20:51 +04:00
extents_used = 0 ;
2001-11-27 16:42:37 +03:00
2005-06-03 23:48:19 +04:00
if ( lp - > stripes | | lp - > stripe_size | | lp - > mirrors )
log_error ( " Ignoring stripes, stripesize and mirrors "
" arguments when reducing " ) ;
2001-11-27 16:42:37 +03:00
2008-11-04 01:14:30 +03:00
dm_list_iterate_items ( seg , & lv - > segments ) {
2001-11-28 16:45:50 +03:00
seg_extents = seg - > len ;
2011-06-09 23:38:56 +04:00
/* Check for underlying stripe sizes */
seg_stripes = lvseg_get_stripes ( seg , & seg_stripesize ) ;
2001-11-27 16:42:37 +03:00
2005-06-03 23:48:19 +04:00
if ( seg_is_mirrored ( seg ) )
2007-12-20 21:55:46 +03:00
seg_mirrors = lv_mirror_count ( seg - > lv ) ;
2005-06-03 23:48:19 +04:00
else
seg_mirrors = 0 ;
2004-05-11 22:47:40 +04:00
if ( lp - > extents < = extents_used + seg_extents )
2001-11-27 16:42:37 +03:00
break ;
extents_used + = seg_extents ;
}
2004-05-11 22:47:40 +04:00
seg_size = lp - > extents - extents_used ;
lp - > stripe_size = seg_stripesize ;
lp - > stripes = seg_stripes ;
2005-06-03 23:48:19 +04:00
lp - > mirrors = seg_mirrors ;
2001-11-27 16:42:37 +03:00
}
2004-05-11 22:47:40 +04:00
if ( lp - > stripes > 1 & & ! lp - > stripe_size ) {
2002-04-24 22:20:51 +04:00
log_error ( " Stripesize for striped segment should not be 0! " ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2002-05-31 23:29:43 +04:00
}
2002-11-18 17:04:08 +03:00
2011-06-09 23:34:49 +04:00
if ( lp - > stripes > 1 ) {
2012-04-11 16:30:48 +04:00
if ( lp - > stripe_size < STRIPE_SIZE_MIN ) {
log_error ( " Invalid stripe size %s " ,
display_size ( cmd , ( uint64_t ) lp - > stripe_size ) ) ;
return EINVALID_CMD_LINE ;
}
2004-05-11 22:47:40 +04:00
if ( ! ( stripesize_extents = lp - > stripe_size / vg - > extent_size ) )
2002-05-31 23:29:43 +04:00
stripesize_extents = 1 ;
2011-06-09 23:34:49 +04:00
size_rest = seg_size % ( lp - > stripes * stripesize_extents ) ;
2011-09-15 22:51:11 +04:00
/* Round toward the original size. */
2012-04-11 16:36:37 +04:00
if ( size_rest & &
( ( lp - > extents < lv - > le_count ) | |
! lp - > percent | |
( vg - > free_count > = ( lp - > extents - lv - > le_count - size_rest +
( lp - > stripes * stripesize_extents ) ) ) ) ) {
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Rounding size (%d extents) up to stripe "
" boundary size for segment (%d extents) " ,
lp - > extents , lp - > extents - size_rest +
( lp - > stripes * stripesize_extents ) ) ;
2011-06-15 14:56:52 +04:00
lp - > extents = lp - > extents - size_rest +
( lp - > stripes * stripesize_extents ) ;
2011-06-09 23:34:49 +04:00
} else if ( size_rest ) {
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Rounding size (%d extents) down to stripe "
" boundary size for segment (%d extents) " ,
lp - > extents , lp - > extents - size_rest ) ;
2004-05-11 22:47:40 +04:00
lp - > extents = lp - > extents - size_rest ;
2002-05-31 23:29:43 +04:00
}
2001-11-27 20:02:24 +03:00
}
2001-11-27 16:42:37 +03:00
2004-05-11 22:47:40 +04:00
if ( lp - > extents < lv - > le_count ) {
if ( lp - > resize = = LV_EXTEND ) {
2001-11-13 17:17:50 +03:00
log_error ( " New size given (%d extents) not larger "
" than existing size (%d extents) " ,
2004-05-11 22:47:40 +04:00
lp - > extents , lv - > le_count ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2009-02-24 18:48:00 +03:00
}
lp - > resize = LV_REDUCE ;
} else if ( lp - > extents > lv - > le_count ) {
2004-05-11 22:47:40 +04:00
if ( lp - > resize = = LV_REDUCE ) {
2001-11-13 17:17:50 +03:00
log_error ( " New size given (%d extents) not less than "
2004-05-11 22:47:40 +04:00
" existing size (%d extents) " , lp - > extents ,
2001-11-13 17:17:50 +03:00
lv - > le_count ) ;
2004-05-24 19:58:50 +04:00
return EINVALID_CMD_LINE ;
2009-02-24 18:48:00 +03:00
}
lp - > resize = LV_EXTEND ;
2012-04-12 19:11:21 +04:00
} else if ( lp - > extents = = lv - > le_count ) {
if ( use_policy )
return ECMD_PROCESSED ; /* Nothing to do. */
if ( ! lp - > resizefs ) {
log_error ( " New size (%d extents) matches existing size "
" (%d extents) " , lp - > extents , lv - > le_count ) ;
return EINVALID_CMD_LINE ;
}
lp - > resize = LV_EXTEND ;
2001-11-13 17:17:50 +03:00
}
2005-04-07 16:17:46 +04:00
if ( lv_is_origin ( lv ) ) {
if ( lp - > resize = = LV_REDUCE ) {
log_error ( " Snapshot origin volumes cannot be reduced "
" in size yet. " ) ;
return ECMD_FAILED ;
}
2013-06-11 15:07:13 +04:00
if ( lv_is_active ( lv ) ) {
2005-04-07 16:17:46 +04:00
log_error ( " Snapshot origin volumes can be resized "
" only while inactive: try lvchange -an " ) ;
return ECMD_FAILED ;
}
}
2011-10-29 00:31:01 +04:00
if ( lv_is_thin_pool ( lv ) ) {
if ( lp - > resize = = LV_REDUCE ) {
log_error ( " Thin pool volumes cannot be reduced in size yet. " ) ;
return ECMD_FAILED ;
}
if ( lp - > resizefs ) {
log_warn ( " Thin pool volumes do not have filesystem. " ) ;
lp - > resizefs = 0 ;
}
2013-06-11 15:45:49 +04:00
} else if ( lp - > poolmetadatasize ) {
log_error ( " --poolmetadatasize can be used only with thin pools. " ) ;
return ECMD_FAILED ;
2011-10-29 00:31:01 +04:00
}
2009-02-28 02:40:11 +03:00
if ( ( lp - > resize = = LV_REDUCE ) & & lp - > argc )
log_warn ( " Ignoring PVs on command line when reducing " ) ;
2001-11-13 17:17:50 +03:00
2009-02-28 02:40:11 +03:00
/* Request confirmation before operations that are often mistakes. */
if ( ( lp - > resizefs | | ( lp - > resize = = LV_REDUCE ) ) & &
2013-07-01 13:27:22 +04:00
! _request_confirmation ( cmd , vg , lv , lp ) )
return_ECMD_FAILED ;
2001-11-13 17:17:50 +03:00
2004-06-15 21:23:49 +04:00
if ( lp - > resizefs ) {
2009-02-28 02:40:11 +03:00
if ( ! lp - > nofsck & &
2010-11-01 17:17:35 +03:00
! _fsadm_cmd ( cmd , vg , lp , FSADM_CMD_CHECK , & status ) ) {
if ( status ! = FSADM_CHECK_FAILS_FOR_MOUNTED ) {
2011-09-21 14:39:47 +04:00
log_error ( " Filesystem check failed. " ) ;
2010-11-01 17:17:35 +03:00
return ECMD_FAILED ;
}
2011-09-21 14:39:47 +04:00
/* some filesystems supports online resize */
2009-02-24 18:48:00 +03:00
}
2009-02-28 02:40:11 +03:00
if ( ( lp - > resize = = LV_REDUCE ) & &
2010-11-01 17:17:35 +03:00
! _fsadm_cmd ( cmd , vg , lp , FSADM_CMD_RESIZE , NULL ) ) {
2011-09-21 14:39:47 +04:00
log_error ( " Filesystem resize failed. " ) ;
2009-02-24 18:48:00 +03:00
return ECMD_FAILED ;
}
2004-06-15 21:23:49 +04:00
}
2002-01-09 16:17:14 +03:00
2013-07-01 13:27:22 +04:00
if ( ! archive ( vg ) )
return_ECMD_FAILED ;
2001-11-13 17:17:50 +03:00
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " %sing logical volume %s to %s " ,
( lp - > resize = = LV_REDUCE ) ? " Reduc " : " Extend " ,
2013-06-05 15:28:26 +04:00
lv - > name ,
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
display_size ( cmd , ( uint64_t ) lp - > extents * vg - > extent_size ) ) ;
2004-06-15 21:23:49 +04:00
if ( lp - > resize = = LV_REDUCE ) {
2013-07-01 13:27:22 +04:00
if ( ! lv_reduce ( lv , lv - > le_count - lp - > extents ) )
2004-05-24 19:58:50 +04:00
return ECMD_FAILED ;
2009-02-28 02:40:11 +03:00
} else if ( ( lp - > extents > lv - > le_count ) & & /* Ensure we extend */
2011-04-07 01:32:20 +04:00
! lv_extend ( lv , lp - > segtype ,
lp - > stripes , lp - > stripe_size ,
lp - > mirrors , first_seg ( lv ) - > region_size ,
2011-09-06 04:26:42 +04:00
lp - > extents - lv - > le_count , NULL ,
2013-07-01 13:27:22 +04:00
pvh , alloc ) )
return_ECMD_FAILED ;
2001-11-13 17:17:50 +03:00
2013-06-11 15:45:49 +04:00
/* If thin metadata, must suspend thin pool */
if ( lv_is_thin_pool_metadata ( lv ) ) {
if ( ! ( lock_lv = find_pool_lv ( lv ) ) )
return_0 ;
/* If snapshot, must suspend all associated devices */
} else if ( lv_is_cow ( lv ) )
lock_lv = origin_from_cow ( lv ) ;
else
lock_lv = lv ;
} /* lp->sizeargs */
if ( lp - > poolmetadatasize ) {
metadata_resize :
2013-07-01 13:27:22 +04:00
if ( ! ( status = _lvresize_poolmetadata ( cmd , vg , lp , lv , pvh , alloc ) ) )
return_ECMD_FAILED ;
else if ( ( status = = 2 ) & & ! lp - > sizeargs )
2013-06-11 15:45:49 +04:00
return ECMD_PROCESSED ;
lock_lv = lv ;
}
2013-06-11 21:46:42 +04:00
if ( ! lock_lv )
return ECMD_PROCESSED ; /* Nothing to do */
2001-11-13 17:17:50 +03:00
/* store vg on disk(s) */
2013-07-01 13:27:22 +04:00
if ( ! vg_write ( vg ) )
return_ECMD_FAILED ;
2001-11-13 17:17:50 +03:00
2005-08-15 16:00:04 +04:00
if ( ! suspend_lv ( cmd , lock_lv ) ) {
2013-06-05 15:28:26 +04:00
log_error ( " Failed to suspend %s " , lock_lv - > name ) ;
2003-07-05 02:34:56 +04:00
vg_revert ( vg ) ;
2009-04-21 18:31:57 +04:00
backup ( vg ) ;
2004-05-24 19:58:50 +04:00
return ECMD_FAILED ;
2003-07-05 02:34:56 +04:00
}
if ( ! vg_commit ( vg ) ) {
stack ;
2010-01-06 00:07:31 +03:00
if ( ! resume_lv ( cmd , lock_lv ) )
stack ;
2009-04-21 18:31:57 +04:00
backup ( vg ) ;
2004-05-24 19:58:50 +04:00
return ECMD_FAILED ;
2003-07-05 02:34:56 +04:00
}
2005-08-15 16:00:04 +04:00
if ( ! resume_lv ( cmd , lock_lv ) ) {
2013-06-05 15:28:26 +04:00
log_error ( " Problem reactivating %s " , lock_lv - > name ) ;
2009-04-21 18:31:57 +04:00
backup ( vg ) ;
2004-05-24 19:58:50 +04:00
return ECMD_FAILED ;
2002-02-21 00:30:27 +03:00
}
2001-11-13 17:17:50 +03:00
2013-05-29 23:23:18 +04:00
if ( lv_is_cow_covering_origin ( lv ) )
if ( ! monitor_dev_for_events ( cmd , lv , 0 , 0 ) )
stack ;
2009-04-21 18:31:57 +04:00
backup ( vg ) ;
2011-11-08 16:19:53 +04:00
/*
* Update lvm pool metadata ( drop messages ) if the pool has been
* resumed and do a pool active / deactivate in other case .
*
* Note : Active thin pool can be waiting for resize .
*
* FIXME : Activate only when thin volume is active
*/
if ( lv_is_thin_pool ( lv ) & &
2013-07-01 13:27:22 +04:00
! update_pool_lv ( lv , ! lv_is_active ( lv ) ) )
return_ECMD_FAILED ;
2011-11-08 16:19:53 +04:00
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
log_print_unless_silent ( " Logical volume %s successfully resized " , lp - > lv_name ) ;
2001-11-13 17:17:50 +03:00
2009-02-28 02:40:11 +03:00
if ( lp - > resizefs & & ( lp - > resize = = LV_EXTEND ) & &
2013-07-01 13:27:22 +04:00
! _fsadm_cmd ( cmd , vg , lp , FSADM_CMD_RESIZE , NULL ) )
return_ECMD_FAILED ;
2004-06-15 21:23:49 +04:00
2003-10-22 02:06:07 +04:00
return ECMD_PROCESSED ;
2001-11-13 17:17:50 +03:00
}
2004-05-11 22:47:40 +04:00
int lvresize ( struct cmd_context * cmd , int argc , char * * argv )
{
2012-03-30 19:17:25 +04:00
struct lvresize_params lp = { 0 } ;
2007-11-15 05:20:03 +03:00
struct volume_group * vg ;
2004-05-11 22:47:40 +04:00
int r ;
2006-04-19 19:33:07 +04:00
if ( ! _lvresize_params ( cmd , argc , argv , & lp ) )
2004-05-11 22:47:40 +04:00
return EINVALID_CMD_LINE ;
log_verbose ( " Finding volume group %s " , lp . vg_name ) ;
2009-07-01 20:59:37 +04:00
vg = vg_read_for_update ( cmd , lp . vg_name , NULL , 0 ) ;
if ( vg_read_error ( vg ) ) {
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2013-07-01 13:27:22 +04:00
return_ECMD_FAILED ;
2008-04-02 16:17:30 +04:00
}
2004-05-11 22:47:40 +04:00
2007-11-15 05:20:03 +03:00
if ( ! ( r = _lvresize ( cmd , vg , & lp ) ) )
2004-05-11 22:47:40 +04:00
stack ;
2011-08-11 00:25:29 +04:00
unlock_and_release_vg ( cmd , vg , lp . vg_name ) ;
2004-05-11 22:47:40 +04:00
return r ;
}