2005-06-06 21:12:08 +04:00
/*
2013-02-05 14:21:21 +04:00
* Copyright ( C ) 2005 - 2013 Red Hat , Inc . All rights reserved .
2005-06-06 21:12:08 +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 .
2005-06-06 21:12:08 +04:00
*
2007-08-21 00:55:30 +04:00
* You should have received a copy of the GNU Lesser General Public License
2005-06-06 21:12:08 +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
*/
# include "tools.h"
2007-12-22 15:13:29 +03:00
# include "polldaemon.h"
2005-11-29 21:20:23 +03:00
# include "lv_alloc.h"
2010-05-24 19:32:20 +04:00
# include "metadata.h"
2005-06-06 21:12:08 +04:00
struct lvconvert_params {
2006-04-06 00:43:23 +04:00
int snapshot ;
2010-01-13 04:45:15 +03:00
int merge ;
2011-08-18 23:43:08 +04:00
int merge_mirror ;
2006-04-06 00:43:23 +04:00
int zero ;
const char * origin ;
2005-08-15 18:10:28 +04:00
const char * lv_name ;
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
const char * lv_split_name ;
2007-12-22 15:13:29 +03:00
const char * lv_name_full ;
2006-04-06 00:43:23 +04:00
const char * vg_name ;
2008-01-15 00:11:47 +03:00
int wait_completion ;
int need_polling ;
2006-04-06 00:43:23 +04:00
uint32_t chunk_size ;
uint32_t region_size ;
2005-08-15 18:10:28 +04:00
uint32_t mirrors ;
2005-11-29 21:20:23 +03:00
sign_t mirrors_sign ;
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
uint32_t keep_mimages ;
2010-04-13 05:54:32 +04:00
uint32_t stripes ;
uint32_t stripe_size ;
2012-11-19 16:37:57 +04:00
uint32_t read_ahead ;
2006-04-06 00:43:23 +04:00
2011-08-11 22:24:40 +04:00
const struct segment_type * segtype ;
2012-11-15 13:32:13 +04:00
unsigned target_attr ;
2005-08-15 18:10:28 +04:00
alloc_policy_t alloc ;
int pv_count ;
char * * pvs ;
2008-11-04 01:14:30 +03:00
struct dm_list * pvh ;
2010-01-13 04:49:52 +03:00
2011-11-30 06:02:10 +04:00
int replace_pv_count ;
char * * replace_pvs ;
struct dm_list * replace_pvh ;
2010-01-13 04:49:52 +03:00
struct logical_volume * lv_to_poll ;
2012-05-09 16:17:06 +04:00
2012-05-14 15:57:30 +04:00
uint64_t poolmetadata_size ;
2012-05-09 16:17:06 +04:00
const char * pool_data_lv_name ;
2012-05-14 15:57:30 +04:00
const char * pool_metadata_lv_name ;
thin_discards_t discards ;
2005-06-06 21:12:08 +04:00
} ;
2006-04-19 19:33:07 +04:00
static int _lvconvert_name_params ( struct lvconvert_params * lp ,
struct cmd_context * cmd ,
int * pargc , char * * * pargv )
2006-04-06 00:43:23 +04:00
{
char * ptr ;
2006-04-07 18:14:31 +04:00
const char * vg_name = NULL ;
2006-04-06 00:43:23 +04:00
2010-02-06 01:44:37 +03:00
if ( lp - > merge )
return 1 ;
if ( lp - > snapshot ) {
2006-04-06 00:43:23 +04:00
if ( ! * pargc ) {
log_error ( " Please specify a logical volume to act as "
" the snapshot origin. " ) ;
return 0 ;
}
lp - > origin = * pargv [ 0 ] ;
( * pargv ) + + , ( * pargc ) - - ;
if ( ! ( lp - > vg_name = extract_vgname ( cmd , lp - > origin ) ) ) {
log_error ( " The origin name should include the "
" volume group. " ) ;
return 0 ;
}
/* Strip the volume group from the origin */
if ( ( ptr = strrchr ( lp - > origin , ( int ) ' / ' ) ) )
lp - > origin = ptr + 1 ;
}
2013-02-04 16:56:54 +04:00
if ( lp - > pool_data_lv_name ) {
if ( * pargc ) {
log_error ( " More then one logical volume name name specified. " ) ;
return 0 ;
}
2012-05-09 16:17:06 +04:00
if ( ! lp - > vg_name | | ! validate_name ( lp - > vg_name ) ) {
log_error ( " Please provide a valid volume group name. " ) ;
return 0 ;
}
lp - > lv_name = lp - > pool_data_lv_name ;
return 1 ; /* Create metadata LV on it's own */
}
2006-04-06 00:43:23 +04:00
if ( ! * pargc ) {
log_error ( " Please provide logical volume path " ) ;
return 0 ;
}
2007-12-22 15:13:29 +03:00
lp - > lv_name = lp - > lv_name_full = ( * pargv ) [ 0 ] ;
2006-04-06 00:43:23 +04:00
( * pargv ) + + , ( * pargc ) - - ;
2007-12-22 15:13:29 +03:00
if ( strchr ( lp - > lv_name_full , ' / ' ) & &
( vg_name = extract_vgname ( cmd , lp - > lv_name_full ) ) & &
2006-04-06 00:43:23 +04:00
lp - > vg_name & & strcmp ( vg_name , lp - > vg_name ) ) {
log_error ( " Please use a single volume group name "
" ( \" %s \" or \" %s \" ) " , vg_name , lp - > vg_name ) ;
return 0 ;
}
if ( ! lp - > vg_name )
lp - > vg_name = vg_name ;
if ( ! validate_name ( lp - > vg_name ) ) {
log_error ( " Please provide a valid volume group name " ) ;
return 0 ;
}
2007-12-22 15:13:29 +03:00
if ( ( ptr = strrchr ( lp - > lv_name_full , ' / ' ) ) )
2006-04-06 00:43:23 +04:00
lp - > lv_name = ptr + 1 ;
2012-05-14 15:57:30 +04:00
if ( ! lp - > merge_mirror & &
! strstr ( lp - > lv_name , " _tdata " ) & &
! strstr ( lp - > lv_name , " _tmeta " ) & &
! apply_lvname_restrictions ( lp - > lv_name ) )
2006-04-06 00:43:23 +04:00
return_0 ;
2010-02-06 01:44:37 +03:00
if ( * pargc & & lp - > snapshot ) {
2010-01-13 04:45:15 +03:00
log_error ( " Too many arguments provided for snapshots " ) ;
return 0 ;
}
2012-05-09 16:17:06 +04:00
if ( lp - > pool_data_lv_name & & lp - > lv_name & & lp - > poolmetadata_size ) {
log_error ( " Please specify either metadata logical volume or its size. " ) ;
return 0 ;
}
2006-04-06 00:43:23 +04:00
return 1 ;
}
2005-08-15 18:10:28 +04:00
static int _read_params ( struct lvconvert_params * lp , struct cmd_context * cmd ,
int argc , char * * argv )
{
2011-11-30 06:02:10 +04:00
int i ;
const char * tmp_str ;
struct arg_value_group_list * group ;
2006-04-28 19:01:39 +04:00
int region_size ;
2006-08-17 22:23:44 +04:00
int pagesize = lvm_getpagesize ( ) ;
2006-04-28 19:01:39 +04:00
2005-08-15 18:10:28 +04:00
memset ( lp , 0 , sizeof ( * lp ) ) ;
2012-11-26 14:05:30 +04:00
lp - > target_attr = ~ 0 ;
2005-08-15 18:10:28 +04:00
2010-01-13 04:45:15 +03:00
if ( ( arg_count ( cmd , snapshot_ARG ) | | arg_count ( cmd , merge_ARG ) ) & &
2009-06-30 22:39:31 +04:00
( arg_count ( cmd , mirrorlog_ARG ) | | arg_count ( cmd , mirrors_ARG ) | |
arg_count ( cmd , repair_ARG ) ) ) {
2010-01-13 04:45:15 +03:00
log_error ( " --snapshot or --merge argument cannot be mixed "
2011-06-29 06:06:26 +04:00
" with --mirrors, --repair or --mirrorlog " ) ;
2006-04-06 00:43:23 +04:00
return 0 ;
}
2012-12-11 18:50:25 +04:00
if ( ( arg_count ( cmd , stripes_long_ARG ) | | arg_count ( cmd , stripesize_ARG ) ) & &
! ( arg_count ( cmd , mirrors_ARG ) | | arg_count ( cmd , repair_ARG ) | |
2012-12-13 14:15:37 +04:00
arg_count ( cmd , thinpool_ARG ) | | arg_count ( cmd , type_ARG ) ) ) {
2012-12-11 18:50:25 +04:00
log_error ( " --stripes or --stripesize argument is only valid "
2012-12-13 14:15:37 +04:00
" with --mirrors, --repair, --thinpool or --type " ) ;
2012-12-11 18:50:25 +04:00
return 0 ;
}
2008-01-15 00:11:47 +03:00
if ( ! arg_count ( cmd , background_ARG ) )
lp - > wait_completion = 1 ;
2006-04-06 00:43:23 +04:00
if ( arg_count ( cmd , snapshot_ARG ) )
lp - > snapshot = 1 ;
2010-01-13 04:45:15 +03:00
if ( arg_count ( cmd , snapshot_ARG ) & & arg_count ( cmd , merge_ARG ) ) {
log_error ( " --snapshot and --merge are mutually exclusive " ) ;
return 0 ;
}
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
if ( arg_count ( cmd , splitmirrors_ARG ) & & arg_count ( cmd , mirrors_ARG ) ) {
log_error ( " --mirrors and --splitmirrors are "
" mutually exclusive " ) ;
return 0 ;
}
2012-05-09 16:17:06 +04:00
if ( arg_count ( cmd , thinpool_ARG ) ) {
if ( arg_count ( cmd , merge_ARG ) ) {
log_error ( " --thinpool and --merge are mutually exlusive. " ) ;
return 0 ;
}
if ( arg_count ( cmd , mirrors_ARG ) ) {
log_error ( " --thinpool and --mirrors are mutually exlusive. " ) ;
return 0 ;
}
if ( arg_count ( cmd , repair_ARG ) ) {
log_error ( " --thinpool and --repair are mutually exlusive. " ) ;
return 0 ;
}
if ( arg_count ( cmd , snapshot_ARG ) ) {
log_error ( " --thinpool and --snapshot are mutually exlusive. " ) ;
return 0 ;
}
if ( arg_count ( cmd , splitmirrors_ARG ) ) {
log_error ( " --thinpool and --splitmirrors are mutually exlusive. " ) ;
return 0 ;
}
2012-05-14 15:57:30 +04:00
lp - > discards = ( thin_discards_t ) arg_uint_value ( cmd , discards_ARG , THIN_DISCARDS_PASSDOWN ) ;
} else if ( arg_count ( cmd , discards_ARG ) ) {
log_error ( " --discards is only valid with --thinpool. " ) ;
return 0 ;
2012-05-09 16:17:06 +04:00
}
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
/*
* The ' - - splitmirrors n ' argument is equivalent to ' - - mirrors - n '
* ( note the minus sign ) , except that it signifies the additional
* intent to keep the mimage that is detached , rather than
* discarding it .
*/
if ( arg_count ( cmd , splitmirrors_ARG ) ) {
2011-08-18 23:38:26 +04:00
if ( ! arg_count ( cmd , name_ARG ) & &
! arg_count ( cmd , trackchanges_ARG ) ) {
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
log_error ( " Please name the new logical volume using '--name' " ) ;
return 0 ;
}
lp - > lv_split_name = arg_value ( cmd , name_ARG ) ;
2012-03-30 12:58:02 +04:00
if ( lp - > lv_split_name ) {
if ( strchr ( lp - > lv_split_name , ' / ' ) ) {
if ( ! ( lp - > vg_name = extract_vgname ( cmd , lp - > lv_split_name ) ) )
return_0 ;
/* Strip VG from lv_split_name */
if ( ( tmp_str = strrchr ( lp - > lv_split_name , ' / ' ) ) )
lp - > lv_split_name = tmp_str + 1 ;
}
if ( ! apply_lvname_restrictions ( lp - > lv_split_name ) )
return_0 ;
}
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
lp - > keep_mimages = 1 ;
lp - > mirrors = arg_uint_value ( cmd , splitmirrors_ARG , 0 ) ;
lp - > mirrors_sign = SIGN_MINUS ;
} else if ( arg_count ( cmd , name_ARG ) ) {
log_error ( " The 'name' argument is only valid "
" with --splitmirrors " ) ;
return 0 ;
}
2011-08-18 23:43:08 +04:00
if ( arg_count ( cmd , merge_ARG ) ) {
if ( ( argc = = 1 ) & & strstr ( argv [ 0 ] , " _rimage_ " ) )
lp - > merge_mirror = 1 ;
else
lp - > merge = 1 ;
}
2010-01-13 04:45:15 +03:00
2006-04-06 00:43:23 +04:00
if ( arg_count ( cmd , mirrors_ARG ) ) {
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
/*
* - - splitmirrors has been chosen as the mechanism for
* specifying the intent of detaching and keeping a mimage
* versus an additional qualifying argument being added here .
*/
2006-04-06 00:43:23 +04:00
lp - > mirrors = arg_uint_value ( cmd , mirrors_ARG , 0 ) ;
2012-02-28 18:24:57 +04:00
lp - > mirrors_sign = arg_sign_value ( cmd , mirrors_ARG , SIGN_NONE ) ;
2006-04-06 00:43:23 +04:00
}
2012-03-02 01:14:43 +04:00
lp - > alloc = ( alloc_policy_t ) arg_uint_value ( cmd , alloc_ARG , ALLOC_INHERIT ) ;
2005-08-15 18:10:28 +04:00
2010-04-13 05:54:32 +04:00
/* There are three types of lvconvert. */
if ( lp - > merge ) { /* Snapshot merge */
2010-01-13 04:45:15 +03:00
if ( arg_count ( cmd , regionsize_ARG ) | | arg_count ( cmd , chunksize_ARG ) | |
2010-04-13 05:54:32 +04:00
arg_count ( cmd , zero_ARG ) | | arg_count ( cmd , regionsize_ARG ) | |
2012-11-26 14:14:36 +04:00
arg_count ( cmd , poolmetadata_ARG ) | | arg_count ( cmd , poolmetadatasize_ARG ) | |
arg_count ( cmd , readahead_ARG ) | |
2010-04-13 05:54:32 +04:00
arg_count ( cmd , stripes_long_ARG ) | | arg_count ( cmd , stripesize_ARG ) ) {
2010-01-13 04:45:15 +03:00
log_error ( " Only --background and --interval are valid "
" arguments for snapshot merge " ) ;
return 0 ;
}
if ( ! ( lp - > segtype = get_segtype_from_string ( cmd , " snapshot " ) ) )
return_0 ;
2010-04-13 05:54:32 +04:00
} else if ( lp - > snapshot ) { /* Snapshot creation from pre-existing cow */
2006-04-06 00:43:23 +04:00
if ( arg_count ( cmd , regionsize_ARG ) ) {
log_error ( " --regionsize is only available with mirrors " ) ;
return 0 ;
}
2010-04-13 05:54:32 +04:00
if ( arg_count ( cmd , stripesize_ARG ) | | arg_count ( cmd , stripes_long_ARG ) ) {
log_error ( " --stripes and --stripesize are only available with striped mirrors " ) ;
return 0 ;
}
2012-02-28 18:24:57 +04:00
if ( arg_sign_value ( cmd , chunksize_ARG , SIGN_NONE ) = = SIGN_MINUS ) {
2006-04-06 00:43:23 +04:00
log_error ( " Negative chunk size is invalid " ) ;
return 0 ;
}
2007-11-14 03:08:25 +03:00
lp - > chunk_size = arg_uint_value ( cmd , chunksize_ARG , 8 ) ;
2006-04-06 00:43:23 +04:00
if ( lp - > chunk_size < 8 | | lp - > chunk_size > 1024 | |
( lp - > chunk_size & ( lp - > chunk_size - 1 ) ) ) {
log_error ( " Chunk size must be a power of 2 in the "
" range 4K to 512K " ) ;
return 0 ;
}
log_verbose ( " Setting chunksize to %d sectors. " , lp - > chunk_size ) ;
2005-08-15 18:10:28 +04:00
2006-04-06 00:43:23 +04:00
if ( ! ( lp - > segtype = get_segtype_from_string ( cmd , " snapshot " ) ) )
return_0 ;
2005-11-29 21:20:23 +03:00
2006-04-06 00:43:23 +04:00
lp - > zero = strcmp ( arg_str_value ( cmd , zero_ARG ,
( lp - > segtype - > flags &
SEG_CANNOT_BE_ZEROED ) ?
" n " : " y " ) , " n " ) ;
2011-11-30 06:02:10 +04:00
} else if ( arg_count ( cmd , replace_ARG ) ) { /* RAID device replacement */
lp - > replace_pv_count = arg_count ( cmd , replace_ARG ) ;
lp - > replace_pvs = dm_pool_alloc ( cmd - > mem , sizeof ( char * ) * lp - > replace_pv_count ) ;
if ( ! lp - > replace_pvs )
return_0 ;
i = 0 ;
dm_list_iterate_items ( group , & cmd - > arg_value_groups ) {
if ( ! grouped_arg_is_set ( group - > arg_values , replace_ARG ) )
continue ;
if ( ! ( tmp_str = grouped_arg_str_value ( group - > arg_values ,
replace_ARG ,
NULL ) ) ) {
log_error ( " Failed to get '--replace' argument " ) ;
return 0 ;
}
if ( ! ( lp - > replace_pvs [ i + + ] = dm_pool_strdup ( cmd - > mem ,
tmp_str ) ) )
return_0 ;
}
2012-05-09 16:17:06 +04:00
} else if ( arg_count ( cmd , thinpool_ARG ) ) {
if ( ! ( lp - > pool_data_lv_name = arg_str_value ( cmd , thinpool_ARG , NULL ) ) ) {
log_error ( " Missing pool logical volume name. " ) ;
return 0 ;
}
2012-11-19 16:37:57 +04:00
if ( ! get_pool_params ( cmd ,
& lp - > chunk_size ,
& lp - > discards ,
& lp - > poolmetadata_size ,
& lp - > zero ) )
return_0 ;
2012-05-14 15:57:30 +04:00
if ( arg_count ( cmd , poolmetadata_ARG ) ) {
2012-11-19 16:37:57 +04:00
if ( arg_count ( cmd , poolmetadatasize_ARG ) ) {
log_error ( " --poolmetadatasize is invalid with --poolmetadata. " ) ;
2012-05-09 16:17:06 +04:00
return 0 ;
}
2012-11-19 16:37:57 +04:00
lp - > pool_metadata_lv_name = arg_str_value ( cmd , poolmetadata_ARG , " " ) ;
2012-05-09 16:17:06 +04:00
}
/* If --thinpool contains VG name, extract it. */
if ( ( tmp_str = strchr ( lp - > pool_data_lv_name , ( int ) ' / ' ) ) ) {
if ( ! ( lp - > vg_name = extract_vgname ( cmd , lp - > pool_data_lv_name ) ) )
return 0 ;
/* Strip VG from pool */
lp - > pool_data_lv_name = tmp_str + 1 ;
}
lp - > segtype = get_segtype_from_string ( cmd , arg_str_value ( cmd , type_ARG , " thin-pool " ) ) ;
if ( ! lp - > segtype )
return_0 ;
2011-11-30 06:02:10 +04:00
} else { /* Mirrors (and some RAID functions) */
2006-04-06 00:43:23 +04:00
if ( arg_count ( cmd , chunksize_ARG ) ) {
log_error ( " --chunksize is only available with "
2012-05-14 15:57:30 +04:00
" snapshots or thin pools. " ) ;
2005-11-29 21:20:23 +03:00
return 0 ;
}
2006-04-06 00:43:23 +04:00
if ( arg_count ( cmd , zero_ARG ) ) {
2012-05-14 15:57:30 +04:00
log_error ( " --zero is only available with snapshots or thin pools. " ) ;
2006-04-06 00:43:23 +04:00
return 0 ;
}
/*
* - - regionsize is only valid if converting an LV into a mirror .
* Checked when we know the state of the LV being converted .
*/
2006-04-28 19:01:39 +04:00
2006-04-06 00:43:23 +04:00
if ( arg_count ( cmd , regionsize_ARG ) ) {
2012-02-28 18:24:57 +04:00
if ( arg_sign_value ( cmd , regionsize_ARG , SIGN_NONE ) = =
2006-04-06 00:43:23 +04:00
SIGN_MINUS ) {
log_error ( " Negative regionsize is invalid " ) ;
return 0 ;
}
2007-11-14 03:08:25 +03:00
lp - > region_size = arg_uint_value ( cmd , regionsize_ARG , 0 ) ;
2006-04-28 19:01:39 +04:00
} else {
2013-02-21 00:40:17 +04:00
region_size = get_default_region_size ( cmd ) ;
2006-04-28 19:01:39 +04:00
if ( region_size < 0 ) {
log_error ( " Negative regionsize in "
" configuration file is invalid " ) ;
return 0 ;
}
lp - > region_size = region_size ;
}
2006-04-28 21:25:54 +04:00
if ( lp - > region_size % ( pagesize > > SECTOR_SHIFT ) ) {
log_error ( " Region size (% " PRIu32 " ) must be "
" a multiple of machine memory "
" page size (%d) " ,
lp - > region_size , pagesize > > SECTOR_SHIFT ) ;
return 0 ;
}
2006-04-06 00:43:23 +04:00
if ( lp - > region_size & ( lp - > region_size - 1 ) ) {
log_error ( " Region size (% " PRIu32
" ) must be a power of 2 " , lp - > region_size ) ;
return 0 ;
}
2006-04-28 17:11:05 +04:00
if ( ! lp - > region_size ) {
log_error ( " Non-zero region size must be supplied. " ) ;
return 0 ;
}
2010-04-13 05:54:32 +04:00
/* Default is never striped, regardless of existing LV configuration. */
if ( ! get_stripe_params ( cmd , & lp - > stripes , & lp - > stripe_size ) ) {
stack ;
return 0 ;
}
2011-10-07 18:52:26 +04:00
lp - > segtype = get_segtype_from_string ( cmd , arg_str_value ( cmd , type_ARG , " mirror " ) ) ;
if ( ! lp - > segtype )
2006-04-06 00:43:23 +04:00
return_0 ;
2005-11-29 21:20:23 +03:00
}
2005-08-15 18:10:28 +04:00
2011-11-30 06:02:10 +04:00
if ( activation ( ) & & lp - > segtype & & lp - > segtype - > ops - > target_present & &
2012-11-15 13:32:13 +04:00
! lp - > segtype - > ops - > target_present ( cmd , NULL , & lp - > target_attr ) ) {
2006-04-06 00:43:23 +04:00
log_error ( " %s: Required device-mapper target(s) not "
" detected in your kernel " , lp - > segtype - > name ) ;
2005-08-15 18:10:28 +04:00
return 0 ;
}
2006-04-19 19:33:07 +04:00
if ( ! _lvconvert_name_params ( lp , cmd , & argc , & argv ) )
2006-04-06 00:43:23 +04:00
return_0 ;
2005-08-15 18:10:28 +04:00
lp - > pv_count = argc ;
lp - > pvs = argv ;
return 1 ;
}
2007-12-22 15:13:29 +03:00
static struct volume_group * _get_lvconvert_vg ( struct cmd_context * cmd ,
2010-02-06 01:40:49 +03:00
const char * name ,
2010-07-09 19:34:40 +04:00
const char * uuid __attribute__ ( ( unused ) ) )
2007-12-22 15:13:29 +03:00
{
2008-01-30 17:00:02 +03:00
dev_close_all ( ) ;
2007-12-22 15:13:29 +03:00
2010-02-06 01:40:49 +03:00
if ( name & & ! strchr ( name , ' / ' ) )
return vg_read_for_update ( cmd , name , NULL , 0 ) ;
/* 'name' is the full LV name; must extract_vgname() */
return vg_read_for_update ( cmd , extract_vgname ( cmd , name ) ,
2009-07-01 20:59:37 +04:00
NULL , 0 ) ;
2007-12-22 15:13:29 +03:00
}
2010-07-09 19:34:40 +04:00
static struct logical_volume * _get_lvconvert_lv ( struct cmd_context * cmd __attribute__ ( ( unused ) ) ,
2007-12-22 15:13:29 +03:00
struct volume_group * vg ,
const char * name ,
2009-06-01 18:43:27 +04:00
const char * uuid ,
2011-09-06 22:49:31 +04:00
uint64_t lv_type __attribute__ ( ( unused ) ) )
2007-12-22 15:13:29 +03:00
{
2009-06-01 18:43:27 +04:00
struct logical_volume * lv = find_lv ( vg , name ) ;
if ( ! lv | | ( uuid & & strcmp ( uuid , ( char * ) & lv - > lvid ) ) )
return NULL ;
return lv ;
2007-12-22 15:13:29 +03:00
}
2012-08-02 13:38:07 +04:00
static int _reload_lv ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct logical_volume * lv )
2012-08-01 17:34:45 +04:00
{
2012-08-02 13:38:07 +04:00
int r = 0 ;
2012-08-01 17:34:45 +04:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2012-08-02 13:38:07 +04:00
if ( ! vg_write ( vg ) )
2012-08-01 17:34:45 +04:00
return_0 ;
if ( ! suspend_lv ( cmd , lv ) ) {
log_error ( " Failed to lock %s " , lv - > name ) ;
2012-08-02 13:38:07 +04:00
vg_revert ( vg ) ;
2013-02-05 14:21:21 +04:00
if ( ! resume_lv ( cmd , lv ) )
stack ;
2012-08-02 13:38:07 +04:00
goto out ;
2012-08-01 17:34:45 +04:00
}
2012-08-02 13:38:07 +04:00
if ( ! vg_commit ( vg ) ) {
2013-02-05 14:21:21 +04:00
vg_revert ( vg ) ;
2012-08-01 17:34:45 +04:00
if ( ! resume_lv ( cmd , lv ) )
stack ;
2012-08-02 13:38:07 +04:00
goto_out ;
2012-08-01 17:34:45 +04:00
}
log_very_verbose ( " Updating \" %s \" in kernel " , lv - > name ) ;
if ( ! resume_lv ( cmd , lv ) ) {
log_error ( " Problem reactivating %s " , lv - > name ) ;
2012-08-02 13:38:07 +04:00
goto out ;
2012-08-01 17:34:45 +04:00
}
2012-08-02 13:38:07 +04:00
r = 1 ;
backup ( vg ) ;
2013-02-05 14:21:21 +04:00
out :
2012-08-02 13:38:07 +04:00
return r ;
2012-08-01 17:34:45 +04:00
}
2007-12-22 15:13:29 +03:00
static int _finish_lvconvert_mirror ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct logical_volume * lv ,
2010-07-09 19:34:40 +04:00
struct dm_list * lvs_changed __attribute__ ( ( unused ) ) )
2007-12-22 15:13:29 +03:00
{
2010-02-06 00:49:16 +03:00
if ( ! ( lv - > status & CONVERTING ) )
return 1 ;
2007-12-22 15:13:29 +03:00
if ( ! collapse_mirrored_lv ( lv ) ) {
log_error ( " Failed to remove temporary sync layer. " ) ;
return 0 ;
}
2008-01-10 21:35:51 +03:00
lv - > status & = ~ CONVERTING ;
2007-12-22 15:13:29 +03:00
log_very_verbose ( " Updating logical volume \" %s \" on disk(s) " , lv - > name ) ;
2012-08-02 13:38:07 +04:00
if ( ! ( _reload_lv ( cmd , vg , lv ) ) )
2007-12-22 15:13:29 +03:00
return_0 ;
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 converted. " , lv - > name ) ;
2012-08-02 13:38:07 +04:00
return 1 ;
2007-12-22 15:13:29 +03:00
}
2010-01-13 04:49:52 +03:00
static int _finish_lvconvert_merge ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct logical_volume * lv ,
2010-07-09 19:34:40 +04:00
struct dm_list * lvs_changed __attribute__ ( ( unused ) ) )
2010-01-13 04:49:52 +03:00
{
2010-01-13 04:55:43 +03:00
struct lv_segment * snap_seg = find_merging_cow ( lv ) ;
2010-01-13 04:49:52 +03:00
if ( ! snap_seg ) {
log_error ( " Logical volume %s has no merging snapshot. " , lv - > name ) ;
return 0 ;
}
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 ( " Merge of snapshot into logical volume %s has finished. " , lv - > name ) ;
2010-01-13 04:49:52 +03:00
if ( ! lv_remove_single ( cmd , snap_seg - > cow , DONT_PROMPT ) ) {
log_error ( " Could not remove snapshot %s merged into %s. " ,
snap_seg - > cow - > name , lv - > name ) ;
return 0 ;
}
return 1 ;
}
static progress_t _poll_merge_progress ( struct cmd_context * cmd ,
struct logical_volume * lv ,
2010-07-09 19:34:40 +04:00
const char * name __attribute__ ( ( unused ) ) ,
2010-01-13 04:49:52 +03:00
struct daemon_parms * parms )
{
2010-11-30 14:53:31 +03:00
percent_t percent = PERCENT_0 ;
2010-01-13 04:49:52 +03:00
2010-11-30 14:53:31 +03:00
if ( ! lv_snapshot_percent ( lv , & percent ) ) {
2010-01-16 01:58:25 +03:00
log_error ( " %s: Failed query for merging percentage. Aborting merge. " , lv - > name ) ;
2010-01-13 04:49:52 +03:00
return PROGRESS_CHECK_FAILED ;
2010-11-30 14:53:31 +03:00
} else if ( percent = = PERCENT_INVALID ) {
2010-01-13 04:49:52 +03:00
log_error ( " %s: Merging snapshot invalidated. Aborting merge. " , lv - > name ) ;
return PROGRESS_CHECK_FAILED ;
2012-01-21 02:02:04 +04:00
} else if ( percent = = PERCENT_MERGE_FAILED ) {
log_error ( " %s: Merge failed. Retry merge or inspect manually. " , lv - > name ) ;
return PROGRESS_CHECK_FAILED ;
2010-01-13 04:49:52 +03:00
}
if ( parms - > progress_display )
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 ( " %s: %s: %.1f%% " , lv - > name , parms - > progress_title ,
100.0 - percent_to_float ( percent ) ) ;
2010-01-13 04:49:52 +03:00
else
2010-11-30 14:53:31 +03:00
log_verbose ( " %s: %s: %.1f%% " , lv - > name , parms - > progress_title ,
2012-07-10 17:30:18 +04:00
100.0 - percent_to_float ( percent ) ) ;
2010-01-13 04:49:52 +03:00
2010-11-30 14:53:31 +03:00
if ( percent = = PERCENT_0 )
2010-01-13 04:49:52 +03:00
return PROGRESS_FINISHED_ALL ;
return PROGRESS_UNFINISHED ;
}
2007-12-22 15:13:29 +03:00
static struct poll_functions _lvconvert_mirror_fns = {
. get_copy_vg = _get_lvconvert_vg ,
. get_copy_lv = _get_lvconvert_lv ,
2009-09-30 22:15:06 +04:00
. poll_progress = poll_mirror_progress ,
2007-12-22 15:13:29 +03:00
. finish_copy = _finish_lvconvert_mirror ,
} ;
2010-01-13 04:49:52 +03:00
static struct poll_functions _lvconvert_merge_fns = {
. get_copy_vg = _get_lvconvert_vg ,
. get_copy_lv = _get_lvconvert_lv ,
. poll_progress = _poll_merge_progress ,
. finish_copy = _finish_lvconvert_merge ,
} ;
2009-06-01 18:43:27 +04:00
int lvconvert_poll ( struct cmd_context * cmd , struct logical_volume * lv ,
2008-01-10 21:35:51 +03:00
unsigned background )
2007-12-22 15:13:29 +03:00
{
2010-02-06 01:40:49 +03:00
/*
* FIXME allocate an " object key " structure with split
* out members ( vg_name , lv_name , uuid , etc ) and pass that
* around the lvconvert and polldaemon code
* - will avoid needless work , e . g . extract_vgname ( )
* - unfortunately there are enough overloaded " name " dragons in
* the polldaemon , lvconvert , pvmove code that a comprehensive
* audit / rework is needed
*/
2009-06-01 18:43:27 +04:00
int len = strlen ( lv - > vg - > name ) + strlen ( lv - > name ) + 2 ;
char * uuid = alloca ( sizeof ( lv - > lvid ) ) ;
char * lv_full_name = alloca ( len ) ;
if ( ! uuid | | ! lv_full_name )
return_0 ;
2011-04-09 23:05:23 +04:00
if ( dm_snprintf ( lv_full_name , len , " %s/%s " , lv - > vg - > name , lv - > name ) < 0 )
2009-06-01 18:43:27 +04:00
return_0 ;
memcpy ( uuid , & lv - > lvid , sizeof ( lv - > lvid ) ) ;
2010-01-13 04:55:43 +03:00
if ( ! lv_is_merging_origin ( lv ) )
2010-01-13 04:49:52 +03:00
return poll_daemon ( cmd , lv_full_name , uuid , background , 0 ,
& _lvconvert_mirror_fns , " Converted " ) ;
else
return poll_daemon ( cmd , lv_full_name , uuid , background , 0 ,
& _lvconvert_merge_fns , " Merged " ) ;
2007-12-22 15:13:29 +03:00
}
2007-12-22 05:13:00 +03:00
static int _insert_lvconvert_layer ( struct cmd_context * cmd ,
struct logical_volume * lv )
{
char * format , * layer_name ;
size_t len ;
int i ;
/*
* We would like to give the same number for this layer
* and the newly added mimage .
* However , LV name of newly added mimage is determined * after *
* the LV name of this layer is determined .
*
* So , use generate_lv_name ( ) to generate mimage name first
* and take the number from it .
*/
len = strlen ( lv - > name ) + 32 ;
if ( ! ( format = alloca ( len ) ) | |
! ( layer_name = alloca ( len ) ) | |
dm_snprintf ( format , len , " %s_mimage_%%d " , lv - > name ) < 0 ) {
log_error ( " lvconvert: layer name allocation failed. " ) ;
return 0 ;
}
if ( ! generate_lv_name ( lv - > vg , format , layer_name , len ) | |
sscanf ( layer_name , format , & i ) ! = 1 ) {
log_error ( " lvconvert: layer name generation failed. " ) ;
return 0 ;
}
if ( dm_snprintf ( layer_name , len , MIRROR_SYNC_LAYER " _%d " , i ) < 0 ) {
log_error ( " layer name allocation failed. " ) ;
return 0 ;
}
if ( ! insert_layer_for_lv ( cmd , lv , 0 , layer_name ) ) {
log_error ( " Failed to insert resync layer " ) ;
return 0 ;
}
return 1 ;
}
2009-05-21 07:04:52 +04:00
static int _failed_mirrors_count ( struct logical_volume * lv )
2009-04-23 20:56:21 +04:00
{
struct lv_segment * lvseg ;
int ret = 0 ;
2011-04-08 18:40:18 +04:00
unsigned s ;
2009-05-21 07:04:52 +04:00
2009-04-23 20:56:21 +04:00
dm_list_iterate_items ( lvseg , & lv - > segments ) {
if ( ! seg_is_mirrored ( lvseg ) )
return - 1 ;
2011-05-07 17:56:13 +04:00
for ( s = 0 ; s < lvseg - > area_count ; s + + ) {
if ( seg_type ( lvseg , s ) = = AREA_LV ) {
if ( is_temporary_mirror_layer ( seg_lv ( lvseg , s ) ) )
ret + = _failed_mirrors_count ( seg_lv ( lvseg , s ) ) ;
else if ( seg_lv ( lvseg , s ) - > status & PARTIAL_LV )
+ + ret ;
else if ( seg_type ( lvseg , s ) = = AREA_PV & &
is_missing_pv ( seg_pv ( lvseg , s ) ) )
+ + ret ;
}
}
2009-04-23 20:56:21 +04:00
}
2009-05-21 07:04:52 +04:00
2009-04-23 20:56:21 +04:00
return ret ;
}
2011-05-07 17:56:13 +04:00
static int _failed_logs_count ( struct logical_volume * lv )
{
2012-02-24 02:36:56 +04:00
int ret = 0 ;
unsigned s ;
2011-05-07 17:56:13 +04:00
struct logical_volume * log_lv = first_seg ( lv ) - > log_lv ;
if ( log_lv & & ( log_lv - > status & PARTIAL_LV ) ) {
if ( log_lv - > status & MIRRORED )
ret + = _failed_mirrors_count ( log_lv ) ;
else
ret + = 1 ;
}
for ( s = 0 ; s < first_seg ( lv ) - > area_count ; s + + ) {
if ( seg_type ( first_seg ( lv ) , s ) = = AREA_LV & &
is_temporary_mirror_layer ( seg_lv ( first_seg ( lv ) , s ) ) )
ret + = _failed_logs_count ( seg_lv ( first_seg ( lv ) , s ) ) ;
}
return ret ;
}
2009-04-23 20:56:21 +04:00
static struct dm_list * _failed_pv_list ( struct volume_group * vg )
{
2009-05-21 07:04:52 +04:00
struct dm_list * failed_pvs ;
2009-04-23 20:56:21 +04:00
struct pv_list * pvl , * new_pvl ;
2009-05-21 07:04:52 +04:00
if ( ! ( failed_pvs = dm_pool_alloc ( vg - > vgmem , sizeof ( * failed_pvs ) ) ) ) {
log_error ( " Allocation of list of failed_pvs failed. " ) ;
return_NULL ;
2009-04-23 20:56:21 +04:00
}
2009-05-21 07:04:52 +04:00
dm_list_init ( failed_pvs ) ;
2009-04-23 20:56:21 +04:00
dm_list_iterate_items ( pvl , & vg - > pvs ) {
2010-03-16 17:37:38 +03:00
if ( ! is_missing_pv ( pvl - > pv ) )
2009-04-23 20:56:21 +04:00
continue ;
2010-01-06 16:26:21 +03:00
/*
* Finally , - - repair will remove empty PVs .
* But we only want remove these which are output of repair ,
* Do not count these which are already empty here .
* FIXME : code should traverse PV in LV not in whole VG .
* FIXME : layer violation ? should it depend on vgreduce - - removemising ?
*/
if ( pvl - > pv - > pe_alloc_count = = 0 )
continue ;
2009-04-23 20:56:21 +04:00
if ( ! ( new_pvl = dm_pool_alloc ( vg - > vgmem , sizeof ( * new_pvl ) ) ) ) {
2009-05-21 07:04:52 +04:00
log_error ( " Allocation of failed_pvs list entry failed. " ) ;
return_NULL ;
2009-04-23 20:56:21 +04:00
}
new_pvl - > pv = pvl - > pv ;
2009-05-21 07:04:52 +04:00
dm_list_add ( failed_pvs , & new_pvl - > list ) ;
2009-04-23 20:56:21 +04:00
}
2009-05-21 07:04:52 +04:00
return failed_pvs ;
2009-04-23 20:56:21 +04:00
}
2010-05-24 19:32:20 +04:00
static int _is_partial_lv ( struct logical_volume * lv ,
2010-07-09 19:34:40 +04:00
void * baton __attribute__ ( ( unused ) ) )
2010-05-24 19:32:20 +04:00
{
return lv - > status & PARTIAL_LV ;
}
2009-05-21 07:04:52 +04:00
/*
* Walk down the stacked mirror LV to the original mirror LV .
*/
2008-01-16 22:16:48 +03:00
static struct logical_volume * _original_lv ( struct logical_volume * lv )
{
struct logical_volume * next_lv = lv , * tmp_lv ;
while ( ( tmp_lv = find_temporary_mirror ( next_lv ) ) )
next_lv = tmp_lv ;
return next_lv ;
}
2009-06-04 16:01:15 +04:00
static void _lvconvert_mirrors_repair_ask ( struct cmd_context * cmd ,
int failed_log , int failed_mirrors ,
int * replace_log , int * replace_mirrors )
{
const char * leg_policy = NULL , * log_policy = NULL ;
int force = arg_count ( cmd , force_ARG ) ;
int yes = arg_count ( cmd , yes_ARG ) ;
* replace_log = * replace_mirrors = 1 ;
if ( arg_count ( cmd , use_policies_ARG ) ) {
leg_policy = find_config_tree_str ( cmd ,
2010-01-06 16:27:06 +03:00
" activation/mirror_image_fault_policy " , NULL ) ;
if ( ! leg_policy )
leg_policy = find_config_tree_str ( cmd ,
2009-06-04 16:01:15 +04:00
" activation/mirror_device_fault_policy " ,
DEFAULT_MIRROR_DEVICE_FAULT_POLICY ) ;
log_policy = find_config_tree_str ( cmd ,
" activation/mirror_log_fault_policy " ,
DEFAULT_MIRROR_LOG_FAULT_POLICY ) ;
* replace_mirrors = strcmp ( leg_policy , " remove " ) ;
* replace_log = strcmp ( log_policy , " remove " ) ;
return ;
}
if ( force ! = PROMPT ) {
* replace_log = * replace_mirrors = 0 ;
return ;
}
2012-12-11 12:52:54 +04:00
if ( yes )
return ;
2009-06-04 16:01:15 +04:00
if ( failed_log & &
yes_no_prompt ( " Attempt to replace failed mirror log? [y/n]: " ) = = ' n ' ) {
* replace_log = 0 ;
}
if ( failed_mirrors & &
yes_no_prompt ( " Attempt to replace failed mirror images "
" (requires full device resync)? [y/n]: " ) = = ' n ' ) {
* replace_mirrors = 0 ;
}
}
2010-03-27 01:15:43 +03:00
/*
* _get_log_count
* @ lv : the mirror LV
*
* Get the number of on - disk copies of the log .
* 0 = ' core '
* 1 = ' disk '
* 2 + = ' mirrored '
*/
static int _get_log_count ( struct logical_volume * lv )
2009-08-03 01:56:29 +04:00
{
2010-03-27 01:15:43 +03:00
struct logical_volume * log_lv ;
log_lv = first_seg ( _original_lv ( lv ) ) - > log_lv ;
2011-05-07 17:56:13 +04:00
if ( log_lv )
return lv_mirror_count ( log_lv ) ;
2010-03-27 01:15:43 +03:00
2011-05-07 17:56:13 +04:00
return 0 ;
2009-08-03 01:56:29 +04:00
}
2010-06-24 00:32:29 +04:00
static int _lv_update_mirrored_log ( struct logical_volume * lv ,
struct dm_list * operable_pvs ,
int log_count )
{
int old_log_count ;
struct logical_volume * log_lv ;
2010-08-03 01:07:40 +04:00
/*
* When log_count is 0 , mirrored log doesn ' t need to be
* updated here but it will be removed later .
*/
if ( ! log_count )
return 1 ;
2010-06-24 00:32:29 +04:00
log_lv = first_seg ( _original_lv ( lv ) ) - > log_lv ;
if ( ! log_lv | | ! ( log_lv - > status & MIRRORED ) )
return 1 ;
old_log_count = _get_log_count ( lv ) ;
if ( old_log_count = = log_count )
return 1 ;
/* Reducing redundancy of the log */
2010-08-03 01:07:40 +04:00
return remove_mirror_images ( log_lv , log_count ,
is_mirror_image_removable ,
operable_pvs , 0U ) ;
2010-06-24 00:32:29 +04:00
}
2009-08-03 01:56:29 +04:00
static int _lv_update_log_type ( struct cmd_context * cmd ,
struct lvconvert_params * lp ,
struct logical_volume * lv ,
2010-03-27 01:15:43 +03:00
struct dm_list * operable_pvs ,
2010-01-09 01:32:35 +03:00
int log_count )
2009-08-03 01:56:29 +04:00
{
2010-03-27 01:15:43 +03:00
int old_log_count ;
2012-02-13 22:36:55 +04:00
uint32_t region_size = ( lp ) ? lp - > region_size :
first_seg ( lv ) - > region_size ;
alloc_policy_t alloc = ( lp ) ? lp - > alloc : lv - > alloc ;
2010-03-27 01:15:43 +03:00
struct logical_volume * original_lv ;
struct logical_volume * log_lv ;
old_log_count = _get_log_count ( lv ) ;
if ( old_log_count = = log_count )
return 1 ;
original_lv = _original_lv ( lv ) ;
/* Remove an existing log completely */
if ( ! log_count ) {
2010-10-12 20:41:17 +04:00
if ( ! remove_mirror_log ( cmd , original_lv , operable_pvs ,
arg_count ( cmd , yes_ARG ) | |
arg_count ( cmd , force_ARG ) ) )
2009-08-03 01:56:29 +04:00
return_0 ;
2010-03-27 01:15:43 +03:00
return 1 ;
2009-08-03 01:56:29 +04:00
}
2010-03-27 01:15:43 +03:00
log_lv = first_seg ( original_lv ) - > log_lv ;
/* Adding redundancy to the log */
if ( old_log_count < log_count ) {
2011-05-07 17:56:13 +04:00
region_size = adjusted_mirror_region_size ( lv - > vg - > extent_size ,
lv - > le_count ,
2012-02-13 22:36:55 +04:00
region_size ) ;
2011-05-07 17:56:13 +04:00
2011-01-11 20:05:08 +03:00
if ( ! add_mirror_log ( cmd , original_lv , log_count ,
2012-02-13 22:36:55 +04:00
region_size , operable_pvs , alloc ) )
2011-01-11 20:05:08 +03:00
return_0 ;
/*
* FIXME : This simple approach won ' t work in cluster mirrors ,
* but it doesn ' t matter because we don ' t support
* mirrored logs in cluster mirrors .
*/
2012-08-02 13:38:07 +04:00
if ( old_log_count & &
! _reload_lv ( cmd , log_lv - > vg , log_lv ) )
return_0 ;
2011-01-11 20:05:08 +03:00
return 1 ;
2010-03-27 01:15:43 +03:00
}
/* Reducing redundancy of the log */
2012-02-13 22:36:55 +04:00
return remove_mirror_images ( log_lv , log_count ,
is_mirror_image_removable , operable_pvs , 1U ) ;
2009-08-03 01:56:29 +04:00
}
2010-01-06 16:26:21 +03:00
/*
* Reomove missing and empty PVs from VG , if are also in provided list
*/
static void _remove_missing_empty_pv ( struct volume_group * vg , struct dm_list * remove_pvs )
{
struct pv_list * pvl , * pvl_vg , * pvlt ;
int removed = 0 ;
if ( ! remove_pvs )
return ;
dm_list_iterate_items ( pvl , remove_pvs ) {
dm_list_iterate_items_safe ( pvl_vg , pvlt , & vg - > pvs ) {
if ( ! id_equal ( & pvl - > pv - > id , & pvl_vg - > pv - > id ) | |
2010-03-16 17:37:38 +03:00
! is_missing_pv ( pvl_vg - > pv ) | |
2010-01-06 16:26:21 +03:00
pvl_vg - > pv - > pe_alloc_count ! = 0 )
continue ;
/* FIXME: duplication of vgreduce code, move this to library */
vg - > free_count - = pvl_vg - > pv - > pe_count ;
vg - > extent_count - = pvl_vg - > pv - > pe_count ;
2010-04-13 21:26:03 +04:00
del_pvl_from_vgs ( vg , pvl_vg ) ;
2011-03-11 17:56:56 +03:00
free_pv_fid ( pvl_vg - > pv ) ;
2010-01-06 16:26:21 +03:00
removed + + ;
}
}
if ( removed ) {
if ( ! vg_write ( vg ) | | ! vg_commit ( vg ) ) {
stack ;
return ;
}
log_warn ( " %d missing and now unallocated Physical Volumes removed from VG. " , removed ) ;
}
}
2010-03-27 01:15:43 +03:00
/*
* _lvconvert_mirrors_parse_params
*
* This function performs the following :
* 1 ) Gets the old values of mimage and log counts
* 2 ) Parses the CLI args to find the new desired values
* 3 ) Adjusts ' lp - > mirrors ' to the appropriate absolute value .
* ( Remember , ' lp - > mirrors ' is specified in terms of the number of " copies "
* vs . the number of mimages . It can also be a relative value . )
* 4 ) Sets ' lp - > need_polling ' if collapsing
* 5 ) Validates other mirror params
*
* Returns : 1 on success , 0 on error
*/
static int _lvconvert_mirrors_parse_params ( struct cmd_context * cmd ,
struct logical_volume * lv ,
struct lvconvert_params * lp ,
uint32_t * old_mimage_count ,
uint32_t * old_log_count ,
uint32_t * new_mimage_count ,
uint32_t * new_log_count )
2005-06-06 21:12:08 +04:00
{
2009-06-04 16:01:15 +04:00
int repair = arg_count ( cmd , repair_ARG ) ;
2010-03-27 01:15:43 +03:00
const char * mirrorlog ;
* old_mimage_count = lv_mirror_count ( lv ) ;
* old_log_count = _get_log_count ( lv ) ;
2007-12-21 04:08:18 +03:00
2010-03-27 01:15:43 +03:00
/*
* Collapsing a stack of mirrors :
*
* If called with no argument , try collapsing the resync layers
*/
2008-01-10 21:35:51 +03:00
if ( ! arg_count ( cmd , mirrors_ARG ) & & ! arg_count ( cmd , mirrorlog_ARG ) & &
2009-04-23 20:56:21 +04:00
! arg_count ( cmd , corelog_ARG ) & & ! arg_count ( cmd , regionsize_ARG ) & &
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
! arg_count ( cmd , splitmirrors_ARG ) & & ! repair ) {
2010-03-27 01:15:43 +03:00
* new_mimage_count = * old_mimage_count ;
* new_log_count = * old_log_count ;
2009-06-15 16:08:59 +04:00
if ( find_temporary_mirror ( lv ) | | ( lv - > status & CONVERTING ) )
lp - > need_polling = 1 ;
2007-12-22 15:13:29 +03:00
return 1 ;
2007-12-21 04:08:18 +03:00
}
2005-11-29 21:20:23 +03:00
2010-03-27 01:15:43 +03:00
if ( ( arg_count ( cmd , mirrors_ARG ) & & repair ) | |
( arg_count ( cmd , mirrorlog_ARG ) & & repair ) | |
( arg_count ( cmd , corelog_ARG ) & & repair ) ) {
log_error ( " --repair cannot be used with --mirrors, --mirrorlog, "
" or --corelog " ) ;
return 0 ;
}
if ( arg_count ( cmd , mirrorlog_ARG ) & & arg_count ( cmd , corelog_ARG ) ) {
log_error ( " --mirrorlog and --corelog are incompatible " ) ;
2009-04-23 20:56:21 +04:00
return 0 ;
}
2007-08-02 00:54:28 +04:00
/*
2010-03-27 01:15:43 +03:00
* Adjusting mimage count ?
2007-08-02 00:54:28 +04:00
*/
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
if ( ! arg_count ( cmd , mirrors_ARG ) & & ! arg_count ( cmd , splitmirrors_ARG ) )
2010-03-27 01:15:43 +03:00
lp - > mirrors = * old_mimage_count ;
2007-08-02 00:54:28 +04:00
else if ( lp - > mirrors_sign = = SIGN_PLUS )
2010-03-27 01:15:43 +03:00
lp - > mirrors = * old_mimage_count + lp - > mirrors ;
2007-08-02 00:54:28 +04:00
else if ( lp - > mirrors_sign = = SIGN_MINUS )
2010-07-14 01:53:07 +04:00
lp - > mirrors = ( * old_mimage_count > lp - > mirrors ) ?
* old_mimage_count - lp - > mirrors : 0 ;
2007-08-02 00:54:28 +04:00
else
2005-11-29 21:20:23 +03:00
lp - > mirrors + = 1 ;
2010-03-27 01:15:43 +03:00
* new_mimage_count = lp - > mirrors ;
/* Too many mimages? */
2009-11-27 17:35:38 +03:00
if ( lp - > mirrors > DEFAULT_MIRROR_MAX_IMAGES ) {
log_error ( " Only up to %d images in mirror supported currently. " ,
DEFAULT_MIRROR_MAX_IMAGES ) ;
return 0 ;
}
2010-03-27 01:15:43 +03:00
/* Did the user try to subtract more legs than available? */
if ( lp - > mirrors < 1 ) {
2010-07-14 01:53:07 +04:00
log_error ( " Unable to reduce images by specified amount - only %d in %s " ,
* old_mimage_count , lv - > name ) ;
2010-03-27 01:15:43 +03:00
return 0 ;
2010-01-07 23:42:55 +03:00
}
2010-03-27 01:15:43 +03:00
/*
* FIXME : It would be nice to say what we are adjusting to , but
* I really don ' t know whether to specify the # of copies or mimages .
*/
if ( * old_mimage_count ! = * new_mimage_count )
log_verbose ( " Adjusting mirror image count of %s " , lv - > name ) ;
2009-04-30 00:11:46 +04:00
2010-03-27 01:15:43 +03:00
/*
* Adjust log type
*
* If we are converting from a mirror to another mirror or simply
* changing the log type , we start by assuming they want the log
* type the same and then parse the given args . OTOH , If we are
* converting from linear to mirror , then we start from the default
* position that the user would like a ' disk ' log .
*/
* new_log_count = ( * old_mimage_count > 1 ) ? * old_log_count : 1 ;
if ( ! arg_count ( cmd , corelog_ARG ) & & ! arg_count ( cmd , mirrorlog_ARG ) )
return 1 ;
2010-01-09 01:32:35 +03:00
2010-03-27 01:15:43 +03:00
if ( arg_count ( cmd , corelog_ARG ) )
* new_log_count = 0 ;
2010-01-09 01:32:35 +03:00
2010-03-27 01:15:43 +03:00
mirrorlog = arg_str_value ( cmd , mirrorlog_ARG ,
! * new_log_count ? " core " : DEFAULT_MIRRORLOG ) ;
2007-08-02 01:01:06 +04:00
2010-03-27 01:15:43 +03:00
if ( ! strcmp ( " mirrored " , mirrorlog ) )
* new_log_count = 2 ;
else if ( ! strcmp ( " disk " , mirrorlog ) )
* new_log_count = 1 ;
else if ( ! strcmp ( " core " , mirrorlog ) )
* new_log_count = 0 ;
else {
log_error ( " Unknown mirrorlog type: %s " , mirrorlog ) ;
return 0 ;
2009-04-23 20:56:21 +04:00
}
2007-08-21 23:46:36 +04:00
2010-08-02 23:03:45 +04:00
/*
* No mirrored logs for cluster mirrors until
* log daemon is multi - threaded .
*/
if ( ( * new_log_count = = 2 ) & & vg_is_clustered ( lv - > vg ) ) {
log_error ( " Log type, \" mirrored \" , is unavailable to cluster mirrors " ) ;
return 0 ;
}
2010-03-27 01:15:43 +03:00
log_verbose ( " Setting logging type to %s " , mirrorlog ) ;
2007-08-02 01:01:06 +04:00
/*
* Region size must not change on existing mirrors
*/
2005-11-29 21:20:23 +03:00
if ( arg_count ( cmd , regionsize_ARG ) & & ( lv - > status & MIRRORED ) & &
2010-03-27 01:15:43 +03:00
( lp - > region_size ! = first_seg ( lv ) - > region_size ) ) {
2005-11-29 21:20:23 +03:00
log_error ( " Mirror log region size cannot be changed on "
" an existing mirror. " ) ;
return 0 ;
}
2005-06-06 21:12:08 +04:00
2009-04-23 20:56:21 +04:00
/*
2009-05-19 14:27:47 +04:00
* For the most part , we cannot handle multi - segment mirrors . Bail out
* early if we have encountered one .
2009-04-23 20:56:21 +04:00
*/
2009-05-19 14:27:47 +04:00
if ( ( lv - > status & MIRRORED ) & & dm_list_size ( & lv - > segments ) ! = 1 ) {
2009-04-23 20:56:21 +04:00
log_error ( " Logical volume %s has multiple "
" mirror segments. " , lv - > name ) ;
return 0 ;
}
2009-04-30 00:11:46 +04:00
2010-03-27 01:15:43 +03:00
return 1 ;
}
2009-06-04 16:01:15 +04:00
2010-05-24 19:32:20 +04:00
2010-03-27 01:15:43 +03:00
/*
* _lvconvert_mirrors_aux
*
* Add / remove mirror images and adjust log type . ' operable_pvs '
* are the set of PVs open to removal or allocation - depending
* on the operation being performed .
*/
static int _lvconvert_mirrors_aux ( struct cmd_context * cmd ,
struct logical_volume * lv ,
struct lvconvert_params * lp ,
struct dm_list * operable_pvs ,
uint32_t new_mimage_count ,
2010-04-14 17:51:58 +04:00
uint32_t new_log_count )
2010-03-27 01:15:43 +03:00
{
uint32_t region_size ;
struct lv_segment * seg ;
struct logical_volume * layer_lv ;
uint32_t old_mimage_count = lv_mirror_count ( lv ) ;
uint32_t old_log_count = _get_log_count ( lv ) ;
if ( ( lp - > mirrors = = 1 ) & & ! ( lv - > status & MIRRORED ) ) {
2012-10-16 12:14:41 +04:00
log_warn ( " Logical volume %s is already not mirrored. " ,
lv - > name ) ;
2010-03-27 01:15:43 +03:00
return 1 ;
2007-08-02 00:54:28 +04:00
}
2010-03-27 01:15:43 +03:00
region_size = adjusted_mirror_region_size ( lv - > vg - > extent_size ,
lv - > le_count ,
lp - > region_size ) ;
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
2010-08-06 19:38:32 +04:00
if ( ! operable_pvs )
2010-03-27 01:15:43 +03:00
operable_pvs = lp - > pvh ;
This patch adds the capability to split off a mirror legs.
It is pretty much the same as reducing the number of
mirror legs, but we just don't delete them afterwards.
The following command line interface is enforced:
prompt> lvconvert --splitmirror <n> -n <name> <VG>/<LV>
where 'n' is the number of images to split off, and
where 'name' is the name of the newly split off logical volume.
If more than one leg is split off, a new mirror will be the
result. The newly split off mirror will have a 'core' log.
Example:
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_1(0),lv_mimage_2(0),lv_mimage_3(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_1] /dev/sdc1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mimage_3] /dev/sde1(0)
[lv_mlog] /dev/sdi1(0)
[root@bp-01 LVM2]# lvconvert --splitmirrors 2 --name split vg/lv /dev/sd[ce]1
Logical volume lv converted.
[root@bp-01 LVM2]# !lvs
lvs -a -o name,copy_percent,devices
LV Copy% Devices
lv 100.00 lv_mimage_0(0),lv_mimage_2(0)
[lv_mimage_0] /dev/sdb1(0)
[lv_mimage_2] /dev/sdd1(0)
[lv_mlog] /dev/sdi1(0)
split 100.00 split_mimage_0(0),split_mimage_1(0)
[split_mimage_0] /dev/sde1(0)
[split_mimage_1] /dev/sdc1(0)
It can be seen that '--splitmirror <n>' is exactly the same
as '--mirrors -<n>' (note the minus sign), except there is the
additional notion to keep the image being detached from the
mirror instead of just throwing it away.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
2010-01-09 01:00:31 +03:00
2010-03-27 01:15:43 +03:00
seg = first_seg ( lv ) ;
2009-04-30 00:11:46 +04:00
2010-03-27 01:15:43 +03:00
/*
* Up - convert from linear to mirror
*/
if ( ! ( lv - > status & MIRRORED ) ) {
2007-08-02 00:54:28 +04:00
/* FIXME Share code with lvcreate */
2009-04-23 20:56:21 +04:00
/*
* FIXME should we give not only lp - > pvh , but also all PVs
* currently taken by the mirror ? Would make more sense from
* user perspective .
*/
2010-04-13 05:54:32 +04:00
if ( ! lv_add_mirrors ( cmd , lv , new_mimage_count - 1 , lp - > stripes ,
lp - > stripe_size , region_size , new_log_count , operable_pvs ,
2012-01-26 02:38:40 +04:00
lp - > alloc , MIRROR_BY_LV ) )
return_0 ;
2008-01-15 00:11:47 +03:00
if ( lp - > wait_completion )
lp - > need_polling = 1 ;
2010-03-27 01:15:43 +03:00
goto out ;
}
/*
* Up - convert m - way mirror to n - way mirror
*/
if ( new_mimage_count > old_mimage_count ) {
2011-03-29 16:51:57 +04:00
if ( lv - > status & LV_NOTSYNCED ) {
2009-06-15 17:43:15 +04:00
log_error ( " Can't add mirror to out-of-sync mirrored "
" LV: use lvchange --resync first. " ) ;
2007-12-22 05:13:00 +03:00
return 0 ;
}
2009-10-26 13:01:56 +03:00
/*
* We allow snapshots of mirrors , but for now , we
* do not allow up converting mirrors that are under
* snapshots . The layering logic is somewhat complex ,
* and preliminary test show that the conversion can ' t
* seem to get the correct % ' age of completion .
*/
if ( lv_is_origin ( lv ) ) {
log_error ( " Can't add additional mirror images to "
" mirrors that are under snapshots " ) ;
2010-04-14 17:51:58 +04:00
return 0 ;
2009-10-26 13:01:56 +03:00
}
2010-04-21 18:04:24 +04:00
/*
* Is there already a convert in progress ? We do not
* currently allow more than one .
*/
if ( find_temporary_mirror ( lv ) | | ( lv - > status & CONVERTING ) ) {
log_error ( " %s is already being converted. Unable to start another conversion. " ,
lv - > name ) ;
return 0 ;
}
2008-01-10 21:35:51 +03:00
/*
* Log addition / removal should be done before the layer
* insertion to make the end result consistent with
* linear - to - mirror conversion .
*/
2010-03-27 01:15:43 +03:00
if ( ! _lv_update_log_type ( cmd , lp , lv ,
operable_pvs , new_log_count ) ) {
2010-01-08 16:04:10 +03:00
stack ;
2010-04-14 17:51:58 +04:00
return 0 ;
2010-01-08 16:04:10 +03:00
}
2010-03-27 01:15:43 +03:00
2008-01-10 21:35:51 +03:00
/* Insert a temporary layer for syncing,
* only if the original lv is using disk log . */
if ( seg - > log_lv & & ! _insert_lvconvert_layer ( cmd , lv ) ) {
2007-12-20 21:55:46 +03:00
log_error ( " Failed to insert resync layer " ) ;
return 0 ;
}
2010-03-27 01:15:43 +03:00
2008-01-10 21:35:51 +03:00
/* FIXME: can't have multiple mlogs. force corelog. */
2010-03-27 01:15:43 +03:00
if ( ! lv_add_mirrors ( cmd , lv ,
2011-01-11 20:05:08 +03:00
new_mimage_count - old_mimage_count ,
lp - > stripes , lp - > stripe_size ,
2010-03-27 01:15:43 +03:00
region_size , 0U , operable_pvs , lp - > alloc ,
2009-10-23 05:24:17 +04:00
MIRROR_BY_LV ) ) {
layer_lv = seg_lv ( first_seg ( lv ) , 0 ) ;
if ( ! remove_layer_from_lv ( lv , layer_lv ) | |
! deactivate_lv ( cmd , layer_lv ) | |
! lv_remove ( layer_lv ) | | ! vg_write ( lv - > vg ) | |
! vg_commit ( lv - > vg ) ) {
log_error ( " ABORTING: Failed to remove "
" temporary mirror layer %s. " ,
layer_lv - > name ) ;
log_error ( " Manual cleanup with vgcfgrestore "
" and dmsetup may be required. " ) ;
return 0 ;
}
2010-01-08 16:04:10 +03:00
stack ;
2010-04-14 17:51:58 +04:00
return 0 ;
2009-10-23 05:24:17 +04:00
}
2010-02-06 00:49:16 +03:00
if ( seg - > log_lv )
lv - > status | = CONVERTING ;
2008-01-15 00:11:47 +03:00
lp - > need_polling = 1 ;
2010-03-27 01:15:43 +03:00
goto out_skip_log_convert ;
2005-06-06 21:12:08 +04:00
}
2010-03-27 01:15:43 +03:00
/*
* Down - convert ( reduce # of mimages ) .
*/
if ( new_mimage_count < old_mimage_count ) {
uint32_t nmc = old_mimage_count - new_mimage_count ;
uint32_t nlc = ( ! new_log_count | | lp - > mirrors = = 1 ) ? 1U : 0U ;
2010-04-20 16:18:31 +04:00
/* FIXME: Why did nlc used to be calculated that way? */
2010-03-27 01:15:43 +03:00
/* Reduce number of mirrors */
if ( lp - > keep_mimages ) {
2011-08-18 23:38:26 +04:00
if ( arg_count ( cmd , trackchanges_ARG ) ) {
log_error ( " --trackchanges is not available "
" to 'mirror' segment type " ) ;
return 0 ;
}
2010-03-27 01:15:43 +03:00
if ( ! lv_split_mirror_images ( lv , lp - > lv_split_name ,
nmc , operable_pvs ) )
return 0 ;
} else if ( ! lv_remove_mirrors ( cmd , lv , nmc , nlc ,
2010-05-24 19:32:20 +04:00
is_mirror_image_removable , operable_pvs , 0 ) )
2010-03-27 01:15:43 +03:00
return_0 ;
goto out ; /* Just in case someone puts code between */
}
out :
/*
* Converting the log type
*/
2010-04-28 21:41:30 +04:00
if ( ( lv - > status & MIRRORED ) & & ( old_log_count ! = new_log_count ) ) {
2010-03-27 01:15:43 +03:00
if ( ! _lv_update_log_type ( cmd , lp , lv ,
operable_pvs , new_log_count ) ) {
stack ;
2010-04-14 17:51:58 +04:00
return 0 ;
2009-04-23 20:56:21 +04:00
}
}
2010-03-27 01:15:43 +03:00
out_skip_log_convert :
2012-08-02 13:38:07 +04:00
if ( ! _reload_lv ( cmd , lv - > vg , lv ) )
return_0 ;
2005-06-06 21:12:08 +04:00
2010-03-27 01:15:43 +03:00
return 1 ;
}
2011-05-07 17:56:13 +04:00
int mirror_remove_missing ( struct cmd_context * cmd ,
struct logical_volume * lv , int force )
{
struct dm_list * failed_pvs ;
int log_count = _get_log_count ( lv ) - _failed_logs_count ( lv ) ;
if ( ! ( failed_pvs = _failed_pv_list ( lv - > vg ) ) )
return_0 ;
if ( force & & _failed_mirrors_count ( lv ) = = lv_mirror_count ( lv ) ) {
log_error ( " No usable images left in %s. " , lv - > name ) ;
2012-03-02 01:14:43 +04:00
return lv_remove_with_dependencies ( cmd , lv , DONT_PROMPT , 0 ) ;
2011-05-07 17:56:13 +04:00
}
/*
* We must adjust the log first , or the entire mirror
* will get stuck during a suspend .
*/
if ( ! _lv_update_mirrored_log ( lv , failed_pvs , log_count ) )
return 0 ;
if ( _failed_mirrors_count ( lv ) > 0 & &
! lv_remove_mirrors ( cmd , lv , _failed_mirrors_count ( lv ) ,
log_count ? 0U : 1U ,
_is_partial_lv , NULL , 0 ) )
return 0 ;
2012-11-15 00:58:47 +04:00
if ( lv_is_mirrored ( lv ) & &
! _lv_update_log_type ( cmd , NULL , lv , failed_pvs , log_count ) )
2011-05-07 17:56:13 +04:00
return 0 ;
2012-08-02 13:38:07 +04:00
if ( ! _reload_lv ( cmd , lv - > vg , lv ) )
return_0 ;
2011-05-07 17:56:13 +04:00
return 1 ;
}
2010-03-27 01:15:43 +03:00
/*
* _lvconvert_mirrors_repair
*
* This function operates in two phases . First , all of the bad
* devices are removed from the mirror . Then , if desired by the
* user , the devices are replaced .
*
* ' old_mimage_count ' and ' old_log_count ' are there so we know
* what to convert to after the removal of devices .
*/
static int _lvconvert_mirrors_repair ( struct cmd_context * cmd ,
struct logical_volume * lv ,
2011-05-07 17:56:13 +04:00
struct lvconvert_params * lp )
2010-03-27 01:15:43 +03:00
{
2011-05-07 17:56:13 +04:00
int failed_logs = 0 ;
int failed_mimages = 0 ;
int replace_logs = 0 ;
int replace_mimages = 0 ;
uint32_t log_count ;
uint32_t original_mimages = lv_mirror_count ( lv ) ;
uint32_t original_logs = _get_log_count ( lv ) ;
2010-03-27 01:15:43 +03:00
cmd - > handles_missing_pvs = 1 ;
cmd - > partial_activation = 1 ;
lp - > need_polling = 0 ;
2010-05-24 19:32:20 +04:00
lv_check_transient ( lv ) ; /* TODO check this in lib for all commands? */
2010-03-27 01:15:43 +03:00
if ( ! ( lv - > status & PARTIAL_LV ) ) {
2012-10-16 12:14:41 +04:00
log_warn ( " %s is consistent. Nothing to repair. " , lv - > name ) ;
2010-03-27 01:15:43 +03:00
return 1 ;
}
2011-05-07 17:56:13 +04:00
failed_mimages = _failed_mirrors_count ( lv ) ;
failed_logs = _failed_logs_count ( lv ) ;
2010-03-27 01:15:43 +03:00
2011-05-07 17:56:13 +04:00
mirror_remove_missing ( cmd , lv , 0 ) ;
2010-03-27 01:15:43 +03:00
2011-05-07 17:56:13 +04:00
if ( failed_mimages )
2010-03-27 01:15:43 +03:00
log_error ( " Mirror status: %d of %d images failed. " ,
2011-05-07 17:56:13 +04:00
failed_mimages , original_mimages ) ;
2010-03-27 01:15:43 +03:00
/*
* Count the failed log devices
*/
2011-05-07 17:56:13 +04:00
if ( failed_logs )
log_error ( " Mirror log status: %d of %d images failed. " ,
failed_logs , original_logs ) ;
2010-03-27 01:15:43 +03:00
/*
* Find out our policies
*/
2011-05-07 17:56:13 +04:00
_lvconvert_mirrors_repair_ask ( cmd , failed_logs , failed_mimages ,
& replace_logs , & replace_mimages ) ;
2010-03-27 01:15:43 +03:00
/*
* Second phase - replace faulty devices
*/
2011-05-07 17:56:13 +04:00
lp - > mirrors = replace_mimages ? original_mimages : ( original_mimages - failed_mimages ) ;
2010-03-27 01:15:43 +03:00
2010-05-24 19:32:20 +04:00
/*
* It does not make sense to replace the log if the volume is no longer
* a mirror .
*/
2011-05-07 17:56:13 +04:00
if ( lp - > mirrors = = 1 )
replace_logs = 0 ;
2010-05-24 19:32:20 +04:00
2011-05-07 17:56:13 +04:00
log_count = replace_logs ? original_logs : ( original_logs - failed_logs ) ;
2010-04-14 17:51:58 +04:00
2011-05-07 17:56:13 +04:00
while ( replace_mimages | | replace_logs ) {
2010-04-14 17:51:58 +04:00
log_warn ( " Trying to up-convert to %d images, %d logs. " , lp - > mirrors , log_count ) ;
if ( _lvconvert_mirrors_aux ( cmd , lv , lp , NULL ,
lp - > mirrors , log_count ) )
break ;
else {
if ( lp - > mirrors > 2 )
- - lp - > mirrors ;
else if ( log_count > 0 )
- - log_count ;
else
break ; /* nowhere to go, anymore... */
}
2009-04-23 20:56:21 +04:00
}
2011-05-07 17:56:13 +04:00
if ( replace_mimages & & lv_mirror_count ( lv ) ! = original_mimages )
2010-04-14 17:51:58 +04:00
log_warn ( " WARNING: Failed to replace %d of %d images in volume %s " ,
2011-05-07 17:56:13 +04:00
original_mimages - lv_mirror_count ( lv ) , original_mimages , lv - > name ) ;
if ( replace_logs & & _get_log_count ( lv ) ! = original_logs )
2010-04-14 17:51:58 +04:00
log_warn ( " WARNING: Failed to replace %d of %d logs in volume %s " ,
2011-05-07 17:56:13 +04:00
original_logs - _get_log_count ( lv ) , original_logs , lv - > name ) ;
2010-04-14 17:51:58 +04:00
/* if (!arg_count(cmd, use_policies_ARG) && (lp->mirrors != old_mimage_count
| | log_count ! = old_log_count ) )
return 0 ; */
2010-03-27 01:15:43 +03:00
return 1 ;
}
/*
* _lvconvert_mirrors
*
* Determine what is being done . Are we doing a conversion , repair , or
* collapsing a stack ? Once determined , call helper functions .
*/
static int _lvconvert_mirrors ( struct cmd_context * cmd ,
struct logical_volume * lv ,
struct lvconvert_params * lp )
{
int repair = arg_count ( cmd , repair_ARG ) ;
uint32_t old_mimage_count ;
uint32_t old_log_count ;
uint32_t new_mimage_count ;
uint32_t new_log_count ;
2011-08-18 23:43:08 +04:00
if ( lp - > merge_mirror ) {
log_error ( " Unable to merge mirror images "
" of segment type 'mirror' " ) ;
return 0 ;
}
2012-10-05 13:06:08 +04:00
/* TODO: decide what should be done here */
if ( lv_is_thin_type ( lv ) ) {
log_error ( " Converting segment type for %s/%s to mirror is not yet supported. " ,
lv - > vg - > name , lv - > name ) ;
return 0 ;
}
2010-03-27 01:15:43 +03:00
/* Adjust mimage and/or log count */
if ( ! _lvconvert_mirrors_parse_params ( cmd , lv , lp ,
& old_mimage_count , & old_log_count ,
& new_mimage_count , & new_log_count ) )
return 0 ;
2010-11-25 20:15:46 +03:00
if ( ( ( old_mimage_count < new_mimage_count & & old_log_count > new_log_count ) | |
( old_mimage_count > new_mimage_count & & old_log_count < new_log_count ) ) & &
lp - > pv_count ) {
2011-01-06 02:18:46 +03:00
log_error ( " Cannot both allocate and free extents when "
" specifying physical volumes to use. " ) ;
2010-11-25 20:15:46 +03:00
log_error ( " Please specify the operation in two steps. " ) ;
return 0 ;
}
2010-03-27 01:15:43 +03:00
/* Nothing to do? (Probably finishing collapse.) */
if ( ( old_mimage_count = = new_mimage_count ) & &
( old_log_count = = new_log_count ) & & ! repair )
return 1 ;
if ( repair )
2011-05-07 17:56:13 +04:00
return _lvconvert_mirrors_repair ( cmd , lv , lp ) ;
2010-03-27 01:15:43 +03:00
if ( ! _lvconvert_mirrors_aux ( cmd , lv , lp , NULL ,
2010-04-14 17:51:58 +04:00
new_mimage_count , new_log_count ) )
2010-03-27 01:15:43 +03:00
return 0 ;
2008-01-15 00:11:47 +03:00
if ( ! lp - > need_polling )
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 converted. " , lv - > name ) ;
2005-06-06 21:12:08 +04:00
2009-04-21 18:31:57 +04:00
backup ( lv - > vg ) ;
2010-03-27 01:15:43 +03:00
return 1 ;
2005-06-06 21:12:08 +04:00
}
2011-08-11 22:24:40 +04:00
static int is_valid_raid_conversion ( const struct segment_type * from_segtype ,
const struct segment_type * to_segtype )
{
if ( from_segtype = = to_segtype )
return 1 ;
if ( ! segtype_is_raid ( from_segtype ) & & ! segtype_is_raid ( to_segtype ) )
return_0 ; /* Not converting to or from RAID? */
2011-10-07 18:52:26 +04:00
return 1 ;
2011-08-11 22:24:40 +04:00
}
2011-12-06 23:30:15 +04:00
static void _lvconvert_raid_repair_ask ( struct cmd_context * cmd , int * replace_dev )
{
const char * dev_policy = NULL ;
int force = arg_count ( cmd , force_ARG ) ;
int yes = arg_count ( cmd , yes_ARG ) ;
2012-12-11 12:52:54 +04:00
* replace_dev = 1 ;
2011-12-06 23:30:15 +04:00
if ( arg_count ( cmd , use_policies_ARG ) ) {
dev_policy = find_config_tree_str ( cmd , " activation/raid_fault_policy " , DEFAULT_RAID_FAULT_POLICY ) ;
if ( ! strcmp ( dev_policy , " allocate " ) | |
! strcmp ( dev_policy , " replace " ) )
2012-12-11 12:52:54 +04:00
return ;
/* else if (!strcmp(dev_policy, "anything_else")) -- no replace */
* replace_dev = 0 ;
2011-12-06 23:30:15 +04:00
return ;
}
2012-12-11 12:52:54 +04:00
if ( force ! = PROMPT ) {
* replace_dev = 0 ;
2011-12-06 23:30:15 +04:00
return ;
}
2012-12-11 12:52:54 +04:00
if ( yes )
2011-12-06 23:30:15 +04:00
return ;
if ( yes_no_prompt ( " Attempt to replace failed RAID images "
2012-12-11 12:52:54 +04:00
" (requires full device resync)? [y/n]: " ) = = ' n ' ) {
* replace_dev = 0 ;
2011-12-06 23:30:15 +04:00
}
}
2011-08-11 22:24:40 +04:00
static int lvconvert_raid ( struct logical_volume * lv , struct lvconvert_params * lp )
{
2011-12-06 23:30:15 +04:00
int replace = 0 ;
2011-12-08 22:00:03 +04:00
int uninitialized_var ( image_count ) ;
2011-12-06 23:30:15 +04:00
struct dm_list * failed_pvs ;
2011-08-11 22:24:40 +04:00
struct cmd_context * cmd = lv - > vg - > cmd ;
struct lv_segment * seg = first_seg ( lv ) ;
2012-12-19 00:40:42 +04:00
percent_t sync_percent ;
2011-08-11 22:24:40 +04:00
if ( ! arg_count ( cmd , type_ARG ) )
lp - > segtype = seg - > segtype ;
2011-10-07 18:52:26 +04:00
/* Can only change image count for raid1 and linear */
if ( arg_count ( cmd , mirrors_ARG ) & &
! seg_is_mirrored ( seg ) & & ! seg_is_linear ( seg ) ) {
2011-08-11 22:24:40 +04:00
log_error ( " '--mirrors/-m' is not compatible with %s " ,
2012-09-05 20:35:54 +04:00
seg - > segtype - > ops - > name ( seg ) ) ;
2011-08-11 22:24:40 +04:00
return 0 ;
}
if ( ! is_valid_raid_conversion ( seg - > segtype , lp - > segtype ) ) {
log_error ( " Unable to convert %s/%s from %s to %s " ,
lv - > vg - > name , lv - > name ,
2012-09-05 20:35:54 +04:00
seg - > segtype - > ops - > name ( seg ) , lp - > segtype - > name ) ;
2011-08-11 22:24:40 +04:00
return 0 ;
}
/* Change number of RAID1 images */
2011-08-18 23:34:18 +04:00
if ( arg_count ( cmd , mirrors_ARG ) | | arg_count ( cmd , splitmirrors_ARG ) ) {
2011-08-11 22:24:40 +04:00
image_count = lv_raid_image_count ( lv ) ;
if ( lp - > mirrors_sign = = SIGN_PLUS )
image_count + = lp - > mirrors ;
else if ( lp - > mirrors_sign = = SIGN_MINUS )
image_count - = lp - > mirrors ;
else
image_count = lp - > mirrors + 1 ;
if ( image_count < 1 ) {
2011-08-18 23:34:18 +04:00
log_error ( " Unable to %s images by specified amount " ,
arg_count ( cmd , splitmirrors_ARG ) ?
" split " : " reduce " ) ;
2011-08-11 22:24:40 +04:00
return 0 ;
}
}
2011-08-18 23:43:08 +04:00
if ( lp - > merge_mirror )
return lv_raid_merge ( lv ) ;
if ( arg_count ( cmd , trackchanges_ARG ) )
return lv_raid_split_and_track ( lv , lp - > pvh ) ;
if ( arg_count ( cmd , splitmirrors_ARG ) )
return lv_raid_split ( lv , lp - > lv_split_name ,
image_count , lp - > pvh ) ;
if ( arg_count ( cmd , mirrors_ARG ) )
return lv_raid_change_image_count ( lv , image_count , lp - > pvh ) ;
2011-10-07 18:56:01 +04:00
if ( arg_count ( cmd , type_ARG ) )
return lv_raid_reshape ( lv , lp - > segtype ) ;
2011-11-30 06:02:10 +04:00
if ( arg_count ( cmd , replace_ARG ) )
return lv_raid_replace ( lv , lp - > replace_pvh , lp - > pvh ) ;
2011-12-06 23:30:15 +04:00
if ( arg_count ( cmd , repair_ARG ) ) {
2012-12-19 00:40:42 +04:00
if ( ! lv_is_active ( lv ) ) {
log_error ( " %s/%s must be active to perform "
" this operation. " , lv - > vg - > name , lv - > name ) ;
return 0 ;
}
if ( ! lv_raid_percent ( lv , & sync_percent ) ) {
log_error ( " Unable to determine sync status of %s/%s. " ,
lv - > vg - > name , lv - > name ) ;
return 0 ;
}
if ( sync_percent ! = PERCENT_100 ) {
log_error ( " WARNING: %s/%s is not in-sync. " ,
lv - > vg - > name , lv - > name ) ;
log_error ( " WARNING: Portions of the array may "
" be unrecoverable. " ) ;
/*
* The kernel will not allow a device to be replaced
* in an array that is not in - sync unless we override
* by forcing the array to be considered " in-sync " .
*/
init_mirror_in_sync ( 1 ) ;
}
2011-12-06 23:30:15 +04:00
_lvconvert_raid_repair_ask ( cmd , & replace ) ;
if ( replace ) {
2012-02-22 19:20:50 +04:00
if ( ! ( failed_pvs = _failed_pv_list ( lv - > vg ) ) )
return_0 ;
2012-02-22 20:03:55 +04:00
if ( ! lv_raid_replace ( lv , failed_pvs , lp - > pvh ) ) {
log_error ( " Failed to replace faulty devices in "
" %s/%s. " , lv - > vg - > name , lv - > name ) ;
return 0 ;
}
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 ( " Faulty devices in %s/%s successfully "
" replaced. " , lv - > vg - > name , lv - > name ) ;
2012-02-22 20:03:55 +04:00
return 1 ;
2011-12-06 23:30:15 +04:00
}
/* "warn" if policy not set to replace */
if ( arg_count ( cmd , use_policies_ARG ) )
2012-10-16 12:14:41 +04:00
log_warn ( " Use 'lvconvert --repair %s/%s' to replace "
" failed device. " , lv - > vg - > name , lv - > name ) ;
2011-12-06 23:30:15 +04:00
return 1 ;
}
2011-08-11 22:24:40 +04:00
log_error ( " Conversion operation not yet supported. " ) ;
return 0 ;
}
2006-04-06 00:43:23 +04:00
static int lvconvert_snapshot ( struct cmd_context * cmd ,
struct logical_volume * lv ,
struct lvconvert_params * lp )
{
struct logical_volume * org ;
if ( ! ( org = find_lv ( lv - > vg , lp - > origin ) ) ) {
log_error ( " Couldn't find origin volume '%s'. " , lp - > origin ) ;
return 0 ;
}
2007-11-07 19:33:12 +03:00
if ( org = = lv ) {
log_error ( " Unable to use \" %s \" as both snapshot and origin. " ,
lv - > name ) ;
return 0 ;
}
2008-06-27 01:38:58 +04:00
if ( org - > status & ( LOCKED | PVMOVE | MIRRORED ) | | lv_is_cow ( org ) ) {
2011-06-01 16:24:15 +04:00
log_error ( " Unable to convert an LV into a snapshot of a %s LV. " ,
2006-04-06 00:43:23 +04:00
org - > status & LOCKED ? " locked " :
2008-06-27 01:38:58 +04:00
org - > status & PVMOVE ? " pvmove " :
org - > status & MIRRORED ? " mirrored " :
" snapshot " ) ;
2006-04-06 00:43:23 +04:00
return 0 ;
}
2007-01-10 17:13:46 +03:00
if ( ! lp - > zero | | ! ( lv - > status & LVM_WRITE ) )
2007-06-28 21:33:44 +04:00
log_warn ( " WARNING: \" %s \" not zeroed " , lv - > name ) ;
2007-08-22 18:38:18 +04:00
else if ( ! set_lv ( cmd , lv , UINT64_C ( 0 ) , 0 ) ) {
2007-08-02 00:54:28 +04:00
log_error ( " Aborting. Failed to wipe snapshot "
" exception store. " ) ;
return 0 ;
2006-04-06 00:43:23 +04:00
}
if ( ! deactivate_lv ( cmd , lv ) ) {
log_error ( " Couldn't deactivate LV %s. " , lv - > name ) ;
return 0 ;
}
2009-05-14 01:21:58 +04:00
if ( ! vg_add_snapshot ( org , lv , NULL , org - > le_count , lp - > chunk_size ) ) {
2006-04-06 00:43:23 +04:00
log_error ( " Couldn't create snapshot. " ) ;
return 0 ;
}
/* store vg on disk(s) */
2012-08-02 13:38:07 +04:00
if ( ! _reload_lv ( cmd , lv - > vg , lv ) )
2006-04-06 00:43:23 +04:00
return_0 ;
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 converted to snapshot. " , lv - > name ) ;
2012-08-02 13:38:07 +04:00
return 1 ;
2006-04-06 00:43:23 +04:00
}
2010-01-13 04:45:15 +03:00
static int lvconvert_merge ( struct cmd_context * cmd ,
struct logical_volume * lv ,
struct lvconvert_params * lp )
{
int r = 0 ;
2010-01-13 04:54:34 +03:00
int merge_on_activate = 0 ;
2010-01-13 04:45:15 +03:00
struct logical_volume * origin = origin_from_cow ( lv ) ;
struct lv_segment * cow_seg = find_cow ( lv ) ;
2010-01-13 04:47:18 +03:00
struct lvinfo info ;
2010-01-13 04:45:15 +03:00
/* Check if merge is possible */
2010-01-13 04:55:43 +03:00
if ( lv_is_merging_cow ( lv ) ) {
2010-01-13 04:45:15 +03:00
log_error ( " Snapshot %s is already merging " , lv - > name ) ;
return 0 ;
}
2010-01-13 04:55:43 +03:00
if ( lv_is_merging_origin ( origin ) ) {
2010-01-13 04:45:15 +03:00
log_error ( " Snapshot %s is already merging into the origin " ,
2010-01-13 04:55:43 +03:00
find_merging_cow ( origin ) - > cow - > name ) ;
2010-01-13 04:45:15 +03:00
return 0 ;
}
2010-01-13 04:47:18 +03:00
/*
* Prevent merge with open device ( s ) as it would likely lead
2010-01-13 04:54:34 +03:00
* to application / filesystem failure . Merge on origin ' s next
* activation if either the origin or snapshot LV are currently
* open .
2010-01-13 04:47:18 +03:00
*
* FIXME testing open_count is racey ; snapshot - merge target ' s
* constructor and DM should prevent appropriate devices from
* being open .
*/
2010-08-17 20:25:32 +04:00
if ( lv_info ( cmd , origin , 0 , & info , 1 , 0 ) ) {
2010-01-13 04:47:18 +03:00
if ( info . open_count ) {
log_error ( " Can't merge over open origin volume " ) ;
2010-01-13 04:54:34 +03:00
merge_on_activate = 1 ;
2010-01-13 04:47:18 +03:00
}
}
2010-08-17 20:25:32 +04:00
if ( lv_info ( cmd , lv , 0 , & info , 1 , 0 ) ) {
2010-01-13 04:47:18 +03:00
if ( info . open_count ) {
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 ( " Can't merge when snapshot is open " ) ;
2010-01-13 04:54:34 +03:00
merge_on_activate = 1 ;
2010-01-13 04:47:18 +03:00
}
}
2010-01-13 04:45:15 +03:00
init_snapshot_merge ( cow_seg , origin ) ;
/* store vg on disk(s) */
if ( ! vg_write ( lv - > vg ) )
return_0 ;
2010-01-13 04:54:34 +03:00
if ( merge_on_activate ) {
/* commit vg but skip starting the merge */
if ( ! vg_commit ( lv - > vg ) )
return_0 ;
r = 1 ;
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 ( " Merging of snapshot %s will start "
" next activation. " , lv - > name ) ;
2010-01-13 04:54:34 +03:00
goto out ;
}
2010-01-13 04:45:15 +03:00
/* Perform merge */
if ( ! suspend_lv ( cmd , origin ) ) {
log_error ( " Failed to suspend origin %s " , origin - > name ) ;
vg_revert ( lv - > vg ) ;
goto out ;
}
if ( ! vg_commit ( lv - > vg ) ) {
if ( ! resume_lv ( cmd , origin ) )
stack ;
goto_out ;
}
if ( ! resume_lv ( cmd , origin ) ) {
log_error ( " Failed to reactivate origin %s " , origin - > name ) ;
goto out ;
}
2010-01-13 04:49:52 +03:00
lp - > need_polling = 1 ;
lp - > lv_to_poll = origin ;
2010-01-13 04:45:15 +03:00
r = 1 ;
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 ( " Merging of volume %s started. " , lv - > name ) ;
2010-01-13 04:45:15 +03:00
out :
backup ( lv - > vg ) ;
return r ;
}
2012-05-14 15:57:30 +04:00
/*
* Thin lvconvert version which
* rename metadata
* convert / layers thinpool over data
* attach metadata
*/
2012-05-09 16:17:06 +04:00
static int _lvconvert_thinpool ( struct cmd_context * cmd ,
2012-05-14 15:57:30 +04:00
struct logical_volume * pool_lv ,
2012-05-09 16:17:06 +04:00
struct lvconvert_params * lp )
{
int r = 0 ;
char * name ;
2012-12-02 19:40:07 +04:00
const char * old_name ;
2012-05-09 16:17:06 +04:00
int len ;
struct lv_segment * seg ;
struct logical_volume * data_lv ;
2012-05-14 15:57:30 +04:00
struct logical_volume * metadata_lv ;
2012-12-02 19:40:07 +04:00
struct logical_volume * pool_metadata_lv ;
2012-05-14 15:57:30 +04:00
2012-11-19 16:37:57 +04:00
if ( ! lv_is_visible ( pool_lv ) ) {
log_error ( " Can't convert internal LV %s/%s. " ,
pool_lv - > vg - > name , pool_lv - > name ) ;
return 0 ;
}
2012-12-02 19:40:07 +04:00
if ( lv_is_thin_type ( pool_lv ) & & ! lp - > pool_metadata_lv_name ) {
2012-05-14 15:57:30 +04:00
log_error ( " Can't use thin logical volume %s/%s for thin pool data. " ,
pool_lv - > vg - > name , pool_lv - > name ) ;
return 0 ;
}
2012-05-09 16:17:06 +04:00
2012-05-14 15:57:30 +04:00
/* We are changing target type, so deactivate first */
if ( ! deactivate_lv ( cmd , pool_lv ) ) {
2012-12-02 19:23:44 +04:00
log_error ( " Aborting. Failed to deactivate logical volume %s/%s. " ,
2012-05-14 15:57:30 +04:00
pool_lv - > vg - > name , pool_lv - > name ) ;
2012-06-05 16:55:00 +04:00
return 0 ;
2012-05-09 16:17:06 +04:00
}
2012-11-19 16:37:57 +04:00
len = strlen ( pool_lv - > name ) + 16 ;
if ( ! ( name = dm_pool_alloc ( pool_lv - > vg - > vgmem , len ) ) ) {
log_error ( " Can't allocate new name. " ) ;
return 0 ;
}
2012-12-02 19:23:44 +04:00
if ( dm_snprintf ( name , len , " %s_tmeta " , pool_lv - > name ) < 0 ) {
log_error ( " Failed to create layer name. " ) ;
return 0 ;
}
2012-11-19 16:37:57 +04:00
2012-05-14 15:57:30 +04:00
if ( lp - > pool_metadata_lv_name ) {
2012-11-19 16:37:57 +04:00
if ( arg_count ( cmd , stripesize_ARG ) | | arg_count ( cmd , stripes_long_ARG ) ) {
log_error ( " Can't use --stripes and --stripesize with --poolmetadata. " ) ;
return 0 ;
}
if ( arg_count ( cmd , readahead_ARG ) ) {
log_error ( " Can't use --readahead with --poolmetadata. " ) ;
return 0 ;
}
2012-05-14 15:57:30 +04:00
metadata_lv = find_lv ( pool_lv - > vg , lp - > pool_metadata_lv_name ) ;
if ( ! metadata_lv ) {
2012-11-19 16:37:57 +04:00
log_error ( " Unknown metadata LV %s. " , lp - > pool_metadata_lv_name ) ;
return 0 ;
}
if ( ! lv_is_visible ( metadata_lv ) ) {
log_error ( " Can't convert internal LV %s/%s. " ,
metadata_lv - > vg - > name , metadata_lv - > name ) ;
return 0 ;
}
if ( metadata_lv - > status & LOCKED ) {
log_error ( " Can't convert locked LV %s/%s. " ,
metadata_lv - > vg - > name , metadata_lv - > name ) ;
2012-05-14 15:57:30 +04:00
return 0 ;
2012-05-09 16:17:06 +04:00
}
2012-05-14 15:57:30 +04:00
if ( metadata_lv = = pool_lv ) {
2012-11-19 16:37:57 +04:00
log_error ( " Can't use same LV for thin pool data and metadata LV %s. " ,
2012-05-14 15:57:30 +04:00
lp - > pool_metadata_lv_name ) ;
return 0 ;
2012-05-09 16:17:06 +04:00
}
2012-05-14 15:57:30 +04:00
if ( lv_is_thin_type ( metadata_lv ) ) {
log_error ( " Can't use thin pool logical volume %s/%s "
" for thin pool metadata. " ,
2012-05-09 16:17:06 +04:00
metadata_lv - > vg - > name , metadata_lv - > name ) ;
2012-05-14 15:57:30 +04:00
return 0 ;
2012-05-09 16:17:06 +04:00
}
2012-12-02 19:40:07 +04:00
/* Swap normal LV with pool's metadata LV ? */
if ( lv_is_thin_pool ( pool_lv ) ) {
if ( ! deactivate_lv ( cmd , metadata_lv ) ) {
log_error ( " Aborting. Failed to deactivate thin metadata lv. " ) ;
return 0 ;
}
if ( ! arg_count ( cmd , yes_ARG ) & &
yes_no_prompt ( " Do you want to swap metadata of %s/%s pool with "
" volume %s/%s? [y/n]: " ,
pool_lv - > vg - > name , pool_lv - > name ,
pool_lv - > vg - > name , metadata_lv - > name ) = = ' n ' ) {
log_error ( " Conversion aborted. " ) ;
return 0 ;
}
seg = first_seg ( pool_lv ) ;
/* Swap names between old and new metadata LV */
if ( ! detach_pool_metadata_lv ( seg , & pool_metadata_lv ) )
return_0 ;
old_name = metadata_lv - > name ;
if ( ! lv_rename_update ( cmd , metadata_lv , " pvmove_tmeta " , 0 ) )
return_0 ;
if ( ! lv_rename_update ( cmd , pool_metadata_lv , old_name , 0 ) )
return_0 ;
if ( ! arg_count ( cmd , chunksize_ARG ) )
lp - > chunk_size = seg - > chunk_size ;
else if ( ( lp - > chunk_size ! = seg - > chunk_size ) & &
! arg_count ( cmd , force_ARG ) & &
yes_no_prompt ( " Do you really want to change chunk size %s to %s for %s/%s "
" pool volume? [y/n]: " , display_size ( cmd , seg - > chunk_size ) ,
display_size ( cmd , lp - > chunk_size ) ,
pool_lv - > vg - > name , pool_lv - > name ) = = ' n ' ) {
log_error ( " Conversion aborted. " ) ;
return 0 ;
}
if ( ! arg_count ( cmd , discards_ARG ) )
lp - > discards = seg - > discards ;
if ( ! arg_count ( cmd , zero_ARG ) )
lp - > zero = seg - > zero_new_blocks ;
goto mda_write ;
}
2012-11-19 16:37:57 +04:00
if ( ! lv_is_active ( metadata_lv ) & &
! activate_lv_local ( cmd , metadata_lv ) ) {
2012-12-02 19:23:44 +04:00
log_error ( " Aborting. Failed to activate thin metadata lv. " ) ;
return 0 ;
2012-11-19 16:37:57 +04:00
}
if ( ! set_lv ( cmd , metadata_lv , UINT64_C ( 0 ) , 0 ) ) {
log_error ( " Aborting. Failed to wipe thin metadata lv. " ) ;
2012-05-14 15:57:30 +04:00
return 0 ;
}
2012-11-19 16:37:57 +04:00
lp - > poolmetadata_size =
( uint64_t ) metadata_lv - > le_count * metadata_lv - > vg - > extent_size ;
if ( lp - > poolmetadata_size > ( 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE ) ) {
log_warn ( " WARNING: Maximum size used by metadata is %s, rest is unused. " ,
display_size ( cmd , 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE ) ) ;
lp - > poolmetadata_size = 2 * DEFAULT_THIN_POOL_MAX_METADATA_SIZE ;
} else if ( lp - > poolmetadata_size < ( 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE ) ) {
log_error ( " Logical volume %s/%s is too small (<%s) for metadata. " ,
metadata_lv - > vg - > name , metadata_lv - > name ,
display_size ( cmd , 2 * DEFAULT_THIN_POOL_MIN_METADATA_SIZE ) ) ;
2012-05-14 15:57:30 +04:00
return 0 ;
2012-05-09 16:17:06 +04:00
}
2012-11-19 16:37:57 +04:00
if ( ! update_pool_params ( cmd , lp - > target_attr ,
pool_lv - > le_count , pool_lv - > vg - > extent_size ,
& lp - > chunk_size , & lp - > discards ,
& lp - > poolmetadata_size ) )
return_0 ;
} else {
if ( ! update_pool_params ( cmd , lp - > target_attr ,
pool_lv - > le_count , pool_lv - > vg - > extent_size ,
& lp - > chunk_size , & lp - > discards ,
& lp - > poolmetadata_size ) )
return_0 ;
2012-05-09 16:17:06 +04:00
2012-11-19 16:37:57 +04:00
if ( ! get_stripe_params ( cmd , & lp - > stripes , & lp - > stripe_size ) )
return_0 ;
/* Hmm _read_activation_params */
lp - > read_ahead = arg_uint_value ( cmd , readahead_ARG ,
cmd - > default_settings . read_ahead ) ;
if ( ! ( metadata_lv = alloc_pool_metadata ( pool_lv , lp - > alloc , name ,
lp - > pvh , lp - > read_ahead ,
lp - > stripes , lp - > stripe_size ,
lp - > poolmetadata_size ) ) )
return_0 ;
2012-05-14 15:57:30 +04:00
}
if ( ! deactivate_lv ( cmd , metadata_lv ) ) {
log_error ( " Aborting. Failed to deactivate thin metadata lv. "
" Manual intervention required. " ) ;
return 0 ;
}
/*
* Since we wish to have underlaying dev , to match _tdata
* rename data LV first , also checks for visible LV
*/
/* FIXME: any more types prohibited here? */
/* FIXME: revert renamed LVs in fail path? */
2012-05-09 16:17:06 +04:00
/* FIXME: common code with metadata/thin_manip.c extend_pool() */
2012-05-14 15:57:30 +04:00
/* Create layer _tdata */
2012-05-09 16:17:06 +04:00
if ( ! ( data_lv = insert_layer_for_lv ( pool_lv - > vg - > cmd , pool_lv ,
pool_lv - > status , " _tdata " ) ) )
return_0 ;
seg = first_seg ( pool_lv ) ;
seg - > segtype = lp - > segtype ;
seg - > lv - > status | = THIN_POOL ;
2012-12-02 19:27:39 +04:00
/* Drop reference as attach_pool_data_lv() takes it again */
remove_seg_from_segs_using_this_lv ( data_lv , seg ) ;
if ( ! attach_pool_data_lv ( seg , data_lv ) )
return_0 ;
2012-05-09 16:17:06 +04:00
seg - > low_water_mark = 0 ;
2012-05-14 15:57:30 +04:00
seg - > transaction_id = 0 ;
2012-12-02 19:40:07 +04:00
mda_write :
2012-12-02 19:27:39 +04:00
seg - > chunk_size = lp - > chunk_size ;
seg - > discards = lp - > discards ;
seg - > zero_new_blocks = lp - > zero ? 1 : 0 ;
2012-05-09 16:17:06 +04:00
2012-12-02 19:27:39 +04:00
/* Rename deactivated metadata LV to have _tmeta suffix */
/* Implicit checks if metadata_lv is visible */
if ( strcmp ( metadata_lv - > name , name ) & &
! lv_rename_update ( cmd , metadata_lv , name , 0 ) )
2012-05-09 16:17:06 +04:00
return_0 ;
2012-12-02 19:27:39 +04:00
if ( ! attach_pool_metadata_lv ( seg , metadata_lv ) )
2012-05-09 16:17:06 +04:00
return_0 ;
if ( ! vg_write ( pool_lv - > vg ) | | ! vg_commit ( pool_lv - > vg ) )
return_0 ;
2012-05-14 15:57:30 +04:00
if ( ! activate_lv_excl ( cmd , pool_lv ) ) {
2012-05-09 16:17:06 +04:00
log_error ( " Failed to activate pool logical volume %s/%s. " ,
pool_lv - > vg - > name , pool_lv - > name ) ;
2012-12-02 19:31:27 +04:00
/* Deactivate subvolumes */
if ( ! deactivate_lv ( cmd , seg_lv ( seg , 0 ) ) )
log_error ( " Failed to deactivate pool data logical volume. " ) ;
if ( ! deactivate_lv ( cmd , seg - > metadata_lv ) )
log_error ( " Failed to deactivate pool metadata logical volume. " ) ;
2012-05-09 16:17:06 +04:00
goto out ;
}
2012-05-14 15:57:30 +04:00
log_print_unless_silent ( " Converted %s/%s to thin pool. " ,
pool_lv - > vg - > name , pool_lv - > name ) ;
2012-05-09 16:17:06 +04:00
r = 1 ;
out :
backup ( pool_lv - > vg ) ;
return r ;
}
2010-02-06 01:44:37 +03:00
static int _lvconvert_single ( struct cmd_context * cmd , struct logical_volume * lv ,
void * handle )
2005-06-06 21:12:08 +04:00
{
struct lvconvert_params * lp = handle ;
2011-05-07 17:56:13 +04:00
struct dm_list * failed_pvs ;
2012-01-21 02:03:48 +04:00
struct lvinfo info ;
percent_t snap_percent ;
2005-06-06 21:12:08 +04:00
if ( lv - > status & LOCKED ) {
log_error ( " Cannot convert locked LV %s " , lv - > name ) ;
return ECMD_FAILED ;
}
2010-01-13 04:45:15 +03:00
if ( lv_is_cow ( lv ) & & ! lp - > merge ) {
2005-06-06 21:12:08 +04:00
log_error ( " Can't convert snapshot logical volume \" %s \" " ,
lv - > name ) ;
return ECMD_FAILED ;
}
if ( lv - > status & PVMOVE ) {
log_error ( " Unable to convert pvmove LV %s " , lv - > name ) ;
return ECMD_FAILED ;
}
2012-02-22 21:18:49 +04:00
if ( arg_count ( cmd , repair_ARG ) & &
! ( lv - > status & MIRRORED ) & & ! ( lv - > status & RAID ) ) {
2010-02-06 10:44:16 +03:00
if ( arg_count ( cmd , use_policies_ARG ) )
return ECMD_PROCESSED ; /* nothing to be done here */
2009-06-10 19:27:57 +04:00
log_error ( " Can't repair non-mirrored LV \" %s \" . " , lv - > name ) ;
return ECMD_FAILED ;
}
2011-11-30 06:02:10 +04:00
if ( ! lp - > segtype )
lp - > segtype = first_seg ( lv ) - > segtype ;
2010-01-13 04:45:15 +03:00
if ( lp - > merge ) {
if ( ! lv_is_cow ( lv ) ) {
2012-04-20 01:50:37 +04:00
log_error ( " \" %s \" is not a mergeable logical volume " ,
2010-01-13 04:45:15 +03:00
lv - > name ) ;
return ECMD_FAILED ;
}
2013-02-05 17:03:43 +04:00
if ( lv_is_external_origin ( origin_from_cow ( lv ) ) ) {
log_error ( " Cannot merge snapshot \" %s \" into "
" the read-only external origin \" %s \" . " ,
lv - > name , origin_from_cow ( lv ) - > name ) ;
return ECMD_FAILED ;
}
2012-01-21 02:03:48 +04:00
if ( lv_info ( lv - > vg - > cmd , lv , 0 , & info , 1 , 0 )
& & info . exists & & info . live_table & &
( ! lv_snapshot_percent ( lv , & snap_percent ) | |
snap_percent = = PERCENT_INVALID ) ) {
log_error ( " Unable to merge invalidated snapshot LV \" %s \" " , lv - > name ) ;
return ECMD_FAILED ;
}
2010-01-13 04:45:15 +03:00
if ( ! archive ( lv - > vg ) ) {
stack ;
return ECMD_FAILED ;
}
if ( ! lvconvert_merge ( cmd , lv , lp ) ) {
2010-11-28 21:37:33 +03:00
log_error ( " Unable to merge LV \" %s \" into its origin. " , lv - > name ) ;
2010-01-13 04:45:15 +03:00
return ECMD_FAILED ;
}
} else if ( lp - > snapshot ) {
2008-06-27 01:38:58 +04:00
if ( lv - > status & MIRRORED ) {
log_error ( " Unable to convert mirrored LV \" %s \" into a snapshot. " , lv - > name ) ;
return ECMD_FAILED ;
}
2009-09-15 02:47:49 +04:00
if ( ! archive ( lv - > vg ) ) {
stack ;
2005-06-06 21:12:08 +04:00
return ECMD_FAILED ;
2009-09-15 02:47:49 +04:00
}
if ( ! lvconvert_snapshot ( cmd , lv , lp ) ) {
stack ;
2005-06-06 21:12:08 +04:00
return ECMD_FAILED ;
2009-09-15 02:47:49 +04:00
}
2012-05-14 15:57:30 +04:00
} else if ( arg_count ( cmd , thinpool_ARG ) ) {
if ( ! archive ( lv - > vg ) ) {
stack ;
return ECMD_FAILED ;
}
if ( ! _lvconvert_thinpool ( cmd , lv , lp ) ) {
stack ;
return ECMD_FAILED ;
}
2011-08-18 23:43:08 +04:00
} else if ( segtype_is_raid ( lp - > segtype ) | |
( lv - > status & RAID ) | | lp - > merge_mirror ) {
2011-08-11 22:24:40 +04:00
if ( ! archive ( lv - > vg ) ) {
stack ;
return ECMD_FAILED ;
}
if ( ! lvconvert_raid ( lv , lp ) ) {
stack ;
return ECMD_FAILED ;
}
if ( ! ( failed_pvs = _failed_pv_list ( lv - > vg ) ) ) {
stack ;
return ECMD_FAILED ;
}
/* If repairing and using policies, remove missing PVs from VG */
if ( arg_count ( cmd , repair_ARG ) & & arg_count ( cmd , use_policies_ARG ) )
_remove_missing_empty_pv ( lv - > vg , failed_pvs ) ;
2010-07-14 01:53:07 +04:00
} else if ( arg_count ( cmd , mirrors_ARG ) | |
arg_count ( cmd , splitmirrors_ARG ) | |
( lv - > status & MIRRORED ) ) {
2009-09-15 02:47:49 +04:00
if ( ! archive ( lv - > vg ) ) {
stack ;
2006-04-06 00:43:23 +04:00
return ECMD_FAILED ;
2009-09-15 02:47:49 +04:00
}
if ( ! _lvconvert_mirrors ( cmd , lv , lp ) ) {
stack ;
2006-04-06 00:43:23 +04:00
return ECMD_FAILED ;
2009-09-15 02:47:49 +04:00
}
2010-01-08 16:04:10 +03:00
2011-05-07 17:56:13 +04:00
if ( ! ( failed_pvs = _failed_pv_list ( lv - > vg ) ) ) {
stack ;
return ECMD_FAILED ;
}
2010-01-08 16:04:10 +03:00
/* If repairing and using policies, remove missing PVs from VG */
if ( arg_count ( cmd , repair_ARG ) & & arg_count ( cmd , use_policies_ARG ) )
2011-05-07 17:56:13 +04:00
_remove_missing_empty_pv ( lv - > vg , failed_pvs ) ;
2005-06-06 21:12:08 +04:00
}
return ECMD_PROCESSED ;
}
2010-02-06 01:44:37 +03:00
/*
* FIXME move to toollib along with the rest of the drop / reacquire
* VG locking that is used by lvconvert_merge_single ( )
*/
static struct logical_volume * get_vg_lock_and_logical_volume ( struct cmd_context * cmd ,
const char * vg_name ,
const char * lv_name )
2005-06-06 21:12:08 +04:00
{
2010-02-06 01:44:37 +03:00
/*
* Returns NULL if the requested LV doesn ' t exist ;
2011-08-11 00:25:29 +04:00
* otherwise the caller must release_vg ( lv - > vg )
2010-02-06 01:44:37 +03:00
* - it is also up to the caller to unlock_vg ( ) as needed
*/
2005-06-06 21:12:08 +04:00
struct volume_group * vg ;
2010-02-06 01:44:37 +03:00
struct logical_volume * lv = NULL ;
vg = _get_lvconvert_vg ( cmd , vg_name , NULL ) ;
if ( vg_read_error ( vg ) ) {
2011-08-11 00:25:29 +04:00
release_vg ( vg ) ;
2010-04-26 22:31:58 +04:00
return_NULL ;
2010-02-06 01:44:37 +03:00
}
if ( ! ( lv = _get_lvconvert_lv ( cmd , vg , lv_name , NULL , 0 ) ) ) {
2010-04-26 22:31:58 +04:00
log_error ( " Can't find LV %s in VG %s " , lv_name , vg_name ) ;
2011-08-11 00:25:29 +04:00
unlock_and_release_vg ( cmd , vg , vg_name ) ;
2010-02-06 01:44:37 +03:00
return NULL ;
}
return lv ;
}
static int poll_logical_volume ( struct cmd_context * cmd , struct logical_volume * lv ,
int wait_completion )
{
2008-01-10 21:35:51 +03:00
struct lvinfo info ;
2005-06-06 21:12:08 +04:00
2011-02-03 04:24:46 +03:00
if ( ! lv_info ( cmd , lv , 0 , & info , 0 , 0 ) | | ! info . exists ) {
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 ( " Conversion starts after activation. " ) ;
2010-02-06 01:44:37 +03:00
return ECMD_PROCESSED ;
2005-06-06 21:12:08 +04:00
}
2010-02-06 01:44:37 +03:00
return lvconvert_poll ( cmd , lv , wait_completion ? 0 : 1U ) ;
}
static int lvconvert_single ( struct cmd_context * cmd , struct lvconvert_params * lp )
{
2010-02-06 01:47:22 +03:00
struct logical_volume * lv = NULL ;
2010-02-06 01:44:37 +03:00
int ret = ECMD_FAILED ;
int saved_ignore_suspended_devices = ignore_suspended_devices ( ) ;
2005-06-06 21:12:08 +04:00
2009-07-15 09:47:55 +04:00
if ( arg_count ( cmd , repair_ARG ) ) {
2009-06-15 18:47:39 +04:00
init_ignore_suspended_devices ( 1 ) ;
2009-07-15 09:47:55 +04:00
cmd - > handles_missing_pvs = 1 ;
}
2009-06-15 18:47:39 +04:00
2010-02-06 01:47:22 +03:00
lv = get_vg_lock_and_logical_volume ( cmd , lp - > vg_name , lp - > lv_name ) ;
if ( ! lv )
goto_out ;
2005-06-06 21:12:08 +04:00
2010-04-26 22:12:40 +04:00
/*
* lp - > pvh holds the list of PVs available for allocation or removal
*/
2010-02-06 01:44:37 +03:00
if ( lp - > pv_count ) {
2010-02-06 01:47:22 +03:00
if ( ! ( lp - > pvh = create_pv_list ( cmd - > mem , lv - > vg , lp - > pv_count ,
2010-02-06 01:44:37 +03:00
lp - > pvs , 0 ) ) )
2008-01-30 16:19:47 +03:00
goto_bad ;
2005-06-06 21:12:08 +04:00
} else
2010-02-06 01:47:22 +03:00
lp - > pvh = & lv - > vg - > pvs ;
2005-06-06 21:12:08 +04:00
2011-11-30 06:02:10 +04:00
if ( lp - > replace_pv_count & &
! ( lp - > replace_pvh = create_pv_list ( cmd - > mem , lv - > vg ,
lp - > replace_pv_count ,
lp - > replace_pvs , 0 ) ) )
goto_bad ;
2010-02-06 01:47:22 +03:00
lp - > lv_to_poll = lv ;
ret = _lvconvert_single ( cmd , lv , lp ) ;
2008-01-30 16:19:47 +03:00
bad :
2010-02-06 01:44:37 +03:00
unlock_vg ( cmd , lp - > vg_name ) ;
2007-12-22 15:13:29 +03:00
2010-02-06 01:44:37 +03:00
if ( ret = = ECMD_PROCESSED & & lp - > need_polling )
ret = poll_logical_volume ( cmd , lp - > lv_to_poll ,
lp - > wait_completion ) ;
2010-02-06 01:47:22 +03:00
2011-08-11 00:25:29 +04:00
release_vg ( lv - > vg ) ;
2009-04-10 14:01:38 +04:00
out :
2009-06-15 18:47:39 +04:00
init_ignore_suspended_devices ( saved_ignore_suspended_devices ) ;
2005-06-06 21:12:08 +04:00
return ret ;
}
2010-02-06 01:44:37 +03:00
static int lvconvert_merge_single ( struct cmd_context * cmd , struct logical_volume * lv ,
void * handle )
{
struct lvconvert_params * lp = handle ;
const char * vg_name = NULL ;
struct logical_volume * refreshed_lv = NULL ;
int ret ;
/*
* FIXME can ' t trust lv ' s VG to be current given that caller
* is process_each_lv ( ) - - poll_logical_volume ( ) may have
* already updated the VG ' s metadata in an earlier iteration .
* - preemptively drop the VG lock , as is needed for
* poll_logical_volume ( ) , refresh LV ( and VG in the process ) .
*/
vg_name = lv - > vg - > name ;
unlock_vg ( cmd , vg_name ) ;
refreshed_lv = get_vg_lock_and_logical_volume ( cmd , vg_name , lv - > name ) ;
2010-04-26 22:31:58 +04:00
if ( ! refreshed_lv ) {
log_error ( " ABORTING: Can't reread LV %s/%s " , vg_name , lv - > name ) ;
2010-02-06 01:44:37 +03:00
return ECMD_FAILED ;
2010-04-26 22:31:58 +04:00
}
2010-02-06 01:44:37 +03:00
lp - > lv_to_poll = refreshed_lv ;
ret = _lvconvert_single ( cmd , refreshed_lv , lp ) ;
if ( ret = = ECMD_PROCESSED & & lp - > need_polling ) {
/*
* Must drop VG lock , because lvconvert_poll ( ) needs it ,
* then reacquire it after polling completes
*/
unlock_vg ( cmd , vg_name ) ;
ret = poll_logical_volume ( cmd , lp - > lv_to_poll ,
lp - > wait_completion ) ;
/* use LCK_VG_WRITE to match lvconvert()'s READ_FOR_UPDATE */
if ( ! lock_vol ( cmd , vg_name , LCK_VG_WRITE ) ) {
log_error ( " ABORTING: Can't relock VG for %s "
" after polling finished " , vg_name ) ;
ret = ECMD_FAILED ;
}
}
2011-08-11 00:25:29 +04:00
release_vg ( refreshed_lv - > vg ) ;
2010-02-06 01:44:37 +03:00
return ret ;
}
int lvconvert ( struct cmd_context * cmd , int argc , char * * argv )
{
struct lvconvert_params lp ;
if ( ! _read_params ( & lp , cmd , argc , argv ) ) {
stack ;
return EINVALID_CMD_LINE ;
}
2010-08-04 00:22:31 +04:00
if ( lp . merge ) {
if ( ! argc ) {
log_error ( " Please provide logical volume path " ) ;
return EINVALID_CMD_LINE ;
}
2010-02-06 01:44:37 +03:00
return process_each_lv ( cmd , argc , argv , READ_FOR_UPDATE , & lp ,
& lvconvert_merge_single ) ;
2010-08-04 00:22:31 +04:00
}
2010-02-06 01:44:37 +03:00
return lvconvert_single ( cmd , & lp ) ;
}