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

raid: Moved degraded activation code to raid_manip.

Adjust some messages & fn names.
This commit is contained in:
Alasdair G Kergon 2014-07-22 20:50:29 +01:00
parent fe5b282a4a
commit 99e3c13012
4 changed files with 120 additions and 118 deletions

View File

@ -2203,112 +2203,6 @@ out:
return r;
}
/* FIXME Move this non-activation code elsewhere */
static int _lv_raid_is_redundant(struct logical_volume *lv)
{
struct lv_segment *raid_seg = first_seg(lv);
uint32_t copies;
uint32_t i, s, rebuilds_per_group = 0;
uint32_t failed_components = 0;
if (!(lv->status & PARTIAL_LV)) {
/*
* Redundant, but this function shouldn't
* be called in this case.
*/
log_error(INTERNAL_ERROR "%s is not a partial LV", lv->name);
return 1;
}
if (!lv_is_raid(lv))
return 0; /* Not RAID, not redundant */
if (!strcmp(raid_seg->segtype->name, "raid10")) {
/* FIXME: We only support 2-way mirrors in RAID10 currently */
copies = 2;
for (i = 0; i < raid_seg->area_count * copies; i++) {
s = i % raid_seg->area_count;
if (!(i % copies))
rebuilds_per_group = 0;
if ((seg_lv(raid_seg, s)->status & PARTIAL_LV) ||
(seg_metalv(raid_seg, s)->status & PARTIAL_LV) ||
lv_is_virtual(seg_lv(raid_seg, s)) ||
lv_is_virtual(seg_metalv(raid_seg, s)))
rebuilds_per_group++;
if (rebuilds_per_group >= copies) {
log_debug("An entire mirror group "
"has failed in %s", lv->name);
return 0; /* Not redundant */
}
}
return 1; /* Redundant */
}
for (s = 0; s < raid_seg->area_count; s++) {
if ((seg_lv(raid_seg, s)->status & PARTIAL_LV) ||
(seg_metalv(raid_seg, s)->status & PARTIAL_LV) ||
lv_is_virtual(seg_lv(raid_seg, s)) ||
lv_is_virtual(seg_metalv(raid_seg, s)))
failed_components++;
}
if (failed_components == raid_seg->area_count) {
log_debug("All components in %s have failed", lv->name);
return 0;
} else if (raid_seg->segtype->parity_devs &&
(failed_components > raid_seg->segtype->parity_devs)) {
log_debug("More than %u components from (%s) %s/%s have failed",
raid_seg->segtype->parity_devs,
raid_seg->segtype->ops->name(raid_seg),
lv->vg->name, lv->name);
return 0;
}
return 1;
}
static int _lv_is_not_degraded_capable(struct logical_volume *lv, void *data)
{
int *not_capable = (int *)data;
uint32_t s;
struct lv_segment *seg;
if (!(lv->status & PARTIAL_LV))
return 1;
if (lv_is_raid(lv))
return _lv_raid_is_redundant(lv);
/* Ignore RAID sub-LVs. */
if (lv_is_raid_type(lv))
return 1;
dm_list_iterate_items(seg, &lv->segments)
for (s = 0; s < seg->area_count; s++)
if (seg_type(seg, s) != AREA_LV) {
log_debug("%s is not capable of degraded mode",
lv->name);
*not_capable = 1;
}
return 1;
}
static int lv_is_degraded_capable(struct logical_volume *lv)
{
int not_capable = 0;
if (!(lv->status & PARTIAL_LV))
return 1;
if (!_lv_is_not_degraded_capable(lv, &not_capable) || not_capable)
return 0;
if (!for_each_sub_lv(lv, _lv_is_not_degraded_capable, &not_capable))
log_error(INTERNAL_ERROR "for_each_sub_lv failure.");
return !not_capable;
}
static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
struct lv_activate_opts *laopts, int filter,
struct logical_volume *lv)
@ -2330,19 +2224,20 @@ static int _lv_activate(struct cmd_context *cmd, const char *lvid_s,
goto out;
}
if ((!lv->vg->cmd->partial_activation) && (lv->status & PARTIAL_LV)) {
if (!lv_is_degraded_capable(lv)) {
if ((!lv->vg->cmd->partial_activation) && (lv->status & PARTIAL_LV) && lv_is_raid_type(lv)) {
if (!partial_raid_lv_supports_degraded_activation(lv)) {
log_error("Refusing activation of partial LV %s. "
"Use '--activationmode partial' to override.",
lv->name);
goto out;
} else if (!lv->vg->cmd->degraded_activation) {
log_error("Refusing activation of partial LV %s. "
"Try '--activationmode degraded'.",
lv->name);
display_lvname(lv));
goto out;
}
if (!lv->vg->cmd->degraded_activation) {
log_error("Refusing activation of partial LV %s. "
"Try '--activationmode degraded'.",
display_lvname(lv));
goto out;
}
log_print_unless_silent("Attempting activation of partial RAID LV, %s.", lv->name);
}
if (lv_has_unknown_segments(lv)) {

View File

@ -1038,6 +1038,7 @@ int lv_raid_reshape(struct logical_volume *lv,
int lv_raid_replace(struct logical_volume *lv, struct dm_list *remove_pvs,
struct dm_list *allocate_pvs);
int lv_raid_remove_missing(struct logical_volume *lv);
int partial_raid_lv_supports_degraded_activation(struct logical_volume *lv);
/* -- metadata/raid_manip.c */
/* ++ metadata/cache_manip.c */

View File

@ -1938,3 +1938,108 @@ int lv_raid_remove_missing(struct logical_volume *lv)
return 1;
}
/* Return 1 if a partial raid LV can be activated redundantly */
static int _partial_raid_lv_is_redundant(struct logical_volume *lv)
{
struct lv_segment *raid_seg = first_seg(lv);
uint32_t copies;
uint32_t i, s, rebuilds_per_group = 0;
uint32_t failed_components = 0;
if (!strcmp(raid_seg->segtype->name, "raid10")) {
/* FIXME: We only support 2-way mirrors in RAID10 currently */
copies = 2;
for (i = 0; i < raid_seg->area_count * copies; i++) {
s = i % raid_seg->area_count;
if (!(i % copies))
rebuilds_per_group = 0;
if ((seg_lv(raid_seg, s)->status & PARTIAL_LV) ||
(seg_metalv(raid_seg, s)->status & PARTIAL_LV) ||
lv_is_virtual(seg_lv(raid_seg, s)) ||
lv_is_virtual(seg_metalv(raid_seg, s)))
rebuilds_per_group++;
if (rebuilds_per_group >= copies) {
log_verbose("An entire mirror group has failed in %s",
display_lvname(lv));
return 0; /* Insufficient redundancy to activate */
}
}
return 1; /* Redundant */
}
for (s = 0; s < raid_seg->area_count; s++) {
if ((seg_lv(raid_seg, s)->status & PARTIAL_LV) ||
(seg_metalv(raid_seg, s)->status & PARTIAL_LV) ||
lv_is_virtual(seg_lv(raid_seg, s)) ||
lv_is_virtual(seg_metalv(raid_seg, s)))
failed_components++;
}
if (failed_components == raid_seg->area_count) {
log_verbose("All components of raid LV %s have failed",
display_lvname(lv));
return 0; /* Insufficient redundancy to activate */
} else if (raid_seg->segtype->parity_devs &&
(failed_components > raid_seg->segtype->parity_devs)) {
log_verbose("More than %u components from %s %s have failed",
raid_seg->segtype->parity_devs,
raid_seg->segtype->ops->name(raid_seg),
display_lvname(lv));
return 0; /* Insufficient redundancy to activate */
}
return 1;
}
/* Sets *data to 1 if the LV cannot be activated without data loss */
static int _lv_may_be_activated_in_degraded_mode(struct logical_volume *lv, void *data)
{
int *not_capable = (int *)data;
uint32_t s;
struct lv_segment *seg;
if (*not_capable)
return 1; /* No further checks needed */
if (!(lv->status & PARTIAL_LV))
return 1;
if (lv_is_raid(lv)) {
*not_capable = !_partial_raid_lv_is_redundant(lv);
return 1;
}
/* Ignore RAID sub-LVs. */
if (lv_is_raid_type(lv))
return 1;
dm_list_iterate_items(seg, &lv->segments)
for (s = 0; s < seg->area_count; s++)
if (seg_type(seg, s) != AREA_LV) {
log_verbose("%s contains a segment incapable of degraded activation",
display_lvname(lv));
*not_capable = 1;
}
return 1;
}
int partial_raid_lv_supports_degraded_activation(struct logical_volume *lv)
{
int not_capable = 0;
if (!_lv_may_be_activated_in_degraded_mode(lv, &not_capable) || not_capable)
return 0;
if (!for_each_sub_lv(lv, _lv_may_be_activated_in_degraded_mode, &not_capable)) {
log_error(INTERNAL_ERROR "for_each_sub_lv failure.");
return 0;
}
return !not_capable;
}

View File

@ -980,10 +980,9 @@ static int _get_settings(struct cmd_context *cmd)
if (!strcmp(activation_mode, "partial")) {
cmd->partial_activation = 1;
log_warn("PARTIAL MODE. Incomplete logical volumes will be processed.");
} else if (!strcmp(activation_mode, "degraded")) {
} else if (!strcmp(activation_mode, "degraded"))
cmd->degraded_activation = 1;
log_verbose("DEGRADED MODE. Incomplete RAID LVs will be processed.");
} else if (strcmp(activation_mode, "complete")) {
else if (strcmp(activation_mode, "complete")) {
log_error("Invalid activation mode given.");
return EINVALID_CMD_LINE;
}
@ -1339,6 +1338,8 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
if ((ret = _get_settings(cmd)))
goto_out;
_apply_settings(cmd);
if (cmd->degraded_activation)
log_verbose("DEGRADED MODE. Incomplete RAID LVs will be processed.");
if (!get_activation_monitoring_mode(cmd, &monitoring))
goto_out;