1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00
lvm2/tools/lvconvert_poll.c

209 lines
5.3 KiB
C
Raw Normal View History

/*
* Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tools.h"
#include "lvconvert_poll.h"
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;
2017-06-27 09:28:36 +03:00
log_print_unless_silent("Logical volume %s converted.", display_lvname(lv));
return 1;
}
/* Swap lvid and LV names */
int swap_lv_identifiers(struct cmd_context *cmd,
struct logical_volume *a, struct logical_volume *b)
{
struct logical_volume tlv = *a;
const char *aname = a->name, *bname = b->name;
a->lvid = b->lvid;
b->lvid = tlv.lvid;
a->alloc = b->alloc;
b->alloc = tlv.alloc;
a->read_ahead = b->read_ahead;
b->read_ahead = tlv.read_ahead;
a->profile = b->profile;
b->profile = tlv.profile;
a->major = b->major;
b->major = tlv.major;
a->minor = b->minor;
b->minor = tlv.minor;
a->timestamp = b->timestamp;
b->timestamp = tlv.timestamp;
a->hostname = b->hostname;
b->hostname = tlv.hostname;
/* swap tags */
dm_list_init(&tlv.tags);
dm_list_splice(&tlv.tags, &a->tags);
dm_list_splice(&a->tags, &b->tags);
dm_list_splice(&b->tags, &tlv.tags);
/* 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))
return_0;
return 1;
}
/* 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.",
2017-06-27 09:28:36 +03:00
display_lvname(lv), display_lvname(merge_lv));
return 0;
}
/* Preserve status */
lv->status = merge_lv->status;
/* 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_print("Logical volume %s is no longer merging origin, polling has finished.",
2017-06-27 09:28:36 +03:00
display_lvname(lv));
return 1;
}
2017-06-27 09:28:36 +03:00
log_print_unless_silent("Merge of snapshot into logical volume %s has finished.",
display_lvname(lv));
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.",
2017-06-27 09:28:36 +03:00
display_lvname(snap_seg->cow), display_lvname(lv));
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))
/* Nothing to monitor here */
return PROGRESS_FINISHED_ALL;
if (!lv_snapshot_percent(lv, &percent)) {
2017-06-27 09:28:36 +03:00
log_error("%s: Failed query for merging percentage. Aborting merge.",
display_lvname(lv));
return PROGRESS_CHECK_FAILED;
} else if (percent == DM_PERCENT_INVALID) {
2017-06-27 09:28:36 +03:00
log_error("%s: Merging snapshot invalidated. Aborting merge.",
display_lvname(lv));
return PROGRESS_CHECK_FAILED;
} else if (percent == LVM_PERCENT_MERGE_FAILED) {
2017-06-27 09:28:36 +03:00
log_error("%s: Merge failed. Retry merge or inspect manually.",
display_lvname(lv));
return PROGRESS_CHECK_FAILED;
}
if (parms->progress_display)
2017-06-27 09:28:36 +03:00
log_print_unless_silent("%s: %s: %s%%", display_lvname(lv), parms->progress_title,
display_percent(cmd, DM_PERCENT_100 - percent));
else
2017-06-27 09:28:36 +03:00
log_verbose("%s: %s: %s%%", display_lvname(lv), parms->progress_title,
display_percent(cmd, DM_PERCENT_100 - 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 = 0;
if (!lv->snapshot)
return PROGRESS_FINISHED_ALL; /* Already merged by someone else */
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) {
2017-06-27 09:28:36 +03:00
log_error("LV %s is not merged.", display_lvname(lv));
return PROGRESS_CHECK_FAILED;
}
return PROGRESS_FINISHED_ALL; /* Merging happend */
}