summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Brassow <jbrassow@redhat.com>2012-09-11 13:01:05 -0500
committerJonathan Brassow <jbrassow@redhat.com>2012-09-11 13:01:05 -0500
commita2d9b1a7e92aab78c80be0e0cbd45fde00d42aa4 (patch)
tree8c0d84f59919d5467bd84948bb6efac0db47168e
parent05131f5853e86419d9c726faa961b8d012298d9c (diff)
downloadlvm2-a2d9b1a7e92aab78c80be0e0cbd45fde00d42aa4.zip
lvm2-a2d9b1a7e92aab78c80be0e0cbd45fde00d42aa4.tar.gz
lvm2-a2d9b1a7e92aab78c80be0e0cbd45fde00d42aa4.tar.xz
cleanup: Restructure code that handles mirror resyncing
When an LV is to be resynced, the metadata areas are cleared and the LV is reactivated. This is true for mirroring and will also be true for RAID LVs. We restructure the code in lvchange_resync() so that we keep all the common steps necessary (validation of ability to resync, deactivation, activation of meta/log devices, clearing of those devices, etc) and place the code that will be divergent in separate functions: detach_metadata_devices() attach_metadata_devices() The common steps will be processed on lists of metadata devices. Before RAID capability is added, this will simply be the mirror log device (if found). This patch lays the ground-work for adding resync of RAID LVs.
-rw-r--r--tools/lvchange.c115
1 files changed, 86 insertions, 29 deletions
diff --git a/tools/lvchange.c b/tools/lvchange.c
index cbdb353..6972aac 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -256,13 +256,57 @@ static int lvchange_refresh(struct cmd_context *cmd, struct logical_volume *lv)
return lv_refresh(cmd, lv);
}
+static int detach_metadata_devices(struct lv_segment *seg, struct dm_list *list)
+{
+ struct cmd_context *cmd = seg->lv->vg->cmd;
+ struct lv_list *lvl;
+
+ if (seg_is_raid(seg)) {
+ return 0;
+ }
+
+ if (!(lvl = dm_pool_alloc(cmd->mem, sizeof(*lvl))))
+ return_0;
+
+ lvl->lv = detach_mirror_log(seg);
+ dm_list_add(list, &lvl->list);
+
+ return 1;
+}
+
+static int attach_metadata_devices(struct lv_segment *seg, struct dm_list *list)
+{
+ struct cmd_context *cmd = seg->lv->vg->cmd;
+ struct lv_list *lvl;
+
+ if (seg_is_raid(seg)) {
+ return 0;
+ }
+
+ dm_list_iterate_items(lvl, list)
+ break; /* get first item */
+
+ if (!attach_mirror_log(seg, lvl->lv)) {
+ dm_pool_free(cmd->mem, lvl);
+ return_0;
+ }
+
+ dm_pool_free(cmd->mem, lvl);
+
+ return 1;
+}
+
static int lvchange_resync(struct cmd_context *cmd,
struct logical_volume *lv)
{
int active = 0;
int monitored;
struct lvinfo info;
- struct logical_volume *log_lv;
+ struct lv_segment *seg = first_seg(lv);
+ struct dm_list device_list;
+ struct lv_list *lvl;
+
+ dm_list_init(&device_list);
if (!(lv->status & MIRRORED)) {
log_error("Unable to resync %s because it is not mirrored.",
@@ -321,21 +365,19 @@ static int lvchange_resync(struct cmd_context *cmd,
init_dmeventd_monitor(monitored);
- log_lv = first_seg(lv)->log_lv;
-
log_very_verbose("Starting resync of %s%s%s mirror \"%s\"",
(active) ? "active " : "",
vg_is_clustered(lv->vg) ? "clustered " : "",
- (log_lv) ? "disk-logged" : "core-logged",
+ (seg->log_lv) ? "disk-logged" : "core-logged",
lv->name);
/*
- * If this mirror has a core log (i.e. !log_lv),
+ * If this mirror has a core log (i.e. !seg->log_lv),
* then simply deactivating/activating will cause
* it to reset the sync status. We only need to
* worry about persistent logs.
*/
- if (!log_lv) {
+ if (!seg->log_lv) {
if (!(lv->status & LV_NOTSYNCED)) {
lv->status &= ~LV_NOTSYNCED;
log_very_verbose("Updating logical volume \"%s\""
@@ -360,12 +402,17 @@ static int lvchange_resync(struct cmd_context *cmd,
*/
lv->status &= ~LV_NOTSYNCED;
- /* Separate mirror log so we can clear it */
- detach_mirror_log(first_seg(lv));
+ /* Separate mirror log or metadata devices so we can clear them */
+ if (!detach_metadata_devices(seg, &device_list)) {
+ log_error("Failed to clear %s %s for %s",
+ seg->segtype->name, seg_is_raid(seg) ?
+ "metadata area" : "mirror log", lv->name);
+ return 0;
+ }
if (!vg_write(lv->vg)) {
log_error("Failed to write intermediate VG metadata.");
- if (!attach_mirror_log(first_seg(lv), log_lv))
+ if (!attach_metadata_devices(seg, &device_list))
stack;
if (active && !activate_lv(cmd, lv))
stack;
@@ -374,7 +421,7 @@ static int lvchange_resync(struct cmd_context *cmd,
if (!vg_commit(lv->vg)) {
log_error("Failed to commit intermediate VG metadata.");
- if (!attach_mirror_log(first_seg(lv), log_lv))
+ if (!attach_metadata_devices(seg, &device_list))
stack;
if (active && !activate_lv(cmd, lv))
stack;
@@ -383,31 +430,41 @@ static int lvchange_resync(struct cmd_context *cmd,
backup(lv->vg);
- if (!activate_lv(cmd, log_lv)) {
- log_error("Unable to activate %s for mirror log resync",
- log_lv->name);
- return 0;
- }
+ dm_list_iterate_items(lvl, &device_list) {
+ if (!activate_lv(cmd, lvl->lv)) {
+ log_error("Unable to activate %s for mirror log resync",
+ lvl->lv->name);
+ return 0;
+ }
- log_very_verbose("Clearing log device %s", log_lv->name);
- if (!set_lv(cmd, log_lv, log_lv->size, 0)) {
- log_error("Unable to reset sync status for %s", lv->name);
- if (!deactivate_lv(cmd, log_lv))
- log_error("Failed to deactivate log LV after "
- "wiping failed");
- return 0;
+ log_very_verbose("Clearing %s device %s",
+ (seg_is_raid(seg)) ? "metadata" : "log",
+ lvl->lv->name);
+ if (!set_lv(cmd, lvl->lv, lvl->lv->size, 0)) {
+ log_error("Unable to reset sync status for %s",
+ lv->name);
+ if (!deactivate_lv(cmd, lvl->lv))
+ log_error("Failed to deactivate log LV after "
+ "wiping failed");
+ return 0;
+ }
+
+ if (!deactivate_lv(cmd, lvl->lv)) {
+ log_error("Unable to deactivate %s LV %s "
+ "after wiping for resync",
+ (seg_is_raid(seg)) ? "metadata" : "log",
+ lvl->lv->name);
+ return 0;
+ }
}
- if (!deactivate_lv(cmd, log_lv)) {
- log_error("Unable to deactivate log LV %s after wiping "
- "for resync", log_lv->name);
+ /* Put metadata sub-LVs back in place */
+ if (!attach_metadata_devices(seg, &device_list)) {
+ log_error("Failed to reattach %s device after clearing",
+ (seg_is_raid(seg)) ? "metadata" : "log");
return 0;
}
- /* Put mirror log back in place */
- if (!attach_mirror_log(first_seg(lv), log_lv))
- stack;
-
log_very_verbose("Updating logical volume \"%s\" on disk(s)", lv->name);
if (!vg_write(lv->vg) || !vg_commit(lv->vg)) {
log_error("Failed to update metadata on disk.");