1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

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.
This commit is contained in:
Jonathan Brassow 2012-09-11 13:01:05 -05:00
parent 05131f5853
commit a2d9b1a7e9

View File

@ -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 %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;
}
}
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");
/* 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;
}
if (!deactivate_lv(cmd, log_lv)) {
log_error("Unable to deactivate log LV %s after wiping "
"for resync", log_lv->name);
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.");