master - raid: Revert _lv_extend_layered_lv non-raid0 area_multiple.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7fffcce9247cba...
Commit: 7fffcce9247cba8ecb40a1c7b0c6d18a5cde2165
Parent: adeb624c3bdfa5b444becb6918486b49a8d9ce4d
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue May 24 14:27:05 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue May 24 14:27:05 2016 +0100
raid: Revert _lv_extend_layered_lv non-raid0 area_multiple.
---
lib/metadata/lv_manip.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 8a2c728..6c2d4e5 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3805,7 +3805,8 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
if (seg_is_raid(seg)) {
stripes = 1;
stripe_size = 0;
- area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, stripes);
+ if (seg_is_raid0(seg))
+ area_multiple = seg->area_count;
}
for (fa = first_area, s = 0; s < seg->area_count; s++) {
7 years, 11 months
master - refactor: split _report fn further into init and config part
by Peter Rajnoha
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=adeb624c3bdfa5...
Commit: adeb624c3bdfa5b444becb6918486b49a8d9ce4d
Parent: 8c872852cdbc4c3f9572379bc87e1455b28fbe6f
Author: Peter Rajnoha <prajnoha(a)redhat.com>
AuthorDate: Mon May 23 11:18:50 2016 +0200
Committer: Peter Rajnoha <prajnoha(a)redhat.com>
CommitterDate: Tue May 24 10:56:57 2016 +0200
refactor: split _report fn further into init and config part
---
tools/reporter.c | 123 +++++++++++++++++++++++++++++------------------------
1 files changed, 67 insertions(+), 56 deletions(-)
diff --git a/tools/reporter.c b/tools/reporter.c
index 4004f9b..04ef8f2 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -628,6 +628,9 @@ static void _check_pv_list(struct cmd_context *cmd, struct report_args *args)
unsigned i;
int rescan_done = 0;
+ if (!args->argv)
+ return;
+
args->args_are_pvs = (args->report_type == PVS ||
args->report_type == LABEL ||
args->report_type == PVSEGS) ? 1 : 0;
@@ -898,76 +901,62 @@ out:
return r;
}
-static int _report(struct cmd_context *cmd, int argc, char **argv, report_type_t report_type)
+static int _config_report(struct cmd_context *cmd, struct report_args *args)
{
- struct report_args args = {0};
-
- /*
- * Include foreign VGs that contain active LVs.
- * That shouldn't happen in general, but if it does by some
- * mistake, then we want to display those VGs and allow the
- * LVs to be deactivated.
- */
- cmd->include_active_foreign_vgs = 1;
-
- args.argc = argc;
- args.argv = argv;
- args.report_type = report_type;
-
- args.aligned = find_config_tree_bool(cmd, report_aligned_CFG, NULL);
- args.buffered = find_config_tree_bool(cmd, report_buffered_CFG, NULL);
- args.headings = find_config_tree_bool(cmd, report_headings_CFG, NULL);
- args.separator = find_config_tree_str(cmd, report_separator_CFG, NULL);
- args.field_prefixes = find_config_tree_bool(cmd, report_prefixes_CFG, NULL);
- args.quoted = find_config_tree_bool(cmd, report_quoted_CFG, NULL);
- args.columns_as_rows = find_config_tree_bool(cmd, report_colums_as_rows_CFG, NULL);
+ args->aligned = find_config_tree_bool(cmd, report_aligned_CFG, NULL);
+ args->buffered = find_config_tree_bool(cmd, report_buffered_CFG, NULL);
+ args->headings = find_config_tree_bool(cmd, report_headings_CFG, NULL);
+ args->separator = find_config_tree_str(cmd, report_separator_CFG, NULL);
+ args->field_prefixes = find_config_tree_bool(cmd, report_prefixes_CFG, NULL);
+ args->quoted = find_config_tree_bool(cmd, report_quoted_CFG, NULL);
+ args->columns_as_rows = find_config_tree_bool(cmd, report_colums_as_rows_CFG, NULL);
/* Check PV specifics and do extra changes/actions if needed. */
- _check_pv_list(cmd, &args);
+ _check_pv_list(cmd, args);
- switch (args.report_type) {
+ switch (args->report_type) {
case DEVTYPES:
- args.keys = find_config_tree_str(cmd, report_devtypes_sort_CFG, NULL);
+ args->keys = find_config_tree_str(cmd, report_devtypes_sort_CFG, NULL);
if (!arg_count(cmd, verbose_ARG))
- args.options = find_config_tree_str(cmd, report_devtypes_cols_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_devtypes_cols_CFG, NULL);
else
- args.options = find_config_tree_str(cmd, report_devtypes_cols_verbose_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_devtypes_cols_verbose_CFG, NULL);
break;
case LVS:
- args.keys = find_config_tree_str(cmd, report_lvs_sort_CFG, NULL);
+ args->keys = find_config_tree_str(cmd, report_lvs_sort_CFG, NULL);
if (!arg_count(cmd, verbose_ARG))
- args.options = find_config_tree_str(cmd, report_lvs_cols_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_lvs_cols_CFG, NULL);
else
- args.options = find_config_tree_str(cmd, report_lvs_cols_verbose_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_lvs_cols_verbose_CFG, NULL);
break;
case VGS:
- args.keys = find_config_tree_str(cmd, report_vgs_sort_CFG, NULL);
+ args->keys = find_config_tree_str(cmd, report_vgs_sort_CFG, NULL);
if (!arg_count(cmd, verbose_ARG))
- args.options = find_config_tree_str(cmd, report_vgs_cols_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_vgs_cols_CFG, NULL);
else
- args.options = find_config_tree_str(cmd, report_vgs_cols_verbose_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_vgs_cols_verbose_CFG, NULL);
break;
case LABEL:
case PVS:
- args.keys = find_config_tree_str(cmd, report_pvs_sort_CFG, NULL);
+ args->keys = find_config_tree_str(cmd, report_pvs_sort_CFG, NULL);
if (!arg_count(cmd, verbose_ARG))
- args.options = find_config_tree_str(cmd, report_pvs_cols_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_pvs_cols_CFG, NULL);
else
- args.options = find_config_tree_str(cmd, report_pvs_cols_verbose_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_pvs_cols_verbose_CFG, NULL);
break;
case SEGS:
- args.keys = find_config_tree_str(cmd, report_segs_sort_CFG, NULL);
+ args->keys = find_config_tree_str(cmd, report_segs_sort_CFG, NULL);
if (!arg_count(cmd, verbose_ARG))
- args.options = find_config_tree_str(cmd, report_segs_cols_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_segs_cols_CFG, NULL);
else
- args.options = find_config_tree_str(cmd, report_segs_cols_verbose_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_segs_cols_verbose_CFG, NULL);
break;
case PVSEGS:
- args.keys = find_config_tree_str(cmd, report_pvsegs_sort_CFG, NULL);
+ args->keys = find_config_tree_str(cmd, report_pvsegs_sort_CFG, NULL);
if (!arg_count(cmd, verbose_ARG))
- args.options = find_config_tree_str(cmd, report_pvsegs_cols_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_pvsegs_cols_CFG, NULL);
else
- args.options = find_config_tree_str(cmd, report_pvsegs_cols_verbose_CFG, NULL);
+ args->options = find_config_tree_str(cmd, report_pvsegs_cols_verbose_CFG, NULL);
break;
default:
log_error(INTERNAL_ERROR "_report: unknown report type.");
@@ -976,35 +965,57 @@ static int _report(struct cmd_context *cmd, int argc, char **argv, report_type_t
/* If -o supplied use it, else use default for report_type */
if (arg_count(cmd, options_ARG) &&
- (_get_report_options(cmd, &args) != ECMD_PROCESSED))
+ (_get_report_options(cmd, args) != ECMD_PROCESSED))
return_0;
- if (!args.fields_to_compact)
- args.fields_to_compact = find_config_tree_str_allow_empty(cmd, report_compact_output_cols_CFG, NULL);
+ if (!args->fields_to_compact)
+ args->fields_to_compact = find_config_tree_str_allow_empty(cmd, report_compact_output_cols_CFG, NULL);
/* -O overrides default sort settings */
- args.keys = arg_str_value(cmd, sort_ARG, args.keys);
+ args->keys = arg_str_value(cmd, sort_ARG, args->keys);
- args.separator = arg_str_value(cmd, separator_ARG, args.separator);
+ args->separator = arg_str_value(cmd, separator_ARG, args->separator);
if (arg_count(cmd, separator_ARG))
- args.aligned = 0;
+ args->aligned = 0;
if (arg_count(cmd, aligned_ARG))
- args.aligned = 1;
+ args->aligned = 1;
if (arg_count(cmd, unbuffered_ARG) && !arg_count(cmd, sort_ARG))
- args.buffered = 0;
+ args->buffered = 0;
if (arg_count(cmd, noheadings_ARG))
- args.headings = 0;
+ args->headings = 0;
if (arg_count(cmd, nameprefixes_ARG)) {
- args.aligned = 0;
- args.field_prefixes = 1;
+ args->aligned = 0;
+ args->field_prefixes = 1;
}
if (arg_count(cmd, unquoted_ARG))
- args.quoted = 0;
+ args->quoted = 0;
if (arg_count(cmd, rows_ARG))
- args.columns_as_rows = 1;
+ args->columns_as_rows = 1;
if (arg_count(cmd, select_ARG))
- args.selection = arg_str_value(cmd, select_ARG, NULL);
+ args->selection = arg_str_value(cmd, select_ARG, NULL);
+
+ return 1;
+}
+
+static int _report(struct cmd_context *cmd, int argc, char **argv, report_type_t report_type)
+{
+ struct report_args args = {0};
+
+ /*
+ * Include foreign VGs that contain active LVs.
+ * That shouldn't happen in general, but if it does by some
+ * mistake, then we want to display those VGs and allow the
+ * LVs to be deactivated.
+ */
+ cmd->include_active_foreign_vgs = 1;
+
+ args.argc = argc;
+ args.argv = argv;
+ args.report_type = report_type;
+
+ if (!_config_report(cmd, &args))
+ return_ECMD_FAILED;
return _do_report(cmd, &args);
}
7 years, 11 months
master - metadata: Tidy merge.c
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=8c872852cdbc4c...
Commit: 8c872852cdbc4c3f9572379bc87e1455b28fbe6f
Parent: 498da2414b90098eb78cdd8c87bda7b022240fda
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue May 24 00:57:48 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue May 24 00:57:48 2016 +0100
metadata: Tidy merge.c
---
lib/metadata/merge.c | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 62fc70a..7aed002 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved.
*
* This file is part of LVM2.
*
@@ -455,13 +455,14 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
seg_found++;
}
if (seg_is_replicator(seg) && lv == seg->rlog_lv)
- seg_found++;
+ seg_found++;
if (seg->log_lv == lv)
seg_found++;
if (seg->metadata_lv == lv || seg->pool_lv == lv)
seg_found++;
if (seg_is_thin_volume(seg) && (seg->origin == lv || seg->external_lv == lv))
seg_found++;
+
if (!seg_found) {
log_error("LV %s is used by LV %s:%" PRIu32 "-%" PRIu32
", but missing ptr from %s to %s",
@@ -480,10 +481,11 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
seg_found = 0;
dm_list_iterate_items(seg2, &seg->lv->segments)
- if (sl->seg == seg2) {
+ if (seg == seg2) {
seg_found++;
break;
}
+
if (!seg_found) {
log_error("LV segment %s:%" PRIu32 "-%" PRIu32
" is incorrectly listed as being used by LV %s",
7 years, 11 months
master - raid10: Fix new use of area multiple calc.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=498da2414b9009...
Commit: 498da2414b90098eb78cdd8c87bda7b022240fda
Parent: b896f7de1e6773ce6c17bf29a9123276695f4b60
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Tue May 24 00:41:09 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Tue May 24 00:41:09 2016 +0100
raid10: Fix new use of area multiple calc.
---
lib/metadata/lv_manip.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 2e9a7a3..8a2c728 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -3803,9 +3803,9 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
* 'stripes' and 'stripe_size' parameters meaningless.
*/
if (seg_is_raid(seg)) {
- area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, 0);
stripes = 1;
stripe_size = 0;
+ area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, stripes);
}
for (fa = first_area, s = 0; s < seg->area_count; s++) {
7 years, 11 months
master - raid0: Standardise meta_areas checks before access.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=b896f7de1e6773...
Commit: b896f7de1e6773ce6c17bf29a9123276695f4b60
Parent: 757f7d55082844a17372e4e83c6a95884c2550a8
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Mon May 23 22:55:13 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Mon May 23 22:55:13 2016 +0100
raid0: Standardise meta_areas checks before access.
---
lib/activate/dev_manager.c | 4 ++--
lib/metadata/lv.c | 4 ++--
lib/metadata/lv_manip.c | 8 ++++----
lib/metadata/merge.c | 2 +-
lib/metadata/raid_manip.c | 6 +++---
lib/metadata/segtype.h | 2 ++
lib/raid/raid.c | 6 +++---
tools/lvchange.c | 2 +-
tools/vgsplit.c | 6 +++---
9 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index 711074d..32295fb 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -2207,7 +2207,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
(!dm->track_pending_delete || !lv_is_cache(lv)) &&
!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
return_0;
- if (seg_is_raid(seg) && seg->meta_areas && seg_metalv(seg, s) &&
+ if (seg_is_raid_with_meta(seg) && seg->meta_areas && seg_metalv(seg, s) &&
!_add_lv_to_dtree(dm, dtree, seg_metalv(seg, s), 0))
return_0;
}
@@ -2713,7 +2713,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
laopts, NULL))
return_0;
- if (seg_is_raid(seg) && seg->meta_areas && seg_metalv(seg, s) &&
+ if (seg_is_raid_with_meta(seg) && seg->meta_areas && seg_metalv(seg, s) &&
!_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
laopts, NULL))
return_0;
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c
index cb30e2d..0a531cf 100644
--- a/lib/metadata/lv.c
+++ b/lib/metadata/lv.c
@@ -53,7 +53,7 @@ static struct dm_list *_format_pvsegs(struct dm_pool *mem, const struct lv_segme
goto bad;
}
- if (metadata_areas_only && (!seg_is_raid(seg) || lv_is_raid_metadata(seg->lv) || lv_is_raid_image(seg->lv)))
+ if (metadata_areas_only && (!seg_is_raid_with_meta(seg) || !seg->meta_areas || lv_is_raid_metadata(seg->lv) || lv_is_raid_image(seg->lv)))
goto out;
for (s = 0; s < seg->area_count; s++) {
@@ -1012,7 +1012,7 @@ int lv_raid_healthy(const struct logical_volume *lv)
/* Find out which sub-LV this is. */
for (s = 0; s < raid_seg->area_count; s++)
if ((lv_is_raid_image(lv) && (seg_lv(raid_seg, s) == lv)) ||
- (lv_is_raid_metadata(lv) && (seg_metalv(raid_seg,s) == lv)))
+ (lv_is_raid_metadata(lv) && (seg_metalv(raid_seg, s) == lv)))
break;
if (s == raid_seg->area_count) {
log_error(INTERNAL_ERROR
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 82faf42..2e9a7a3 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -1019,7 +1019,7 @@ static int _release_and_discard_lv_segment_area(struct lv_segment *seg, uint32_t
}
/* Remove metadata area if image has been removed */
- if (area_reduction == seg->area_len) {
+ if (seg->meta_areas && seg_metalv(seg, s) && (area_reduction == seg->area_len)) {
if (!lv_reduce(seg_metalv(seg, s),
seg_metalv(seg, s)->le_count)) {
log_error("Failed to remove RAID meta-device %s",
@@ -3826,7 +3826,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
}
/* Extend metadata LVs only on initial creation */
- if (seg_is_raid(seg) && !seg_is_raid0(seg) && !lv->le_count) {
+ if (seg_is_raid_with_meta(seg) && !lv->le_count) {
if (!seg->meta_areas) {
log_error("No meta_areas for RAID type");
return 0;
@@ -4190,12 +4190,12 @@ static int _for_each_sub_lv(struct logical_volume *lv, int skip_pools,
return_0;
}
- if (!seg_is_raid(seg))
+ if (!seg_is_raid_with_meta(seg))
continue;
/* RAID has meta_areas */
for (s = 0; s < seg->area_count; s++) {
- if (seg_metatype(seg, s) != AREA_LV)
+ if ((seg_metatype(seg, s) != AREA_LV) || !seg_metalv(seg, s))
continue;
if (!fn(seg_metalv(seg, s), data))
return_0;
diff --git a/lib/metadata/merge.c b/lib/metadata/merge.c
index 4f730e0..62fc70a 100644
--- a/lib/metadata/merge.c
+++ b/lib/metadata/merge.c
@@ -441,7 +441,7 @@ int check_lv_segments(struct logical_volume *lv, int complete_vg)
continue;
if (lv == seg_lv(seg, s))
seg_found++;
- if (seg_is_raid(seg) && (lv == seg_metalv(seg, s)))
+ if (seg_is_raid_with_meta(seg) && (lv == seg_metalv(seg, s)))
seg_found++;
}
if (seg_is_replicator_dev(seg)) {
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c
index 887b27f..739e144 100644
--- a/lib/metadata/raid_manip.c
+++ b/lib/metadata/raid_manip.c
@@ -1871,8 +1871,8 @@ int lv_raid_remove_missing(struct logical_volume *lv)
*/
for (s = 0; s < seg->area_count; s++) {
- if (!lv_is_partial(seg_lv(seg, s)) &&
- !lv_is_partial(seg_metalv(seg, s)))
+ if (!lv_is_partial(seg_lv(seg, s)) &&
+ (!seg->meta_areas || !seg_metalv(seg, s) || !lv_is_partial(seg_metalv(seg, s))))
continue;
log_debug("Replacing %s and %s segments with error target",
@@ -1882,7 +1882,7 @@ int lv_raid_remove_missing(struct logical_volume *lv)
display_lvname(seg_lv(seg, s)));
return 0;
}
- if (!replace_lv_with_error_segment(seg_metalv(seg, s))) {
+ if (seg->meta_areas && !replace_lv_with_error_segment(seg_metalv(seg, s))) {
log_error("Failed to replace %s's extents with error target.",
display_lvname(seg_metalv(seg, s)));
return 0;
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 3fc4266..f3b1510 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -119,6 +119,7 @@ struct dev_manager;
#define segtype_is_raid6_nr(segtype) ((segtype)->flags & SEG_RAID6_NR ? 1 : 0)
#define segtype_is_raid6_zr(segtype) ((segtype)->flags & SEG_RAID6_ZR ? 1 : 0)
#define segtype_is_raid10(segtype) ((segtype)->flags & SEG_RAID10 ? 1 : 0)
+#define segtype_is_raid_with_meta(segtype) (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
#define segtype_is_snapshot(segtype) ((segtype)->flags & SEG_SNAPSHOT ? 1 : 0)
#define segtype_is_striped(segtype) ((segtype)->flags & SEG_AREAS_STRIPED ? 1 : 0)
#define segtype_is_thin(segtype) ((segtype)->flags & (SEG_THIN_POOL|SEG_THIN_VOLUME) ? 1 : 0)
@@ -148,6 +149,7 @@ struct dev_manager;
#define seg_is_raid6_nr(seg) segtype_is_raid6_nr((seg)->segtype)
#define seg_is_raid6_nc(seg) segtype_is_raid6_nc((seg)->segtype)
#define seg_is_raid10(seg) segtype_is_raid10((seg)->segtype)
+#define seg_is_raid_with_meta(seg) segtype_is_raid_with_meta((seg)->segtype)
#define seg_is_replicator(seg) ((seg)->segtype->flags & SEG_REPLICATOR ? 1 : 0)
#define seg_is_replicator_dev(seg) ((seg)->segtype->flags & SEG_REPLICATOR_DEV ? 1 : 0)
#define seg_is_snapshot(seg) segtype_is_snapshot((seg)->segtype)
diff --git a/lib/raid/raid.c b/lib/raid/raid.c
index 4987f91..e299e17 100644
--- a/lib/raid/raid.c
+++ b/lib/raid/raid.c
@@ -33,10 +33,10 @@ static void _raid_display(const struct lv_segment *seg)
display_stripe(seg, s, " ");
}
- if (seg->meta_areas) {
+ if (seg->meta_areas)
for (s = 0; s < seg->area_count; ++s)
- log_print(" Raid Metadata LV%2d\t%s", s, seg_metalv(seg, s)->name);
- }
+ if (seg_metalv(seg, s))
+ log_print(" Raid Metadata LV%2d\t%s", s, seg_metalv(seg, s)->name);
log_print(" ");
}
diff --git a/tools/lvchange.c b/tools/lvchange.c
index c37a597..1ce19c5 100644
--- a/tools/lvchange.c
+++ b/tools/lvchange.c
@@ -243,7 +243,7 @@ static int detach_metadata_devices(struct lv_segment *seg, struct dm_list *list)
if (!(lvl = dm_pool_alloc(seg->lv->vg->vgmem, sizeof(*lvl) * num_meta_lvs)))
return_0;
- if (seg_is_raid(seg)) {
+ if (seg_is_raid_with_meta(seg)) {
for (s = 0; s < seg->area_count; s++) {
if (!seg_metalv(seg, s))
return_0; /* Trap this future possibility */
diff --git a/tools/vgsplit.c b/tools/vgsplit.c
index 8335570..e7c6e19 100644
--- a/tools/vgsplit.c
+++ b/tools/vgsplit.c
@@ -253,11 +253,11 @@ static int _move_raid(struct volume_group *vg_from,
for (s = 0; s < seg->area_count; s++) {
if (_lv_is_in_vg(vg_to, seg_lv(seg, s)))
seg_in++;
- if (_lv_is_in_vg(vg_to, seg_metalv(seg, s)))
- seg_in++;
+ if (seg->meta_areas && seg_metalv(seg, s) && _lv_is_in_vg(vg_to, seg_metalv(seg, s)))
+ seg_in++; /* FIXME Inadequate - must count separately */
}
- if (seg_in && seg_in != (seg->area_count * 2)) {
+ if (seg_in && seg_in != (seg->area_count * (seg->meta_areas ? 2 : 1))) {
log_error("Can't split RAID %s between "
"two Volume Groups", lv->name);
return 0;
7 years, 11 months
master - test: lvmetad-disabled
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=757f7d55082844...
Commit: 757f7d55082844a17372e4e83c6a95884c2550a8
Parent: 3d3efd7ab80f200148f8c133521320642aa9d221
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu May 5 15:44:27 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon May 23 12:01:11 2016 -0500
test: lvmetad-disabled
---
test/shell/lvmetad-disabled.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/test/shell/lvmetad-disabled.sh b/test/shell/lvmetad-disabled.sh
index e905ba7..41f1126 100644
--- a/test/shell/lvmetad-disabled.sh
+++ b/test/shell/lvmetad-disabled.sh
@@ -42,7 +42,7 @@ while ! test -e "$TESTDIR/lvmetad.socket"; do echo -n .; sleep .1; done # wait f
test -e "$LVM_LVMETAD_PIDFILE"
cp "$LVM_LVMETAD_PIDFILE" LOCAL_LVMETAD
-not pvscan --cache 2>&1 | tee out
+pvscan --cache 2>&1 | tee out
grep "WARNING: Disabling lvmetad cache" out
pvs 2>&1 | tee out
7 years, 11 months
master - test: lvmetad-pvscan-filter
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=3d3efd7ab80f20...
Commit: 3d3efd7ab80f200148f8c133521320642aa9d221
Parent: 9b640c36841e2790731d54a5830dcea8203f9e80
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu May 5 15:16:38 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon May 23 12:00:25 2016 -0500
test: lvmetad-pvscan-filter
update for pvscan changes
---
test/shell/lvmetad-pvscan-filter.sh | 30 ++++++++++++++++++++++++------
1 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/test/shell/lvmetad-pvscan-filter.sh b/test/shell/lvmetad-pvscan-filter.sh
index 91bb930..cb3fcdc 100644
--- a/test/shell/lvmetad-pvscan-filter.sh
+++ b/test/shell/lvmetad-pvscan-filter.sh
@@ -22,17 +22,35 @@ min=$(($(stat -L --printf=0x%T "$dev2")))
# Filter out device, pvscan should trigger
# clearing of the device from lvmetad cache.
-aux hide_dev "$dev2"
-pvscan --cache "$dev2" 2>&1 | grep "not found"
+
+# We can't use aux hide_dev here because that
+# changes the global_filter which triggers a
+# token mismatch rescan by subsequent pvscan
+# commands instead of the single-dev scans
+# that are testing here.
+
+mv "$dev2" "$dev2-HIDDEN"
+
+pvscan --cache "$dev2" 2>&1 | tee out || true
+grep "not found" out
+
# pvscan with --major/--minor does not fail: lvmetad needs to
# be notified about device removal on REMOVE uevent, hence
# this should not fail so udev does not grab a "failed" state
# incorrectly. We notify device addition and removal with
# exactly the same command "pvscan --cache" - in case of removal,
# this is detected by nonexistence of the device itself.
-pvscan --cache --major $maj --minor $min 2>&1 | grep "not found"
-aux unhide_dev "$dev2"
-pvscan --cache "$dev2" 2>&1 | not grep "not found"
-pvscan --cache --major $maj --minor $min 2>&1 | not grep "not found"
+pvscan --cache --major $maj --minor $min 2>&1 | tee out || true
+grep "not found" out
+
+# aux unhide_dev "$dev2"
+mv "$dev2-HIDDEN" "$dev2"
+
+pvscan --cache "$dev2" 2>&1 | tee out || true
+not grep "not found" out
+
+pvscan --cache --major $maj --minor $min 2>&1 | tee out || true
+not grep "not found" out
+
pvs | grep "$dev2"
7 years, 11 months
master - pvscan: use process_each_vg for autoactivate
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=9b640c36841e27...
Commit: 9b640c36841e2790731d54a5830dcea8203f9e80
Parent: 55683a659f9bf6875dd930e2dff62f1e1bdb88aa
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Apr 28 09:37:03 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon May 23 11:57:32 2016 -0500
pvscan: use process_each_vg for autoactivate
This refactors the code for autoactivation. Previously,
as each PV was found, it would be sent to lvmetad, and
the VG would be autoactivated using a non-standard VG
processing function (the "activation_handler") called via
a function pointer from within the lvmetad notification path.
Now, any scanning that the command needs to do (scanning
only the named device args, or scanning all devices when
there are no args), is done first, before any activation
is attempted. During the scans, the VG names are saved.
After scanning is complete, process_each_vg is used to do
autoactivation of the saved VG names. This makes pvscan
activation much more similar to activation done with
vgchange or lvchange.
The separate autoactivate phase also means that if lvmetad
is disabled (either before or during the scan), the command
can continue with the activation step by simply not using
lvmetad and reverting to disk scanning to do the
activation.
---
lib/cache/lvmetad.c | 154 +++++---------
lib/cache/lvmetad.h | 27 ++--
lib/metadata/metadata.c | 5 +-
lib/metadata/pv_manip.c | 2 +-
test/shell/lvmetad-pvscan-nomda.sh | 10 +-
tools/lvmcmdline.c | 2 +-
tools/lvscan.c | 4 +-
tools/pvscan.c | 406 ++++++++++++++++++++++--------------
tools/toollib.c | 4 +-
tools/vgimport.c | 2 +-
tools/vgscan.c | 2 +-
11 files changed, 334 insertions(+), 284 deletions(-)
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 9f7bf32..6f914b2 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -23,6 +23,7 @@
#include "crc.h"
#include "lvm-signal.h"
#include "lvmlockd.h"
+#include "str_list.h"
#include <time.h>
@@ -399,9 +400,6 @@ out:
return ret;
}
-static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler,
- int ignore_obsolete, int do_wait);
-
static daemon_reply _lvmetad_send(struct cmd_context *cmd, const char *id, ...)
{
va_list ap;
@@ -1017,9 +1015,9 @@ int lvmetad_vg_update(struct volume_group *vg)
dm_list_iterate_items(pvl, &vg->pvs) {
/* NB. the PV fmt pointer is sometimes wrong during vgconvert */
- if (pvl->pv->dev && !lvmetad_pv_found(&pvl->pv->id, pvl->pv->dev,
+ if (pvl->pv->dev && !lvmetad_pv_found(vg->cmd, &pvl->pv->id, pvl->pv->dev,
vg->fid ? vg->fid->fmt : pvl->pv->fmt,
- pvl->pv->label_sector, NULL, NULL))
+ pvl->pv->label_sector, NULL, NULL, NULL))
return 0;
}
@@ -1303,14 +1301,16 @@ static int _extract_mdas(struct lvmcache_info *info, struct dm_config_tree *cft,
return 1;
}
-int lvmetad_pv_found(const struct id *pvid, struct device *dev, const struct format_type *fmt,
- uint64_t label_sector, struct volume_group *vg, activation_handler handler)
+int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct device *dev, const struct format_type *fmt,
+ uint64_t label_sector, struct volume_group *vg,
+ struct dm_list *found_vgnames,
+ struct dm_list *changed_vgnames)
{
char uuid[64];
daemon_reply reply;
struct lvmcache_info *info;
struct dm_config_tree *pvmeta, *vgmeta;
- const char *status, *vgname, *vgid;
+ const char *status, *vgname;
int64_t changed;
int result;
@@ -1358,7 +1358,7 @@ int lvmetad_pv_found(const struct id *pvid, struct device *dev, const struct for
}
log_debug_lvmetad("Telling lvmetad to store PV %s (%s) in VG %s", dev_name(dev), uuid, vg->name);
- reply = _lvmetad_send(vg->cmd, "pv_found",
+ reply = _lvmetad_send(cmd, "pv_found",
"pvmeta = %t", pvmeta,
"vgname = %s", vg->name,
"metadata = %t", vgmeta,
@@ -1382,65 +1382,41 @@ int lvmetad_pv_found(const struct id *pvid, struct device *dev, const struct for
daemon_reply_int(reply, "seqno_after", -1) != daemon_reply_int(reply, "seqno_before", -1)))
log_warn("WARNING: Inconsistent metadata found for VG %s", vg->name);
+ if (result && found_vgnames) {
+ status = daemon_reply_str(reply, "status", NULL);
+ vgname = daemon_reply_str(reply, "vgname", NULL);
+ changed = daemon_reply_int(reply, "changed", 0);
+ }
+
/*
- * pvscan --cache does not perform any lvmlockd locking, and
- * pvscan --cache -aay skips autoactivation in lockd VGs.
- *
- * pvscan --cache populates lvmetad with VG metadata from disk.
- * No lvmlockd locking is needed. It is expected that lockd VG
- * metadata that is read by pvscan and populated in lvmetad may
- * be immediately stale due to changes to the VG from other hosts
- * during or after this pvscan. This is normal and not a problem.
- * When a subsequent lvm command uses the VG, it will lock the VG
- * with lvmlockd, read the VG from lvmetad, and update the cached
- * copy from disk if necessary.
- *
- * pvscan --cache -aay does not activate LVs in lockd VGs because
- * activation requires locking, and a lock-start operation is needed
- * on a lockd VG before any locking can be performed in it.
+ * If lvmetad now sees all PVs in the VG, it returned the
+ * "complete" status string. Add this VG name to the list
+ * of found VGs so that the caller can do autoactivation.
*
- * An equivalent of pvscan --cache -aay for lockd VGs is:
- * 1. pvscan --cache
- * 2. vgchange --lock-start
- * 3. vgchange -aay -S 'locktype=sanlock || locktype=dlm'
+ * If there was a problem notifying lvmetad about the new
+ * PV, e.g. lvmetad was disabled due to a duplicate, then
+ * no autoactivation is attempted.
*
- * [We could eventually add support for autoactivating lockd VGs
- * using pvscan by incorporating the lock start step (which can
- * take a long time), but there may be a better option than
- * continuing to overload pvscan.]
- *
- * Stages of starting a lockd VG:
+ * FIXME: there was a previous fixme indicating that
+ * autoactivation might also be done for VGs with the
+ * "partial" status.
*
- * . pvscan --cache populates lockd VGs in lvmetad without locks,
- * and this initial cached copy may quickly become stale.
- *
- * . vgchange --lock-start VG reads the VG without the VG lock
- * because no locks are available until the locking is started.
- * It only uses the VG name and lock_type from the VG metadata,
- * and then only uses it to start the VG lockspace in lvmlockd.
- *
- * . Further lvm commands, e.g. activation, can then lock the VG
- * with lvmlockd and use current VG metdata.
+ * If the VG has "changed" by finding the PV, lvmetad returns
+ * the "changed" flag. The names of "changed" VGs are saved
+ * in the changed_vgnames lists, which is used during autoactivation.
+ * If a VG is changed, then autoactivation refreshes LVs in the VG.
*/
- if (handler && vg && is_lockd_type(vg->lock_type)) {
- log_debug_lvmetad("Skip pvscan activation for lockd type VG %s", vg->name);
- handler = NULL;
- }
- if (result && handler) {
- status = daemon_reply_str(reply, "status", "<missing>");
- vgname = daemon_reply_str(reply, "vgname", "<missing>");
- vgid = daemon_reply_str(reply, "vgid", "<missing>");
- changed = daemon_reply_int(reply, "changed", 0);
- if (!strcmp(status, "partial"))
- handler(_lvmetad_cmd, vgname, vgid, 1, changed, CHANGE_AAY);
- else if (!strcmp(status, "complete"))
- handler(_lvmetad_cmd, vgname, vgid, 0, changed, CHANGE_AAY);
- else if (!strcmp(status, "orphan"))
- ;
- else
- log_error("Request to %s %s in lvmetad gave status %s.",
- "update PV", uuid, status);
+ if (found_vgnames && vgname && status && !strcmp(status, "complete")) {
+ log_debug("VG %s is complete in lvmetad with dev %s.", vgname, dev_name(dev));
+ if (!str_list_add(cmd->mem, found_vgnames, dm_pool_strdup(cmd->mem, vgname)))
+ log_error("str_list_add failed");
+
+ if (changed_vgnames && changed) {
+ log_debug("VG %s is changed in lvmetad.", vgname);
+ if (!str_list_add(cmd->mem, changed_vgnames, dm_pool_strdup(cmd->mem, vgname)))
+ log_error("str_list_add failed");
+ }
}
daemon_reply_destroy(reply);
@@ -1448,7 +1424,7 @@ int lvmetad_pv_found(const struct id *pvid, struct device *dev, const struct for
return result;
}
-int lvmetad_pv_gone(dev_t devno, const char *pv_name, activation_handler handler)
+int lvmetad_pv_gone(dev_t devno, const char *pv_name)
{
daemon_reply reply;
int result;
@@ -1475,9 +1451,9 @@ int lvmetad_pv_gone(dev_t devno, const char *pv_name, activation_handler handler
return result;
}
-int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler)
+int lvmetad_pv_gone_by_dev(struct device *dev)
{
- return lvmetad_pv_gone(dev->dev, dev_name(dev), handler);
+ return lvmetad_pv_gone(dev->dev, dev_name(dev));
}
/*
@@ -1546,10 +1522,8 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo
return NULL;
if (baton.fid->fmt->features & FMT_OBSOLETE) {
- log_error("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
- baton.fid->fmt->name, dev_name(pvl->pv->dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
- log_warn("WARNING: Disabling lvmetad cache which does not support obsolete metadata.");
+ log_warn("WARNING: Disabling lvmetad cache which does not support obsolete (lvm1) metadata.");
lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
_found_lvm1_metadata = 1;
return NULL;
@@ -1635,7 +1609,8 @@ out:
}
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
- activation_handler handler, int ignore_obsolete)
+ struct dm_list *found_vgnames,
+ struct dm_list *changed_vgnames)
{
struct label *label;
struct lvmcache_info *info;
@@ -1651,7 +1626,7 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
if (!label_read(dev, &label, 0)) {
log_print_unless_silent("No PV label found on %s.", dev_name(dev));
- if (!lvmetad_pv_gone_by_dev(dev, handler))
+ if (!lvmetad_pv_gone_by_dev(dev))
goto_bad;
return 1;
}
@@ -1665,21 +1640,11 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
goto_bad;
if (baton.fid->fmt->features & FMT_OBSOLETE) {
- if (ignore_obsolete)
- log_warn("WARNING: Ignoring obsolete format of metadata (%s) on device %s when using lvmetad",
- baton.fid->fmt->name, dev_name(dev));
- else
- log_error("Ignoring obsolete format of metadata (%s) on device %s when using lvmetad.",
- baton.fid->fmt->name, dev_name(dev));
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
-
- log_warn("WARNING: Disabling lvmetad cache which does not support obsolete metadata.");
+ log_warn("WARNING: Disabling lvmetad cache which does not support obsolete (lvm1) metadata.");
lvmetad_set_disabled(cmd, LVMETAD_DISABLE_REASON_LVM1);
_found_lvm1_metadata = 1;
-
- if (ignore_obsolete)
- return 1;
- return 0;
+ return 1;
}
lvmcache_foreach_mda(info, _lvmetad_pvscan_single, &baton);
@@ -1700,8 +1665,8 @@ int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
if (!baton.vg)
lvmcache_fmt(info)->ops->destroy_instance(baton.fid);
- if (!lvmetad_pv_found((const struct id *) &dev->pvid, dev, lvmcache_fmt(info),
- label->sector, baton.vg, handler)) {
+ if (!lvmetad_pv_found(cmd, (const struct id *) &dev->pvid, dev, lvmcache_fmt(info),
+ label->sector, baton.vg, found_vgnames, changed_vgnames)) {
release_vg(baton.vg);
goto_bad;
}
@@ -1738,8 +1703,7 @@ bad:
* generally revert disk scanning and not use lvmetad.
*/
-static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler,
- int ignore_obsolete, int do_wait)
+int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait)
{
struct dev_iter *iter;
struct device *dev;
@@ -1820,7 +1784,7 @@ static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler
stack;
break;
}
- if (!lvmetad_pvscan_single(cmd, dev, handler, ignore_obsolete))
+ if (!lvmetad_pvscan_single(cmd, dev, NULL, NULL))
ret = 0;
}
@@ -1850,20 +1814,6 @@ static int _lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler
return ret;
}
-int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler, int do_wait)
-{
- return _lvmetad_pvscan_all_devs(cmd, handler, 0, do_wait);
-}
-
-/*
- * FIXME Implement this function, skipping PVs known to belong to local or clustered,
- * non-exported VGs.
- */
-int lvmetad_pvscan_foreign_vgs(struct cmd_context *cmd, activation_handler handler)
-{
- return _lvmetad_pvscan_all_devs(cmd, handler, 1, 1);
-}
-
int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg)
{
char uuid[64];
@@ -2145,7 +2095,7 @@ void lvmetad_validate_global_cache(struct cmd_context *cmd, int force)
* we rescanned for the token, and the time we acquired the global
* lock.)
*/
- if (!lvmetad_pvscan_all_devs(cmd, NULL, 1)) {
+ if (!lvmetad_pvscan_all_devs(cmd, 1)) {
log_warn("WARNING: Not using lvmetad because cache update failed.");
lvmetad_make_unused(cmd);
return;
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index 0985a54..3bb2b7c 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -95,15 +95,17 @@ int lvmetad_vg_remove(struct volume_group *vg);
* number on the cached and on the discovered PV match but the metadata content
* does not.
*/
-int lvmetad_pv_found(const struct id *pvid, struct device *dev,
+int lvmetad_pv_found(struct cmd_context *cmd, const struct id *pvid, struct device *dev,
const struct format_type *fmt, uint64_t label_sector,
- struct volume_group *vg, activation_handler handler);
+ struct volume_group *vg,
+ struct dm_list *found_vgnames,
+ struct dm_list *changed_vgnames);
/*
* Inform the daemon that the device no longer exists.
*/
-int lvmetad_pv_gone(dev_t devno, const char *pv_name, activation_handler handler);
-int lvmetad_pv_gone_by_dev(struct device *dev, activation_handler handler);
+int lvmetad_pv_gone(dev_t devno, const char *pv_name);
+int lvmetad_pv_gone_by_dev(struct device *dev);
/*
* Request a list of all PVs available to lvmetad. If requested, this will also
@@ -142,10 +144,10 @@ struct volume_group *lvmetad_vg_lookup(struct cmd_context *cmd,
* Scan a single device and update lvmetad with the result(s).
*/
int lvmetad_pvscan_single(struct cmd_context *cmd, struct device *dev,
- activation_handler handler, int ignore_obsolete);
+ struct dm_list *found_vgnames,
+ struct dm_list *changed_vgnames);
-int lvmetad_pvscan_all_devs(struct cmd_context *cmd, activation_handler handler, int do_wait);
-int lvmetad_pvscan_foreign_vgs(struct cmd_context *cmd, activation_handler handler);
+int lvmetad_pvscan_all_devs(struct cmd_context *cmd, int do_wait);
int lvmetad_vg_clear_outdated_pvs(struct volume_group *vg);
void lvmetad_validate_global_cache(struct cmd_context *cmd, int force);
@@ -170,18 +172,17 @@ void lvmetad_clear_disabled(struct cmd_context *cmd);
# define lvmetad_release_token() do { } while (0)
# define lvmetad_vg_update(vg) (1)
# define lvmetad_vg_remove(vg) (1)
-# define lvmetad_pv_found(pvid, dev, fmt, label_sector, vg, handler) (1)
-# define lvmetad_pv_gone(devno, pv_name, handler) (1)
-# define lvmetad_pv_gone_by_dev(dev, handler) (1)
+# define lvmetad_pv_found(cmd, pvid, dev, fmt, label_sector, vg, found_vgnames, changed_vgnames) (1)
+# define lvmetad_pv_gone(devno, pv_name) (1)
+# define lvmetad_pv_gone_by_dev(dev) (1)
# define lvmetad_pv_list_to_lvmcache(cmd) (1)
# define lvmetad_pv_lookup(cmd, pvid, found) (0)
# define lvmetad_pv_lookup_by_dev(cmd, dev, found) (0)
# define lvmetad_vg_list_to_lvmcache(cmd) (1)
# define lvmetad_get_vgnameids(cmd, vgnameids) do { } while (0)
# define lvmetad_vg_lookup(cmd, vgname, vgid) (NULL)
-# define lvmetad_pvscan_single(cmd, dev, handler, ignore_obsolete) (0)
-# define lvmetad_pvscan_all_devs(cmd, handler, do_wait) (0)
-# define lvmetad_pvscan_foreign_vgs(cmd, handler) (0)
+# define lvmetad_pvscan_single(cmd, dev, found_vgnames, changed_vgnames) (0)
+# define lvmetad_pvscan_all_devs(cmd, do_wait) (0)
# define lvmetad_vg_clear_outdated_pvs(vg) do { } while (0)
# define lvmetad_validate_global_cache(cmd, force) do { } while (0)
# define lvmetad_vg_is_foreign(cmd, vgname, vgid) (0)
diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c
index 8adcbbd..9e31ba4 100644
--- a/lib/metadata/metadata.c
+++ b/lib/metadata/metadata.c
@@ -5242,7 +5242,7 @@ int scan_vgs_for_pvs(struct cmd_context *cmd, uint32_t warn_flags)
return _get_pvs(cmd, warn_flags, NULL, NULL);
}
-int pv_write(struct cmd_context *cmd __attribute__((unused)),
+int pv_write(struct cmd_context *cmd,
struct physical_volume *pv, int allow_non_orphan)
{
if (!pv->fmt->ops->pv_write) {
@@ -5268,8 +5268,7 @@ int pv_write(struct cmd_context *cmd __attribute__((unused)),
pv->status &= ~UNLABELLED_PV;
- if (!lvmetad_pv_found(&pv->id, pv->dev, pv->fmt, pv->label_sector,
- NULL, NULL))
+ if (!lvmetad_pv_found(cmd, &pv->id, pv->dev, pv->fmt, pv->label_sector, NULL, NULL, NULL))
return_0;
return 1;
diff --git a/lib/metadata/pv_manip.c b/lib/metadata/pv_manip.c
index d38262d..fa18c99 100644
--- a/lib/metadata/pv_manip.c
+++ b/lib/metadata/pv_manip.c
@@ -810,7 +810,7 @@ int pvremove_single(struct cmd_context *cmd, const char *pv_name,
if (info)
lvmcache_del(info);
- if (!lvmetad_pv_gone_by_dev(dev, NULL))
+ if (!lvmetad_pv_gone_by_dev(dev))
goto_out;
log_print_unless_silent("Labels on physical volume \"%s\" successfully wiped",
diff --git a/test/shell/lvmetad-pvscan-nomda.sh b/test/shell/lvmetad-pvscan-nomda.sh
index 59912ad..6cb2062 100644
--- a/test/shell/lvmetad-pvscan-nomda.sh
+++ b/test/shell/lvmetad-pvscan-nomda.sh
@@ -37,13 +37,19 @@ aux lvmconf 'global/use_lvmetad = 0'
check inactive $vg1 foo
aux lvmconf 'global/use_lvmetad = 1'
-pvscan --cache "$dev2" -aay
+# Tell lvmetad about dev2, but the VG is not complete with
+# only dev2, so the -aay should not yet activate the LV.
+
+pvscan --cache -aay "$dev2"
aux lvmconf 'global/use_lvmetad = 0'
check inactive $vg1 foo
aux lvmconf 'global/use_lvmetad = 1'
-pvscan --cache "$dev1" -aay
+# Tell lvmetad about dev1, now the VG is complete with
+# both devs, so the -aay should activate the LV.
+
+pvscan --cache -aay "$dev1"
aux lvmconf 'global/use_lvmetad = 0'
check active $vg1 foo
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c
index 4009921..be6821b 100644
--- a/tools/lvmcmdline.c
+++ b/tools/lvmcmdline.c
@@ -1681,7 +1681,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
*/
if (lvmetad_used() && !(cmd->command->flags & NO_LVMETAD_AUTOSCAN)) {
if (cmd->include_foreign_vgs || !lvmetad_token_matches(cmd)) {
- if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, NULL, cmd->include_foreign_vgs ? 1 : 0)) {
+ if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, cmd->include_foreign_vgs ? 1 : 0)) {
log_warn("WARNING: Not using lvmetad because cache update failed.");
lvmetad_make_unused(cmd);
}
diff --git a/tools/lvscan.c b/tools/lvscan.c
index 4ae3ce6..23d3d7f 100644
--- a/tools/lvscan.c
+++ b/tools/lvscan.c
@@ -38,7 +38,7 @@ static int _lvscan_single_lvmetad(struct cmd_context *cmd, struct logical_volume
pvid_s);
continue;
}
- if (!lvmetad_pvscan_single(cmd, pvl->pv->dev, NULL, 0))
+ if (!lvmetad_pvscan_single(cmd, pvl->pv->dev, NULL, NULL))
return ECMD_FAILED;
}
@@ -103,7 +103,7 @@ int lvscan(struct cmd_context *cmd, int argc, char **argv)
/* Needed because this command has NO_LVMETAD_AUTOSCAN. */
if (lvmetad_used() && (!lvmetad_token_matches(cmd) || lvmetad_is_disabled(cmd, &reason))) {
- if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, NULL, 0)) {
+ if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0)) {
log_warn("WARNING: Not using lvmetad because cache update failed.");
lvmetad_make_unused(cmd);
}
diff --git a/tools/pvscan.c b/tools/pvscan.c
index 50753fd..3e9efef 100644
--- a/tools/pvscan.c
+++ b/tools/pvscan.c
@@ -29,6 +29,12 @@ struct pvscan_params {
char *pv_tmp_name;
};
+struct pvscan_aa_params {
+ int refresh_all;
+ unsigned int activate_errors;
+ struct dm_list changed_vgnames;
+};
+
static int _pvscan_display_single(struct cmd_context *cmd,
struct physical_volume *pv,
struct pvscan_params *params)
@@ -120,70 +126,85 @@ static int _pvscan_single(struct cmd_context *cmd, struct volume_group *vg,
return ECMD_PROCESSED;
}
-#define REFRESH_BEFORE_AUTOACTIVATION_RETRIES 5
-#define REFRESH_BEFORE_AUTOACTIVATION_RETRY_USLEEP_DELAY 100000
-
-static int _auto_activation_handler(struct cmd_context *cmd,
- const char *vgname, const char *vgid,
- int partial, int changed,
- activation_change_t activate)
+static int _lvmetad_clear_dev(dev_t devno, int32_t major, int32_t minor)
{
- unsigned int refresh_retries = REFRESH_BEFORE_AUTOACTIVATION_RETRIES;
- int refresh_done = 0;
- struct volume_group *vg;
- struct id vgid_raw;
- uint32_t read_error;
- int r = 0;
+ char buf[24];
- /* TODO: add support for partial and clustered VGs */
- if (partial)
- return 1;
+ (void) dm_snprintf(buf, sizeof(buf), FMTi32 ":" FMTi32, major, minor);
- if (!id_read_format(&vgid_raw, vgid))
+ if (!lvmetad_pv_gone(devno, buf))
return_0;
- /*
- * FIXME: pvscan activation really needs to be changed to use
- * the standard process_each_vg() interface. It should save
- * a list of VG names that are found during the scan, then
- * call process_each_vg() with that list to do activation.
- */
+ log_print_unless_silent("Device %s not found. Cleared from lvmetad cache.", buf);
- cmd->vg_read_print_access_error = 0;
-
- /* NB. This is safe because we know lvmetad is running and we won't hit disk. */
- vg = vg_read(cmd, vgname, (const char *)&vgid_raw, 0, 0);
- read_error = vg_read_error(vg);
- if (read_error) {
- /*
- * foreign VGs: we want to read and update lvmetad, but that's
- * all, we don't want to even attempt to autoactivate.
- *
- * shared VGs: we want to read and update lvmetad, and for now
- * ignore them for autoactivation. Once pvscan autoactivation
- * uses process_each_vg, then shared VGs could be autoactivated.
- */
- if (read_error & (FAILED_SYSTEMID | FAILED_LOCK_TYPE | FAILED_LOCK_MODE)) {
- release_vg(vg);
- return 1;
- }
+ return 1;
+}
- log_error("Failed to read Volume Group \"%s\" (%s) during autoactivation.", vgname, vgid);
- release_vg(vg);
- return 0;
- }
+/*
+ * pvscan --cache does not perform any lvmlockd locking, and
+ * pvscan --cache -aay skips autoactivation in lockd VGs.
+ *
+ * pvscan --cache populates lvmetad with VG metadata from disk.
+ * No lvmlockd locking is needed. It is expected that lockd VG
+ * metadata that is read by pvscan and populated in lvmetad may
+ * be immediately stale due to changes to the VG from other hosts
+ * during or after this pvscan. This is normal and not a problem.
+ * When a subsequent lvm command uses the VG, it will lock the VG
+ * with lvmlockd, read the VG from lvmetad, and update the cached
+ * copy from disk if necessary.
+ *
+ * pvscan --cache -aay does not activate LVs in lockd VGs because
+ * activation requires locking, and a lock-start operation is needed
+ * on a lockd VG before any locking can be performed in it.
+ *
+ * An equivalent of pvscan --cache -aay for lockd VGs is:
+ * 1. pvscan --cache
+ * 2. vgchange --lock-start
+ * 3. vgchange -aay -S 'locktype=sanlock || locktype=dlm'
+ *
+ * [We could eventually add support for autoactivating lockd VGs
+ * using pvscan by incorporating the lock start step (which can
+ * take a long time), but there may be a better option than
+ * continuing to overload pvscan.]
+ *
+ * Stages of starting a lockd VG:
+ *
+ * . pvscan --cache populates lockd VGs in lvmetad without locks,
+ * and this initial cached copy may quickly become stale.
+ *
+ * . vgchange --lock-start VG reads the VG without the VG lock
+ * because no locks are available until the locking is started.
+ * It only uses the VG name and lock_type from the VG metadata,
+ * and then only uses it to start the VG lockspace in lvmlockd.
+ *
+ * . Further lvm commands, e.g. activation, can then lock the VG
+ * with lvmlockd and use current VG metdata.
+ */
- if (is_lockd_type(vg->lock_type)) {
- r = 1;
- goto out;
- }
+#define REFRESH_BEFORE_AUTOACTIVATION_RETRIES 5
+#define REFRESH_BEFORE_AUTOACTIVATION_RETRY_USLEEP_DELAY 100000
- if (vg_is_clustered(vg)) {
- r = 1;
- goto out;
- }
+static int _pvscan_autoactivate_single(struct cmd_context *cmd, const char *vg_name,
+ struct volume_group *vg, struct processing_handle *handle)
+{
+ struct pvscan_aa_params *pp = (struct pvscan_aa_params *)handle->custom_handle;
+ unsigned int refresh_retries = REFRESH_BEFORE_AUTOACTIVATION_RETRIES;
+ int refresh_done = 0;
- /* FIXME: There's a tiny race when suspending the device which is part
+ if (vg_is_clustered(vg))
+ return ECMD_PROCESSED;
+
+ if (is_lockd_type(vg->lock_type))
+ return ECMD_PROCESSED;
+
+ log_debug("pvscan autoactivating VG %s.", vg_name);
+
+ /*
+ * Refresh LVs in a VG that has "changed" from finding a PV.
+ * The meaning of "changed" is determined in lvmetad, and is
+ * returned to the command as a flag.
+ *
+ * FIXME: There's a tiny race when suspending the device which is part
* of the refresh because when suspend ioctl is performed, the dm
* kernel driver executes (do_suspend and dm_suspend kernel fn):
*
@@ -202,9 +223,10 @@ static int _auto_activation_handler(struct cmd_context *cmd,
*
* Remove this workaround with "refresh_retries" once we have proper locking in!
*/
- if (changed) {
+ if (pp->refresh_all || str_list_match_item(&pp->changed_vgnames, vg_name)) {
while (refresh_retries--) {
- if (vg_refresh_visible(vg->cmd, vg)) {
+ log_debug_activation("Refreshing VG %s before autoactivation.", vg_name);
+ if (vg_refresh_visible(cmd, vg)) {
refresh_done = 1;
break;
}
@@ -215,8 +237,11 @@ static int _auto_activation_handler(struct cmd_context *cmd,
log_warn("%s: refresh before autoactivation failed.", vg->name);
}
- if (!vgchange_activate(vg->cmd, vg, activate)) {
+ log_debug_activation("Autoactivating VG %s.", vg_name);
+
+ if (!vgchange_activate(cmd, vg, CHANGE_AAY)) {
log_error("%s: autoactivation failed.", vg->name);
+ pp->activate_errors++;
goto out;
}
@@ -226,35 +251,53 @@ static int _auto_activation_handler(struct cmd_context *cmd,
* be adding --poll y|n cmdline option for pvscan and call
* init_background_polling routine in autoactivation handler.
*/
- if (!(vgchange_background_polling(vg->cmd, vg)))
- goto_out;
-
- r = 1;
+ log_debug_activation("Starting background polling for VG %s.", vg_name);
+ if (!(vgchange_background_polling(cmd, vg)))
+ goto_out;
out:
- unlock_and_release_vg(cmd, vg, vgname);
- return r;
+ return ECMD_PROCESSED;
}
-static int _clear_dev_from_lvmetad_cache(dev_t devno, int32_t major, int32_t minor,
- activation_handler handler)
+static int _pvscan_autoactivate(struct cmd_context *cmd, struct pvscan_aa_params *pp,
+ int all_vgs, struct dm_list *vgnames)
{
- char buf[24];
+ struct processing_handle *handle = NULL;
+ int ret;
- (void) dm_snprintf(buf, sizeof(buf), FMTi32 ":" FMTi32, major, minor);
+ if (!all_vgs && dm_list_empty(vgnames)) {
+ log_debug("No VGs to autoactivate.");
+ return ECMD_PROCESSED;
+ }
- if (!lvmetad_pv_gone(devno, buf, handler))
- return_0;
+ if (!lvmetad_used())
+ log_warn("WARNING: Autoactivation reading from disk instead of lvmetad.");
+
+ if (!(handle = init_processing_handle(cmd))) {
+ log_error("Failed to initialize processing handle.");
+ return ECMD_FAILED;
+ }
- log_print_unless_silent("Device %s not found. "
- "Cleared from lvmetad cache.", buf);
+ handle->custom_handle = pp;
- return 1;
+ if (all_vgs) {
+ cmd->command->flags |= ALL_VGS_IS_DEFAULT;
+ pp->refresh_all = 1;
+ }
+
+ dev_cache_full_scan(cmd->full_filter);
+
+ ret = process_each_vg(cmd, 0, NULL, NULL, vgnames, 0, handle, _pvscan_autoactivate_single);
+
+ destroy_processing_handle(cmd, handle);
+
+ return ret;
}
-static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
+static int _pvscan_cache(struct cmd_context *cmd, int argc, char **argv)
{
- int ret = ECMD_PROCESSED;
+ struct pvscan_aa_params pp = { 0 };
+ struct dm_list found_vgnames;
struct device *dev;
const char *pv_name;
const char *reason = NULL;
@@ -263,28 +306,26 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
int devno_args = 0;
struct arg_value_group_list *current_group;
dev_t devno;
- activation_handler handler = NULL;
+ int do_activate = 0;
+ int all_vgs = 0;
+ int remove_errors = 0;
+ int add_errors = 0;
+ int ret = ECMD_PROCESSED;
+
+ dm_list_init(&found_vgnames);
+ dm_list_init(&pp.changed_vgnames);
- /*
- * Return here immediately if lvmetad is not used.
- * Also return if locking_type=3 (clustered) as we
- * dont't support cluster + lvmetad yet.
- *
- * This is to avoid taking the global lock uselessly
- * and to prevent hangs in clustered environment.
- */
- /* TODO: Remove this once lvmetad + cluster supported! */
if (!lvmetad_used()) {
log_verbose("Ignoring pvscan --cache command because lvmetad is not in use.");
return ret;
}
- if (arg_count(cmd, activate_ARG)) {
+ if (arg_is_set(cmd, activate_ARG)) {
if (arg_uint_value(cmd, activate_ARG, CHANGE_AAY) != CHANGE_AAY) {
log_error("Only --activate ay allowed with pvscan.");
return 0;
}
- handler = _auto_activation_handler;
+ do_activate = 1;
}
if (arg_count(cmd, major_ARG) + arg_count(cmd, minor_ARG))
@@ -300,96 +341,130 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
return ECMD_FAILED;
}
- /* Scan everything? */
+ /*
+ * Scan all devices when no args are given.
+ */
if (!argc && !devno_args) {
- if (!lvmetad_pvscan_all_devs(cmd, handler, 1)) {
- log_error("Failed to update cache.");
- ret = ECMD_FAILED;
+ log_verbose("Scanning all devices.");
+
+ if (!lvmetad_pvscan_all_devs(cmd, 1)) {
+ log_warn("WARNING: Not using lvmetad because cache update failed.");
+ lvmetad_make_unused(cmd);
}
- goto out;
+ if (lvmetad_used() && lvmetad_is_disabled(cmd, &reason)) {
+ log_warn("WARNING: Not using lvmetad because %s.", reason);
+ lvmetad_make_unused(cmd);
+ }
+ all_vgs = 1;
+ goto activate;
+ }
+
+ /*
+ * FIXME: when specific devs are named, we generally don't want to scan
+ * any other devs, but if lvmetad is not yet populated, the first
+ * 'pvscan --cache dev' does need to do a full scan. We want to remove
+ * the need for this case so that 'pvscan --cache dev' is guaranteed to
+ * never scan any devices other than those specified.
+ */
+ if (!lvmetad_token_matches(cmd)) {
+ log_verbose("Scanning all devices to initialize lvmetad.");
+
+ if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0)) {
+ log_warn("WARNING: Not using lvmetad because cache update failed.");
+ lvmetad_make_unused(cmd);
+ }
+ if (lvmetad_used() && lvmetad_is_disabled(cmd, &reason)) {
+ log_warn("WARNING: Not using lvmetad because %s.", reason);
+ lvmetad_make_unused(cmd);
+ }
+ all_vgs = 1;
+ goto activate;
}
/*
- * When lvmetad is disabled, all devices need to be rescanned,
- * i.e. the !argc case above, pvscan --cache.
+ * When args are given, scan only those devices. If lvmetad is already
+ * disabled, a full scan is required to reenable it, so there's no
+ * point in doing individual device scans, so go directly to
+ * autoactivation. (FIXME: Should we also skip autoactivation in this
+ * case since that will read disks with lvmetad disabled?
+ * i.e. avoid disk access and not activate LVs, or or read from disk
+ * and activate LVs?)
*/
- if (lvmetad_used() && lvmetad_is_disabled(cmd, &reason)) {
+ if (lvmetad_is_disabled(cmd, &reason)) {
log_warn("WARNING: Not using lvmetad because %s.", reason);
- log_warn("WARNING: Rescan all devices to update lvmetad cache (pvscan --cache).");
- log_error("Failed to update cache.");
- ret = ECMD_FAILED;
- goto out;
+ lvmetad_make_unused(cmd);
+ all_vgs = 1;
+ goto activate;
}
/*
- * FIXME: when specific devs are named, we generally don't
- * want to scan any other devs, but if lvmetad is not yet
- * populated, the first 'pvscan --cache dev' does need to
- * do a full scan. We want to remove the need for this
- * case so that 'pvscan --cache dev' is guaranteed to never
- * scan any devices other than those specified.
+ * Step 1: for each device, if it's no longer found, then tell lvmetad
+ * to drop it. If the device exists, read metadata from it and send
+ * that to lvmetad.
+ *
+ * When given a device name, check if the device is not visible to
+ * lvmetad, but still visible to the system, and if so, tell lvmetad to
+ * drop it (using the major:minor from the system).
+ *
+ * When given a major:minor which is not visible to the system, just
+ * tell lvmetad to drop it directly using that major:minor.
+ *
+ * When a device has left the system, it must be dropped using
+ * --major/--minor because we cannot map the device name to major:minor
+ * after the device has left. (A full rescan could of course be used
+ * to drop any devices that have left.)
*/
- if (lvmetad_used() && !lvmetad_token_matches(cmd)) {
- if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, NULL, 0)) {
- log_error("Failed to update cache.");
- ret = ECMD_FAILED;
- goto out;
- }
- }
- log_verbose("Using physical volume(s) on command line");
+ if (argc || devno_args)
+ log_verbose("Scanning devices on command line.");
- /* Process any command line PVs first. */
while (argc--) {
pv_name = *argv++;
if (pv_name[0] == '/') {
- /* device path */
if (!(dev = dev_cache_get(pv_name, cmd->lvmetad_filter))) {
+ /* Remove device path from lvmetad. */
+ log_debug("Removing dev %s from lvmetad cache.", pv_name);
if ((dev = dev_cache_get(pv_name, NULL))) {
- if (!_clear_dev_from_lvmetad_cache(dev->dev, MAJOR(dev->dev), MINOR(dev->dev), handler)) {
- stack;
- ret = ECMD_FAILED;
- break;
- }
+ if (!_lvmetad_clear_dev(dev->dev, MAJOR(dev->dev), MINOR(dev->dev)))
+ remove_errors++;
} else {
log_error("Physical Volume %s not found.", pv_name);
ret = ECMD_FAILED;
- break;
}
- continue;
+ } else {
+ /* Add device path to lvmetad. */
+ log_debug("Scanning dev %s for lvmetad cache.", pv_name);
+ if (!lvmetad_pvscan_single(cmd, dev, &found_vgnames, &pp.changed_vgnames))
+ add_errors++;
}
- }
- else {
- /* device major:minor */
+ } else {
if (sscanf(pv_name, "%d:%d", &major, &minor) != 2) {
- log_error("Failed to parse major:minor from %s", pv_name);
- ret = ECMD_FAILED;
+ log_warn("WARNING: Failed to parse major:minor from %s, skipping.", pv_name);
continue;
}
devno = MKDEV((dev_t)major, (dev_t)minor);
+
if (!(dev = dev_cache_get_by_devt(devno, cmd->lvmetad_filter))) {
- if (!(_clear_dev_from_lvmetad_cache(devno, major, minor, handler))) {
- stack;
- ret = ECMD_FAILED;
- break;
- }
- continue;
+ /* Remove major:minor from lvmetad. */
+ log_debug("Removing dev %d:%d from lvmetad cache.", major, minor);
+ if (!_lvmetad_clear_dev(devno, major, minor))
+ remove_errors++;
+ } else {
+ /* Add major:minor to lvmetad. */
+ log_debug("Scanning dev %d:%d for lvmetad cache.", major, minor);
+ if (!lvmetad_pvscan_single(cmd, dev, &found_vgnames, &pp.changed_vgnames))
+ add_errors++;
}
}
+
if (sigint_caught()) {
ret = ECMD_FAILED;
- stack;
- break;
- }
- if (!lvmetad_pvscan_single(cmd, dev, handler, 0)) {
- ret = ECMD_FAILED;
- stack;
- break;
+ goto_out;
}
}
if (!devno_args)
- goto out;
+ goto activate;
/* Process any grouped --major --minor args */
dm_list_iterate_items(current_group, &cmd->arg_value_groups) {
@@ -402,27 +477,47 @@ static int _pvscan_lvmetad(struct cmd_context *cmd, int argc, char **argv)
devno = MKDEV((dev_t)major, (dev_t)minor);
if (!(dev = dev_cache_get_by_devt(devno, cmd->lvmetad_filter))) {
- if (!(_clear_dev_from_lvmetad_cache(devno, major, minor, handler))) {
- stack;
- ret = ECMD_FAILED;
- break;
- }
- continue;
+ /* Remove major:minor from lvmetad. */
+ log_debug("Removing dev %d:%d from lvmetad cache.", major, minor);
+ if (!_lvmetad_clear_dev(devno, major, minor))
+ remove_errors++;
+ } else {
+ /* Add major:minor to lvmetad. */
+ log_debug("Scanning dev %d:%d for lvmetad cache.", major, minor);
+ if (!lvmetad_pvscan_single(cmd, dev, &found_vgnames, &pp.changed_vgnames))
+ add_errors++;
}
+
if (sigint_caught()) {
ret = ECMD_FAILED;
- stack;
- break;
- }
- if (!lvmetad_pvscan_single(cmd, dev, handler, 0)) {
- ret = ECMD_FAILED;
- stack;
- break;
+ goto_out;
}
+ }
+ /*
+ * In the process of scanning devices, lvmetad may have become
+ * disabled. If so, revert to scanning for the autoactivation step.
+ * Only autoactivate the VGs that were found during the dev scans.
+ */
+ if (lvmetad_used() && lvmetad_is_disabled(cmd, &reason)) {
+ log_warn("WARNING: Not using lvmetad because %s.", reason);
+ lvmetad_make_unused(cmd);
}
+activate:
+ /*
+ * Step 2: when the PV was sent to lvmetad, the lvmetad reply
+ * indicated if all the PVs for the VG are now found. If so,
+ * the vgname was added to the list, and we can attempt to
+ * autoactivate LVs in the VG.
+ */
+ if (do_activate)
+ ret = _pvscan_autoactivate(cmd, &pp, all_vgs, &found_vgnames);
+
out:
+ if (remove_errors || add_errors || pp.activate_errors)
+ ret = ECMD_FAILED;
+
if (!sync_local_dev_names(cmd))
stack;
unlock_vg(cmd, VG_GLOBAL);
@@ -477,7 +572,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
int ret;
if (arg_count(cmd, cache_long_ARG))
- return _pvscan_lvmetad(cmd, argc, argv);
+ return _pvscan_cache(cmd, argc, argv);
if (argc) {
log_error("Too many parameters on command line.");
@@ -506,7 +601,7 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
/* Needed because this command has NO_LVMETAD_AUTOSCAN. */
if (lvmetad_used() && (!lvmetad_token_matches(cmd) || lvmetad_is_disabled(cmd, &reason))) {
- if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, NULL, 0)) {
+ if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, 0)) {
log_warn("WARNING: Not using lvmetad because cache update failed.");
lvmetad_make_unused(cmd);
}
@@ -526,7 +621,6 @@ int pvscan(struct cmd_context *cmd, int argc, char **argv)
if (!lockd_gl(cmd, "sh", 0))
return_ECMD_FAILED;
-
if (!(handle = init_processing_handle(cmd))) {
log_error("Failed to initialize processing handle.");
ret = ECMD_FAILED;
diff --git a/tools/toollib.c b/tools/toollib.c
index e879850..5383734 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -4624,7 +4624,7 @@ do_command:
if (info)
lvmcache_del(info);
- if (!lvmetad_pv_gone_by_dev(pd->dev, NULL)) {
+ if (!lvmetad_pv_gone_by_dev(pd->dev)) {
log_error("Failed to remove PV %s from lvmetad.", pd->name);
dm_list_move(&pp->arg_fail, &pd->list);
continue;
@@ -4644,7 +4644,7 @@ do_command:
continue;
}
- if (!lvmetad_pv_gone_by_dev(pd->dev, NULL)) {
+ if (!lvmetad_pv_gone_by_dev(pd->dev)) {
log_error("Failed to remove PV %s from lvmetad.", pd->name);
dm_list_move(&pp->arg_fail, &pd->list);
continue;
diff --git a/tools/vgimport.c b/tools/vgimport.c
index c499f8b..1f2e14d 100644
--- a/tools/vgimport.c
+++ b/tools/vgimport.c
@@ -96,7 +96,7 @@ int vgimport(struct cmd_context *cmd, int argc, char **argv)
* import it.
*/
if (lvmetad_used()) {
- if (!lvmetad_pvscan_all_devs(cmd, NULL, 1)) {
+ if (!lvmetad_pvscan_all_devs(cmd, 1)) {
log_warn("WARNING: Not using lvmetad because cache update failed.");
lvmetad_make_unused(cmd);
}
diff --git a/tools/vgscan.c b/tools/vgscan.c
index 67797f5..688e361 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -101,7 +101,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
log_verbose("Ignoring vgscan --cache command because lvmetad is not in use.");
if (lvmetad_used() && (arg_is_set(cmd, cache_long_ARG) || !lvmetad_token_matches(cmd) || lvmetad_is_disabled(cmd, &reason))) {
- if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, NULL, arg_is_set(cmd, cache_long_ARG))) {
+ if (lvmetad_used() && !lvmetad_pvscan_all_devs(cmd, arg_is_set(cmd, cache_long_ARG))) {
log_warn("WARNING: Not using lvmetad because cache update failed.");
lvmetad_make_unused(cmd);
}
7 years, 11 months
master - toollib: add vg name list arg to process_each_vg
by David Teigland
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=55683a659f9bf6...
Commit: 55683a659f9bf6875dd930e2dff62f1e1bdb88aa
Parent: bf8d00985ada723778701530c7ea863c617dda8a
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Apr 28 16:18:20 2016 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Mon May 23 11:18:16 2016 -0500
toollib: add vg name list arg to process_each_vg
---
tools/lvcreate.c | 2 +-
tools/lvrename.c | 2 +-
tools/lvresize.c | 2 +-
tools/polldaemon.c | 4 ++--
tools/reporter.c | 6 +++---
tools/toollib.c | 17 +++++++++++++----
tools/toollib.h | 7 +++++--
tools/vgcfgbackup.c | 2 +-
tools/vgchange.c | 2 +-
tools/vgck.c | 2 +-
tools/vgconvert.c | 2 +-
tools/vgdisplay.c | 2 +-
tools/vgexport.c | 2 +-
tools/vgextend.c | 2 +-
tools/vgimport.c | 2 +-
tools/vgremove.c | 2 +-
tools/vgrename.c | 2 +-
tools/vgscan.c | 2 +-
18 files changed, 37 insertions(+), 25 deletions(-)
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 8ddecae..b1bf1af 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -1564,7 +1564,7 @@ int lvcreate(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &pp;
- ret = process_each_vg(cmd, 0, NULL, lp.vg_name, READ_FOR_UPDATE, handle,
+ ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, handle,
&_lvcreate_single);
_destroy_lvcreate_params(&lp);
diff --git a/tools/lvrename.c b/tools/lvrename.c
index 56c19fd..e9dd061 100644
--- a/tools/lvrename.c
+++ b/tools/lvrename.c
@@ -217,7 +217,7 @@ int lvrename(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lp;
- ret = process_each_vg(cmd, 0, NULL, vg_name, READ_FOR_UPDATE, handle,
+ ret = process_each_vg(cmd, 0, NULL, vg_name, NULL, READ_FOR_UPDATE, handle,
_lvrename_single);
destroy_processing_handle(cmd, handle);
diff --git a/tools/lvresize.c b/tools/lvresize.c
index a35a03d..7a86178 100644
--- a/tools/lvresize.c
+++ b/tools/lvresize.c
@@ -223,7 +223,7 @@ int lvresize(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &lp;
- ret = process_each_vg(cmd, 0, NULL, lp.vg_name, READ_FOR_UPDATE, handle,
+ ret = process_each_vg(cmd, 0, NULL, lp.vg_name, NULL, READ_FOR_UPDATE, handle,
&_lvresize_single);
destroy_processing_handle(cmd, handle);
diff --git a/tools/polldaemon.c b/tools/polldaemon.c
index 6b15a0d..f8aa49c 100644
--- a/tools/polldaemon.c
+++ b/tools/polldaemon.c
@@ -364,7 +364,7 @@ static void _poll_for_all_vgs(struct cmd_context *cmd,
while (1) {
parms->outstanding_count = 0;
- process_each_vg(cmd, 0, NULL, NULL, READ_FOR_UPDATE, handle, _poll_vg);
+ process_each_vg(cmd, 0, NULL, NULL, NULL, READ_FOR_UPDATE, handle, _poll_vg);
if (!parms->outstanding_count)
break;
if (parms->interval)
@@ -508,7 +508,7 @@ static void _lvmpolld_poll_for_all_vgs(struct cmd_context *cmd,
handle->custom_handle = &lpdp;
- process_each_vg(cmd, 0, NULL, NULL, 0, handle, _lvmpolld_init_poll_vg);
+ process_each_vg(cmd, 0, NULL, NULL, NULL, 0, handle, _lvmpolld_init_poll_vg);
first = dm_list_first(&lpdp.idls);
diff --git a/tools/reporter.c b/tools/reporter.c
index 4e27159..4004f9b 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -837,7 +837,7 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args)
&_lvs_single);
break;
case VGS:
- r = process_each_vg(cmd, args->argc, args->argv, NULL, 0,
+ r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL, 0,
handle, &_vgs_single);
break;
case LABEL:
@@ -850,7 +850,7 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args)
arg_is_set(cmd, all_ARG), 0,
handle, &_pvs_single);
else
- r = process_each_vg(cmd, args->argc, args->argv, NULL,
+ r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
0, handle, &_pvs_in_vg);
break;
case SEGS:
@@ -870,7 +870,7 @@ static int _do_report(struct cmd_context *cmd, struct report_args *args)
lv_info_needed && lv_segment_status_needed ? &_pvsegs_with_lv_info_and_status_single :
&_pvsegs_single);
else
- r = process_each_vg(cmd, args->argc, args->argv, NULL,
+ r = process_each_vg(cmd, args->argc, args->argv, NULL, NULL,
0, handle, &_pvsegs_in_vg);
break;
default:
diff --git a/tools/toollib.c b/tools/toollib.c
index 17a29e0..e879850 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1645,6 +1645,7 @@ int validate_restricted_lvname_param(struct cmd_context *cmd, const char **vg_na
static int _get_arg_vgnames(struct cmd_context *cmd,
int argc, char **argv,
const char *one_vgname,
+ struct dm_list *use_vgnames,
struct dm_list *arg_vgnames,
struct dm_list *arg_tags)
{
@@ -1661,6 +1662,11 @@ static int _get_arg_vgnames(struct cmd_context *cmd,
return ret_max;
}
+ if (use_vgnames && !dm_list_empty(use_vgnames)) {
+ dm_list_splice(arg_vgnames, use_vgnames);
+ return ret_max;
+ }
+
for (; opt < argc; opt++) {
vg_name = argv[opt];
@@ -2073,11 +2079,14 @@ static void _choose_vgs_to_process(struct cmd_context *cmd,
/*
* Call process_single_vg() for each VG selected by the command line arguments.
- * If one_vgname is set, process only that VG and ignore argc/argv (which should be 0/NULL)..
+ * If one_vgname is set, process only that VG and ignore argc/argv (which should be 0/NULL).
* If one_vgname is not set, get VG names to process from argc/argv.
*/
-int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- const char *one_vgname, uint32_t read_flags,
+int process_each_vg(struct cmd_context *cmd,
+ int argc, char **argv,
+ const char *one_vgname,
+ struct dm_list *use_vgnames,
+ uint32_t read_flags,
struct processing_handle *handle,
process_single_vg_fn_t process_single_vg)
{
@@ -2104,7 +2113,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
/*
* Find any VGs or tags explicitly provided on the command line.
*/
- if ((ret = _get_arg_vgnames(cmd, argc, argv, one_vgname, &arg_vgnames, &arg_tags)) != ECMD_PROCESSED) {
+ if ((ret = _get_arg_vgnames(cmd, argc, argv, one_vgname, use_vgnames, &arg_vgnames, &arg_tags)) != ECMD_PROCESSED) {
ret_max = ret;
goto_out;
}
diff --git a/tools/toollib.h b/tools/toollib.h
index 2b3ca6e..a79c426 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -97,8 +97,11 @@ typedef int (*process_single_pvseg_fn_t) (struct cmd_context * cmd,
struct pv_segment * pvseg,
struct processing_handle *handle);
-int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- const char *one_vgname, uint32_t flags,
+int process_each_vg(struct cmd_context *cmd,
+ int argc, char **argv,
+ const char *one_vgname,
+ struct dm_list *use_vgnames,
+ uint32_t flags,
struct processing_handle *handle,
process_single_vg_fn_t process_single_vg);
diff --git a/tools/vgcfgbackup.c b/tools/vgcfgbackup.c
index 1b256c5..554317e 100644
--- a/tools/vgcfgbackup.c
+++ b/tools/vgcfgbackup.c
@@ -94,7 +94,7 @@ int vgcfgbackup(struct cmd_context *cmd, int argc, char **argv)
init_pvmove(1);
- ret = process_each_vg(cmd, argc, argv, NULL, READ_ALLOW_INCONSISTENT,
+ ret = process_each_vg(cmd, argc, argv, NULL, NULL, READ_ALLOW_INCONSISTENT,
handle, &vg_backup_single);
dm_free(last_filename);
diff --git a/tools/vgchange.c b/tools/vgchange.c
index 49c64b9..bbd9e1f 100644
--- a/tools/vgchange.c
+++ b/tools/vgchange.c
@@ -1216,7 +1216,7 @@ int vgchange(struct cmd_context *cmd, int argc, char **argv)
if (arg_is_set(cmd, lockstart_ARG) || arg_is_set(cmd, lockstop_ARG))
flags |= READ_ALLOW_EXPORTED;
- ret = process_each_vg(cmd, argc, argv, NULL, flags, NULL, &vgchange_single);
+ ret = process_each_vg(cmd, argc, argv, NULL, NULL, flags, NULL, &vgchange_single);
/* Wait for lock-start ops that were initiated in vgchange_lockstart. */
diff --git a/tools/vgck.c b/tools/vgck.c
index 15f7bc3..27a1d00 100644
--- a/tools/vgck.c
+++ b/tools/vgck.c
@@ -38,6 +38,6 @@ static int vgck_single(struct cmd_context *cmd __attribute__((unused)),
int vgck(struct cmd_context *cmd, int argc, char **argv)
{
lvmetad_make_unused(cmd);
- return process_each_vg(cmd, argc, argv, NULL, 0, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL,
&vgck_single);
}
diff --git a/tools/vgconvert.c b/tools/vgconvert.c
index 666b484..6ae675f 100644
--- a/tools/vgconvert.c
+++ b/tools/vgconvert.c
@@ -181,6 +181,6 @@ int vgconvert(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- return process_each_vg(cmd, argc, argv, NULL, READ_FOR_UPDATE, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL,
&vgconvert_single);
}
diff --git a/tools/vgdisplay.c b/tools/vgdisplay.c
index 85e5185..c805e68 100644
--- a/tools/vgdisplay.c
+++ b/tools/vgdisplay.c
@@ -89,7 +89,7 @@ int vgdisplay(struct cmd_context *cmd, int argc, char **argv)
}
**********/
- return process_each_vg(cmd, argc, argv, NULL, 0, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL,
vgdisplay_single);
/******** FIXME Need to count number processed
diff --git a/tools/vgexport.c b/tools/vgexport.c
index 8f5db9c..afe9a14 100644
--- a/tools/vgexport.c
+++ b/tools/vgexport.c
@@ -80,6 +80,6 @@ int vgexport(struct cmd_context *cmd, int argc, char **argv)
return EINVALID_CMD_LINE;
}
- return process_each_vg(cmd, argc, argv, NULL, READ_FOR_UPDATE, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL, READ_FOR_UPDATE, NULL,
&vgexport_single);
}
diff --git a/tools/vgextend.c b/tools/vgextend.c
index 9cfd3a7..24b51cf 100644
--- a/tools/vgextend.c
+++ b/tools/vgextend.c
@@ -197,7 +197,7 @@ int vgextend(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &vp;
- ret = process_each_vg(cmd, 0, NULL, vg_name,
+ ret = process_each_vg(cmd, 0, NULL, vg_name, NULL,
READ_FOR_UPDATE, handle,
restoremissing ? &_vgextend_restoremissing : &_vgextend_single);
diff --git a/tools/vgimport.c b/tools/vgimport.c
index 5bcf7e0..c499f8b 100644
--- a/tools/vgimport.c
+++ b/tools/vgimport.c
@@ -107,7 +107,7 @@ int vgimport(struct cmd_context *cmd, int argc, char **argv)
}
}
- return process_each_vg(cmd, argc, argv, NULL,
+ return process_each_vg(cmd, argc, argv, NULL, NULL,
READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
NULL,
&vgimport_single);
diff --git a/tools/vgremove.c b/tools/vgremove.c
index f030a20..1d1a40f 100644
--- a/tools/vgremove.c
+++ b/tools/vgremove.c
@@ -109,7 +109,7 @@ int vgremove(struct cmd_context *cmd, int argc, char **argv)
cmd->lockd_gl_disable = 1;
cmd->handles_missing_pvs = 1;
- ret = process_each_vg(cmd, argc, argv, NULL,
+ ret = process_each_vg(cmd, argc, argv, NULL, NULL,
READ_FOR_UPDATE,
NULL, &vgremove_single);
diff --git a/tools/vgrename.c b/tools/vgrename.c
index e5af820..ee6a91f 100644
--- a/tools/vgrename.c
+++ b/tools/vgrename.c
@@ -244,7 +244,7 @@ int vgrename(struct cmd_context *cmd, int argc, char **argv)
handle->custom_handle = &vp;
- ret = process_each_vg(cmd, 0, NULL, vg_name_old,
+ ret = process_each_vg(cmd, 0, NULL, vg_name_old, NULL,
READ_FOR_UPDATE | READ_ALLOW_EXPORTED,
handle, _vgrename_single);
diff --git a/tools/vgscan.c b/tools/vgscan.c
index 59a0f6a..67797f5 100644
--- a/tools/vgscan.c
+++ b/tools/vgscan.c
@@ -117,7 +117,7 @@ int vgscan(struct cmd_context *cmd, int argc, char **argv)
else
log_print_unless_silent("Reading volume groups from cache.");
- maxret = process_each_vg(cmd, argc, argv, NULL, 0, NULL,
+ maxret = process_each_vg(cmd, argc, argv, NULL, NULL, 0, NULL,
&vgscan_single);
if (arg_count(cmd, mknodes_ARG)) {
7 years, 11 months
master - raid0: Add raid0 segment type.
by Alasdair Kergon
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=bf8d00985ada72...
Commit: bf8d00985ada723778701530c7ea863c617dda8a
Parent: ad4ca55543428f909fde8ba03e88d355560fe320
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Mon May 23 16:46:38 2016 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Mon May 23 16:46:38 2016 +0100
raid0: Add raid0 segment type.
This remains experimental and quite restrictive so should only be used
for testing at this stage. (E.g. lvreduce is not supported.)
---
WHATS_NEW | 1 +
lib/activate/dev_manager.c | 14 +++--
lib/format_text/export.c | 13 +++--
lib/metadata/lv_manip.c | 31 +++++++----
lib/metadata/segtype.h | 5 ++
lib/raid/raid.c | 128 +++++++++++++++++++++++++++++++-------------
lib/report/report.c | 2 +-
libdm/libdm-deptree.c | 5 ++
man/lvcreate.8.in | 12 ++++-
tools/lvcreate.c | 27 +++++++---
10 files changed, 168 insertions(+), 70 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 645e87e..eac3477 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.155 -
================================
+ Add basic support for --type raid0 using md.
Add support for lvchange --cachemode for cached LV.
Fix liblvm2app error handling when setting up context.
Delay liblvm2app init in python code until it is needed.
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index f6cc0be..711074d 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -2207,7 +2207,7 @@ static int _add_lv_to_dtree(struct dev_manager *dm, struct dm_tree *dtree,
(!dm->track_pending_delete || !lv_is_cache(lv)) &&
!_add_lv_to_dtree(dm, dtree, seg_lv(seg, s), 0))
return_0;
- if (seg_is_raid(seg) &&
+ if (seg_is_raid(seg) && seg->meta_areas && seg_metalv(seg, s) &&
!_add_lv_to_dtree(dm, dtree, seg_metalv(seg, s), 0))
return_0;
}
@@ -2379,9 +2379,13 @@ int add_areas_line(struct dev_manager *dm, struct lv_segment *seg,
return_0;
continue;
}
- if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s), NULL)))
- return_0;
- if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_metale(seg, s)))
+
+ if (seg->meta_areas && seg_metalv(seg, s)) {
+ if (!(dlid = build_dm_uuid(dm->mem, seg_metalv(seg, s), NULL)))
+ return_0;
+ if (!dm_tree_node_add_target_area(node, NULL, dlid, extent_size * seg_metale(seg, s)))
+ return_0;
+ } else if (!dm_tree_node_add_null_area(node, 0))
return_0;
if (!(dlid = build_dm_uuid(dm->mem, seg_lv(seg, s), NULL)))
@@ -2709,7 +2713,7 @@ static int _add_segment_to_dtree(struct dev_manager *dm,
!_add_new_lv_to_dtree(dm, dtree, seg_lv(seg, s),
laopts, NULL))
return_0;
- if (seg_is_raid(seg) &&
+ if (seg_is_raid(seg) && seg->meta_areas && seg_metalv(seg, s) &&
!_add_new_lv_to_dtree(dm, dtree, seg_metalv(seg, s),
laopts, NULL))
return_0;
diff --git a/lib/format_text/export.c b/lib/format_text/export.c
index c0af3fa..a762c74 100644
--- a/lib/format_text/export.c
+++ b/lib/format_text/export.c
@@ -621,6 +621,7 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
(s == seg->area_count - 1) ? "" : ",");
break;
case AREA_LV:
+ /* FIXME This helper code should be target-independent! Check for metadata LV property. */
if (!(seg->status & RAID)) {
outf(f, "\"%s\", %u%s",
seg_lv(seg, s)->name,
@@ -630,15 +631,19 @@ int out_areas(struct formatter *f, const struct lv_segment *seg,
}
/* RAID devices are laid-out in metadata/data pairs */
+ /* FIXME Validation should be elsewhere, not here! */
if (!lv_is_raid_image(seg_lv(seg, s)) ||
- !lv_is_raid_metadata(seg_metalv(seg, s))) {
+ (seg->meta_areas && seg_metalv(seg, s) && !lv_is_raid_metadata(seg_metalv(seg, s)))) {
log_error("RAID segment has non-RAID areas");
return 0;
}
- outf(f, "\"%s\", \"%s\"%s",
- seg_metalv(seg, s)->name, seg_lv(seg, s)->name,
- (s == seg->area_count - 1) ? "" : ",");
+ if (seg->meta_areas && seg_metalv(seg,s))
+ outf(f, "\"%s\", \"%s\"%s",
+ (seg->meta_areas && seg_metalv(seg, s)) ? seg_metalv(seg, s)->name : "",
+ seg_lv(seg, s)->name, (s == seg->area_count - 1) ? "" : ",");
+ else
+ outf(f, "\"%s\"%s", seg_lv(seg, s)->name, (s == seg->area_count - 1) ? "" : ",");
break;
case AREA_UNASSIGNED:
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 9bfef45..82faf42 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -114,6 +114,7 @@ enum {
LV_TYPE_DATA,
LV_TYPE_SPARE,
LV_TYPE_VIRTUAL,
+ LV_TYPE_RAID0,
LV_TYPE_RAID1,
LV_TYPE_RAID10,
LV_TYPE_RAID4,
@@ -162,6 +163,7 @@ static const char *_lv_type_names[] = {
[LV_TYPE_DATA] = "data",
[LV_TYPE_SPARE] = "spare",
[LV_TYPE_VIRTUAL] = "virtual",
+ [LV_TYPE_RAID0] = SEG_TYPE_NAME_RAID0,
[LV_TYPE_RAID1] = SEG_TYPE_NAME_RAID1,
[LV_TYPE_RAID10] = SEG_TYPE_NAME_RAID10,
[LV_TYPE_RAID4] = SEG_TYPE_NAME_RAID4,
@@ -256,7 +258,10 @@ static int _lv_layout_and_role_raid(struct dm_pool *mem,
segtype = first_seg(lv)->segtype;
- if (segtype_is_raid1(segtype)) {
+ if (segtype_is_raid0(segtype)) {
+ if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID0]))
+ goto_bad;
+ } else if (segtype_is_raid1(segtype)) {
if (!str_list_add_no_dup_check(mem, layout, _lv_type_names[LV_TYPE_RAID1]))
goto_bad;
} else if (segtype_is_raid10(segtype)) {
@@ -860,7 +865,7 @@ dm_percent_t copy_percent(const struct logical_volume *lv)
denominator += seg->area_len;
/* FIXME Generalise name of 'extents_copied' field */
- if ((seg_is_raid(seg) || seg_is_mirrored(seg)) &&
+ if (((seg_is_raid(seg) && !seg_is_any_raid0(seg)) || seg_is_mirrored(seg)) &&
(seg->area_count > 1))
numerator += seg->extents_copied;
else
@@ -3751,7 +3756,7 @@ static int _lv_insert_empty_sublvs(struct logical_volume *lv,
return_0;
/* Metadata LVs for raid */
- if (segtype_is_raid(segtype)) {
+ if (segtype_is_raid(segtype) && !segtype_is_raid0(segtype)) {
if (dm_snprintf(img_name, sizeof(img_name), "%s_rmeta_%u",
lv->name, i) < 0)
goto_bad;
@@ -3787,6 +3792,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
struct lv_segment *seg = first_seg(lv);
uint32_t fa, s;
int clear_metadata = 0;
+ uint32_t area_multiple = 1;
if (!(segtype = get_segtype_from_string(lv->vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
@@ -3797,13 +3803,14 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
* 'stripes' and 'stripe_size' parameters meaningless.
*/
if (seg_is_raid(seg)) {
+ area_multiple = _calc_area_multiple(seg->segtype, seg->area_count, 0);
stripes = 1;
stripe_size = 0;
}
for (fa = first_area, s = 0; s < seg->area_count; s++) {
if (is_temporary_mirror_layer(seg_lv(seg, s))) {
- if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents,
+ if (!_lv_extend_layered_lv(ah, seg_lv(seg, s), extents / area_multiple,
fa, stripes, stripe_size))
return_0;
fa += lv_mirror_count(seg_lv(seg, s));
@@ -3819,7 +3826,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
}
/* Extend metadata LVs only on initial creation */
- if (seg_is_raid(seg) && !lv->le_count) {
+ if (seg_is_raid(seg) && !seg_is_raid0(seg) && !lv->le_count) {
if (!seg->meta_areas) {
log_error("No meta_areas for RAID type");
return 0;
@@ -3854,6 +3861,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
/*
* We must clear the metadata areas upon creation.
*/
+ /* FIXME VG is not in a fully-consistent state here and should not be committed! */
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
return_0;
@@ -3898,7 +3906,7 @@ static int _lv_extend_layered_lv(struct alloc_handle *ah,
}
}
- seg->area_len += extents;
+ seg->area_len += extents / area_multiple;
seg->len += extents;
if (!_setup_lv_size(lv, lv->le_count + extents))
@@ -3953,7 +3961,7 @@ int lv_extend(struct logical_volume *lv,
*/
/* FIXME Support striped metadata pool */
log_count = 1;
- } else if (segtype_is_raid(segtype) && !lv->le_count)
+ } else if (segtype_is_raid(segtype) && !segtype_is_raid0(segtype) && !lv->le_count)
log_count = mirrors * stripes;
/* FIXME log_count should be 1 for mirrors */
@@ -3963,7 +3971,7 @@ int lv_extend(struct logical_volume *lv,
return_0;
new_extents = ah->new_extents;
- if (segtype_is_raid(segtype))
+ if (segtype_is_raid(segtype) && !segtype_is_raid0(segtype))
new_extents -= ah->log_len * ah->area_multiple;
if (segtype_is_pool(segtype)) {
@@ -7078,7 +7086,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!activation()) {
if (seg_is_cache(lp) ||
seg_is_mirror(lp) ||
- seg_is_raid(lp) ||
+ (seg_is_raid(lp) && !seg_is_raid0(lp)) ||
seg_is_thin(lp) ||
lp->snapshot) {
/*
@@ -7256,7 +7264,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
/* FIXME Eventually support raid/mirrors with -m */
if (!(create_segtype = get_segtype_from_string(vg->cmd, SEG_TYPE_NAME_STRIPED)))
return_0;
- } else if (seg_is_mirrored(lp) || seg_is_raid(lp)) {
+ } else if (seg_is_mirrored(lp) || (seg_is_raid(lp) && !seg_is_any_raid0(lp))) {
if (is_change_activating(lp->activate) && (lp->activate != CHANGE_AEY) &&
vg_is_clustered(vg) && seg_is_mirrored(lp) && !seg_is_raid(lp) &&
!cluster_mirror_is_available(vg->cmd)) {
@@ -7389,7 +7397,6 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
if (!archive(vg))
return_NULL;
-
if (pool_lv && segtype_is_thin_volume(create_segtype)) {
/* Ensure all stacked messages are submitted */
if ((pool_is_active(pool_lv) || is_change_activating(lp->activate)) &&
@@ -7444,7 +7451,7 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg,
stack;
goto revert_new_lv;
}
- } else if (lv_is_raid(lv)) {
+ } else if (lv_is_raid(lv) && !seg_is_any_raid0(first_seg(lv))) {
first_seg(lv)->min_recovery_rate = lp->min_recovery_rate;
first_seg(lv)->max_recovery_rate = lp->max_recovery_rate;
} else if (lv_is_thin_pool(lv)) {
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h
index 67fb11c..3fc4266 100644
--- a/lib/metadata/segtype.h
+++ b/lib/metadata/segtype.h
@@ -47,6 +47,7 @@ struct dev_manager;
#define SEG_ONLY_EXCLUSIVE 0x0000000000010000ULL /* In cluster only exlusive activation */
#define SEG_CAN_ERROR_WHEN_FULL 0x0000000000020000ULL
+#define SEG_RAID0 0x0000000000040000ULL
#define SEG_RAID1 0x0000000000100000ULL
#define SEG_RAID10 0x0000000000200000ULL
#define SEG_RAID4 0x0000000000400000ULL
@@ -100,6 +101,8 @@ struct dev_manager;
#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_raid0(segtype) ((segtype)->flags & SEG_RAID0 ? 1 : 0)
+#define segtype_is_any_raid0(segtype) ((segtype)->flags & SEG_RAID0 ? 1 : 0)
#define segtype_is_raid(segtype) ((segtype)->flags & SEG_RAID ? 1 : 0)
#define segtype_is_raid1(segtype) ((segtype)->flags & SEG_RAID1 ? 1 : 0)
#define segtype_is_raid4(segtype) ((segtype)->flags & SEG_RAID4 ? 1 : 0)
@@ -130,6 +133,8 @@ struct dev_manager;
#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_raid0(seg) segtype_is_raid0((seg)->segtype)
+#define seg_is_any_raid0(seg) segtype_is_any_raid0((seg)->segtype)
#define seg_is_raid(seg) segtype_is_raid((seg)->segtype)
#define seg_is_raid1(seg) segtype_is_raid1((seg)->segtype)
#define seg_is_raid4(seg) segtype_is_raid4((seg)->segtype)
diff --git a/lib/raid/raid.c b/lib/raid/raid.c
index 28fd45b..4987f91 100644
--- a/lib/raid/raid.c
+++ b/lib/raid/raid.c
@@ -33,8 +33,10 @@ static void _raid_display(const struct lv_segment *seg)
display_stripe(seg, s, " ");
}
- for (s = 0; s < seg->area_count; ++s)
- log_print(" Raid Metadata LV%2d\t%s", s, seg_metalv(seg, s)->name);
+ if (seg->meta_areas) {
+ for (s = 0; s < seg->area_count; ++s)
+ log_print(" Raid Metadata LV%2d\t%s", s, seg_metalv(seg, s)->name);
+ }
log_print(" ");
}
@@ -42,11 +44,26 @@ static void _raid_display(const struct lv_segment *seg)
static int _raid_text_import_area_count(const struct dm_config_node *sn,
uint32_t *area_count)
{
- if (!dm_config_get_uint32(sn, "device_count", area_count)) {
- log_error("Couldn't read 'device_count' for "
+ uint32_t stripe_count = 0, device_count = 0;
+ int stripe_count_found, device_count_found;
+
+ device_count_found = dm_config_get_uint32(sn, "device_count", &device_count);
+ stripe_count_found = dm_config_get_uint32(sn, "stripe_count", &stripe_count);
+
+ if (!device_count_found && !stripe_count_found) {
+ log_error("Couldn't read 'device_count' or 'stripe_count' for "
+ "segment '%s'.", dm_config_parent_name(sn));
+ return 0;
+ }
+
+ if (device_count_found && stripe_count_found) {
+ log_error("Only one of 'device_count' and 'stripe_count' allowed for "
"segment '%s'.", dm_config_parent_name(sn));
return 0;
}
+
+ *area_count = stripe_count + device_count;
+
return 1;
}
@@ -69,22 +86,25 @@ static int _raid_text_import_areas(struct lv_segment *seg,
return 0;
}
- if (!cv->next) {
- log_error("Missing data device in areas array for segment %s.", seg_name);
- return 0;
+ /* Metadata device comes first. */
+ if (!seg_is_raid0(seg)) {
+ if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
+ log_error("Couldn't find volume '%s' for segment '%s'.",
+ cv->v.str ? : "NULL", seg_name);
+ return 0;
+ }
+
+ if (!set_lv_segment_area_lv(seg, s, lv, 0, RAID_META))
+ return_0;
+ cv = cv->next;
}
- /* Metadata device comes first */
- if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
- log_error("Couldn't find volume '%s' for segment '%s'.",
- cv->v.str ? : "NULL", seg_name);
+ if (!cv) {
+ log_error("Missing data device in areas array for segment %s.", seg_name);
return 0;
}
- if (!set_lv_segment_area_lv(seg, s, lv, 0, RAID_META))
- return_0;
/* Data device comes second */
- cv = cv->next;
if (!(lv = find_lv(seg->lv->vg, cv->v.str))) {
log_error("Couldn't find volume '%s' for segment '%s'.",
cv->v.str ? : "NULL", seg_name);
@@ -133,7 +153,7 @@ static int _raid_text_import(struct lv_segment *seg,
}
}
- if (!dm_config_get_list(sn, "raids", &cv)) {
+ if (!dm_config_get_list(sn, seg_is_any_raid0(seg) ? "raid0_lvs" : "raids", &cv)) {
log_error("Couldn't find RAID array for "
"segment %s of logical volume %s.",
dm_config_parent_name(sn), seg->lv->name);
@@ -145,18 +165,31 @@ static int _raid_text_import(struct lv_segment *seg,
return 0;
}
+ if (seg_is_any_raid0(seg))
+ seg->area_len /= seg->area_count;
seg->status |= RAID;
return 1;
}
-static int _raid_text_export(const struct lv_segment *seg, struct formatter *f)
+static int _raid_text_export_raid0(const struct lv_segment *seg, struct formatter *f)
+{
+ outf(f, "stripe_count = %u", seg->area_count);
+
+ if (seg->stripe_size)
+ outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
+
+ return out_areas(f, seg, "raid0_lv");
+}
+
+static int _raid_text_export_raid(const struct lv_segment *seg, struct formatter *f)
{
outf(f, "device_count = %u", seg->area_count);
- if (seg->region_size)
- outf(f, "region_size = %" PRIu32, seg->region_size);
+
if (seg->stripe_size)
outf(f, "stripe_size = %" PRIu32, seg->stripe_size);
+ if (seg->region_size)
+ outf(f, "region_size = %" PRIu32, seg->region_size);
if (seg->writebehind)
outf(f, "writebehind = %" PRIu32, seg->writebehind);
if (seg->min_recovery_rate)
@@ -167,6 +200,14 @@ static int _raid_text_export(const struct lv_segment *seg, struct formatter *f)
return out_areas(f, seg, "raid");
}
+static int _raid_text_export(const struct lv_segment *seg, struct formatter *f)
+{
+ if (seg_is_any_raid0(seg))
+ return _raid_text_export_raid0(seg, f);
+
+ return _raid_text_export_raid(seg, f);
+}
+
static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
struct dm_pool *mem __attribute__((unused)),
struct cmd_context *cmd __attribute__((unused)),
@@ -181,6 +222,7 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
uint64_t rebuilds = 0;
uint64_t writemostly = 0;
struct dm_tree_node_raid_params params;
+ int raid0 = seg_is_any_raid0(seg);
memset(¶ms, 0, sizeof(params));
@@ -200,24 +242,32 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
return 0;
}
- if (!seg->region_size) {
- log_error("Missing region size for mirror segment.");
- return 0;
- }
+ if (!raid0) {
+ if (!seg->region_size) {
+ log_error("Missing region size for mirror segment.");
+ return 0;
+ }
- for (s = 0; s < seg->area_count; s++)
- if (seg_lv(seg, s)->status & LV_REBUILD)
- rebuilds |= 1ULL << s;
+ for (s = 0; s < seg->area_count; s++)
+ if (seg_lv(seg, s)->status & LV_REBUILD)
+ rebuilds |= 1ULL << s;
- for (s = 0; s < seg->area_count; s++)
- if (seg_lv(seg, s)->status & LV_WRITEMOSTLY)
- writemostly |= 1ULL << s;
+ for (s = 0; s < seg->area_count; s++)
+ if (seg_lv(seg, s)->status & LV_WRITEMOSTLY)
+ writemostly |= 1ULL << s;
- if (mirror_in_sync())
- flags = DM_NOSYNC;
+ if (mirror_in_sync())
+ flags = DM_NOSYNC;
+ }
params.raid_type = lvseg_name(seg);
- if (seg->segtype->parity_devs) {
+ params.stripe_size = seg->stripe_size;
+ params.flags = flags;
+
+ if (raid0) {
+ params.mirrors = 1;
+ params.stripes = seg->area_count;
+ } else if (seg->segtype->parity_devs) {
/* RAID 4/5/6 */
params.mirrors = 1;
params.stripes = seg->area_count - seg->segtype->parity_devs;
@@ -231,13 +281,14 @@ static int _raid_add_target_line(struct dev_manager *dm __attribute__((unused)),
params.stripes = 1;
params.writebehind = seg->writebehind;
}
- params.region_size = seg->region_size;
- params.stripe_size = seg->stripe_size;
- params.rebuilds = rebuilds;
- params.writemostly = writemostly;
- params.min_recovery_rate = seg->min_recovery_rate;
- params.max_recovery_rate = seg->max_recovery_rate;
- params.flags = flags;
+
+ if (!raid0) {
+ params.region_size = seg->region_size;
+ params.rebuilds = rebuilds;
+ params.writemostly = writemostly;
+ params.min_recovery_rate = seg->min_recovery_rate;
+ params.max_recovery_rate = seg->max_recovery_rate;
+ }
if (!dm_tree_node_add_raid_target_with_params(node, len, ¶ms))
return_0;
@@ -418,6 +469,7 @@ static const struct raid_type {
unsigned parity;
uint64_t extra_flags;
} _raid_types[] = {
+ { SEG_TYPE_NAME_RAID0, 0, SEG_RAID0 | SEG_AREAS_STRIPED },
{ SEG_TYPE_NAME_RAID1, 0, SEG_RAID1 | SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID10, 0, SEG_RAID10 | SEG_AREAS_MIRRORED },
{ SEG_TYPE_NAME_RAID4, 1, SEG_RAID4 },
diff --git a/lib/report/report.c b/lib/report/report.c
index 92eb64c..8fa9daf 100644
--- a/lib/report/report.c
+++ b/lib/report/report.c
@@ -2845,7 +2845,7 @@ static int _copypercent_disp(struct dm_report *rh,
struct lv_status_cache *status;
dm_percent_t percent = DM_PERCENT_INVALID;
- if (((lv_is_raid(lv) && lv_raid_percent(lv, &percent)) ||
+ if (((lv_is_raid(lv) && !seg_is_any_raid0(first_seg(lv)) && lv_raid_percent(lv, &percent)) ||
(lv_is_mirror(lv) && lv_mirror_percent(lv->vg->cmd, lv, 0, &percent, NULL))) &&
(percent != DM_PERCENT_INVALID)) {
percent = copy_percent(lv);
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index 6f18ae2..dd5ee9e 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -42,6 +42,7 @@ enum {
SEG_ZERO,
SEG_THIN_POOL,
SEG_THIN,
+ SEG_RAID0,
SEG_RAID1,
SEG_RAID10,
SEG_RAID4,
@@ -74,6 +75,7 @@ static const struct {
{ SEG_ZERO, "zero"},
{ SEG_THIN_POOL, "thin-pool"},
{ SEG_THIN, "thin"},
+ { SEG_RAID0, "raid0"},
{ SEG_RAID1, "raid1"},
{ SEG_RAID10, "raid10"},
{ SEG_RAID4, "raid4"},
@@ -2131,6 +2133,7 @@ static int _emit_areas_line(struct dm_task *dmt __attribute__((unused)),
EMIT_PARAMS(*pos, "%s", synctype);
}
break;
+ case SEG_RAID0:
case SEG_RAID1:
case SEG_RAID10:
case SEG_RAID4:
@@ -2572,6 +2575,7 @@ static int _emit_segment_line(struct dm_task *dmt, uint32_t major,
seg->iv_offset != DM_CRYPT_IV_DEFAULT ?
seg->iv_offset : *seg_start);
break;
+ case SEG_RAID0:
case SEG_RAID1:
case SEG_RAID10:
case SEG_RAID4:
@@ -3848,6 +3852,7 @@ int dm_tree_node_add_null_area(struct dm_tree_node *node, uint64_t offset)
seg = dm_list_item(dm_list_last(&node->props.segs), struct load_segment);
switch (seg->type) {
+ case SEG_RAID0:
case SEG_RAID1:
case SEG_RAID4:
case SEG_RAID5_LA:
diff --git a/man/lvcreate.8.in b/man/lvcreate.8.in
index e008b58..8614cb1 100644
--- a/man/lvcreate.8.in
+++ b/man/lvcreate.8.in
@@ -606,7 +606,14 @@ would use 3 devices for striped logical volumes,
RAID 4/5/6 will stripe across all PVs in the volume group or
all of the PVs specified if the \fB\-i\fP
argument is omitted.
-.
+Two implementations of basic striping are available in the kernel.
+The original device-mapper implementation is the default and should
+normally be used. The alternative implementation using MD, available
+since version 1.7 of the RAID device-mapper kernel target (kernel
+version 4.2) is provided to facilitate the development of new RAID
+features. It may be accessed with \fB--type raid0\fP, but is best
+avoided at present because of assorted restrictions on resizing and converting
+such devices.
.HP
.BR \-I | \-\-stripesize
.IR StripeSize
@@ -649,6 +656,7 @@ Supported types are:
.BR error ,
.BR linear ,
.BR mirror,
+.BR raid0 ,
.BR raid1 ,
.BR raid4 ,
.BR raid5_la ,
@@ -683,7 +691,7 @@ is selected from combination of options:
(snapshot or thin),
.BR \-i | \-\-stripes
(striped).
-Default segment type is \fBlinear\fP.
+The default segment type is \fBlinear\fP.
.
.HP
.BR \-V | \-\-virtualsize
diff --git a/tools/lvcreate.c b/tools/lvcreate.c
index 9714789..8ddecae 100644
--- a/tools/lvcreate.c
+++ b/tools/lvcreate.c
@@ -987,6 +987,12 @@ static int _lvcreate_params(struct cmd_context *cmd,
return 0;
}
+ if (segtype_is_any_raid0(lp->segtype) &&
+ !(lp->target_attr & RAID_FEATURE_RAID0)) {
+ log_error("RAID module does not support RAID0.");
+ return 0;
+ }
+
if (segtype_is_raid10(lp->segtype) && !(lp->target_attr & RAID_FEATURE_RAID10)) {
log_error("RAID module does not support RAID10.");
return 0;
@@ -1209,18 +1215,23 @@ static int _check_raid_parameters(struct volume_group *vg,
unsigned devs = lcp->pv_count ? : dm_list_size(&vg->pvs);
struct cmd_context *cmd = vg->cmd;
- /*
- * If number of devices was not supplied, we can infer from
- * the PVs given.
- */
- if (!seg_is_mirrored(lp)) {
+ if (!seg_is_mirrored(lp) && !lp->stripe_size)
+ lp->stripe_size = find_config_tree_int(cmd, metadata_stripesize_CFG, NULL) * 2;
+
+ if (seg_is_any_raid0(lp)) {
+ if (lp->stripes < 2) {
+ log_error("Segment type 'raid0' requires 2 or more stripes.");
+ return 0;
+ }
+ } else if (!seg_is_mirrored(lp)) {
+ /*
+ * If number of devices was not supplied, we can infer from
+ * the PVs given.
+ */
if (!arg_count(cmd, stripes_ARG) &&
(devs > 2 * lp->segtype->parity_devs))
lp->stripes = devs - lp->segtype->parity_devs;
- if (!lp->stripe_size)
- lp->stripe_size = find_config_tree_int(cmd, metadata_stripesize_CFG, NULL) * 2;
-
if (lp->stripes <= lp->segtype->parity_devs) {
log_error("Number of stripes must be at least %d for %s",
lp->segtype->parity_devs + 1,
7 years, 11 months