mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-02 01:18:26 +03:00
RAID: Make 'vgreduce --removemissing' work with RAID LVs
Currently it is impossible to remove a failed PV which has a RAID LV on it. This patch fixes the issue by replacing the failed PV with an 'error' segment within the affected sub-LVs. Once there is no longer a RAID LV using the PV, it can be removed. Most often, it is better to replace a failed RAID device with a spare. (You can use 'lvconvert --repair <vg>/<LV>' to accomplish that.) However, if there are no spares in the volume group and none will be added, it is useful to be able to removed the failed device. Following patches address the ability to perform 'lvconvert' operations on RAID LVs that contain sub-LVs composed of 'error' segments.
This commit is contained in:
parent
0e4ffd9d3b
commit
845852d6b4
@ -1,5 +1,6 @@
|
|||||||
Version 2.02.99 -
|
Version 2.02.99 -
|
||||||
===================================
|
===================================
|
||||||
|
Make 'vgreduce --removemissing' able to handle RAID LVs with missing PVs.
|
||||||
Rename lvm.conf setting 'mirror_region_size' to 'raid_region_size'.
|
Rename lvm.conf setting 'mirror_region_size' to 'raid_region_size'.
|
||||||
Fix pvs -o pv_free reporting for PVs with zero PE count.
|
Fix pvs -o pv_free reporting for PVs with zero PE count.
|
||||||
Fix missing cleanup of flags when the LV is detached from pool.
|
Fix missing cleanup of flags when the LV is detached from pool.
|
||||||
|
@ -808,6 +808,7 @@ int lv_raid_reshape(struct logical_volume *lv,
|
|||||||
const struct segment_type *new_segtype);
|
const struct segment_type *new_segtype);
|
||||||
int lv_raid_replace(struct logical_volume *lv, struct dm_list *remove_pvs,
|
int lv_raid_replace(struct logical_volume *lv, struct dm_list *remove_pvs,
|
||||||
struct dm_list *allocate_pvs);
|
struct dm_list *allocate_pvs);
|
||||||
|
int lv_raid_remove_missing(struct logical_volume *lv);
|
||||||
|
|
||||||
/* -- metadata/raid_manip.c */
|
/* -- metadata/raid_manip.c */
|
||||||
|
|
||||||
|
@ -1853,3 +1853,67 @@ try_again:
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lv_raid_remove_missing(struct logical_volume *lv)
|
||||||
|
{
|
||||||
|
uint32_t s, lvl_idx;
|
||||||
|
struct lv_segment *seg = first_seg(lv);
|
||||||
|
struct cmd_context *cmd = lv->vg->cmd;
|
||||||
|
|
||||||
|
if (!(lv->status & PARTIAL_LV)) {
|
||||||
|
log_error(INTERNAL_ERROR "%s/%s is not a partial LV",
|
||||||
|
lv->vg->name, lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("Attempting to remove missing devices from %s LV, %s",
|
||||||
|
seg->segtype->ops->name(seg), lv->name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FIXME: Make sure # of compromised components will not affect RAID
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (s = 0, lvl_idx = 0; s < seg->area_count; s++) {
|
||||||
|
if (!(seg_lv(seg, s)->status & PARTIAL_LV) &&
|
||||||
|
!(seg_metalv(seg, s)->status & PARTIAL_LV))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
log_debug("Replacing %s and %s segments with error target",
|
||||||
|
seg_lv(seg, s)->name, seg_metalv(seg, s)->name);
|
||||||
|
if (!replace_lv_with_error_segment(seg_lv(seg, s))) {
|
||||||
|
log_error("Failed to replace %s/%s's extents"
|
||||||
|
" with error target", lv->vg->name,
|
||||||
|
seg_lv(seg, s)->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!replace_lv_with_error_segment(seg_metalv(seg, s))) {
|
||||||
|
log_error("Failed to replace %s/%s's extents"
|
||||||
|
" with error target", lv->vg->name,
|
||||||
|
seg_metalv(seg, s)->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vg_write(lv->vg)) {
|
||||||
|
log_error("Failed to write changes to %s in %s",
|
||||||
|
lv->name, lv->vg->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!suspend_lv(cmd, lv)) {
|
||||||
|
log_error("Failed to suspend %s/%s before committing changes",
|
||||||
|
lv->vg->name, lv->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vg_commit(lv->vg)) {
|
||||||
|
log_error("Failed to commit changes to %s in %s",
|
||||||
|
lv->name, lv->vg->name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!resume_lv(cmd, lv))
|
||||||
|
return_0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
@ -89,6 +89,12 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
|
|||||||
|
|
||||||
/* Are any segments of this LV on missing PVs? */
|
/* Are any segments of this LV on missing PVs? */
|
||||||
if (lv->status & PARTIAL_LV) {
|
if (lv->status & PARTIAL_LV) {
|
||||||
|
if (seg_is_raid(first_seg(lv))) {
|
||||||
|
if (!lv_raid_remove_missing(lv))
|
||||||
|
return_0;
|
||||||
|
goto restart;
|
||||||
|
}
|
||||||
|
|
||||||
if (lv->status & MIRRORED) {
|
if (lv->status & MIRRORED) {
|
||||||
if (!mirror_remove_missing(cmd, lv, 1))
|
if (!mirror_remove_missing(cmd, lv, 1))
|
||||||
return_0;
|
return_0;
|
||||||
|
Loading…
Reference in New Issue
Block a user