master - polldaemon: prepare wrapper poll_daemon function
by okozina
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3929b00466c3c4...
Commit: 3929b00466c3c415a8e82e8346d79ec6c5c0eb76
Parent: 65623b63a20a221b48dfd87455dc77f5ac0c6bf4
Author: Ondrej Kozina <okozina(a)redhat.com>
AuthorDate: Tue Mar 17 18:31:41 2015 +0100
Committer: Ondrej Kozina <okozina(a)redhat.com>
CommitterDate: Wed Apr 1 20:41:30 2015 +0200
polldaemon: prepare wrapper poll_daemon function
with lvmpolld we'll have two polldaemon implementations
---
tools/polldaemon.c | 18 +++++++++++++-----
1 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/tools/polldaemon.c b/tools/polldaemon.c
index 6b06506..dd53055 100644
--- a/tools/polldaemon.c
+++ b/tools/polldaemon.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -275,10 +275,10 @@ static void _poll_for_all_vgs(struct cmd_context *cmd,
* - 'background' is advisory so a child polldaemon may not be used even
* if it was requested.
*/
-int poll_daemon(struct cmd_context *cmd, const char *name, const char *uuid,
- unsigned background,
- uint64_t lv_type, struct poll_functions *poll_fns,
- const char *progress_title)
+static int _poll_daemon(struct cmd_context *cmd, const char *name,
+ const char *uuid, unsigned background, uint64_t lv_type,
+ struct poll_functions *poll_fns,
+ const char *progress_title)
{
struct processing_handle *handle = NULL;
struct daemon_parms parms;
@@ -357,3 +357,11 @@ int poll_daemon(struct cmd_context *cmd, const char *name, const char *uuid,
destroy_processing_handle(cmd, handle);
return ret;
}
+
+int poll_daemon(struct cmd_context *cmd, const char *name, const char *uuid,
+ unsigned background,
+ uint64_t lv_type, struct poll_functions *poll_fns,
+ const char *progress_title)
+{
+ return _poll_daemon(cmd, name, uuid, background, lv_type, poll_fns, progress_title);
+}
8 years, 12 months
master - pvmove: split pvmove_update_metadata function
by okozina
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=65623b63a20a22...
Commit: 65623b63a20a221b48dfd87455dc77f5ac0c6bf4
Parent: 5190f566055ab4584772b1288fd8cbf69565eb4a
Author: Ondrej Kozina <okozina(a)redhat.com>
AuthorDate: Mon Mar 16 20:23:58 2015 +0100
Committer: Ondrej Kozina <okozina(a)redhat.com>
CommitterDate: Wed Apr 1 20:41:03 2015 +0200
pvmove: split pvmove_update_metadata function
So far pvmove_update_metadata (originaly _update_metadata) was
used for both initial and subsequent metadata updates during polling.
With a new polldaemon (lvmpolld) all operations that require polling
have to be split in two parts: The initiating one and the polling one.
The later step will be used from lvm command spawned by lvmpolld to
monitor and advance the mirror on next segment if required.
1) The initiation part is _update_metadata in pvmove.c which performs
only the first update, setting up the pvmove itself in metadata.
2) pvmove_update_metadata in pvmove_poll.c now handles all other
subsequent metadata updates except the last one.
Due to the split we could remove some code. Also some functions were
moved back to pvmove.c as they were suited for initialisation of pvmove
only.
---
tools/pvmove.c | 131 +++++++++++++++++++++++++++++++++++++++---
tools/pvmove_poll.c | 160 ++++++--------------------------------------------
tools/pvmove_poll.h | 10 ---
3 files changed, 143 insertions(+), 158 deletions(-)
diff --git a/tools/pvmove.c b/tools/pvmove.c
index 7c01dcc..bef900b 100644
--- a/tools/pvmove.c
+++ b/tools/pvmove.c
@@ -18,6 +18,45 @@
#include "display.h"
#include "pvmove_poll.h"
+#define PVMOVE_FIRST_TIME 0x00000001 /* Called for first time */
+
+static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
+{
+ const struct segment_type *segtype;
+ unsigned attr = 0;
+ int found = 1;
+ static int _clustered_found = -1;
+
+ if (clustered && _clustered_found >= 0)
+ return _clustered_found;
+
+ if (!(segtype = get_segtype_from_string(cmd, "mirror")))
+ return_0;
+
+ if (activation() && segtype->ops->target_present &&
+ !segtype->ops->target_present(cmd, NULL, clustered ? &attr : NULL))
+ found = 0;
+
+ if (activation() && clustered) {
+ if (found && (attr & MIRROR_LOG_CLUSTERED))
+ _clustered_found = found = 1;
+ else
+ _clustered_found = found = 0;
+ }
+
+ return found;
+}
+
+static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
+ struct volume_group *vg)
+{
+ if (vg_is_clustered(vg))
+ if (!_pvmove_target_present(cmd, 1))
+ return 1;
+
+ return 0;
+}
+
/* Allow /dev/vgname/lvname, vgname/lvname or lvname */
static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
const char *arg)
@@ -451,6 +490,86 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
return lv_mirr;
}
+static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
+ unsigned exclusive)
+{
+ int r = 0;
+
+ if (exclusive || lv_is_active_exclusive(lv_mirr))
+ r = activate_lv_excl(cmd, lv_mirr);
+ else
+ r = activate_lv(cmd, lv_mirr);
+
+ if (!r)
+ stack;
+
+ return r;
+}
+
+/*
+ * Called to set up initial pvmove LV only.
+ * (Not called after first or any other section completes.)
+ */
+static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
+ struct logical_volume *lv_mirr,
+ struct dm_list *lvs_changed, unsigned exclusive)
+{
+ int r = 0;
+
+ log_verbose("Updating volume group metadata for the first time.");
+ if (!vg_write(vg)) {
+ log_error("ABORTING: Volume group metadata update failed.");
+ return 0;
+ }
+
+ if (!suspend_lvs(cmd, lvs_changed, vg)) {
+ log_error("ABORTING: Temporary pvmove mirror activation failed.");
+ /* FIXME Add a recovery path for first time too. */
+ return 0;
+ }
+
+ /* Commit on-disk metadata */
+ if (!vg_commit(vg)) {
+ log_error("ABORTING: First volume group metadata update failed.");
+ if (!resume_lvs(cmd, lvs_changed)) {
+ log_error("Unable to resume logical volumes.");
+ return 0;
+ }
+ }
+
+ /* Activate the temporary mirror LV */
+ /* Only the first mirror segment gets activated as a mirror */
+ /* FIXME: Add option to use a log */
+ if (!exclusive && _pvmove_is_exclusive(cmd, vg))
+ exclusive = 1;
+
+ if (!_activate_lv(cmd, lv_mirr, exclusive)) {
+ if (test_mode()) {
+ r = 1;
+ goto out;
+ }
+
+ /*
+ * FIXME Run --abort internally here.
+ */
+ log_error("ABORTING: Temporary pvmove mirror activation failed. Run pvmove --abort.");
+ goto out;
+ }
+
+ r = 1;
+
+out:
+ if (!resume_lvs(cmd, lvs_changed)) {
+ log_error("Unable to resume logical volumes.");
+ r = 0;
+ }
+
+ if (r)
+ backup(vg);
+
+ return r;
+}
+
static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
int argc, char **argv)
{
@@ -501,7 +620,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
return_ECMD_FAILED;
}
- exclusive = pvmove_is_exclusive(cmd, vg);
+ exclusive = _pvmove_is_exclusive(cmd, vg);
if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
log_print_unless_silent("Detected pvmove in progress for %s", pv_name);
@@ -552,13 +671,9 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
/* init_pvmove(1); */
/* vg->status |= PVMOVE; */
- if (flags & PVMOVE_FIRST_TIME) {
- if (exclusive)
- flags |= PVMOVE_EXCLUSIVE;
- if (!pvmove_update_metadata
- (cmd, vg, lv_mirr, lvs_changed, flags))
+ if (flags & PVMOVE_FIRST_TIME)
+ if (!_update_metadata(cmd, vg, lv_mirr, lvs_changed, exclusive))
goto_out;
- }
/* LVs are all in status LOCKED */
r = ECMD_PROCESSED;
@@ -594,7 +709,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
int ret;
/* dm raid1 target must be present in every case */
- if (!pvmove_target_present(cmd, 0)) {
+ if (!_pvmove_target_present(cmd, 0)) {
log_error("Required device-mapper target(s) not "
"detected in your kernel");
return ECMD_FAILED;
diff --git a/tools/pvmove_poll.c b/tools/pvmove_poll.c
index a5c5971..0e9d639 100644
--- a/tools/pvmove_poll.c
+++ b/tools/pvmove_poll.c
@@ -15,42 +15,6 @@
#include "pvmove_poll.h"
#include "tools.h"
-int pvmove_target_present(struct cmd_context *cmd, int clustered)
-{
- const struct segment_type *segtype;
- unsigned attr = 0;
- int found = 1;
- static int _clustered_found = -1;
-
- if (clustered && _clustered_found >= 0)
- return _clustered_found;
-
- if (!(segtype = get_segtype_from_string(cmd, "mirror")))
- return_0;
-
- if (activation() && segtype->ops->target_present &&
- !segtype->ops->target_present(cmd, NULL, clustered ? &attr : NULL))
- found = 0;
-
- if (activation() && clustered) {
- if (found && (attr & MIRROR_LOG_CLUSTERED))
- _clustered_found = found = 1;
- else
- _clustered_found = found = 0;
- }
-
- return found;
-}
-
-unsigned pvmove_is_exclusive(struct cmd_context *cmd, struct volume_group *vg)
-{
- if (vg_is_clustered(vg))
- if (!pvmove_target_present(cmd, 1))
- return 1;
-
- return 0;
-}
-
struct volume_group *get_vg(struct cmd_context *cmd, const char *vgname)
{
dev_close_all();
@@ -58,22 +22,6 @@ struct volume_group *get_vg(struct cmd_context *cmd, const char *vgname)
return vg_read_for_update(cmd, vgname, NULL, 0);
}
-int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
- unsigned exclusive)
-{
- int r = 0;
-
- if (exclusive || lv_is_active_exclusive(lv_mirr))
- r = activate_lv_excl(cmd, lv_mirr);
- else
- r = activate_lv(cmd, lv_mirr);
-
- if (!r)
- stack;
-
- return r;
-}
-
static int _is_pvmove_image_removable(struct logical_volume *mimage_lv,
void *baton)
{
@@ -131,73 +79,26 @@ static int _detach_pvmove_mirror(struct cmd_context *cmd,
return 1;
}
-static int _suspend_lvs(struct cmd_context *cmd, unsigned first_time,
- struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed,
- struct volume_group *vg_to_revert)
-{
- /*
- * Suspend lvs_changed the first time.
- * Suspend mirrors on subsequent calls.
- */
- if (first_time) {
- if (!suspend_lvs(cmd, lvs_changed, vg_to_revert))
- return_0;
- } else if (!suspend_lv(cmd, lv_mirr)) {
- if (vg_to_revert)
- vg_revert(vg_to_revert);
- return_0;
- }
-
- return 1;
-}
-
-static int _resume_lvs(struct cmd_context *cmd, unsigned first_time,
- struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed)
-{
- /*
- * Suspend lvs_changed the first time.
- * Suspend mirrors on subsequent calls.
- */
-
- if (first_time) {
- if (!resume_lvs(cmd, lvs_changed)) {
- log_error("Unable to resume logical volumes");
- return 0;
- }
- } else if (!resume_lv(cmd, lv_mirr)) {
- log_error("Unable to reactivate logical volume \"%s\"",
- lv_mirr->name);
- return 0;
- }
-
- return 1;
-}
-
/*
- * Called to set up initial pvmove LV and to advance the mirror
- * to successive sections of it.
- * (Not called after the last section completes.)
+ * Called to advance the mirror to successive sections of it.
+ * (Not called first time or after the last section completes.)
*/
int pvmove_update_metadata(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed, unsigned flags)
+ struct dm_list *lvs_changed __attribute__((unused)),
+ unsigned flags __attribute__((unused)))
{
- unsigned exclusive = (flags & PVMOVE_EXCLUSIVE) ? 1 : 0;
- unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
- int r = 0;
-
- log_verbose("Updating volume group metadata");
+ log_verbose("Updating volume group metadata.");
if (!vg_write(vg)) {
log_error("ABORTING: Volume group metadata update failed.");
return 0;
}
- if (!_suspend_lvs(cmd, first_time, lv_mirr, lvs_changed, vg)) {
- log_error("ABORTING: Temporary pvmove mirror %s failed.", first_time ? "activation" : "reload");
- /* FIXME Add a recovery path for first time too. */
- if (!first_time && !revert_lv(cmd, lv_mirr))
+ if (!suspend_lv(cmd, lv_mirr)) {
+ if (vg)
+ vg_revert(vg);
+ log_error("ABORTING: Temporary pvmove mirror reload failed.");
+ if (!revert_lv(cmd, lv_mirr))
stack;
return 0;
}
@@ -205,44 +106,23 @@ int pvmove_update_metadata(struct cmd_context *cmd, struct volume_group *vg,
/* Commit on-disk metadata */
if (!vg_commit(vg)) {
log_error("ABORTING: Volume group metadata update failed.");
- if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
- stack;
- if (!first_time && !revert_lv(cmd, lv_mirr))
+ if (!resume_lv(cmd, lv_mirr))
+ log_error("Unable to reactivate logical volume \"%s\".",
+ lv_mirr->name);
+ if (!revert_lv(cmd, lv_mirr))
stack;
return 0;
}
- /* Activate the temporary mirror LV */
- /* Only the first mirror segment gets activated as a mirror */
- /* FIXME: Add option to use a log */
- if (first_time) {
- if (!exclusive && pvmove_is_exclusive(cmd, vg))
- exclusive = 1;
-
- if (!_activate_lv(cmd, lv_mirr, exclusive)) {
- if (test_mode()) {
- r = 1;
- goto out;
- }
-
- /*
- * FIXME Run --abort internally here.
- */
- log_error("ABORTING: Temporary pvmove mirror activation failed. Run pvmove --abort.");
- goto out;
- }
+ if (!resume_lv(cmd, lv_mirr)) {
+ log_error("Unable to reactivate logical volume \"%s\".",
+ lv_mirr->name);
+ return 0;
}
- r = 1;
-
-out:
- if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
- r = 0;
-
- if (r)
- backup(vg);
+ backup(vg);
- return r;
+ return 1;
}
int pvmove_finish(struct cmd_context *cmd, struct volume_group *vg,
diff --git a/tools/pvmove_poll.h b/tools/pvmove_poll.h
index 2fee23a..776920c 100644
--- a/tools/pvmove_poll.h
+++ b/tools/pvmove_poll.h
@@ -15,23 +15,13 @@
#ifndef _LVM_PVMOVE_H
#define _LVM_PVMOVE_H
-#define PVMOVE_FIRST_TIME 0x00000001 /* Called for first time */
-#define PVMOVE_EXCLUSIVE 0x00000002 /* Require exclusive LV */
-
struct cmd_context;
struct dm_list;
struct logical_volume;
struct volume_group;
-int pvmove_target_present(struct cmd_context *cmd, int clustered);
-
-unsigned pvmove_is_exclusive(struct cmd_context *cmd, struct volume_group *vg);
-
struct volume_group *get_vg(struct cmd_context *cmd, const char *vgname);
-int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
- unsigned exclusive);
-
int pvmove_update_metadata(struct cmd_context *cmd, struct volume_group *vg,
struct logical_volume *lv_mirr,
struct dm_list *lvs_changed, unsigned flags);
8 years, 12 months
master - lvconvert: move poll code in before refactoring
by okozina
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=5190f566055ab4...
Commit: 5190f566055ab4584772b1288fd8cbf69565eb4a
Parent: a098aa419f5be5d8f805ab6dc747770e58a4b7b1
Author: Ondrej Kozina <okozina(a)redhat.com>
AuthorDate: Thu Mar 12 16:23:19 2015 +0100
Committer: Ondrej Kozina <okozina(a)redhat.com>
CommitterDate: Wed Apr 1 20:40:50 2015 +0200
lvconvert: move poll code in before refactoring
This commit has no impact on functionality. Code required to
be visible outside lvconvert.c is just moved into new file
lvconvert_poll.c and some calls are made non-static and
declared in new header file lvconvert.h
---
tools/Makefile.in | 1 +
tools/lvconvert.c | 233 ++++--------------------------------------------
tools/lvconvert_poll.c | 213 +++++++++++++++++++++++++++++++++++++++++++
tools/lvconvert_poll.h | 61 +++++++++++++
4 files changed, 294 insertions(+), 214 deletions(-)
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 96cb91d..1d294dd 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -21,6 +21,7 @@ SOURCES =\
formats.c \
lvchange.c \
lvconvert.c \
+ lvconvert_poll.c \
lvcreate.c \
lvdisplay.c \
lvextend.c \
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 0e6f162..732f6fd 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2014 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -15,6 +15,7 @@
#include "tools.h"
#include "polldaemon.h"
#include "lv_alloc.h"
+#include "lvconvert_poll.h"
struct lvconvert_params {
int cache;
@@ -698,221 +699,25 @@ static int _read_params(struct cmd_context *cmd, int argc, char **argv,
return 1;
}
-static struct volume_group *_get_lvconvert_vg(struct cmd_context *cmd,
- const char *name,
- const char *uuid __attribute__((unused)))
-{
- dev_close_all();
-
- 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),
- NULL, 0);
-}
-
-static struct logical_volume *_get_lvconvert_lv(struct cmd_context *cmd __attribute__((unused)),
- struct volume_group *vg,
- const char *name,
- const char *uuid,
- uint64_t lv_type __attribute__((unused)))
-{
- struct logical_volume *lv = find_lv(vg, name);
-
- if (!lv || (uuid && strcmp(uuid, (char *)&lv->lvid)))
- return NULL;
-
- return lv;
-}
-
-static int _finish_lvconvert_mirror(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 */
-static int _swap_lv_identifiers(struct cmd_context *cmd,
- struct logical_volume *a, struct logical_volume *b)
-{
- union lvid lvid;
- const char *name;
-
- lvid = a->lvid;
- a->lvid = b->lvid;
- b->lvid = lvid;
-
- name = a->name;
- a->name = b->name;
- if (!lv_rename_update(cmd, b, name, 0))
- return_0;
-
- return 1;
-}
-
-static void _move_lv_attributes(struct logical_volume *to, struct logical_volume *from)
-{
- /* Maybe move this code into _finish_thin_merge() */
- 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 */
-static int _finish_thin_merge(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;
-}
-
-static int _finish_lvconvert_merge(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 (!_finish_thin_merge(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;
-}
-
-static 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;
-}
-
-static 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 */
-}
-
static struct poll_functions _lvconvert_mirror_fns = {
- .get_copy_vg = _get_lvconvert_vg,
- .get_copy_lv = _get_lvconvert_lv,
+ .get_copy_vg = lvconvert_get_copy_vg,
+ .get_copy_lv = lvconvert_get_copy_lv,
.poll_progress = poll_mirror_progress,
- .finish_copy = _finish_lvconvert_mirror,
+ .finish_copy = lvconvert_mirror_finish,
};
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,
+ .get_copy_vg = lvconvert_get_copy_vg,
+ .get_copy_lv = lvconvert_get_copy_lv,
+ .poll_progress = poll_merge_progress,
+ .finish_copy = lvconvert_merge_finish,
};
static struct poll_functions _lvconvert_thin_merge_fns = {
- .get_copy_vg = _get_lvconvert_vg,
- .get_copy_lv = _get_lvconvert_lv,
- .poll_progress = _poll_thin_merge_progress,
- .finish_copy = _finish_lvconvert_merge,
+ .get_copy_vg = lvconvert_get_copy_vg,
+ .get_copy_lv = lvconvert_get_copy_lv,
+ .poll_progress = poll_thin_merge_progress,
+ .finish_copy = lvconvert_merge_finish,
};
int lvconvert_poll(struct cmd_context *cmd, struct logical_volume *lv,
@@ -2421,7 +2226,7 @@ static int _lvconvert_merge_thin_snapshot(struct cmd_context *cmd,
* Both thin snapshot and origin are inactive,
* replace the origin LV with its snapshot LV.
*/
- if (!_finish_thin_merge(cmd, origin, lv))
+ if (!thin_merge_finish(cmd, origin, lv))
goto_out;
if (origin_is_active && !activate_lv(cmd, lv)) {
@@ -2626,7 +2431,7 @@ deactivate_pmslv:
if (!detach_pool_metadata_lv(first_seg(pool_lv), &mlv))
return_0;
- if (!_swap_lv_identifiers(cmd, mlv, pmslv))
+ if (!swap_lv_identifiers(cmd, mlv, pmslv))
return_0;
/* Used _pmspare will become _tmeta */
@@ -2718,7 +2523,7 @@ static int _lvconvert_thin(struct cmd_context *cmd,
* which could be easily removed by the user after i.e. power-off
*/
- if (!_swap_lv_identifiers(cmd, torigin_lv, lv)) {
+ if (!swap_lv_identifiers(cmd, torigin_lv, lv)) {
stack;
goto revert_new_lv;
}
@@ -2744,7 +2549,7 @@ static int _lvconvert_thin(struct cmd_context *cmd,
return 1;
deactivate_and_revert_new_lv:
- if (!_swap_lv_identifiers(cmd, torigin_lv, lv))
+ if (!swap_lv_identifiers(cmd, torigin_lv, lv))
stack;
if (!deactivate_lv(cmd, torigin_lv)) {
@@ -3414,13 +3219,13 @@ static struct logical_volume *get_vg_lock_and_logical_volume(struct cmd_context
struct volume_group *vg;
struct logical_volume* lv = NULL;
- vg = _get_lvconvert_vg(cmd, vg_name, NULL);
+ vg = lvconvert_get_copy_vg(cmd, vg_name, NULL);
if (vg_read_error(vg)) {
release_vg(vg);
return_NULL;
}
- if (!(lv = _get_lvconvert_lv(cmd, vg, lv_name, NULL, 0))) {
+ if (!(lv = lvconvert_get_copy_lv(cmd, vg, lv_name, NULL, 0))) {
log_error("Can't find LV %s in VG %s", lv_name, vg_name);
unlock_and_release_vg(cmd, vg, vg_name);
return NULL;
diff --git a/tools/lvconvert_poll.c b/tools/lvconvert_poll.c
new file mode 100644
index 0000000..012911e
--- /dev/null
+++ b/tools/lvconvert_poll.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "libdevmapper.h"
+#include "lvconvert_poll.h"
+#include "tools.h"
+
+struct volume_group *lvconvert_get_copy_vg(struct cmd_context *cmd,
+ const char *name,
+ const char *uuid __attribute__((unused)))
+{
+ dev_close_all();
+
+ 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),
+ NULL, 0);
+}
+
+struct logical_volume *lvconvert_get_copy_lv(struct cmd_context *cmd __attribute__((unused)),
+ struct volume_group *vg,
+ const char *name,
+ const char *uuid,
+ uint64_t lv_type __attribute__((unused)))
+{
+ struct logical_volume *lv = find_lv(vg, name);
+
+ if (!lv || (uuid && strcmp(uuid, (char *)&lv->lvid)))
+ return NULL;
+
+ return lv;
+}
+
+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;
+ const char *name;
+
+ lvid = a->lvid;
+ a->lvid = b->lvid;
+ b->lvid = lvid;
+
+ name = a->name;
+ a->name = b->name;
+ if (!lv_rename_update(cmd, b, name, 0))
+ 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 */
+}
diff --git a/tools/lvconvert_poll.h b/tools/lvconvert_poll.h
new file mode 100644
index 0000000..d79962c
--- /dev/null
+++ b/tools/lvconvert_poll.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_LVCONVERT_H
+#define _LVM_LVCONVERT_H
+
+#include "polldaemon.h"
+
+struct cmd_context;
+struct logical_volume;
+struct volume_group;
+
+struct volume_group *lvconvert_get_copy_vg(struct cmd_context *cmd,
+ const char *name,
+ const char *uuid __attribute__((unused)));
+
+struct logical_volume *lvconvert_get_copy_lv(struct cmd_context *cmd __attribute__((unused)),
+ struct volume_group *vg,
+ const char *name,
+ const char *uuid,
+ uint64_t lv_type __attribute__((unused)));
+
+int lvconvert_mirror_finish(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct logical_volume *lv,
+ struct dm_list *lvs_changed __attribute__((unused)));
+
+int swap_lv_identifiers(struct cmd_context *cmd,
+ struct logical_volume *a, struct logical_volume *b);
+
+int thin_merge_finish(struct cmd_context *cmd,
+ struct logical_volume *merge_lv,
+ struct logical_volume *lv);
+
+int lvconvert_merge_finish(struct cmd_context *cmd,
+ struct volume_group *vg,
+ struct logical_volume *lv,
+ struct dm_list *lvs_changed __attribute__((unused)));
+
+progress_t poll_merge_progress(struct cmd_context *cmd,
+ struct logical_volume *lv,
+ const char *name __attribute__((unused)),
+ struct daemon_parms *parms);
+
+progress_t poll_thin_merge_progress(struct cmd_context *cmd,
+ struct logical_volume *lv,
+ const char *name __attribute__((unused)),
+ struct daemon_parms *parms);
+
+#endif /* _LVM_LVCONVERT_H */
8 years, 12 months
master - pvmove: move poll code in before refactoring
by okozina
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=a098aa419f5be5...
Commit: a098aa419f5be5d8f805ab6dc747770e58a4b7b1
Parent: bf2d831e7e9ceb7fe0528dba8587a4157b4ac789
Author: Ondrej Kozina <okozina(a)redhat.com>
AuthorDate: Thu Mar 12 16:21:43 2015 +0100
Committer: Ondrej Kozina <okozina(a)redhat.com>
CommitterDate: Wed Apr 1 20:40:39 2015 +0200
pvmove: move poll code in before refactoring
This commit has no impact on functionality. Code required to
be visible outside pvmove.c is just moved into new file
pvmove_poll.c and some calls are made non-static and declared in
new header file pvmove.h
---
tools/Makefile.in | 1 +
tools/pvmove.c | 348 ++-------------------------------------------------
tools/pvmove_poll.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++++
tools/pvmove_poll.h | 45 +++++++
4 files changed, 396 insertions(+), 339 deletions(-)
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 5c1583f..96cb91d 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -38,6 +38,7 @@ SOURCES =\
pvcreate.c \
pvdisplay.c \
pvmove.c \
+ pvmove_poll.c \
pvremove.c \
pvresize.c \
pvscan.c \
diff --git a/tools/pvmove.c b/tools/pvmove.c
index 3072584..7c01dcc 100644
--- a/tools/pvmove.c
+++ b/tools/pvmove.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2010 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -16,46 +16,7 @@
#include "tools.h"
#include "polldaemon.h"
#include "display.h"
-
-#define PVMOVE_FIRST_TIME 0x00000001 /* Called for first time */
-#define PVMOVE_EXCLUSIVE 0x00000002 /* Require exclusive LV */
-
-static int _pvmove_target_present(struct cmd_context *cmd, int clustered)
-{
- const struct segment_type *segtype;
- unsigned attr = 0;
- int found = 1;
- static int _clustered_found = -1;
-
- if (clustered && _clustered_found >= 0)
- return _clustered_found;
-
- if (!(segtype = get_segtype_from_string(cmd, "mirror")))
- return_0;
-
- if (activation() && segtype->ops->target_present &&
- !segtype->ops->target_present(cmd, NULL, clustered ? &attr : NULL))
- found = 0;
-
- if (activation() && clustered) {
- if (found && (attr & MIRROR_LOG_CLUSTERED))
- _clustered_found = found = 1;
- else
- _clustered_found = found = 0;
- }
-
- return found;
-}
-
-static unsigned _pvmove_is_exclusive(struct cmd_context *cmd,
- struct volume_group *vg)
-{
- if (vg_is_clustered(vg))
- if (!_pvmove_target_present(cmd, 1))
- return 1;
-
- return 0;
-}
+#include "pvmove_poll.h"
/* Allow /dev/vgname/lvname, vgname/lvname or lvname */
static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
@@ -88,13 +49,6 @@ static const char *_extract_lvname(struct cmd_context *cmd, const char *vgname,
return lvname;
}
-static struct volume_group *_get_vg(struct cmd_context *cmd, const char *vgname)
-{
- dev_close_all();
-
- return vg_read_for_update(cmd, vgname, NULL, 0);
-}
-
/* Create list of PVs for allocation of replacement extents */
static struct dm_list *_get_allocatable_pvs(struct cmd_context *cmd, int argc,
char **argv, struct volume_group *vg,
@@ -497,193 +451,6 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
return lv_mirr;
}
-static int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
- unsigned exclusive)
-{
- int r = 0;
-
- if (exclusive || lv_is_active_exclusive(lv_mirr))
- r = activate_lv_excl(cmd, lv_mirr);
- else
- r = activate_lv(cmd, lv_mirr);
-
- if (!r)
- stack;
-
- return r;
-}
-
-static int _is_pvmove_image_removable(struct logical_volume *mimage_lv,
- void *baton)
-{
- uint32_t mimage_to_remove = *((uint32_t *)baton);
- struct lv_segment *mirror_seg;
-
- if (!(mirror_seg = get_only_segment_using_this_lv(mimage_lv))) {
- log_error(INTERNAL_ERROR "%s is not a proper mirror image",
- mimage_lv->name);
- return 0;
- }
-
- if (seg_type(mirror_seg, 0) != AREA_LV) {
- log_error(INTERNAL_ERROR "%s is not a pvmove mirror of LV-type",
- mirror_seg->lv->name);
- return 0;
- }
-
- if (mimage_to_remove > mirror_seg->area_count) {
- log_error(INTERNAL_ERROR "Mirror image %" PRIu32 " not found in segment",
- mimage_to_remove);
- return 0;
- }
-
- if (seg_lv(mirror_seg, mimage_to_remove) == mimage_lv)
- return 1;
-
- return 0;
-}
-
-static int _detach_pvmove_mirror(struct cmd_context *cmd,
- struct logical_volume *lv_mirr)
-{
- uint32_t mimage_to_remove = 0;
- struct dm_list lvs_completed;
- struct lv_list *lvl;
-
- /* Update metadata to remove mirror segments and break dependencies */
- dm_list_init(&lvs_completed);
-
- if (arg_is_set(cmd, abort_ARG) &&
- (seg_type(first_seg(lv_mirr), 0) == AREA_LV))
- mimage_to_remove = 1; /* remove the second mirror leg */
-
- if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, _is_pvmove_image_removable, &mimage_to_remove, PVMOVE) ||
- !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
- &lvs_completed)) {
- return 0;
- }
-
- dm_list_iterate_items(lvl, &lvs_completed)
- /* FIXME Assumes only one pvmove at a time! */
- lvl->lv->status &= ~LOCKED;
-
- return 1;
-}
-
-static int _suspend_lvs(struct cmd_context *cmd, unsigned first_time,
- struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed,
- struct volume_group *vg_to_revert)
-{
- /*
- * Suspend lvs_changed the first time.
- * Suspend mirrors on subsequent calls.
- */
- if (first_time) {
- if (!suspend_lvs(cmd, lvs_changed, vg_to_revert))
- return_0;
- } else if (!suspend_lv(cmd, lv_mirr)) {
- if (vg_to_revert)
- vg_revert(vg_to_revert);
- return_0;
- }
-
- return 1;
-}
-
-static int _resume_lvs(struct cmd_context *cmd, unsigned first_time,
- struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed)
-{
- /*
- * Suspend lvs_changed the first time.
- * Suspend mirrors on subsequent calls.
- */
-
- if (first_time) {
- if (!resume_lvs(cmd, lvs_changed)) {
- log_error("Unable to resume logical volumes");
- return 0;
- }
- } else if (!resume_lv(cmd, lv_mirr)) {
- log_error("Unable to reactivate logical volume \"%s\"",
- lv_mirr->name);
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Called to set up initial pvmove LV and to advance the mirror
- * to successive sections of it.
- * (Not called after the last section completes.)
- */
-static int _update_metadata(struct cmd_context *cmd, struct volume_group *vg,
- struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed, unsigned flags)
-{
- unsigned exclusive = (flags & PVMOVE_EXCLUSIVE) ? 1 : 0;
- unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
- int r = 0;
-
- log_verbose("Updating volume group metadata");
- if (!vg_write(vg)) {
- log_error("ABORTING: Volume group metadata update failed.");
- return 0;
- }
-
- if (!_suspend_lvs(cmd, first_time, lv_mirr, lvs_changed, vg)) {
- log_error("ABORTING: Temporary pvmove mirror %s failed.", first_time ? "activation" : "reload");
- /* FIXME Add a recovery path for first time too. */
- if (!first_time && !revert_lv(cmd, lv_mirr))
- stack;
- return 0;
- }
-
- /* Commit on-disk metadata */
- if (!vg_commit(vg)) {
- log_error("ABORTING: Volume group metadata update failed.");
- if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
- stack;
- if (!first_time && !revert_lv(cmd, lv_mirr))
- stack;
- return 0;
- }
-
- /* Activate the temporary mirror LV */
- /* Only the first mirror segment gets activated as a mirror */
- /* FIXME: Add option to use a log */
- if (first_time) {
- if (!exclusive && _pvmove_is_exclusive(cmd, vg))
- exclusive = 1;
-
- if (!_activate_lv(cmd, lv_mirr, exclusive)) {
- if (test_mode()) {
- r = 1;
- goto out;
- }
-
- /*
- * FIXME Run --abort internally here.
- */
- log_error("ABORTING: Temporary pvmove mirror activation failed. Run pvmove --abort.");
- goto out;
- }
- }
-
- r = 1;
-
-out:
- if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
- r = 0;
-
- if (r)
- backup(vg);
-
- return r;
-}
-
static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
int argc, char **argv)
{
@@ -728,13 +495,13 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
/* Read VG */
log_verbose("Finding volume group \"%s\"", pv_vg_name(pv));
- vg = _get_vg(cmd, pv_vg_name(pv));
+ vg = get_vg(cmd, pv_vg_name(pv));
if (vg_read_error(vg)) {
release_vg(vg);
return_ECMD_FAILED;
}
- exclusive = _pvmove_is_exclusive(cmd, vg);
+ exclusive = pvmove_is_exclusive(cmd, vg);
if ((lv_mirr = find_pvmove_lv(vg, pv_dev(pv), PVMOVE))) {
log_print_unless_silent("Detected pvmove in progress for %s", pv_name);
@@ -788,7 +555,7 @@ static int _set_up_pvmove(struct cmd_context *cmd, const char *pv_name,
if (flags & PVMOVE_FIRST_TIME) {
if (exclusive)
flags |= PVMOVE_EXCLUSIVE;
- if (!_update_metadata
+ if (!pvmove_update_metadata
(cmd, vg, lv_mirr, lvs_changed, flags))
goto_out;
}
@@ -801,110 +568,13 @@ out:
return r;
}
-static int _finish_pvmove(struct cmd_context *cmd, struct volume_group *vg,
- struct logical_volume *lv_mirr,
- struct dm_list *lvs_changed)
-{
- int r = 1;
-
- if (!dm_list_empty(lvs_changed) &&
- (!_detach_pvmove_mirror(cmd, lv_mirr) ||
- !replace_lv_with_error_segment(lv_mirr))) {
- log_error("ABORTING: Removal of temporary mirror failed");
- return 0;
- }
-
- /* Store metadata without dependencies on mirror segments */
- if (!vg_write(vg)) {
- log_error("ABORTING: Failed to write new data locations "
- "to disk.");
- return 0;
- }
-
- /* Suspend LVs changed (implicitly suspends lv_mirr) */
- if (!suspend_lvs(cmd, lvs_changed, vg)) {
- log_error("ABORTING: Locking LVs to remove temporary mirror failed");
- if (!revert_lv(cmd, lv_mirr))
- stack;
- return 0;
- }
-
- /* Store metadata without dependencies on mirror segments */
- if (!vg_commit(vg)) {
- log_error("ABORTING: Failed to write new data locations "
- "to disk.");
- if (!revert_lv(cmd, lv_mirr))
- stack;
- if (!revert_lvs(cmd, lvs_changed))
- stack;
- return 0;
- }
-
- /* Release mirror LV. (No pending I/O because it's been suspended.) */
- if (!resume_lv(cmd, lv_mirr)) {
- log_error("Unable to reactivate logical volume \"%s\"",
- lv_mirr->name);
- r = 0;
- }
-
- /* Unsuspend LVs */
- if (!resume_lvs(cmd, lvs_changed))
- stack;
-
- /* Deactivate mirror LV */
- if (!deactivate_lv(cmd, lv_mirr)) {
- log_error("ABORTING: Unable to deactivate temporary logical "
- "volume \"%s\"", lv_mirr->name);
- r = 0;
- }
-
- log_verbose("Removing temporary pvmove LV");
- if (!lv_remove(lv_mirr)) {
- log_error("ABORTING: Removal of temporary pvmove LV failed");
- return 0;
- }
-
- /* Store it on disks */
- log_verbose("Writing out final volume group after pvmove");
- if (!vg_write(vg) || !vg_commit(vg)) {
- log_error("ABORTING: Failed to write new data locations "
- "to disk.");
- return 0;
- }
-
- /* FIXME backup positioning */
- backup(vg);
-
- return r;
-}
-
-static struct volume_group *_get_move_vg(struct cmd_context *cmd,
- const char *name,
- const char *uuid __attribute__((unused)))
-{
- struct physical_volume *pv;
- struct volume_group *vg;
-
- /* Reread all metadata in case it got changed */
- if (!(pv = find_pv_by_name(cmd, name, 0, 0))) {
- log_error("ABORTING: Can't reread PV %s", name);
- /* What more could we do here? */
- return NULL;
- }
-
- vg = _get_vg(cmd, pv_vg_name(pv));
- free_pv_fid(pv);
-
- return vg;
-}
-
static struct poll_functions _pvmove_fns = {
.get_copy_name_from_lv = get_pvmove_pvname_from_lv_mirr,
- .get_copy_vg = _get_move_vg,
+ .get_copy_vg = pvmove_get_copy_vg,
.get_copy_lv = find_pvmove_lv_from_pvname,
.poll_progress = poll_mirror_progress,
- .update_metadata = _update_metadata,
- .finish_copy = _finish_pvmove,
+ .update_metadata = pvmove_update_metadata,
+ .finish_copy = pvmove_finish,
};
int pvmove_poll(struct cmd_context *cmd, const char *pv_name,
@@ -924,7 +594,7 @@ int pvmove(struct cmd_context *cmd, int argc, char **argv)
int ret;
/* dm raid1 target must be present in every case */
- if (!_pvmove_target_present(cmd, 0)) {
+ if (!pvmove_target_present(cmd, 0)) {
log_error("Required device-mapper target(s) not "
"detected in your kernel");
return ECMD_FAILED;
diff --git a/tools/pvmove_poll.c b/tools/pvmove_poll.c
new file mode 100644
index 0000000..a5c5971
--- /dev/null
+++ b/tools/pvmove_poll.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "pvmove_poll.h"
+#include "tools.h"
+
+int pvmove_target_present(struct cmd_context *cmd, int clustered)
+{
+ const struct segment_type *segtype;
+ unsigned attr = 0;
+ int found = 1;
+ static int _clustered_found = -1;
+
+ if (clustered && _clustered_found >= 0)
+ return _clustered_found;
+
+ if (!(segtype = get_segtype_from_string(cmd, "mirror")))
+ return_0;
+
+ if (activation() && segtype->ops->target_present &&
+ !segtype->ops->target_present(cmd, NULL, clustered ? &attr : NULL))
+ found = 0;
+
+ if (activation() && clustered) {
+ if (found && (attr & MIRROR_LOG_CLUSTERED))
+ _clustered_found = found = 1;
+ else
+ _clustered_found = found = 0;
+ }
+
+ return found;
+}
+
+unsigned pvmove_is_exclusive(struct cmd_context *cmd, struct volume_group *vg)
+{
+ if (vg_is_clustered(vg))
+ if (!pvmove_target_present(cmd, 1))
+ return 1;
+
+ return 0;
+}
+
+struct volume_group *get_vg(struct cmd_context *cmd, const char *vgname)
+{
+ dev_close_all();
+
+ return vg_read_for_update(cmd, vgname, NULL, 0);
+}
+
+int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
+ unsigned exclusive)
+{
+ int r = 0;
+
+ if (exclusive || lv_is_active_exclusive(lv_mirr))
+ r = activate_lv_excl(cmd, lv_mirr);
+ else
+ r = activate_lv(cmd, lv_mirr);
+
+ if (!r)
+ stack;
+
+ return r;
+}
+
+static int _is_pvmove_image_removable(struct logical_volume *mimage_lv,
+ void *baton)
+{
+ uint32_t mimage_to_remove = *((uint32_t *)baton);
+ struct lv_segment *mirror_seg;
+
+ if (!(mirror_seg = get_only_segment_using_this_lv(mimage_lv))) {
+ log_error(INTERNAL_ERROR "%s is not a proper mirror image",
+ mimage_lv->name);
+ return 0;
+ }
+
+ if (seg_type(mirror_seg, 0) != AREA_LV) {
+ log_error(INTERNAL_ERROR "%s is not a pvmove mirror of LV-type",
+ mirror_seg->lv->name);
+ return 0;
+ }
+
+ if (mimage_to_remove > mirror_seg->area_count) {
+ log_error(INTERNAL_ERROR "Mirror image %" PRIu32 " not found in segment",
+ mimage_to_remove);
+ return 0;
+ }
+
+ if (seg_lv(mirror_seg, mimage_to_remove) == mimage_lv)
+ return 1;
+
+ return 0;
+}
+
+static int _detach_pvmove_mirror(struct cmd_context *cmd,
+ struct logical_volume *lv_mirr)
+{
+ uint32_t mimage_to_remove = 0;
+ struct dm_list lvs_completed;
+ struct lv_list *lvl;
+
+ /* Update metadata to remove mirror segments and break dependencies */
+ dm_list_init(&lvs_completed);
+
+ if (arg_is_set(cmd, abort_ARG) &&
+ (seg_type(first_seg(lv_mirr), 0) == AREA_LV))
+ mimage_to_remove = 1; /* remove the second mirror leg */
+
+ if (!lv_remove_mirrors(cmd, lv_mirr, 1, 0, _is_pvmove_image_removable, &mimage_to_remove, PVMOVE) ||
+ !remove_layers_for_segments_all(cmd, lv_mirr, PVMOVE,
+ &lvs_completed)) {
+ return 0;
+ }
+
+ dm_list_iterate_items(lvl, &lvs_completed)
+ /* FIXME Assumes only one pvmove at a time! */
+ lvl->lv->status &= ~LOCKED;
+
+ return 1;
+}
+
+static int _suspend_lvs(struct cmd_context *cmd, unsigned first_time,
+ struct logical_volume *lv_mirr,
+ struct dm_list *lvs_changed,
+ struct volume_group *vg_to_revert)
+{
+ /*
+ * Suspend lvs_changed the first time.
+ * Suspend mirrors on subsequent calls.
+ */
+ if (first_time) {
+ if (!suspend_lvs(cmd, lvs_changed, vg_to_revert))
+ return_0;
+ } else if (!suspend_lv(cmd, lv_mirr)) {
+ if (vg_to_revert)
+ vg_revert(vg_to_revert);
+ return_0;
+ }
+
+ return 1;
+}
+
+static int _resume_lvs(struct cmd_context *cmd, unsigned first_time,
+ struct logical_volume *lv_mirr,
+ struct dm_list *lvs_changed)
+{
+ /*
+ * Suspend lvs_changed the first time.
+ * Suspend mirrors on subsequent calls.
+ */
+
+ if (first_time) {
+ if (!resume_lvs(cmd, lvs_changed)) {
+ log_error("Unable to resume logical volumes");
+ return 0;
+ }
+ } else if (!resume_lv(cmd, lv_mirr)) {
+ log_error("Unable to reactivate logical volume \"%s\"",
+ lv_mirr->name);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Called to set up initial pvmove LV and to advance the mirror
+ * to successive sections of it.
+ * (Not called after the last section completes.)
+ */
+int pvmove_update_metadata(struct cmd_context *cmd, struct volume_group *vg,
+ struct logical_volume *lv_mirr,
+ struct dm_list *lvs_changed, unsigned flags)
+{
+ unsigned exclusive = (flags & PVMOVE_EXCLUSIVE) ? 1 : 0;
+ unsigned first_time = (flags & PVMOVE_FIRST_TIME) ? 1 : 0;
+ int r = 0;
+
+ log_verbose("Updating volume group metadata");
+ if (!vg_write(vg)) {
+ log_error("ABORTING: Volume group metadata update failed.");
+ return 0;
+ }
+
+ if (!_suspend_lvs(cmd, first_time, lv_mirr, lvs_changed, vg)) {
+ log_error("ABORTING: Temporary pvmove mirror %s failed.", first_time ? "activation" : "reload");
+ /* FIXME Add a recovery path for first time too. */
+ if (!first_time && !revert_lv(cmd, lv_mirr))
+ stack;
+ return 0;
+ }
+
+ /* Commit on-disk metadata */
+ if (!vg_commit(vg)) {
+ log_error("ABORTING: Volume group metadata update failed.");
+ if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
+ stack;
+ if (!first_time && !revert_lv(cmd, lv_mirr))
+ stack;
+ return 0;
+ }
+
+ /* Activate the temporary mirror LV */
+ /* Only the first mirror segment gets activated as a mirror */
+ /* FIXME: Add option to use a log */
+ if (first_time) {
+ if (!exclusive && pvmove_is_exclusive(cmd, vg))
+ exclusive = 1;
+
+ if (!_activate_lv(cmd, lv_mirr, exclusive)) {
+ if (test_mode()) {
+ r = 1;
+ goto out;
+ }
+
+ /*
+ * FIXME Run --abort internally here.
+ */
+ log_error("ABORTING: Temporary pvmove mirror activation failed. Run pvmove --abort.");
+ goto out;
+ }
+ }
+
+ r = 1;
+
+out:
+ if (!_resume_lvs(cmd, first_time, lv_mirr, lvs_changed))
+ r = 0;
+
+ if (r)
+ backup(vg);
+
+ return r;
+}
+
+int pvmove_finish(struct cmd_context *cmd, struct volume_group *vg,
+ struct logical_volume *lv_mirr, struct dm_list *lvs_changed)
+{
+ int r = 1;
+
+ if (!dm_list_empty(lvs_changed) &&
+ (!_detach_pvmove_mirror(cmd, lv_mirr) ||
+ !replace_lv_with_error_segment(lv_mirr))) {
+ log_error("ABORTING: Removal of temporary mirror failed");
+ return 0;
+ }
+
+ /* Store metadata without dependencies on mirror segments */
+ if (!vg_write(vg)) {
+ log_error("ABORTING: Failed to write new data locations "
+ "to disk.");
+ return 0;
+ }
+
+ /* Suspend LVs changed (implicitly suspends lv_mirr) */
+ if (!suspend_lvs(cmd, lvs_changed, vg)) {
+ log_error("ABORTING: Locking LVs to remove temporary mirror failed");
+ if (!revert_lv(cmd, lv_mirr))
+ stack;
+ return 0;
+ }
+
+ /* Store metadata without dependencies on mirror segments */
+ if (!vg_commit(vg)) {
+ log_error("ABORTING: Failed to write new data locations "
+ "to disk.");
+ if (!revert_lv(cmd, lv_mirr))
+ stack;
+ if (!revert_lvs(cmd, lvs_changed))
+ stack;
+ return 0;
+ }
+
+ /* Release mirror LV. (No pending I/O because it's been suspended.) */
+ if (!resume_lv(cmd, lv_mirr)) {
+ log_error("Unable to reactivate logical volume \"%s\"",
+ lv_mirr->name);
+ r = 0;
+ }
+
+ /* Unsuspend LVs */
+ if (!resume_lvs(cmd, lvs_changed))
+ stack;
+
+ /* Deactivate mirror LV */
+ if (!deactivate_lv(cmd, lv_mirr)) {
+ log_error("ABORTING: Unable to deactivate temporary logical "
+ "volume \"%s\"", lv_mirr->name);
+ r = 0;
+ }
+
+ log_verbose("Removing temporary pvmove LV");
+ if (!lv_remove(lv_mirr)) {
+ log_error("ABORTING: Removal of temporary pvmove LV failed");
+ return 0;
+ }
+
+ /* Store it on disks */
+ log_verbose("Writing out final volume group after pvmove");
+ if (!vg_write(vg) || !vg_commit(vg)) {
+ log_error("ABORTING: Failed to write new data locations "
+ "to disk.");
+ return 0;
+ }
+
+ /* FIXME backup positioning */
+ backup(vg);
+
+ return r;
+}
+
+struct volume_group *pvmove_get_copy_vg(struct cmd_context *cmd, const char *name,
+ const char *uuid __attribute__((unused)))
+{
+ struct physical_volume *pv;
+ struct volume_group *vg;
+
+ /* Reread all metadata in case it got changed */
+ if (!(pv = find_pv_by_name(cmd, name, 0, 0))) {
+ log_error("ABORTING: Can't reread PV %s", name);
+ /* What more could we do here? */
+ return NULL;
+ }
+
+ vg = get_vg(cmd, pv_vg_name(pv));
+ free_pv_fid(pv);
+
+ return vg;
+}
diff --git a/tools/pvmove_poll.h b/tools/pvmove_poll.h
new file mode 100644
index 0000000..2fee23a
--- /dev/null
+++ b/tools/pvmove_poll.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _LVM_PVMOVE_H
+#define _LVM_PVMOVE_H
+
+#define PVMOVE_FIRST_TIME 0x00000001 /* Called for first time */
+#define PVMOVE_EXCLUSIVE 0x00000002 /* Require exclusive LV */
+
+struct cmd_context;
+struct dm_list;
+struct logical_volume;
+struct volume_group;
+
+int pvmove_target_present(struct cmd_context *cmd, int clustered);
+
+unsigned pvmove_is_exclusive(struct cmd_context *cmd, struct volume_group *vg);
+
+struct volume_group *get_vg(struct cmd_context *cmd, const char *vgname);
+
+int _activate_lv(struct cmd_context *cmd, struct logical_volume *lv_mirr,
+ unsigned exclusive);
+
+int pvmove_update_metadata(struct cmd_context *cmd, struct volume_group *vg,
+ struct logical_volume *lv_mirr,
+ struct dm_list *lvs_changed, unsigned flags);
+
+int pvmove_finish(struct cmd_context *cmd, struct volume_group *vg,
+ struct logical_volume *lv_mirr, struct dm_list *lvs_changed);
+
+struct volume_group *pvmove_get_copy_vg(struct cmd_context *cmd,
+ const char *name, const char *uuid);
+
+#endif /* _LVM_PVMOVE_H */
8 years, 12 months