You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
323 lines
9.9 KiB
323 lines
9.9 KiB
WHATS_NEW | 1 - |
|
daemons/dmeventd/plugins/raid/dmeventd_raid.c | 42 +++-------- |
|
lib/metadata/lv.c | 7 ++ |
|
lib/metadata/raid_manip.c | 2 +- |
|
test/shell/lvconvert-repair-raid.sh | 104 ++------------------------ |
|
tools/lvconvert.c | 19 +++++ |
|
6 files changed, 41 insertions(+), 134 deletions(-) |
|
|
|
diff --git a/WHATS_NEW b/WHATS_NEW |
|
index 25f6742..977e578 100644 |
|
--- a/WHATS_NEW |
|
+++ b/WHATS_NEW |
|
@@ -3,7 +3,6 @@ Version 2.02.166 - 26th September 2016 |
|
Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155) |
|
Fix lvchange-rebuild-raid.sh to cope with older target versions. |
|
Use dm_config_parse_without_dup_node_check() to speedup metadata reading. |
|
- Fix lvconvert --repair regression |
|
Fix reported origin lv field for cache volumes. (2.02.133) |
|
Always specify snapshot cow LV for monitoring not internal LV. (2.02.165) |
|
Fix lvchange --discard|--zero for active thin-pool. |
|
diff --git a/daemons/dmeventd/plugins/raid/dmeventd_raid.c b/daemons/dmeventd/plugins/raid/dmeventd_raid.c |
|
index bec594a..770fbc6 100644 |
|
--- a/daemons/dmeventd/plugins/raid/dmeventd_raid.c |
|
+++ b/daemons/dmeventd/plugins/raid/dmeventd_raid.c |
|
@@ -1,5 +1,5 @@ |
|
/* |
|
- * Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved. |
|
+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved. |
|
* |
|
* This file is part of LVM2. |
|
* |
|
@@ -13,20 +13,14 @@ |
|
*/ |
|
|
|
#include "lib.h" |
|
-#include "defaults.h" |
|
#include "dmeventd_lvm.h" |
|
#include "libdevmapper-event.h" |
|
|
|
-/* Hold enough elements for the mximum number of RAID images */ |
|
-#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64) |
|
- |
|
struct dso_state { |
|
struct dm_pool *mem; |
|
char cmd_lvscan[512]; |
|
char cmd_lvconvert[512]; |
|
- uint64_t raid_devs[RAID_DEVS_ELEMS]; |
|
int failed; |
|
- int warned; |
|
}; |
|
|
|
DM_EVENT_LOG_FN("raid") |
|
@@ -37,39 +31,20 @@ static int _process_raid_event(struct dso_state *state, char *params, const char |
|
{ |
|
struct dm_status_raid *status; |
|
const char *d; |
|
- int dead = 0, r = 1; |
|
|
|
if (!dm_get_status_raid(state->mem, params, &status)) { |
|
log_error("Failed to process status line for %s.", device); |
|
return 0; |
|
} |
|
|
|
- d = status->dev_health; |
|
- while ((d = strchr(d, 'D'))) { |
|
- uint32_t dev = (uint32_t)(d - status->dev_health); |
|
- |
|
- if (!(state->raid_devs[dev / 64] & (1 << (dev % 64)))) |
|
- log_error("Device #%u of %s array, %s, has failed.", |
|
- dev, status->raid_type, device); |
|
- |
|
- state->raid_devs[dev / 64] |= (1 << (dev % 64)); |
|
- d++; |
|
- dead = 1; |
|
- } |
|
- |
|
- if (dead) { |
|
- if (status->insync_regions < status->total_regions) { |
|
- if (!state->warned) |
|
- log_warn("WARNING: waiting for resynchronization to finish " |
|
- "before initiating repair on RAID device %s", device); |
|
- |
|
- state->warned = 1; |
|
- goto out; /* Not yet done syncing with accessible devices */ |
|
- } |
|
- |
|
+ if ((d = strchr(status->dev_health, 'D'))) { |
|
if (state->failed) |
|
goto out; /* already reported */ |
|
|
|
+ log_error("Device #%d of %s array, %s, has failed.", |
|
+ (int)(d - status->dev_health), |
|
+ status->raid_type, device); |
|
+ |
|
state->failed = 1; |
|
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan)) |
|
log_warn("WARNING: Re-scan of RAID device %s failed.", device); |
|
@@ -77,7 +52,8 @@ static int _process_raid_event(struct dso_state *state, char *params, const char |
|
/* if repair goes OK, report success even if lvscan has failed */ |
|
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) { |
|
log_info("Repair of RAID device %s failed.", device); |
|
- r = 0; |
|
+ dm_pool_free(state->mem, status); |
|
+ return 0; |
|
} |
|
} else { |
|
state->failed = 0; |
|
@@ -88,7 +64,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char |
|
out: |
|
dm_pool_free(state->mem, status); |
|
|
|
- return r; |
|
+ return 1; |
|
} |
|
|
|
void process_event(struct dm_task *dmt, |
|
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c |
|
index 70036f9..53a1044 100644 |
|
--- a/lib/metadata/lv.c |
|
+++ b/lib/metadata/lv.c |
|
@@ -988,6 +988,7 @@ int lv_mirror_image_in_sync(const struct logical_volume *lv) |
|
int lv_raid_image_in_sync(const struct logical_volume *lv) |
|
{ |
|
unsigned s; |
|
+ dm_percent_t percent; |
|
char *raid_health; |
|
struct lv_segment *seg, *raid_seg = NULL; |
|
|
|
@@ -1017,6 +1018,12 @@ int lv_raid_image_in_sync(const struct logical_volume *lv) |
|
return 0; |
|
} |
|
|
|
+ if (!lv_raid_percent(raid_seg->lv, &percent)) |
|
+ return_0; |
|
+ |
|
+ if (percent == DM_PERCENT_100) |
|
+ return 1; |
|
+ |
|
/* Find out which sub-LV this is. */ |
|
for (s = 0; s < raid_seg->area_count; s++) |
|
if (seg_lv(raid_seg, s) == lv) |
|
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
|
index deb88a2..e5fdf4f 100644 |
|
--- a/lib/metadata/raid_manip.c |
|
+++ b/lib/metadata/raid_manip.c |
|
@@ -3658,7 +3658,7 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv, |
|
return 0; |
|
} |
|
|
|
- if (!_raid_in_sync(lv)) { |
|
+ if (!mirror_in_sync() && !_raid_in_sync(lv)) { |
|
log_error("Unable to replace devices in %s/%s while it is" |
|
" not in-sync.", lv->vg->name, lv->name); |
|
return 0; |
|
diff --git a/test/shell/lvconvert-repair-raid.sh b/test/shell/lvconvert-repair-raid.sh |
|
index b51d8fe..1ef91c4 100644 |
|
--- a/test/shell/lvconvert-repair-raid.sh |
|
+++ b/test/shell/lvconvert-repair-raid.sh |
|
@@ -22,52 +22,11 @@ aux lvmconf 'allocation/maximise_cling = 0' \ |
|
|
|
aux prepare_vg 8 |
|
|
|
-function delay |
|
-{ |
|
- for d in $(< DEVICES) |
|
- do |
|
- aux delay_dev "$d" 0 $1 $(get first_extent_sector "$d") |
|
- done |
|
-} |
|
- |
|
# It's possible small raid arrays do have problems with reporting in-sync. |
|
# So try bigger size |
|
-RAID_SIZE=32 |
|
- |
|
-# Fast sync and repair afterwards |
|
-delay 0 |
|
- |
|
-# RAID1 dual-leg single replace after initial sync |
|
-lvcreate --type raid1 -m 1 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" |
|
-aux wait_for_sync $vg $lv1 |
|
-aux disable_dev "$dev2" |
|
-lvconvert -y --repair $vg/$lv1 |
|
-vgreduce --removemissing $vg |
|
-aux enable_dev "$dev2" |
|
-vgextend $vg "$dev2" |
|
-lvremove -ff $vg/$lv1 |
|
- |
|
-# Delayed sync to allow for repair during rebuild |
|
-delay 50 |
|
- |
|
-# RAID1 triple-leg single replace during initial sync |
|
-lvcreate --type raid1 -m 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" |
|
-aux disable_dev "$dev2" "$dev3" |
|
-not lvconvert -y --repair $vg/$lv1 |
|
-aux wait_for_sync $vg $lv1 |
|
-lvconvert -y --repair $vg/$lv1 |
|
-vgreduce --removemissing $vg |
|
-aux enable_dev "$dev2" "$dev3" |
|
-vgextend $vg "$dev2" "$dev3" |
|
-lvremove -ff $vg/$lv1 |
|
- |
|
- |
|
-# Larger RAID size possible for striped RAID |
|
RAID_SIZE=64 |
|
|
|
-# Fast sync and repair afterwards |
|
-delay 0 |
|
-# RAID5 single replace after initial sync |
|
+# RAID5 single replace |
|
lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" |
|
aux wait_for_sync $vg $lv1 |
|
aux disable_dev "$dev3" |
|
@@ -75,69 +34,16 @@ lvconvert -y --repair $vg/$lv1 |
|
vgreduce --removemissing $vg |
|
aux enable_dev "$dev3" |
|
vgextend $vg "$dev3" |
|
-lvremove -ff $vg/$lv1 |
|
+lvremove -ff $vg |
|
|
|
-# Delayed sync to allow for repair during rebuild |
|
-delay 50 |
|
- |
|
-# RAID5 single replace during initial sync |
|
-lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" |
|
-aux disable_dev "$dev3" |
|
-not lvconvert -y --repair $vg/$lv1 |
|
-aux wait_for_sync $vg $lv1 |
|
-lvconvert -y --repair $vg/$lv1 |
|
-vgreduce --removemissing $vg |
|
-aux enable_dev "$dev3" |
|
-vgextend $vg "$dev3" |
|
-lvremove -ff $vg/$lv1 |
|
- |
|
-# Fast sync and repair afterwards |
|
-delay 0 |
|
- |
|
-# RAID6 double replace after initial sync |
|
+# RAID6 double replace |
|
lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \ |
|
"$dev1" "$dev2" "$dev3" "$dev4" "$dev5" |
|
aux wait_for_sync $vg $lv1 |
|
aux disable_dev "$dev4" "$dev5" |
|
lvconvert -y --repair $vg/$lv1 |
|
vgreduce --removemissing $vg |
|
-aux enable_dev "$dev4" "$dev5" |
|
-vgextend $vg "$dev4" "$dev5" |
|
-lvremove -ff $vg/$lv1 |
|
- |
|
-# Delayed sync to allow for repair during rebuild |
|
-delay 50 |
|
- |
|
-# RAID6 single replace after initial sync |
|
-lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \ |
|
- "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" |
|
-aux disable_dev "$dev4" |
|
-not lvconvert -y --repair $vg/$lv1 |
|
-delay 0 # Fast sync and repair afterwards |
|
-aux disable_dev "$dev4" # Need to disable again after changing delay |
|
-aux wait_for_sync $vg $lv1 |
|
-lvconvert -y --repair $vg/$lv1 |
|
-vgreduce --removemissing $vg |
|
aux enable_dev "$dev4" |
|
-vgextend $vg "$dev4" |
|
-lvremove -ff $vg/$lv1 |
|
- |
|
-# Delayed sync to allow for repair during rebuild |
|
-delay 50 |
|
- |
|
-# RAID10 single replace after initial sync |
|
-lvcreate --type raid10 -m 1 -i 2 -L $RAID_SIZE -n $lv1 $vg \ |
|
- "$dev1" "$dev2" "$dev3" "$dev4" |
|
-aux disable_dev "$dev4" |
|
-not lvconvert -y --repair $vg/$lv1 |
|
-delay 0 # Fast sync and repair afterwards |
|
-aux disable_dev "$dev4" # Need to disable again after changing delay |
|
-aux disable_dev "$dev1" |
|
-aux wait_for_sync $vg $lv1 |
|
-lvconvert -y --repair $vg/$lv1 |
|
-vgreduce --removemissing $vg |
|
-aux enable_dev "$dev4" |
|
-vgextend $vg "$dev4" |
|
-lvremove -ff $vg/$lv1 |
|
- |
|
+aux enable_dev "$dev5" |
|
+vgextend $vg "$dev4" "$dev5" |
|
vgremove -ff $vg |
|
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
|
index 3607247..d1d21b6 100644 |
|
--- a/tools/lvconvert.c |
|
+++ b/tools/lvconvert.c |
|
@@ -1826,6 +1826,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
|
struct dm_list *failed_pvs; |
|
struct cmd_context *cmd = lv->vg->cmd; |
|
struct lv_segment *seg = first_seg(lv); |
|
+ dm_percent_t sync_percent; |
|
|
|
if (_linear_type_requested(lp->type_str)) { |
|
if (arg_is_set(cmd, mirrors_ARG) && (arg_uint_value(cmd, mirrors_ARG, 0) != 0)) { |
|
@@ -1973,6 +1974,24 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
|
return 0; |
|
} |
|
|
|
+ if (!lv_raid_percent(lv, &sync_percent)) { |
|
+ log_error("Unable to determine sync status of %s.", |
|
+ display_lvname(lv)); |
|
+ return 0; |
|
+ } |
|
+ |
|
+ if (sync_percent != DM_PERCENT_100) { |
|
+ log_warn("WARNING: %s is not in-sync.", display_lvname(lv)); |
|
+ log_warn("WARNING: Portions of the array may be unrecoverable."); |
|
+ |
|
+ /* |
|
+ * The kernel will not allow a device to be replaced |
|
+ * in an array that is not in-sync unless we override |
|
+ * by forcing the array to be considered "in-sync". |
|
+ */ |
|
+ init_mirror_in_sync(1); |
|
+ } |
|
+ |
|
_lvconvert_raid_repair_ask(cmd, lp, &replace); |
|
|
|
if (replace) {
|
|
|