2015-03-12 18:23:19 +03:00
/*
2015-04-16 18:31:07 +03:00
* Copyright ( C ) 2005 - 2015 Red Hat , Inc . All rights reserved .
2015-03-12 18:23:19 +03: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
* of the GNU Lesser General Public License v .2 .1 .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
# include "tools.h"
2015-07-06 19:30:18 +03:00
# include "lvconvert_poll.h"
2015-03-12 18:23:19 +03:00
int lvconvert_mirror_finish ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct logical_volume * lv ,
struct dm_list * lvs_changed __attribute__ ( ( unused ) ) )
{
if ( ! lv_is_converting ( lv ) )
return 1 ;
if ( ! collapse_mirrored_lv ( lv ) ) {
log_error ( " Failed to remove temporary sync layer. " ) ;
return 0 ;
}
lv - > status & = ~ CONVERTING ;
if ( ! lv_update_and_reload ( lv ) )
return_0 ;
log_print_unless_silent ( " Logical volume %s converted. " , lv - > name ) ;
return 1 ;
}
/* Swap lvid and LV names */
int swap_lv_identifiers ( struct cmd_context * cmd ,
struct logical_volume * a , struct logical_volume * b )
{
union lvid lvid ;
2015-09-11 21:56:53 +03:00
const char * aname = a - > name , * bname = b - > name ;
2015-03-12 18:23:19 +03:00
lvid = a - > lvid ;
a - > lvid = b - > lvid ;
b - > lvid = lvid ;
2015-09-11 21:56:53 +03:00
/* rename temporarily to 'unused' name */
if ( ! lv_rename_update ( cmd , a , " pmove_tmeta " , 0 ) )
return_0 ;
/* name rename 'b' to unused name of 'a' */
if ( ! lv_rename_update ( cmd , b , aname , 0 ) )
return_0 ;
/* finish name swapping */
if ( ! lv_rename_update ( cmd , a , bname , 0 ) )
2015-03-12 18:23:19 +03:00
return_0 ;
return 1 ;
}
static void _move_lv_attributes ( struct logical_volume * to , struct logical_volume * from )
{
/* Maybe move this code into thin_merge_finish() */
to - > status = from - > status ; // FIXME maybe some masking ?
to - > alloc = from - > alloc ;
to - > profile = from - > profile ;
to - > read_ahead = from - > read_ahead ;
to - > major = from - > major ;
to - > minor = from - > minor ;
to - > timestamp = from - > timestamp ;
to - > hostname = from - > hostname ;
/* Move tags */
dm_list_init ( & to - > tags ) ;
dm_list_splice ( & to - > tags , & from - > tags ) ;
/* Anything else to preserve? */
}
/* Finalise merging of lv into merge_lv */
int thin_merge_finish ( struct cmd_context * cmd ,
struct logical_volume * merge_lv ,
struct logical_volume * lv )
{
if ( ! swap_lv_identifiers ( cmd , merge_lv , lv ) ) {
log_error ( " Failed to swap %s with merging %s. " ,
lv - > name , merge_lv - > name ) ;
return 0 ;
}
/* Preserve origins' attributes */
_move_lv_attributes ( lv , merge_lv ) ;
/* Removed LV has to be visible */
if ( ! lv_remove_single ( cmd , merge_lv , DONT_PROMPT , 1 ) )
return_0 ;
return 1 ;
}
int lvconvert_merge_finish ( struct cmd_context * cmd ,
struct volume_group * vg ,
struct logical_volume * lv ,
struct dm_list * lvs_changed __attribute__ ( ( unused ) ) )
{
struct lv_segment * snap_seg = find_snapshot ( lv ) ;
if ( ! lv_is_merging_origin ( lv ) ) {
log_error ( " Logical volume %s has no merging snapshot. " , lv - > name ) ;
return 0 ;
}
log_print_unless_silent ( " Merge of snapshot into logical volume %s has finished. " , lv - > name ) ;
if ( seg_is_thin_volume ( snap_seg ) ) {
clear_snapshot_merge ( lv ) ;
if ( ! thin_merge_finish ( cmd , lv , snap_seg - > lv ) )
return_0 ;
} else if ( ! lv_remove_single ( cmd , snap_seg - > cow , DONT_PROMPT , 0 ) ) {
log_error ( " Could not remove snapshot %s merged into %s. " ,
snap_seg - > cow - > name , lv - > name ) ;
return 0 ;
}
return 1 ;
}
progress_t poll_merge_progress ( struct cmd_context * cmd ,
struct logical_volume * lv ,
const char * name __attribute__ ( ( unused ) ) ,
struct daemon_parms * parms )
{
dm_percent_t percent = DM_PERCENT_0 ;
if ( ! lv_is_merging_origin ( lv ) | |
! lv_snapshot_percent ( lv , & percent ) ) {
log_error ( " %s: Failed query for merging percentage. Aborting merge. " , lv - > name ) ;
return PROGRESS_CHECK_FAILED ;
} else if ( percent = = DM_PERCENT_INVALID ) {
log_error ( " %s: Merging snapshot invalidated. Aborting merge. " , lv - > name ) ;
return PROGRESS_CHECK_FAILED ;
} else if ( percent = = LVM_PERCENT_MERGE_FAILED ) {
log_error ( " %s: Merge failed. Retry merge or inspect manually. " , lv - > name ) ;
return PROGRESS_CHECK_FAILED ;
}
if ( parms - > progress_display )
log_print_unless_silent ( " %s: %s: %.1f%% " , lv - > name , parms - > progress_title ,
100.0 - dm_percent_to_float ( percent ) ) ;
else
log_verbose ( " %s: %s: %.1f%% " , lv - > name , parms - > progress_title ,
100.0 - dm_percent_to_float ( percent ) ) ;
if ( percent = = DM_PERCENT_0 )
return PROGRESS_FINISHED_ALL ;
return PROGRESS_UNFINISHED ;
}
progress_t poll_thin_merge_progress ( struct cmd_context * cmd ,
struct logical_volume * lv ,
const char * name __attribute__ ( ( unused ) ) ,
struct daemon_parms * parms )
{
uint32_t device_id ;
if ( ! lv_thin_device_id ( lv , & device_id ) ) {
stack ;
return PROGRESS_CHECK_FAILED ;
}
/*
* There is no need to poll more than once ,
* a thin snapshot merge is immediate .
*/
if ( device_id ! = find_snapshot ( lv ) - > device_id ) {
log_error ( " LV %s is not merged. " , lv - > name ) ;
return PROGRESS_CHECK_FAILED ;
}
return PROGRESS_FINISHED_ALL ; /* Merging happend */
}