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

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
This commit is contained in:
Alasdair G Kergon 2014-09-16 00:13:46 +01:00
parent 829e5a4037
commit 979be63f25
15 changed files with 45 additions and 22 deletions

View File

@ -1,5 +1,8 @@
Version 2.02.112 - 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. Introduce lv_is_pvmove/locked/converting/merging macros.
Avoid leaving linear logical volume when thin pool creation fails. Avoid leaving linear logical volume when thin pool creation fails.
Demote an error to a warning when devices known to lvmetad are filtered out. Demote an error to a warning when devices known to lvmetad are filtered out.

View File

@ -2917,7 +2917,7 @@ static int _tree_action(struct dev_manager *dm, struct logical_volume *lv,
break; break;
case SUSPEND: case SUSPEND:
dm_tree_skip_lockfs(root); 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); dm_tree_use_no_flush_suspend(root);
/* Fall through */ /* Fall through */
case SUSPEND_WITH_LOCKFS: case SUSPEND_WITH_LOCKFS:

View File

@ -67,6 +67,7 @@ static const struct flag _lv_flags[] = {
{RAID, NULL, 0}, {RAID, NULL, 0},
{RAID_META, NULL, 0}, {RAID_META, NULL, 0},
{RAID_IMAGE, NULL, 0}, {RAID_IMAGE, NULL, 0},
{MIRROR, NULL, 0},
{MIRROR_IMAGE, NULL, 0}, {MIRROR_IMAGE, NULL, 0},
{MIRROR_LOG, NULL, 0}, {MIRROR_LOG, NULL, 0},
{MIRRORED, NULL, 0}, {MIRRORED, NULL, 0},

View File

@ -386,6 +386,9 @@ static int _read_segment(struct logical_volume *lv, const struct dm_config_node
*/ */
_insert_segment(lv, seg); _insert_segment(lv, seg);
if (seg_is_mirror(seg))
lv->status |= MIRROR;
if (seg_is_mirrored(seg)) if (seg_is_mirrored(seg))
lv->status |= MIRRORED; lv->status |= MIRRORED;

View File

@ -361,7 +361,7 @@ char *lv_move_pv_dup(struct dm_pool *mem, const struct logical_volume *lv)
if (seg->status & PVMOVE) { if (seg->status & PVMOVE) {
if (seg_type(seg, 0) == AREA_LV) { /* atomic pvmove */ if (seg_type(seg, 0) == AREA_LV) { /* atomic pvmove */
mimage0_lv = seg_lv(seg, 0); mimage0_lv = seg_lv(seg, 0);
if (!lv_is_mirrored(mimage0_lv)) { if (!lv_is_mirror_image(mimage0_lv)) {
log_error(INTERNAL_ERROR log_error(INTERNAL_ERROR
"Bad pvmove structure"); "Bad pvmove structure");
return NULL; return NULL;
@ -648,7 +648,7 @@ char *lv_attr_dup(struct dm_pool *mem, const struct logical_volume *lv)
repstr[0] = 'C'; repstr[0] = 'C';
else if (lv_is_raid(lv)) else if (lv_is_raid(lv))
repstr[0] = (lv->status & LV_NOTSYNCED) ? 'R' : 'r'; 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'; repstr[0] = (lv->status & LV_NOTSYNCED) ? 'M' : 'm';
else if (lv_is_thin_volume(lv)) else if (lv_is_thin_volume(lv))
repstr[0] = lv_is_merging_origin(lv) ? repstr[0] = lv_is_merging_origin(lv) ?

View File

@ -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]) || 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])) !str_list_add_no_dup_check(mem, role, _lv_type_names[LV_TYPE_METADATA]))
goto_bad; 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 } else
top_level = 1; top_level = 1;
@ -464,7 +468,7 @@ int lv_layout_and_role(struct dm_pool *mem, const struct logical_volume *lv,
} }
/* Mirrors and related */ /* 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)) !_lv_layout_and_role_mirror(mem, lv, *layout, *role, &public_lv))
goto_bad; 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)) if (log_lv && !attach_mirror_log(seg, log_lv))
return_NULL; return_NULL;
if (segtype_is_mirror(segtype))
lv->status |= MIRROR;
if (segtype_is_mirrored(segtype))
lv->status |= MIRRORED;
return seg; 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 * an error segment, we should also clear any flags
* that suggest it is anything other than "error". * 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)) if (!lv_add_virtual_segment(lv, 0, len, get_segtype_from_string(lv->vg->cmd, "error"), NULL))
return_0; return_0;
@ -1858,9 +1869,6 @@ static int _setup_alloced_segment(struct logical_volume *lv, uint64_t status,
lv->le_count += extents; lv->le_count += extents;
lv->size += (uint64_t) extents *lv->vg->extent_size; lv->size += (uint64_t) extents *lv->vg->extent_size;
if (segtype_is_mirrored(segtype))
lv->status |= MIRRORED;
return 1; return 1;
} }
@ -6723,8 +6731,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
return NULL; return NULL;
} }
if (lv_is_mirror_type(org) && if (lv_is_mirror_type(org)) {
!seg_is_raid(first_seg(org))) {
log_warn("WARNING: Snapshots of mirrors can deadlock under rare device failures."); 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: Consider using the raid1 mirror type to avoid this.");
log_warn("WARNING: See global/mirror_segtype_default in lvm.conf."); log_warn("WARNING: See global/mirror_segtype_default in lvm.conf.");

View File

@ -67,6 +67,7 @@
#define LOCKED UINT64_C(0x0000000000004000) /* LV */ #define LOCKED UINT64_C(0x0000000000004000) /* LV */
#define MIRRORED UINT64_C(0x0000000000008000) /* LV - internal use only */ #define MIRRORED UINT64_C(0x0000000000008000) /* LV - internal use only */
//#define VIRTUAL UINT64_C(0x0000000000010000) /* 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_LOG UINT64_C(0x0000000000020000) /* LV - Internal use only */
#define MIRROR_IMAGE UINT64_C(0x0000000000040000) /* 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_POOL_METADATA UINT64_C(0x0000800000000000) /* LV - Internal use only */
#define CACHE UINT64_C(0x0001000000000000) /* 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 */ /* Format features flags */
#define FMT_SEGMENTS 0x00000001U /* Arbitrary segment params? */ #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_image(lv) (((lv)->status & MIRROR_IMAGE) ? 1 : 0)
#define lv_is_mirror_log(lv) (((lv)->status & MIRROR_LOG) ? 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) #define lv_is_pvmove(lv) (((lv)->status & PVMOVE) ? 1 : 0)

View File

@ -742,6 +742,7 @@ static int _split_mirror_images(struct logical_volume *lv,
detached_log_lv = detach_mirror_log(mirrored_seg); detached_log_lv = detach_mirror_log(mirrored_seg);
if (!remove_layer_from_lv(lv, sub_lv)) if (!remove_layer_from_lv(lv, sub_lv))
return_0; return_0;
lv->status &= ~MIRROR;
lv->status &= ~MIRRORED; lv->status &= ~MIRRORED;
lv->status &= ~LV_NOTSYNCED; 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. * mirror. Fix up the flags if we only have one image left.
*/ */
if (lv_mirror_count(lv) == 1) { if (lv_mirror_count(lv) == 1) {
lv->status &= ~MIRROR;
lv->status &= ~MIRRORED; lv->status &= ~MIRRORED;
lv->status &= ~LV_NOTSYNCED; lv->status &= ~LV_NOTSYNCED;
} }
@ -957,6 +959,7 @@ static int _remove_mirror_images(struct logical_volume *lv,
/* All mirror images are gone. /* All mirror images are gone.
* It can happen for vgreduce --removemissing. */ * It can happen for vgreduce --removemissing. */
detached_log_lv = detach_mirror_log(mirrored_seg); detached_log_lv = detach_mirror_log(mirrored_seg);
lv->status &= ~MIRROR;
lv->status &= ~MIRRORED; lv->status &= ~MIRRORED;
lv->status &= ~LV_NOTSYNCED; lv->status &= ~LV_NOTSYNCED;
if (!replace_lv_with_error_segment(lv)) 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) { dm_list_iterate_items(seg, &lv_mirr->segments) {
if (!seg_is_mirrored(seg)) if (!seg_is_mirrored(seg))
continue; continue;
if (seg_type(seg, 0) != AREA_PV) if (seg_type(seg, 0) == AREA_PV)
continue; return dev_name(seg_dev(seg, 0));
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; return NULL;

View File

@ -1403,6 +1403,7 @@ static int _convert_mirror_to_raid1(struct logical_volume *lv,
log_debug_metadata("Setting new segtype for %s", lv->name); log_debug_metadata("Setting new segtype for %s", lv->name);
seg->segtype = new_segtype; seg->segtype = new_segtype;
lv->status &= ~MIRROR;
lv->status &= ~MIRRORED; lv->status &= ~MIRRORED;
lv->status |= RAID; lv->status |= RAID;
seg->status |= RAID; seg->status |= RAID;

View File

@ -43,11 +43,13 @@ struct dev_manager;
#define SEG_THIN_VOLUME 0x00001000U #define SEG_THIN_VOLUME 0x00001000U
#define SEG_CACHE 0x00002000U #define SEG_CACHE 0x00002000U
#define SEG_CACHE_POOL 0x00004000U #define SEG_CACHE_POOL 0x00004000U
#define SEG_MIRROR 0x00008000U
#define SEG_UNKNOWN 0x80000000U #define SEG_UNKNOWN 0x80000000U
#define segtype_is_cache(segtype) ((segtype)->flags & SEG_CACHE ? 1 : 0) #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_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_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_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_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 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(seg) segtype_is_cache((seg)->segtype)
#define seg_is_cache_pool(seg) segtype_is_cache_pool((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_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_mirrored(seg) segtype_is_mirrored((seg)->segtype)
#define seg_is_pool(seg) segtype_is_pool((seg)->segtype) #define seg_is_pool(seg) segtype_is_pool((seg)->segtype)
#define seg_is_raid(seg) segtype_is_raid((seg)->segtype) #define seg_is_raid(seg) segtype_is_raid((seg)->segtype)

View File

@ -628,7 +628,7 @@ struct segment_type *init_segtype(struct cmd_context *cmd)
segtype->ops = &_mirrored_ops; segtype->ops = &_mirrored_ops;
segtype->name = "mirror"; segtype->name = "mirror";
segtype->private = NULL; segtype->private = NULL;
segtype->flags = SEG_AREAS_MIRRORED; segtype->flags = SEG_MIRROR | SEG_AREAS_MIRRORED;
#ifdef DEVMAPPER_SUPPORT #ifdef DEVMAPPER_SUPPORT
# ifdef DMEVENTD # ifdef DMEVENTD

View File

@ -1042,8 +1042,7 @@ static int _copypercent_disp(struct dm_report *rh,
dm_percent_t percent = DM_PERCENT_INVALID; dm_percent_t percent = DM_PERCENT_INVALID;
if (((lv_is_raid(lv) && lv_raid_percent(lv, &percent)) || if (((lv_is_raid(lv) && lv_raid_percent(lv, &percent)) ||
((lv_is_pvmove(lv) || lv_is_mirrored(lv)) && (lv_is_mirror(lv) && lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL))) &&
lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL))) &&
(percent != DM_PERCENT_INVALID)) { (percent != DM_PERCENT_INVALID)) {
percent = copy_percent(lv); percent = copy_percent(lv);
return dm_report_field_percent(rh, field, &percent); return dm_report_field_percent(rh, field, &percent);

View File

@ -287,7 +287,7 @@ static int lvchange_resync(struct cmd_context *cmd, struct logical_volume *lv)
dm_list_init(&device_list); 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.", log_error("Unable to resync %s. It is not RAID or mirrored.",
lv->name); lv->name);
return 0; return 0;

View File

@ -325,7 +325,7 @@ static struct logical_volume *_set_up_pvmove_lv(struct cmd_context *cmd,
* *
* Allow clustered mirror, but not raid mirror. * 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; continue;
if (!lv_is_on_pvs(lv, source_pvl)) if (!lv_is_on_pvs(lv, source_pvl))

View File

@ -95,7 +95,7 @@ static int _make_vg_consistent(struct cmd_context *cmd, struct volume_group *vg)
goto restart; goto restart;
} }
if (lv_is_mirrored(lv)) { if (lv_is_mirror(lv)) {
if (!mirror_remove_missing(cmd, lv, 1)) if (!mirror_remove_missing(cmd, lv, 1))
return_0; return_0;
goto restart; goto restart;