summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlasdair G Kergon <agk@redhat.com>2014-09-16 00:13:46 +0100
committerAlasdair G Kergon <agk@redhat.com>2014-09-16 00:13:46 +0100
commit979be63f2537373b49e47aa3e8ce3f9bf2a4279f (patch)
treec9a5b0c098382ff201847565e9fea7afc39baaba
parent829e5a40373a2ef1721dc9210350c86c4b9d70f7 (diff)
downloadlvm2-979be63f2537373b49e47aa3e8ce3f9bf2a4279f.tar.gz
mirrors: Fix checks for mirror/raid/pvmove LVs.
Try to enforce consistent macro usage along these lines: lv_is_mirror - mirror that uses the original dm-raid1 implementation (segment type "mirror") lv_is_mirror_type - also includes internal mirror image and log LVs lv_is_raid - raid volume that uses the new dm-raid implementation (segment type "raid") lv_is_raid_type - also includes internal raid image / log / metadata LVs lv_is_mirrored - LV is mirrored using either kernel implementation (excludes non-mirror modes like raid5 etc.) lv_is_pvmove - internal pvmove volume
-rw-r--r--WHATS_NEW3
-rw-r--r--lib/activate/dev_manager.c2
-rw-r--r--lib/format_text/flags.c1
-rw-r--r--lib/format_text/import_vsn1.c3
-rw-r--r--lib/metadata/lv.c4
-rw-r--r--lib/metadata/lv_manip.c23
-rw-r--r--lib/metadata/metadata-exported.h6
-rw-r--r--lib/metadata/mirror.c10
-rw-r--r--lib/metadata/raid_manip.c1
-rw-r--r--lib/metadata/segtype.h3
-rw-r--r--lib/mirror/mirrored.c2
-rw-r--r--lib/report/report.c3
-rw-r--r--tools/lvchange.c2
-rw-r--r--tools/pvmove.c2
-rw-r--r--tools/vgreduce.c2
15 files changed, 45 insertions, 22 deletions
diff --git a/WHATS_NEW b/WHATS_NEW
index 3c0244050..70d8a9a22 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,8 @@
Version 2.02.112 -
=====================================
+ Review internal checks for mirror/raid/pvmove volumes.
+ Track mirror segment type with separate MIRROR flag.
+ Fix cmirror endian conversions.
Introduce lv_is_pvmove/locked/converting/merging macros.
Avoid leaving linear logical volume when thin pool creation fails.
Demote an error to a warning when devices known to lvmetad are filtered out.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index c5581eb24..4ee5a256c 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -2917,7 +2917,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv,
break;
case SUSPEND:
dm_tree_skip_lockfs(root);
- if (!dm->flush_required && !seg_is_raid(first_seg(lv)) && lv_is_mirrored(lv) && !lv_is_pvmove(lv))
+ if (!dm->flush_required && lv_is_mirror(lv) && !lv_is_pvmove(lv))
dm_tree_use_no_flush_suspend(root);
/* Fall through */
case SUSPEND_WITH_LOCKFS:
diff --git a/lib/format_text/flags.c b/lib/format_text/flags.c
index bc4895257..55681d4f7 100644
--- a/lib/format_text/flags.c
+++ b/lib/format_text/flags.c
@@ -67,6 +67,7 @@ static const struct flag _lv_flags[] = {
{RAID, NULL, 0},
{RAID_META, NULL, 0},
{RAID_IMAGE, NULL, 0},
+ {MIRROR, NULL, 0},
{MIRROR_IMAGE, NULL, 0},
{MIRROR_LOG, NULL, 0},
{MIRRORED, NULL, 0},
diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c
index 9ddf99e88..174b3bf31 100644
--- a/lib/format_text/import_vsn1.c
+++ b/lib/format_text/import_vsn1.c
@@ -386,6 +386,9 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
*/
_insert_segment(lv, seg);
+ if (seg_is_mirror(seg))
+ lv->status |= MIRROR;
+
if (seg_is_mirrored(seg))
lv->status |= MIRRORED;
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index a8ad2d251..3ebb14d6e 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -361,7 +361,7 @@ char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (seg->status & PVMOVE) {
if (seg_type(seg, 0) == AREA_LV) { /* atomic pvmove */
mimage0_lv = seg_lv(seg, 0);
- if (!lv_is_mirrored(mimage0_lv)) {
+ if (!lv_is_mirror_image(mimage0_lv)) {
log_error(INTERNAL_ERROR
"Bad pvmove structure");
return NULL;
@@ -648,7 +648,7 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[0] = 'C';
else if (lv_is_raid(lv))
repstr[0] = (lv->status & LV_NOTSYNCED) ? 'R' : 'r';
- else if (lv_is_mirrored(lv))
+ else if (lv_is_mirror(lv))
repstr[0] = (lv->status & LV_NOTSYNCED) ? 'M' : 'm';
else if (lv_is_thin_volume(lv))
repstr[0] = lv_is_merging_origin(lv) ?
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 6d80dfb30..58bc79b06 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -231,6 +231,10 @@ static int _lv_layout_and_role_raid(struct dm_pool *mem,
if (!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_RAID]) ||
!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_METADATA]))
goto_bad;
+ } else if (lv_is_pvmove(lv)) {
+ if (!str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_PVMOVE]) ||
+ !str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID]))
+ goto_bad;
} else
top_level = 1;
@@ -464,7 +468,7 @@ int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
}
/* Mirrors and related */
- if ((lv_is_mirror_type(lv) || lv_is_pvmove(lv)) && !lv_is_raid(lv) &&
+ if ((lv_is_mirror_type(lv) || lv_is_pvmove(lv)) &&
!_lv_layout_and_role_mirror(mem, lv, *layout, *role, &public_lv))
goto_bad;
@@ -985,6 +989,12 @@ struct lv_segment *alloc_lv_segment(const struct segment_type *segtype,
if (log_lv && !attach_mirror_log(seg, log_lv))
return_NULL;
+ if (segtype_is_mirror(segtype))
+ lv->status |= MIRROR;
+
+ if (segtype_is_mirrored(segtype))
+ lv->status |= MIRRORED;
+
return seg;
}
@@ -1347,9 +1357,10 @@ int replace_lv_with_error_segment(struct logical_volume *lv)
* an error segment, we should also clear any flags
* that suggest it is anything other than "error".
*/
- lv->status &= ~(MIRRORED|PVMOVE|LOCKED);
+ /* FIXME Check for other flags that need removing */
+ lv->status &= ~(MIRROR|MIRRORED|PVMOVE|LOCKED);
- /* FIXME: Should we bug if we find a log_lv attached? */
+ /* FIXME Check for any attached LVs that will become orphans e.g. mirror logs */
if (!lv_add_virtual_segment(lv, 0, len, get_segtype_from_string(lv->vg->cmd, "error"), NULL))
return_0;
@@ -1858,9 +1869,6 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size;
- if (segtype_is_mirrored(segtype))
- lv->status |= MIRRORED;
-
return 1;
}
@@ -6723,8 +6731,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL;
}
- if (lv_is_mirror_type(org) &&
- !seg_is_raid(first_seg(org))) {
+ if (lv_is_mirror_type(org)) {
log_warn("WARNING: Snapshots of mirrors can deadlock under rare device failures.");
log_warn("WARNING: Consider using the raid1 mirror type to avoid this.");
log_warn("WARNING: See global/mirror_segtype_default in lvm.conf.");
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 0026ba920..01b04ffc1 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -67,6 +67,7 @@
#define LOCKED UINT64_C(0x0000000000004000) /* LV */
#define MIRRORED UINT64_C(0x0000000000008000) /* LV - internal use only */
//#define VIRTUAL UINT64_C(0x0000000000010000) /* LV - internal use only */
+#define MIRROR UINT64_C(0x0002000000000000) /* LV - Internal use only */
#define MIRROR_LOG UINT64_C(0x0000000000020000) /* LV - Internal use only */
#define MIRROR_IMAGE UINT64_C(0x0000000000040000) /* LV - Internal use only */
@@ -115,7 +116,7 @@
#define CACHE_POOL_METADATA UINT64_C(0x0000800000000000) /* LV - Internal use only */
#define CACHE UINT64_C(0x0001000000000000) /* LV - Internal use only */
-/* Next unused flag: UINT64_C(0x0002000000000000) */
+/* Next unused flag: UINT64_C(0x0004000000000000) */
/* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */
@@ -181,7 +182,8 @@
#define lv_is_mirror_image(lv) (((lv)->status & MIRROR_IMAGE) ? 1 : 0)
#define lv_is_mirror_log(lv) (((lv)->status & MIRROR_LOG) ? 1 : 0)
-#define lv_is_mirror_type(lv) (((lv)->status & (MIRROR_LOG | MIRROR_IMAGE | MIRRORED)) ? 1 : 0)
+#define lv_is_mirror(lv) (((lv)->status & MIRROR) ? 1 : 0)
+#define lv_is_mirror_type(lv) (((lv)->status & (MIRROR | MIRROR_LOG | MIRROR_IMAGE)) ? 1 : 0)
#define lv_is_pvmove(lv) (((lv)->status & PVMOVE) ? 1 : 0)
diff --git a/lib/metadata/mirror.c b/lib/metadata/mirror.c
index 4505eb900..0fc9314ac 100644
--- a/lib/metadata/mirror.c
+++ b/lib/metadata/mirror.c
@@ -742,6 +742,7 @@ static int _split_mirror_images(struct logical_volume *lv,
detached_log_lv = detach_mirror_log(mirrored_seg);
if (!remove_layer_from_lv(lv, sub_lv))
return_0;
+ lv->status &= ~MIRROR;
lv->status &= ~MIRRORED;
lv->status &= ~LV_NOTSYNCED;
}
@@ -941,6 +942,7 @@ static int _remove_mirror_images(struct logical_volume *lv,
* mirror. Fix up the flags if we only have one image left.
*/
if (lv_mirror_count(lv) == 1) {
+ lv->status &= ~MIRROR;
lv->status &= ~MIRRORED;
lv->status &= ~LV_NOTSYNCED;
}
@@ -957,6 +959,7 @@ static int _remove_mirror_images(struct logical_volume *lv,
/* All mirror images are gone.
* It can happen for vgreduce --removemissing. */
detached_log_lv = detach_mirror_log(mirrored_seg);
+ lv->status &= ~MIRROR;
lv->status &= ~MIRRORED;
lv->status &= ~LV_NOTSYNCED;
if (!replace_lv_with_error_segment(lv))
@@ -1502,9 +1505,10 @@ const char *get_pvmove_pvname_from_lv_mirr(struct logical_volume *lv_mirr)
dm_list_iterate_items(seg, &lv_mirr->segments) {
if (!seg_is_mirrored(seg))
continue;
- if (seg_type(seg, 0) != AREA_PV)
- continue;
- return dev_name(seg_dev(seg, 0));
+ if (seg_type(seg, 0) == AREA_PV)
+ return dev_name(seg_dev(seg, 0));
+ if (seg_type(seg, 0) == AREA_LV)
+ return dev_name(seg_dev(first_seg(seg_lv(seg, 0)), 0));
}
return NULL;
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index c9ac4054e..f494f11bf 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -1403,6 +1403,7 @@ static int _convert_mirror_to_raid1(struct logical_volume *lv,
log_debug_metadata("Setting new segtype for %s", lv->name);
seg->segtype = new_segtype;
+ lv->status &= ~MIRROR;
lv->status &= ~MIRRORED;
lv->status |= RAID;
seg->status |= RAID;
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 080cf4ea6..e0c46df18 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -43,11 +43,13 @@ struct dev_manager;
#define SEG_THIN_VOLUME 0x00001000U
#define SEG_CACHE 0x00002000U
#define SEG_CACHE_POOL 0x00004000U
+#define SEG_MIRROR 0x00008000U
#define SEG_UNKNOWN 0x80000000U
#define segtype_is_cache(segtype) ((segtype)->flags & SEG_CACHE ? 1 : 0)
#define segtype_is_cache_pool(segtype) ((segtype)->flags & SEG_CACHE_POOL ? 1 : 0)
#define segtype_is_mirrored(segtype) ((segtype)->flags & SEG_AREAS_MIRRORED ? 1 : 0)
+#define segtype_is_mirror(segtype) ((segtype)->flags & SEG_MIRROR ? 1 : 0)
#define segtype_is_pool(segtype) ((segtype)->flags & (SEG_CACHE_POOL | SEG_THIN_POOL) ? 1 : 0)
#define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
@@ -59,6 +61,7 @@ struct dev_manager;
#define seg_is_cache(seg) segtype_is_cache((seg)->segtype)
#define seg_is_cache_pool(seg) segtype_is_cache_pool((seg)->segtype)
#define seg_is_linear(seg) (seg_is_striped(seg) && ((seg)->area_count == 1))
+#define seg_is_mirror(seg) segtype_is_mirror((seg)->segtype)
#define seg_is_mirrored(seg) segtype_is_mirrored((seg)->segtype)
#define seg_is_pool(seg) segtype_is_pool((seg)->segtype)
#define seg_is_raid(seg) segtype_is_raid((seg)->segtype)
diff --git a/lib/mirror/mirrored.c b/lib/mirror/mirrored.c
index 1ab06cefd..74a8e376b 100644
--- a/lib/mirror/mirrored.c
+++ b/lib/mirror/mirrored.c
@@ -628,7 +628,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->ops = &_mirrored_ops;
segtype->name = "mirror";
segtype->private = NULL;
- segtype->flags = SEG_AREAS_MIRRORED;
+ segtype->flags = SEG_MIRROR | SEG_AREAS_MIRRORED;
#ifdef DEVMAPPER_SUPPORT
# ifdef DMEVENTD
diff --git a/lib/report/report.c b/lib/report/report.c
index 24bc437b0..c34aa5e6f 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -1042,8 +1042,7 @@ static int _copypercent_disp(struct dm_report *rh,
dm_percent_t percent = DM_PERCENT_INVALID;
if (((lv_is_raid(lv) && lv_raid_percent(lv, &percent)) ||
- ((lv_is_pvmove(lv) || lv_is_mirrored(lv)) &&
- lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL))) &&
+ (lv_is_mirror(lv) && lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL))) &&
(percent != DM_PERCENT_INVALID)) {
percent = copy_percent(lv);
return dm_report_field_percent(rh, field, &percent);
diff --git a/tools/lvchange.c b/tools/lvchange.c
index 3ac5165a6..e0e3b03a3 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -287,7 +287,7 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
dm_list_init(&device_list);
- if (!lv_is_mirrored(lv) && !seg_is_raid(seg)) {
+ if (!seg_is_mirror(seg) && !seg_is_raid(seg)) {
log_error("Unable to resync %s. It is not RAID or mirrored.",
lv->name);
return 0;
diff --git a/tools/pvmove.c b/tools/pvmove.c
index 5b458b1ea..a9d750ded 100644
--- a/tools/pvmove.c
+++ b/tools/pvmove.c
@@ -325,7 +325,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
*
* Allow clustered mirror, but not raid mirror.
*/
- if (vg_is_clustered(lv->vg) && (!lv_is_mirror_type(lv) || lv_is_raid(lv)))
+ if (vg_is_clustered(lv->vg) && !lv_is_mirror_type(lv))
continue;
if (!lv_is_on_pvs(lv, source_pvl))
diff --git a/tools/vgreduce.c b/tools/vgreduce.c
index 62162af23..970f61c4e 100644
--- a/tools/vgreduce.c
+++ b/tools/vgreduce.c
@@ -95,7 +95,7 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
goto restart;
}
- if (lv_is_mirrored(lv)) {
+ if (lv_is_mirror(lv)) {
if (!mirror_remove_missing(cmd, lv, 1))
return_0;
goto restart;