basebuilder_pel7ppc64bebuilder0
7 years ago
30 changed files with 8997 additions and 0 deletions
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
WHATS_NEW | 1 + |
||||
tools/lvcreate.c | 5 ++++- |
||||
2 files changed, 5 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 5260321..1147dad 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.131 - |
||||
===================================== |
||||
+ Disallow usage of --stripe and --stripesize when creating cache pool. |
||||
Swapping of LV identifiers handles more complex LVs. |
||||
Fix VG metadata comparison failure while scanning the VG for lvmetad. |
||||
Ignore persistent cache if configuration changed. (2.02.127) |
||||
diff --git a/tools/lvcreate.c b/tools/lvcreate.c |
||||
index 364a16a..7bba761 100644 |
||||
--- a/tools/lvcreate.c |
||||
+++ b/tools/lvcreate.c |
||||
@@ -770,7 +770,8 @@ static int _lvcreate_params(struct cmd_context *cmd, |
||||
CACHE_POOL_ARGS, |
||||
LVCREATE_ARGS, |
||||
POOL_ARGS, |
||||
- SIZE_ARGS, |
||||
+ extents_ARG, |
||||
+ size_ARG, |
||||
cache_ARG, |
||||
chunksize_ARG, |
||||
-1)) |
||||
@@ -1096,6 +1097,8 @@ static int _determine_cache_argument(struct volume_group *vg, |
||||
} |
||||
/* FIXME How to handle skip flag? */ |
||||
if (arg_from_list_is_set(cmd, "is unsupported with cache conversion", |
||||
+ stripes_ARG, |
||||
+ stripesize_ARG, |
||||
setactivationskip_ARG, |
||||
ignoreactivationskip_ARG, |
||||
-1)) |
@ -0,0 +1,521 @@
@@ -0,0 +1,521 @@
|
||||
libdm/libdm-stats.c | 223 ++++++++++++++++++++++++++++++---------------------- |
||||
tools/dmsetup.c | 1 + |
||||
2 files changed, 131 insertions(+), 93 deletions(-) |
||||
|
||||
diff --git a/libdm/libdm-stats.c b/libdm/libdm-stats.c |
||||
index 93c7760..ee62fe6 100644 |
||||
--- a/libdm/libdm-stats.c |
||||
+++ b/libdm/libdm-stats.c |
||||
@@ -144,17 +144,24 @@ struct dm_stats *dm_stats_create(const char *program_id) |
||||
return_NULL; |
||||
|
||||
/* FIXME: better hint. */ |
||||
- if (!(dms->mem = dm_pool_create("stats_pool", 4096))) |
||||
- goto_bad; |
||||
+ if (!(dms->mem = dm_pool_create("stats_pool", 4096))) { |
||||
+ dm_free(dms); |
||||
+ return_NULL; |
||||
+ } |
||||
|
||||
if (!(dms->hist_mem = dm_pool_create("histogram_pool", hist_hint))) |
||||
- return_0; |
||||
+ goto_bad; |
||||
|
||||
if (!program_id || !strlen(program_id)) |
||||
dms->program_id = _program_id_from_proc(); |
||||
else |
||||
dms->program_id = dm_strdup(program_id); |
||||
|
||||
+ if (!dms->program_id) { |
||||
+ dm_pool_destroy(dms->hist_mem); |
||||
+ goto_bad; |
||||
+ } |
||||
+ |
||||
dms->major = -1; |
||||
dms->minor = -1; |
||||
dms->name = NULL; |
||||
@@ -171,6 +178,7 @@ struct dm_stats *dm_stats_create(const char *program_id) |
||||
return dms; |
||||
|
||||
bad: |
||||
+ dm_pool_destroy(dms->mem); |
||||
dm_free(dms); |
||||
return NULL; |
||||
} |
||||
@@ -186,15 +194,15 @@ static int _stats_region_present(const struct dm_stats_region *region) |
||||
static void _stats_histograms_destroy(struct dm_pool *mem, |
||||
struct dm_stats_region *region) |
||||
{ |
||||
- uint64_t n; |
||||
- |
||||
/* Unpopulated handle. */ |
||||
if (!region->counters) |
||||
return; |
||||
|
||||
- for (n = _nr_areas_region(region) - 1; n; n--) |
||||
- if (region->counters[n].histogram) |
||||
- dm_pool_free(mem, region->counters[n].histogram); |
||||
+ /* |
||||
+ * Only the first histogram needs to be freed explicitly. |
||||
+ */ |
||||
+ if (region->counters[0].histogram) |
||||
+ dm_pool_free(mem, region->counters[0].histogram); |
||||
} |
||||
|
||||
static void _stats_region_destroy(struct dm_stats_region *region) |
||||
@@ -316,11 +324,54 @@ int dm_stats_driver_supports_histogram(void) |
||||
return _stats_check_precise_timestamps(NULL); |
||||
} |
||||
|
||||
+static int _fill_hist_arg(char *hist_arg, size_t hist_len, uint64_t scale, |
||||
+ struct dm_histogram *bounds) |
||||
+{ |
||||
+ int i, l, len = 0, nr_bins; |
||||
+ char *arg = hist_arg; |
||||
+ uint64_t value; |
||||
+ |
||||
+ nr_bins = bounds->nr_bins; |
||||
+ |
||||
+ for (i = 0; i < nr_bins; i++) { |
||||
+ value = bounds->bins[i].upper / scale; |
||||
+ if ((l = dm_snprintf(arg, hist_len - len, FMTu64"%s", value, |
||||
+ (i == (nr_bins - 1)) ? "" : ",")) < 0) |
||||
+ return_0; |
||||
+ len += l; |
||||
+ arg += l; |
||||
+ } |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
+static void *_get_hist_arg(struct dm_histogram *bounds, uint64_t scale, |
||||
+ size_t *len) |
||||
+{ |
||||
+ struct dm_histogram_bin *entry, *bins; |
||||
+ size_t hist_len = 1; /* terminating '\0' */ |
||||
+ double value; |
||||
+ |
||||
+ entry = bins = bounds->bins; |
||||
+ |
||||
+ entry += bounds->nr_bins - 1; |
||||
+ while(entry >= bins) { |
||||
+ value = (double) (entry--)->upper; |
||||
+ /* Use lround to avoid size_t -> double cast warning. */ |
||||
+ hist_len += 1 + (size_t) lround(log10(value / scale)); |
||||
+ if (entry != bins) |
||||
+ hist_len++; /* ',' */ |
||||
+ } |
||||
+ |
||||
+ *len = hist_len; |
||||
+ |
||||
+ return dm_zalloc(hist_len); |
||||
+} |
||||
+ |
||||
static char *_build_histogram_arg(struct dm_histogram *bounds, int *precise) |
||||
{ |
||||
struct dm_histogram_bin *entry, *bins; |
||||
- size_t hist_len = 1, len = 0; |
||||
- char *hist_arg, *arg = NULL; |
||||
+ size_t hist_len; |
||||
+ char *hist_arg; |
||||
uint64_t scale; |
||||
|
||||
entry = bins = bounds->bins; |
||||
@@ -331,53 +382,37 @@ static char *_build_histogram_arg(struct dm_histogram *bounds, int *precise) |
||||
return NULL; |
||||
} |
||||
|
||||
+ /* Validate entries and set *precise if precision < 1ms. */ |
||||
entry += bounds->nr_bins - 1; |
||||
- while(entry >= bins) { |
||||
- double value; |
||||
+ while (entry >= bins) { |
||||
if (entry != bins) { |
||||
if (entry->upper < (entry - 1)->upper) { |
||||
log_error("Histogram boundaries must be in " |
||||
"order of increasing magnitude."); |
||||
return 0; |
||||
} |
||||
- hist_len++; /* ',' */ |
||||
} |
||||
|
||||
/* |
||||
* Only enable precise_timestamps automatically if any |
||||
* value in the histogram bounds uses precision < 1ms. |
||||
*/ |
||||
- if (!*precise && (entry->upper % NSEC_PER_MSEC)) |
||||
+ if (((entry--)->upper % NSEC_PER_MSEC) && !*precise) |
||||
*precise = 1; |
||||
- |
||||
- value = (double) (entry--)->upper; |
||||
- /* Use lround to avoid size_t -> double cast warning. */ |
||||
- hist_len += 1 + (size_t) lround(log10(value)); |
||||
} |
||||
|
||||
- if (!(hist_arg = dm_zalloc(hist_len))) { |
||||
+ scale = (*precise) ? 1 : NSEC_PER_MSEC; |
||||
+ |
||||
+ /* Calculate hist_len and allocate a character buffer. */ |
||||
+ if (!(hist_arg = _get_hist_arg(bounds, scale, &hist_len))) { |
||||
log_error("Could not allocate memory for histogram argument."); |
||||
return 0; |
||||
} |
||||
|
||||
- arg = hist_arg; |
||||
- |
||||
- if (*precise) |
||||
- scale = 1; |
||||
- else |
||||
- scale = (*precise) ? 1 : NSEC_PER_MSEC; |
||||
+ /* Fill hist_arg with boundary strings. */ |
||||
+ if (!_fill_hist_arg(hist_arg, hist_len, scale, bounds)) |
||||
+ goto_bad; |
||||
|
||||
- for (entry = bins; entry < (bins + bounds->nr_bins); entry++) { |
||||
- uint64_t value; |
||||
- ssize_t l = 0; |
||||
- int last = !(entry < (bins + bounds->nr_bins - 1)); |
||||
- value = entry->upper / scale; |
||||
- if ((l = dm_snprintf(arg, hist_len - len, FMTu64"%s", value, |
||||
- (last) ? "" : ",")) < 0) |
||||
- goto_bad; |
||||
- len += (size_t) l; |
||||
- arg += (size_t) l; |
||||
- } |
||||
return hist_arg; |
||||
|
||||
bad: |
||||
@@ -419,13 +454,13 @@ static int _stats_parse_histogram_spec(struct dm_stats *dms, |
||||
const char *histogram) |
||||
{ |
||||
static const char *_valid_chars = "0123456789,"; |
||||
- uint64_t scale = region->timescale; |
||||
+ uint64_t scale = region->timescale, this_val = 0; |
||||
struct dm_pool *mem = dms->hist_mem; |
||||
struct dm_histogram_bin cur; |
||||
struct dm_histogram hist; |
||||
int nr_bins = 1; |
||||
- const char *c, *v; |
||||
- char *p; |
||||
+ const char *c, *v, *val_start; |
||||
+ char *p, *endptr = NULL; |
||||
|
||||
/* Advance past "histogram:". */ |
||||
histogram = strchr(histogram, ':'); |
||||
@@ -466,9 +501,8 @@ static int _stats_parse_histogram_spec(struct dm_stats *dms, |
||||
histogram); |
||||
goto bad; |
||||
} else { |
||||
- const char *val_start = c; |
||||
- char *endptr = NULL; |
||||
- uint64_t this_val = 0; |
||||
+ val_start = c; |
||||
+ endptr = NULL; |
||||
|
||||
this_val = strtoull(val_start, &endptr, 10); |
||||
if (!endptr) { |
||||
@@ -592,11 +626,11 @@ static int _stats_parse_list_region(struct dm_stats *dms, |
||||
|
||||
static int _stats_parse_list(struct dm_stats *dms, const char *resp) |
||||
{ |
||||
- struct dm_pool *mem = dms->mem; |
||||
- struct dm_stats_region cur; |
||||
uint64_t max_region = 0, nr_regions = 0; |
||||
+ struct dm_stats_region cur, fill; |
||||
+ struct dm_pool *mem = dms->mem; |
||||
FILE *list_rows; |
||||
- /* FIXME: determine correct maximum line length based on kernel format */ |
||||
+ /* FIXME: use correct maximum line length for kernel format */ |
||||
char line[256]; |
||||
|
||||
if (!resp) { |
||||
@@ -631,7 +665,6 @@ static int _stats_parse_list(struct dm_stats *dms, const char *resp) |
||||
|
||||
/* handle holes in the list of region_ids */ |
||||
if (cur.region_id > max_region) { |
||||
- struct dm_stats_region fill; |
||||
memset(&fill, 0, sizeof(fill)); |
||||
fill.region_id = DM_STATS_REGION_NOT_PRESENT; |
||||
do { |
||||
@@ -707,54 +740,51 @@ static int _stats_parse_histogram(struct dm_pool *mem, char *hist_str, |
||||
struct dm_histogram **histogram, |
||||
struct dm_stats_region *region) |
||||
{ |
||||
+ struct dm_histogram hist, *bounds = region->bounds; |
||||
static const char *_valid_chars = "0123456789:"; |
||||
int nr_bins = region->bounds->nr_bins; |
||||
- struct dm_histogram hist, *bounds = region->bounds; |
||||
+ const char *c, *v, *val_start; |
||||
struct dm_histogram_bin cur; |
||||
- uint64_t sum = 0; |
||||
- const char *c, *v; |
||||
+ uint64_t sum = 0, this_val; |
||||
+ char *endptr = NULL; |
||||
int bin = 0; |
||||
|
||||
c = hist_str; |
||||
|
||||
- dm_pool_begin_object(mem, sizeof(cur)); |
||||
+ if (!dm_pool_begin_object(mem, sizeof(cur))) |
||||
+ return_0; |
||||
|
||||
hist.nr_bins = nr_bins; |
||||
|
||||
- dm_pool_grow_object(mem, &hist, sizeof(hist)); |
||||
+ if (!dm_pool_grow_object(mem, &hist, sizeof(hist))) |
||||
+ goto_bad; |
||||
|
||||
do { |
||||
memset(&cur, 0, sizeof(cur)); |
||||
for (v = _valid_chars; *v; v++) |
||||
if (*c == *v) |
||||
break; |
||||
- if (!*v) { |
||||
- stack; |
||||
+ if (!*v) |
||||
goto badchar; |
||||
- } |
||||
|
||||
- if (*c == ',') { |
||||
- log_error("Invalid histogram: %s", hist_str); |
||||
- return 0; |
||||
- } else { |
||||
- const char *val_start = c; |
||||
- char *endptr = NULL; |
||||
- uint64_t this_val = 0; |
||||
+ if (*c == ',') |
||||
+ goto badchar; |
||||
+ else { |
||||
+ val_start = c; |
||||
+ endptr = NULL; |
||||
|
||||
this_val = strtoull(val_start, &endptr, 10); |
||||
if (!endptr) { |
||||
log_error("Could not parse histogram value."); |
||||
- return 0; |
||||
+ goto bad; |
||||
} |
||||
c = endptr; /* Advance to colon, or end. */ |
||||
|
||||
if (*c == ':') |
||||
c++; |
||||
- else if (*c & (*c != '\n')) { |
||||
+ else if (*c & (*c != '\n')) |
||||
/* Expected ':', '\n', or NULL. */ |
||||
- stack; |
||||
goto badchar; |
||||
- } |
||||
|
||||
if (*c == ':') |
||||
c++; |
||||
@@ -763,7 +793,8 @@ static int _stats_parse_histogram(struct dm_pool *mem, char *hist_str, |
||||
cur.count = this_val; |
||||
sum += this_val; |
||||
|
||||
- dm_pool_grow_object(mem, &cur, sizeof(cur)); |
||||
+ if (!dm_pool_grow_object(mem, &cur, sizeof(cur))) |
||||
+ goto_bad; |
||||
|
||||
bin++; |
||||
} |
||||
@@ -778,6 +809,8 @@ static int _stats_parse_histogram(struct dm_pool *mem, char *hist_str, |
||||
|
||||
badchar: |
||||
log_error("Invalid character in histogram data: '%c' (0x%x)", *c, *c); |
||||
+bad: |
||||
+ dm_pool_abandon_object(mem); |
||||
return 0; |
||||
} |
||||
|
||||
@@ -786,8 +819,8 @@ static int _stats_parse_region(struct dm_stats *dms, const char *resp, |
||||
uint64_t timescale) |
||||
{ |
||||
struct dm_histogram *hist = NULL; |
||||
- struct dm_stats_counters cur; |
||||
struct dm_pool *mem = dms->mem; |
||||
+ struct dm_stats_counters cur; |
||||
FILE *stats_rows = NULL; |
||||
uint64_t start, len; |
||||
char row[256]; |
||||
@@ -1040,12 +1073,12 @@ static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id, |
||||
int precise, const char *hist_arg, |
||||
const char *program_id, const char *aux_data) |
||||
{ |
||||
- struct dm_task *dmt = NULL; |
||||
- char msg[1024], range[64]; |
||||
const char *err_fmt = "Could not prepare @stats_create %s."; |
||||
const char *precise_str = PRECISE_ARG; |
||||
const char *resp, *opt_args = NULL; |
||||
- int r = 0, nr_opt = 0; /* number of optional args. */ |
||||
+ char msg[1024], range[64], *endptr = NULL; |
||||
+ struct dm_task *dmt = NULL; |
||||
+ int r = 0, nr_opt = 0; |
||||
|
||||
if (!_stats_bound(dms)) |
||||
return_0; |
||||
@@ -1105,7 +1138,6 @@ static int _stats_create_region(struct dm_stats *dms, uint64_t *region_id, |
||||
} |
||||
|
||||
if (region_id) { |
||||
- char *endptr = NULL; |
||||
*region_id = strtoull(resp, &endptr, 10); |
||||
if (resp == endptr) |
||||
goto_out; |
||||
@@ -1195,11 +1227,11 @@ static struct dm_task *_stats_print_region(struct dm_stats *dms, |
||||
uint64_t region_id, unsigned start_line, |
||||
unsigned num_lines, unsigned clear) |
||||
{ |
||||
- struct dm_task *dmt = NULL; |
||||
/* @stats_print[_clear] <region_id> [<start_line> <num_lines>] */ |
||||
const char *clear_str = "_clear", *lines_fmt = "%u %u"; |
||||
const char *msg_fmt = "@stats_print%s " FMTu64 " %s"; |
||||
const char *err_fmt = "Could not prepare @stats_print %s."; |
||||
+ struct dm_task *dmt = NULL; |
||||
char msg[1024], lines[64]; |
||||
|
||||
if (start_line || num_lines) |
||||
@@ -1292,6 +1324,8 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id, |
||||
uint64_t region_id) |
||||
{ |
||||
int all_regions = (region_id == DM_STATS_REGIONS_ALL); |
||||
+ struct dm_task *dmt = NULL; /* @stats_print task */ |
||||
+ const char *resp; |
||||
|
||||
if (!_stats_bound(dms)) |
||||
return_0; |
||||
@@ -1311,9 +1345,6 @@ int dm_stats_populate(struct dm_stats *dms, const char *program_id, |
||||
|
||||
dm_stats_walk_start(dms); |
||||
do { |
||||
- struct dm_task *dmt = NULL; /* @stats_print task */ |
||||
- const char *resp; |
||||
- |
||||
region_id = (all_regions) |
||||
? dm_stats_get_current_region(dms) : region_id; |
||||
|
||||
@@ -1967,10 +1998,12 @@ static struct dm_histogram *_alloc_dm_histogram(int nr_bins) |
||||
struct dm_histogram *dm_histogram_bounds_from_string(const char *bounds_str) |
||||
{ |
||||
static const char *_valid_chars = "0123456789,muns"; |
||||
- struct dm_histogram *dmh; |
||||
+ uint64_t this_val = 0, mult = 1; |
||||
+ const char *c, *v, *val_start; |
||||
struct dm_histogram_bin *cur; |
||||
- const char *c, *v; |
||||
+ struct dm_histogram *dmh; |
||||
int nr_entries = 1; |
||||
+ char *endptr; |
||||
|
||||
c = bounds_str; |
||||
|
||||
@@ -2003,9 +2036,8 @@ struct dm_histogram *dm_histogram_bounds_from_string(const char *bounds_str) |
||||
bounds_str); |
||||
goto bad; |
||||
} else { |
||||
- const char *val_start = c; |
||||
- char *endptr = NULL; |
||||
- uint64_t this_val = 0, mult = 1; |
||||
+ val_start = c; |
||||
+ endptr = NULL; |
||||
|
||||
this_val = strtoull(val_start, &endptr, 10); |
||||
if (!endptr) { |
||||
@@ -2058,10 +2090,10 @@ bad: |
||||
|
||||
struct dm_histogram *dm_histogram_bounds_from_uint64(const uint64_t *bounds) |
||||
{ |
||||
- struct dm_histogram *dmh; |
||||
+ const uint64_t *entry = bounds; |
||||
struct dm_histogram_bin *cur; |
||||
+ struct dm_histogram *dmh; |
||||
int nr_entries = 1; |
||||
- const uint64_t *entry = bounds; |
||||
|
||||
if (!bounds || !bounds[0]) { |
||||
log_error("Could not parse empty histogram bounds array"); |
||||
@@ -2113,6 +2145,7 @@ void dm_histogram_bounds_destroy(struct dm_histogram *bounds) |
||||
*/ |
||||
static void _scale_bound_value_to_suffix(uint64_t *bound, const char **suffix) |
||||
{ |
||||
+ *suffix = "ns"; |
||||
if (!(*bound % NSEC_PER_SEC)) { |
||||
*bound /= NSEC_PER_SEC; |
||||
*suffix = "s"; |
||||
@@ -2191,12 +2224,14 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin, |
||||
int width, int flags) |
||||
{ |
||||
int minwidth, bounds, values, start, last; |
||||
- uint64_t lower, upper; /* bounds of the current bin. */ |
||||
+ uint64_t lower, upper, val_u64; /* bounds of the current bin. */ |
||||
/* Use the histogram pool for string building. */ |
||||
struct dm_pool *mem = dmh->dms->hist_mem; |
||||
char buf[64], bounds_buf[64]; |
||||
const char *sep = ""; |
||||
+ int bounds_width; |
||||
ssize_t len = 0; |
||||
+ float val_flt; |
||||
|
||||
bounds = flags & DM_HISTOGRAM_BOUNDS_MASK; |
||||
values = flags & DM_HISTOGRAM_VALUES; |
||||
@@ -2222,12 +2257,11 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin, |
||||
/* Set bounds string to the empty string. */ |
||||
bounds_buf[0] = '\0'; |
||||
|
||||
- dm_pool_begin_object(mem, 64); |
||||
+ if (!dm_pool_begin_object(mem, 64)) |
||||
+ return_0; |
||||
|
||||
for (bin = start; bin <= last; bin++) { |
||||
if (bounds) { |
||||
- int bounds_width; |
||||
- |
||||
/* Default bounds width depends on time suffixes. */ |
||||
bounds_width = (!(flags & DM_HISTOGRAM_SUFFIX)) |
||||
? BOUND_WIDTH_NOSUFFIX |
||||
@@ -2260,15 +2294,14 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin, |
||||
|
||||
if (flags & DM_HISTOGRAM_PERCENT) { |
||||
dm_percent_t pr; |
||||
- float value; |
||||
pr = dm_histogram_get_bin_percent(dmh, bin); |
||||
- value = dm_percent_to_float(pr); |
||||
+ val_flt = dm_percent_to_float(pr); |
||||
len = dm_snprintf(buf, sizeof(buf), "%s%*.2f%%%s", |
||||
- bounds_buf, width, value, sep); |
||||
+ bounds_buf, width, val_flt, sep); |
||||
} else if (values) { |
||||
- uint64_t value = dmh->bins[bin].count; |
||||
+ val_u64 = dmh->bins[bin].count; |
||||
len = dm_snprintf(buf, sizeof(buf), "%s%*"PRIu64"%s", |
||||
- bounds_buf, width, value, sep); |
||||
+ bounds_buf, width, val_u64, sep); |
||||
} else if (bounds) |
||||
len = dm_snprintf(buf, sizeof(buf), "%s%s", bounds_buf, |
||||
sep); |
||||
@@ -2277,9 +2310,13 @@ const char *dm_histogram_to_string(const struct dm_histogram *dmh, int bin, |
||||
goto_bad; |
||||
|
||||
width = minwidth; /* re-set histogram column width. */ |
||||
- dm_pool_grow_object(mem, buf, (size_t) len); |
||||
+ if (!dm_pool_grow_object(mem, buf, (size_t) len)) |
||||
+ goto_bad; |
||||
} |
||||
- dm_pool_grow_object(mem, "\0", 1); |
||||
+ |
||||
+ if (!dm_pool_grow_object(mem, "\0", 1)) |
||||
+ goto_bad; |
||||
+ |
||||
return (const char *) dm_pool_end_object(mem); |
||||
|
||||
bad: |
||||
diff --git a/tools/dmsetup.c b/tools/dmsetup.c |
||||
index 61ad5a9..8b7ad74 100644 |
||||
--- a/tools/dmsetup.c |
||||
+++ b/tools/dmsetup.c |
||||
@@ -4674,6 +4674,7 @@ static int _do_stats_create_regions(struct dm_stats *dms, |
||||
return_0; |
||||
|
||||
if (!(dmt = dm_task_create(DM_DEVICE_TABLE))) { |
||||
+ dm_histogram_bounds_destroy(bounds); |
||||
dm_stats_destroy(dms); |
||||
return_0; |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
WHATS_NEW_DM | 4 ++++ |
||||
libdm/libdm-deptree.c | 2 +- |
||||
2 files changed, 5 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM |
||||
index b509d68..9e30786 100644 |
||||
--- a/WHATS_NEW_DM |
||||
+++ b/WHATS_NEW_DM |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 1.02.108 - |
||||
+===================================== |
||||
+ Do not check for full thin pool when activating without messages (1.02.107). |
||||
+ |
||||
Version 1.02.107 - 5th September 2015 |
||||
===================================== |
||||
Parse thin-pool status with one single routine internally. |
||||
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c |
||||
index d40362d..7b7ca5b 100644 |
||||
--- a/libdm/libdm-deptree.c |
||||
+++ b/libdm/libdm-deptree.c |
||||
@@ -1633,7 +1633,7 @@ static int _node_send_messages(struct dm_tree_node *dnode, |
||||
return 0; |
||||
} |
||||
|
||||
- if (!send) |
||||
+ if (!have_messages || !send) |
||||
return 1; /* transaction_id is matching */ |
||||
|
||||
dm_list_iterate_items(tmsg, &seg->thin_messages) { |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
WHATS_NEW | 1 + |
||||
lib/cache/lvmetad.c | 2 +- |
||||
2 files changed, 2 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 5de648c..9ddecbc 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.131 - |
||||
===================================== |
||||
+ Fix VG metadata comparison failure while scanning the VG for lvmetad. |
||||
Ignore persistent cache if configuration changed. (2.02.127) |
||||
|
||||
Version 2.02.130 - 5th September 2015 |
||||
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c |
||||
index b2e2f55..0fff65a 100644 |
||||
--- a/lib/cache/lvmetad.c |
||||
+++ b/lib/cache/lvmetad.c |
||||
@@ -1174,7 +1174,7 @@ static struct volume_group *lvmetad_pvscan_vg(struct cmd_context *cmd, struct vo |
||||
if (!vgmeta_ret) { |
||||
vgmeta_ret = vgmeta; |
||||
} else { |
||||
- if (!compare_config(vgmeta_ret->root, vgmeta->root)) { |
||||
+ if (compare_config(vgmeta_ret->root, vgmeta->root)) { |
||||
log_error("VG metadata comparison failed"); |
||||
dm_config_destroy(vgmeta); |
||||
dm_config_destroy(vgmeta_ret); |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
WHATS_NEW | 1 + |
||||
scripts/vgimportclone.sh | 4 ++-- |
||||
2 files changed, 3 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index f41475c..1718c29 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.131 - |
||||
===================================== |
||||
+ Fix vgimportclone cache_dir path name (2.02.115). |
||||
Disallow usage of --stripe and --stripesize when creating cache pool. |
||||
Swapping of LV identifiers handles more complex LVs. |
||||
Fix VG metadata comparison failure while scanning the VG for lvmetad. |
||||
diff --git a/scripts/vgimportclone.sh b/scripts/vgimportclone.sh |
||||
index 388d14c..af8cf5c 100755 |
||||
--- a/scripts/vgimportclone.sh |
||||
+++ b/scripts/vgimportclone.sh |
||||
@@ -1,7 +1,7 @@ |
||||
#!/bin/bash |
||||
|
||||
# Copyright (C) 2009 Chris Procter All rights reserved. |
||||
-# Copyright (C) 2009 Red Hat, Inc. All rights reserved. |
||||
+# Copyright (C) 2009-2015 Red Hat, Inc. All rights reserved. |
||||
# |
||||
# This file is part of LVM2. |
||||
# |
||||
@@ -239,7 +239,7 @@ LVMCONF=${TMP_LVM_SYSTEM_DIR}/lvm.conf |
||||
|
||||
CMD_CONFIG_LINE="devices { \ |
||||
scan = [ \"${TMP_LVM_SYSTEM_DIR}\" ] \ |
||||
- cache_dir = \"$TMP_LVM_SYSTEM_DIR}/cache\" |
||||
+ cache_dir = \"${TMP_LVM_SYSTEM_DIR}/cache\" |
||||
global_filter = [ \"a|.*|\" ] \ |
||||
${FILTER} |
||||
} \ |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
tools/lvmcmdline.c | 8 +++++++- |
||||
2 files changed, 11 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index e74fd55..5de648c 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.131 - |
||||
+===================================== |
||||
+ Ignore persistent cache if configuration changed. (2.02.127) |
||||
+ |
||||
Version 2.02.130 - 5th September 2015 |
||||
===================================== |
||||
Fix use of uninitialized device status if reading outdated .cache record. |
||||
diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c |
||||
index b7809c7..d3bace7 100644 |
||||
--- a/tools/lvmcmdline.c |
||||
+++ b/tools/lvmcmdline.c |
||||
@@ -1478,6 +1478,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) |
||||
char *arg_new, *arg; |
||||
int i; |
||||
int skip_hyphens; |
||||
+ int refresh_done = 0; |
||||
|
||||
init_error_message_produced(0); |
||||
|
||||
@@ -1554,6 +1555,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) |
||||
log_error("Updated config file invalid. Aborting."); |
||||
return ECMD_FAILED; |
||||
} |
||||
+ refresh_done = 1; |
||||
} |
||||
|
||||
if (!_prepare_profiles(cmd)) |
||||
@@ -1562,7 +1564,11 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) |
||||
if (!cmd->initialized.connections && !_cmd_no_meta_proc(cmd) && !init_connections(cmd)) |
||||
return_ECMD_FAILED; |
||||
|
||||
- if (!cmd->initialized.filters && !_cmd_no_meta_proc(cmd) && !init_filters(cmd, 1)) |
||||
+ /* Note: Load persistent cache only if we haven't refreshed toolcontext! |
||||
+ * If toolcontext has been refreshed, it means config has changed |
||||
+ * and we can't rely on persistent cache anymore. |
||||
+ */ |
||||
+ if (!cmd->initialized.filters && !_cmd_no_meta_proc(cmd) && !init_filters(cmd, !refresh_done)) |
||||
return_ECMD_FAILED; |
||||
|
||||
if (arg_count(cmd, readonly_ARG)) |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
WHATS_NEW | 1 + |
||||
tools/lvconvert.c | 4 ++-- |
||||
tools/lvconvert_poll.c | 13 +++++++++---- |
||||
3 files changed, 12 insertions(+), 6 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 9ddecbc..5260321 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.131 - |
||||
===================================== |
||||
+ Swapping of LV identifiers handles more complex LVs. |
||||
Fix VG metadata comparison failure while scanning the VG for lvmetad. |
||||
Ignore persistent cache if configuration changed. (2.02.127) |
||||
|
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 2bffb07..919537a 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -2489,14 +2489,14 @@ deactivate_pmslv: |
||||
if (!detach_pool_metadata_lv(first_seg(pool_lv), &mlv)) |
||||
return_0; |
||||
|
||||
+ /* Swap _pmspare and _tmeta name */ |
||||
if (!swap_lv_identifiers(cmd, mlv, pmslv)) |
||||
return_0; |
||||
|
||||
- /* Used _pmspare will become _tmeta */ |
||||
if (!attach_pool_metadata_lv(first_seg(pool_lv), pmslv)) |
||||
return_0; |
||||
|
||||
- /* Used _tmeta will become visible _meta%d */ |
||||
+ /* Used _tmeta (now _pmspare) becomes _meta%d */ |
||||
if (!lv_rename_update(cmd, mlv, pms_path, 0)) |
||||
return_0; |
||||
|
||||
diff --git a/tools/lvconvert_poll.c b/tools/lvconvert_poll.c |
||||
index e3a3709..1b230bc 100644 |
||||
--- a/tools/lvconvert_poll.c |
||||
+++ b/tools/lvconvert_poll.c |
||||
@@ -44,15 +44,20 @@ int swap_lv_identifiers(struct cmd_context *cmd, |
||||
struct logical_volume *a, struct logical_volume *b) |
||||
{ |
||||
union lvid lvid; |
||||
- const char *name; |
||||
+ const char *aname = a->name, *bname = b->name; |
||||
|
||||
lvid = a->lvid; |
||||
a->lvid = b->lvid; |
||||
b->lvid = lvid; |
||||
|
||||
- name = a->name; |
||||
- a->name = b->name; |
||||
- if (!lv_rename_update(cmd, b, name, 0)) |
||||
+ /* rename temporarily to 'unused' name */ |
||||
+ if (!lv_rename_update(cmd, a, "pmove_tmeta", 0)) |
||||
+ return_0; |
||||
+ /* name rename 'b' to unused name of 'a' */ |
||||
+ if (!lv_rename_update(cmd, b, aname, 0)) |
||||
+ return_0; |
||||
+ /* finish name swapping */ |
||||
+ if (!lv_rename_update(cmd, a, bname, 0)) |
||||
return_0; |
||||
|
||||
return 1; |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
lib/metadata/lv_manip.c | 23 ++++++++++++++++++----- |
||||
2 files changed, 22 insertions(+), 5 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 1718c29..0fa6bb6 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.133 - |
||||
+====================================== |
||||
+ Check for enough space in thin-pool in command before creating new thin. |
||||
+ |
||||
Version 2.02.131 - |
||||
===================================== |
||||
Fix vgimportclone cache_dir path name (2.02.115). |
||||
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c |
||||
index 88c516b..32aa666 100644 |
||||
--- a/lib/metadata/lv_manip.c |
||||
+++ b/lib/metadata/lv_manip.c |
||||
@@ -7038,12 +7038,25 @@ static struct logical_volume *_lv_create_an_lv(struct volume_group *vg, |
||||
} |
||||
} |
||||
|
||||
- if (seg_is_thin_volume(lp) && |
||||
- lv_is_new_thin_pool(pool_lv)) { |
||||
+ if (seg_is_thin_volume(lp)) { |
||||
thin_pool_was_active = lv_is_active(pool_lv); |
||||
- if (!check_new_thin_pool(pool_lv)) |
||||
- return_NULL; |
||||
- /* New pool is now inactive */ |
||||
+ if (lv_is_new_thin_pool(pool_lv)) { |
||||
+ if (!check_new_thin_pool(pool_lv)) |
||||
+ return_NULL; |
||||
+ /* New pool is now inactive */ |
||||
+ } else { |
||||
+ if (!activate_lv_excl_local(cmd, pool_lv)) { |
||||
+ log_error("Aborting. Failed to locally activate thin pool %s.", |
||||
+ display_lvname(pool_lv)); |
||||
+ return 0; |
||||
+ } |
||||
+ if (!pool_below_threshold(first_seg(pool_lv))) { |
||||
+ log_error("Cannot create new thin volume, free space in " |
||||
+ "thin pool %s reached threshold.", |
||||
+ display_lvname(pool_lv)); |
||||
+ return NULL; |
||||
+ } |
||||
+ } |
||||
} |
||||
|
||||
if (seg_is_cache(lp) && |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
WHATS_NEW_DM | 4 ++++ |
||||
libdm/libdm-deptree.c | 3 ++- |
||||
2 files changed, 6 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM |
||||
index 9e30786..71b25ba 100644 |
||||
--- a/WHATS_NEW_DM |
||||
+++ b/WHATS_NEW_DM |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 1.02.110 - |
||||
+====================================== |
||||
+ Enforce writethrough mode for cleaner policy. |
||||
+ |
||||
Version 1.02.108 - |
||||
===================================== |
||||
Do not check for full thin pool when activating without messages (1.02.107). |
||||
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c |
||||
index 7b7ca5b..fc79e33 100644 |
||||
--- a/libdm/libdm-deptree.c |
||||
+++ b/libdm/libdm-deptree.c |
||||
@@ -3456,7 +3456,8 @@ int dm_tree_node_add_cache_target(struct dm_tree_node *node, |
||||
return_0; |
||||
|
||||
seg->data_block_size = data_block_size; |
||||
- seg->flags = feature_flags; |
||||
+ /* Enforce WriteThough mode for cleaner policy */ |
||||
+ seg->flags = (strcmp(policy_name, "cleaner") == 0) ? DM_CACHE_FEATURE_WRITETHROUGH : feature_flags; |
||||
seg->policy_name = policy_name; |
||||
|
||||
/* FIXME: better validation missing */ |
@ -0,0 +1,204 @@
@@ -0,0 +1,204 @@
|
||||
commit 8aa13d867d8c707450bb1de1479e18a3bbbc324a |
||||
Author: Peter Rajnoha <prajnoha@redhat.com> |
||||
Date: Tue Dec 1 13:10:31 2015 +0100 |
||||
|
||||
bz1274676 |
||||
--- |
||||
lib/activate/dev_manager.c | 11 ++++-- |
||||
libdm/.exported_symbols.Base | 1 - |
||||
libdm/.exported_symbols.DM_1_02_107 | 1 + |
||||
libdm/libdevmapper.h | 5 +++ |
||||
libdm/libdm-deptree.c | 25 ++++++++++++-- |
||||
test/shell/lvextend-thin-bz1274676.sh | 63 +++++++++++++++++++++++++++++++++++ |
||||
6 files changed, 100 insertions(+), 6 deletions(-) |
||||
|
||||
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c |
||||
index c8e9589..e1f547f 100644 |
||||
--- a/lib/activate/dev_manager.c |
||||
+++ b/lib/activate/dev_manager.c |
||||
@@ -3277,7 +3277,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv, |
||||
break; |
||||
case SUSPEND: |
||||
dm_tree_skip_lockfs(root); |
||||
- if (!dm->flush_required && lv_is_mirror(lv) && !lv_is_pvmove(lv)) |
||||
+ if (!dm->flush_required && !lv_is_pvmove(lv)) |
||||
dm_tree_use_no_flush_suspend(root); |
||||
/* Fall through */ |
||||
case SUSPEND_WITH_LOCKFS: |
||||
@@ -3296,7 +3296,14 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv, |
||||
if (!dm_tree_preload_children(root, dlid, DLID_SIZE)) |
||||
goto_out; |
||||
|
||||
- if (dm_tree_node_size_changed(root)) |
||||
+ if ((dm_tree_node_size_changed(root) < 0)) |
||||
+ dm->flush_required = 1; |
||||
+ |
||||
+ /* Currently keep the code require flush for any |
||||
+ * non 'thin pool/volume, mirror' or with any size change */ |
||||
+ if (!lv_is_thin_volume(lv) && |
||||
+ !lv_is_thin_pool(lv) && |
||||
+ (!lv_is_mirror(lv) || dm_tree_node_size_changed(root))) |
||||
dm->flush_required = 1; |
||||
|
||||
if (action == ACTIVATE) { |
||||
diff --git a/libdm/.exported_symbols.Base b/libdm/.exported_symbols.Base |
||||
index f9c3cb1..27fef53 100644 |
||||
--- a/libdm/.exported_symbols.Base |
||||
+++ b/libdm/.exported_symbols.Base |
||||
@@ -262,7 +262,6 @@ dm_tree_node_set_thin_external_origin |
||||
dm_tree_node_set_thin_pool_discard |
||||
dm_tree_node_set_thin_pool_error_if_no_space |
||||
dm_tree_node_set_udev_flags |
||||
-dm_tree_node_size_changed |
||||
dm_tree_preload_children |
||||
dm_tree_retry_remove |
||||
dm_tree_set_cookie |
||||
diff --git a/libdm/.exported_symbols.DM_1_02_107 b/libdm/.exported_symbols.DM_1_02_107 |
||||
index 89d3464..0c7b7af 100644 |
||||
--- a/libdm/.exported_symbols.DM_1_02_107 |
||||
+++ b/libdm/.exported_symbols.DM_1_02_107 |
||||
@@ -13,3 +13,4 @@ dm_stats_create_region |
||||
dm_stats_driver_supports_histogram |
||||
dm_stats_get_histogram |
||||
dm_stats_get_region_nr_histogram_bins |
||||
+dm_tree_node_size_changed |
||||
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h |
||||
index 098fa85..8d4b096 100644 |
||||
--- a/libdm/libdevmapper.h |
||||
+++ b/libdm/libdevmapper.h |
||||
@@ -1252,6 +1252,11 @@ const char *dm_tree_node_get_name(const struct dm_tree_node *node); |
||||
const char *dm_tree_node_get_uuid(const struct dm_tree_node *node); |
||||
const struct dm_info *dm_tree_node_get_info(const struct dm_tree_node *node); |
||||
void *dm_tree_node_get_context(const struct dm_tree_node *node); |
||||
+/* |
||||
+ * Returns 0 when node size and its children is unchanged. |
||||
+ * Returns 1 when node or any of its children has increased size. |
||||
+ * Rerurns -1 when node or any of its children has reduced size. |
||||
+ */ |
||||
int dm_tree_node_size_changed(const struct dm_tree_node *dnode); |
||||
|
||||
/* |
||||
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c |
||||
index fc79e33..0584079 100644 |
||||
--- a/libdm/libdm-deptree.c |
||||
+++ b/libdm/libdm-deptree.c |
||||
@@ -220,7 +220,7 @@ struct load_properties { |
||||
uint32_t read_ahead_flags; |
||||
|
||||
unsigned segment_count; |
||||
- unsigned size_changed; |
||||
+ int size_changed; |
||||
struct dm_list segs; |
||||
|
||||
const char *new_name; |
||||
@@ -2768,7 +2768,8 @@ static int _load_node(struct dm_tree_node *dnode) |
||||
|
||||
existing_table_size = dm_task_get_existing_table_size(dmt); |
||||
if ((dnode->props.size_changed = |
||||
- (existing_table_size == seg_start) ? 0 : 1)) { |
||||
+ (existing_table_size == seg_start) ? 0 : |
||||
+ (existing_table_size > seg_start) ? -1 : 1)) { |
||||
/* |
||||
* Kernel usually skips size validation on zero-length devices |
||||
* now so no need to preload them. |
||||
@@ -2864,8 +2865,10 @@ int dm_tree_preload_children(struct dm_tree_node *dnode, |
||||
} |
||||
|
||||
/* Propagate device size change change */ |
||||
- if (child->props.size_changed) |
||||
+ if (child->props.size_changed > 0 && !dnode->props.size_changed) |
||||
dnode->props.size_changed = 1; |
||||
+ else if (child->props.size_changed < 0) |
||||
+ dnode->props.size_changed = -1; |
||||
|
||||
/* Resume device immediately if it has parents and its size changed */ |
||||
if (!dm_tree_node_num_children(child, 1) || !child->props.size_changed) |
||||
@@ -4190,3 +4193,19 @@ void dm_tree_node_set_callback(struct dm_tree_node *dnode, |
||||
dnode->callback = cb; |
||||
dnode->callback_data = data; |
||||
} |
||||
+ |
||||
+/* |
||||
+ * Backward compatible dm_tree_node_size_changed() implementations. |
||||
+ * |
||||
+ * Keep these at the end of the file to avoid adding clutter around the |
||||
+ * current dm_tree_node_size_changed() version. |
||||
+ */ |
||||
+#if defined(__GNUC__) |
||||
+int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode); |
||||
+DM_EXPORT_SYMBOL_BASE(dm_tree_node_size_changed); |
||||
+int dm_tree_node_size_changed_base(const struct dm_tree_node *dnode) |
||||
+{ |
||||
+ /* Base does not make difference between smaller and bigger */ |
||||
+ return dm_tree_node_size_changed(dnode) ? 1 : 0; |
||||
+} |
||||
+#endif |
||||
diff --git a/test/shell/lvextend-thin-bz1274676.sh b/test/shell/lvextend-thin-bz1274676.sh |
||||
new file mode 100644 |
||||
index 0000000..facace0 |
||||
--- /dev/null |
||||
+++ b/test/shell/lvextend-thin-bz1274676.sh |
||||
@@ -0,0 +1,63 @@ |
||||
+#!/bin/bash |
||||
+# Copyright (C) 2015 Red Hat, Inc. All rights reserved. |
||||
+# |
||||
+# This copyrighted material is made available to anyone wishing to use, |
||||
+# modify, copy, or redistribute it subject to the terms and conditions |
||||
+# of the GNU General Public License v.2. |
||||
+# |
||||
+# You should have received a copy of the GNU General Public License |
||||
+# along with this program; if not, write to the Free Software Foundation, |
||||
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
+ |
||||
+# ensure there is no data loss during thin-pool resize |
||||
+ |
||||
+export LVM_TEST_THIN_REPAIR_CMD=${LVM_TEST_THIN_REPAIR_CMD-/bin/false} |
||||
+ |
||||
+. lib/inittest |
||||
+ |
||||
+test -e LOCAL_LVMPOLLD && skip |
||||
+ |
||||
+which md5sum || skip |
||||
+ |
||||
+aux have_thin 1 0 0 || skip |
||||
+ |
||||
+aux prepare_pvs 2 20 |
||||
+ |
||||
+vgcreate -s 512K $vg $(< DEVICES) |
||||
+ |
||||
+lvcreate -L1M -V2M -n $lv1 -T $vg/pool |
||||
+ |
||||
+# just ensure we check what we need to check |
||||
+check lv_field $vg/pool size "1.00m" |
||||
+check lv_field $vg/$lv1 size "2.00m" |
||||
+ |
||||
+# prepare 2097152 file content |
||||
+seq 0 315465 > 2M |
||||
+md5sum 2M | cut -f 1 -d ' ' | tee MD5 |
||||
+dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=512K conv=fdatasync 2>&1 >log & |
||||
+#dd if=2M of="$DM_DEV_DIR/mapper/$vg-$lv1" bs=2M oflag=direct & |
||||
+ |
||||
+# give it some time to fill thin-volume |
||||
+# eventually loop to wait for 100% full pool... |
||||
+sleep .1 |
||||
+lvs -a $vg |
||||
+ |
||||
+# this must not 'block & wait' on suspending flush |
||||
+# if it waits on thin-pool's target timeout |
||||
+# it will harm queued data |
||||
+lvextend -L+512k $vg/pool |
||||
+lvextend -L+512k $vg/pool |
||||
+ |
||||
+# collect 'dd' result |
||||
+wait |
||||
+cat log |
||||
+ |
||||
+lvs -a $vg |
||||
+ |
||||
+dd if="$DM_DEV_DIR/mapper/$vg-$lv1" of=2M-2 iflag=direct |
||||
+md5sum 2M-2 | cut -f 1 -d ' ' | tee MD5-2 |
||||
+ |
||||
+# these 2 are supposed to match |
||||
+diff MD5 MD5-2 |
||||
+ |
||||
+vgremove -f $vg |
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
tools/pvscan.c | 9 +++++++++ |
||||
tools/tools.h | 2 ++ |
||||
tools/vgchange.c | 4 ++-- |
||||
4 files changed, 17 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 945b282..8c87a92 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -2,6 +2,10 @@ Version 2.02.142 - |
||||
==================================== |
||||
Do not check for suspended devices if scanning for lvmetad update. |
||||
|
||||
+Version 2.02.140 - |
||||
+=================================== |
||||
+ Restore background polling processing during auto-activation (2.02.119). |
||||
+ |
||||
Version 2.02.133 - |
||||
====================================== |
||||
Check for enough space in thin-pool in command before creating new thin. |
||||
diff --git a/tools/pvscan.c b/tools/pvscan.c |
||||
index 3adb91c..b3b5911 100644 |
||||
--- a/tools/pvscan.c |
||||
+++ b/tools/pvscan.c |
||||
@@ -154,6 +154,15 @@ static int _auto_activation_handler(struct cmd_context *cmd, |
||||
goto out; |
||||
} |
||||
|
||||
+ /* |
||||
+ * After sucessfull activation we need to initialise polling |
||||
+ * for all activated LVs in a VG. Possible enhancement would |
||||
+ * 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; |
||||
|
||||
out: |
||||
diff --git a/tools/tools.h b/tools/tools.h |
||||
index 4ed893f..634b101 100644 |
||||
--- a/tools/tools.h |
||||
+++ b/tools/tools.h |
||||
@@ -183,4 +183,6 @@ int mirror_remove_missing(struct cmd_context *cmd, |
||||
int vgchange_activate(struct cmd_context *cmd, struct volume_group *vg, |
||||
activation_change_t activate); |
||||
|
||||
+int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg); |
||||
+ |
||||
#endif |
||||
diff --git a/tools/vgchange.c b/tools/vgchange.c |
||||
index 1d3c64a..d572220 100644 |
||||
--- a/tools/vgchange.c |
||||
+++ b/tools/vgchange.c |
||||
@@ -174,7 +174,7 @@ static int _vgchange_monitoring(struct cmd_context *cmd, struct volume_group *vg |
||||
return r; |
||||
} |
||||
|
||||
-static int _vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg) |
||||
+int vgchange_background_polling(struct cmd_context *cmd, struct volume_group *vg) |
||||
{ |
||||
int polled; |
||||
|
||||
@@ -999,7 +999,7 @@ static int vgchange_single(struct cmd_context *cmd, const char *vg_name, |
||||
|
||||
if (!arg_count(cmd, refresh_ARG) && |
||||
background_polling()) |
||||
- if (!_vgchange_background_polling(cmd, vg)) |
||||
+ if (!vgchange_background_polling(cmd, vg)) |
||||
return_ECMD_FAILED; |
||||
|
||||
if (arg_is_set(cmd, lockstart_ARG)) { |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
lib/filters/filter-usable.c | 9 +-------- |
||||
2 files changed, 5 insertions(+), 8 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 0fa6bb6..945b282 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.142 - |
||||
+==================================== |
||||
+ Do not check for suspended devices if scanning for lvmetad update. |
||||
+ |
||||
Version 2.02.133 - |
||||
====================================== |
||||
Check for enough space in thin-pool in command before creating new thin. |
||||
diff --git a/lib/filters/filter-usable.c b/lib/filters/filter-usable.c |
||||
index 9377661..b24a30c 100644 |
||||
--- a/lib/filters/filter-usable.c |
||||
+++ b/lib/filters/filter-usable.c |
||||
@@ -126,15 +126,8 @@ static int _passes_usable_filter(struct dev_filter *f, struct device *dev) |
||||
break; |
||||
case FILTER_MODE_PRE_LVMETAD: |
||||
ucp.check_empty = 1; |
||||
- /* |
||||
- * If we're scanning for lvmetad update, |
||||
- * we don't want to hang on blocked/suspended devices. |
||||
- * When the device is unblocked/resumed, surely, |
||||
- * there's going to be a CHANGE event so the device |
||||
- * gets scanned via udev rule anyway after resume. |
||||
- */ |
||||
ucp.check_blocked = 1; |
||||
- ucp.check_suspended = 1; |
||||
+ ucp.check_suspended = 0; |
||||
ucp.check_error_target = 1; |
||||
ucp.check_reserved = 1; |
||||
break; |
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
lib/activate/activate.c | 10 ++++++++++ |
||||
lib/activate/dev_manager.c | 13 +++++++------ |
||||
3 files changed, 21 insertions(+), 6 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 8c87a92..6441cc1 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.155 - |
||||
+==================================== |
||||
+ Fix flushing for mirror target. |
||||
+ |
||||
Version 2.02.142 - |
||||
==================================== |
||||
Do not check for suspended devices if scanning for lvmetad update. |
||||
diff --git a/lib/activate/activate.c b/lib/activate/activate.c |
||||
index 7d2adf1..8b0fcb3 100644 |
||||
--- a/lib/activate/activate.c |
||||
+++ b/lib/activate/activate.c |
||||
@@ -1900,6 +1900,16 @@ static int _lv_suspend(struct cmd_context *cmd, const char *lvid_s, |
||||
} |
||||
} |
||||
|
||||
+ /* Flush is ATM required for the tested cases |
||||
+ * NOTE: Mirror repair requires noflush for proper repair! |
||||
+ * TODO: Relax this limiting condition further */ |
||||
+ if (!flush_required && |
||||
+ (lv_is_pvmove(ondisk_lv) || |
||||
+ (!lv_is_mirror(ondisk_lv) && !lv_is_thin_pool(ondisk_lv) && !lv_is_thin_volume(ondisk_lv)))) { |
||||
+ log_debug("Requiring flush for LV %s.", display_lvname(ondisk_lv)); |
||||
+ flush_required = 1; |
||||
+ } |
||||
+ |
||||
if (!monitor_dev_for_events(cmd, ondisk_lv, laopts, 0)) |
||||
/* FIXME Consider aborting here */ |
||||
stack; |
||||
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c |
||||
index e1f547f..c95dfbe 100644 |
||||
--- a/lib/activate/dev_manager.c |
||||
+++ b/lib/activate/dev_manager.c |
||||
@@ -3277,7 +3277,7 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv, |
||||
break; |
||||
case SUSPEND: |
||||
dm_tree_skip_lockfs(root); |
||||
- if (!dm->flush_required && !lv_is_pvmove(lv)) |
||||
+ if (!dm->flush_required) |
||||
dm_tree_use_no_flush_suspend(root); |
||||
/* Fall through */ |
||||
case SUSPEND_WITH_LOCKFS: |
||||
@@ -3298,12 +3298,11 @@ static int _tree_action(struct dev_manager *dm, const struct logical_volume *lv, |
||||
|
||||
if ((dm_tree_node_size_changed(root) < 0)) |
||||
dm->flush_required = 1; |
||||
- |
||||
/* Currently keep the code require flush for any |
||||
- * non 'thin pool/volume, mirror' or with any size change */ |
||||
- if (!lv_is_thin_volume(lv) && |
||||
- !lv_is_thin_pool(lv) && |
||||
- (!lv_is_mirror(lv) || dm_tree_node_size_changed(root))) |
||||
+ * non 'thin pool/volume' and size increase */ |
||||
+ else if (!lv_is_thin_volume(lv) && |
||||
+ !lv_is_thin_pool(lv) && |
||||
+ dm_tree_node_size_changed(root)) |
||||
dm->flush_required = 1; |
||||
|
||||
if (action == ACTIVATE) { |
||||
@@ -3347,6 +3346,8 @@ int dev_manager_activate(struct dev_manager *dm, const struct logical_volume *lv |
||||
int dev_manager_preload(struct dev_manager *dm, const struct logical_volume *lv, |
||||
struct lv_activate_opts *laopts, int *flush_required) |
||||
{ |
||||
+ dm->flush_required = *flush_required; |
||||
+ |
||||
if (!_tree_action(dm, lv, laopts, PRELOAD)) |
||||
return_0; |
||||
|
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
lib/metadata/raid_manip.c | 5 +++++ |
||||
2 files changed, 9 insertions(+) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 977e578..5cbf4ec 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.167 - |
||||
+====================================== |
||||
+ Disable lvconvert of thin pool to raid while active. |
||||
+ |
||||
Version 2.02.166 - 26th September 2016 |
||||
====================================== |
||||
Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155) |
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index e5fdf4f..5fc520e 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -776,6 +776,11 @@ static int _raid_add_images_without_commit(struct logical_volume *lv, |
||||
return 0; |
||||
} |
||||
|
||||
+ if (lv_is_active(lv_lock_holder(lv)) && (old_count == 1) && (lv_is_thin_pool_data(lv) || lv_is_thin_pool_metadata(lv))) { |
||||
+ log_error("Can't add image to active thin pool LV %s yet. Deactivate first.", display_lvname(lv)); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
if (!archive(lv->vg)) |
||||
return_0; |
||||
|
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
@@ -, +, @@ |
||||
convert internal LV" |
||||
--- |
||||
tools/lvconvert.c | 4 +++- |
||||
1 file changed, 3 insertions(+), 1 deletion(-) |
||||
--- a/tools/lvconvert.c |
||||
+++ a/tools/lvconvert.c |
||||
@@ -243,6 +243,7 @@ static int _lvconvert_name_params(struct lvconvert_params *lp, |
||||
!strstr(lp->lv_name, "_tmeta") && |
||||
!strstr(lp->lv_name, "_cdata") && |
||||
!strstr(lp->lv_name, "_cmeta") && |
||||
+ !strstr(lp->lv_name, "_corig") && |
||||
!apply_lvname_restrictions(lp->lv_name)) |
||||
return_0; |
||||
|
||||
@@ -4440,7 +4441,8 @@ static int _lvconvert(struct cmd_context *cmd, struct logical_volume *lv, |
||||
!lv_is_thin_pool_metadata(lv) && |
||||
!lv_is_thin_pool_data(lv) && |
||||
!lv_is_used_cache_pool(lv) && |
||||
- !lv_is_raid_image(lv)) { |
||||
+ !lv_is_raid_image(lv) && |
||||
+ !(lv_is_raid(lv) && strstr(lv->name, "_corig"))) { |
||||
log_error("Cannot convert internal LV %s.", display_lvname(lv)); |
||||
ret = 0; |
||||
goto out; |
||||
-- |
||||
|
@ -0,0 +1,532 @@
@@ -0,0 +1,532 @@
|
||||
WHATS_NEW | 2 + |
||||
lib/metadata/raid_manip.c | 277 +++++++++++++++++++++++++++++++--- |
||||
test/shell/lvconvert-raid-takeover.sh | 53 ++++++- |
||||
tools/lvconvert.c | 24 +-- |
||||
4 files changed, 314 insertions(+), 42 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 5cbf4ec..6a0c311 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,7 @@ |
||||
Version 2.02.167 - |
||||
====================================== |
||||
+ Add direct striped -> raid4 conversion |
||||
+ Fix raid4 parity image pair position on conversions from striped/raid0* |
||||
Disable lvconvert of thin pool to raid while active. |
||||
|
||||
Version 2.02.166 - 26th September 2016 |
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index 5fc520e..e5fd195 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -2459,7 +2459,7 @@ static struct lv_segment *_convert_striped_to_raid0(struct logical_volume *lv, |
||||
0 /* chunk_size */, |
||||
0 /* seg->region_size */, 0u /* extents_copied */ , |
||||
NULL /* pvmove_source_seg */))) { |
||||
- log_error("Failed to allocate new raid0 segement for LV %s.", display_lvname(lv)); |
||||
+ log_error("Failed to allocate new raid0 segment for LV %s.", display_lvname(lv)); |
||||
return NULL; |
||||
} |
||||
|
||||
@@ -2519,42 +2519,51 @@ static struct possible_takeover_reshape_type _possible_takeover_reshape_types[] |
||||
{ .current_types = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */ |
||||
.possible_types = SEG_RAID1, |
||||
.current_areas = 1, |
||||
- .options = ALLOW_NONE }, |
||||
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
||||
{ .current_types = SEG_STRIPED_TARGET, /* linear, i.e. seg->area_count = 1 */ |
||||
.possible_types = SEG_RAID0|SEG_RAID0_META, |
||||
.current_areas = 1, |
||||
.options = ALLOW_STRIPE_SIZE }, |
||||
- { .current_types = SEG_STRIPED_TARGET, /* striped, i.e. seg->area_count > 1 */ |
||||
+ { .current_types = SEG_STRIPED_TARGET, /* striped -> raid0*, i.e. seg->area_count > 1 */ |
||||
.possible_types = SEG_RAID0|SEG_RAID0_META, |
||||
.current_areas = ~0U, |
||||
.options = ALLOW_NONE }, |
||||
+ { .current_types = SEG_STRIPED_TARGET, /* striped -> raid4 , i.e. seg->area_count > 1 */ |
||||
+ .possible_types = SEG_RAID4, |
||||
+ .current_areas = ~0U, |
||||
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
||||
/* raid0* -> */ |
||||
{ .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count = 1 */ |
||||
.possible_types = SEG_RAID1, |
||||
.current_areas = 1, |
||||
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
||||
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> striped, i.e. seg->area_count > 1 */ |
||||
+ .possible_types = SEG_STRIPED_TARGET, |
||||
+ .current_areas = ~0U, |
||||
.options = ALLOW_NONE }, |
||||
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* seg->area_count > 1 */ |
||||
- .possible_types = SEG_RAID4, |
||||
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid0*, i.e. seg->area_count > 1 */ |
||||
+ .possible_types = SEG_RAID0_META|SEG_RAID0, |
||||
.current_areas = ~0U, |
||||
.options = ALLOW_NONE }, |
||||
- { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0 striped, i.e. seg->area_count > 0 */ |
||||
+ { .current_types = SEG_RAID0|SEG_RAID0_META, /* raid0* -> raid4, i.e. seg->area_count > 1 */ |
||||
+ .possible_types = SEG_RAID4, |
||||
+ .current_areas = ~0U, |
||||
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
||||
+ /* raid4 -> -> */ |
||||
+ { .current_types = SEG_RAID4, /* raid4 ->striped/raid0*, i.e. seg->area_count > 1 */ |
||||
.possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META, |
||||
.current_areas = ~0U, |
||||
.options = ALLOW_NONE }, |
||||
- /* raid1 -> */ |
||||
+ /* raid1 -> mirror */ |
||||
{ .current_types = SEG_RAID1, |
||||
- .possible_types = SEG_RAID1|SEG_MIRROR, |
||||
+ .possible_types = SEG_MIRROR, |
||||
.current_areas = ~0U, |
||||
- .options = ALLOW_NONE }, |
||||
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
||||
/* mirror -> raid1 with arbitrary number of legs */ |
||||
{ .current_types = SEG_MIRROR, |
||||
- .possible_types = SEG_MIRROR|SEG_RAID1, |
||||
- .current_areas = ~0U, |
||||
- .options = ALLOW_NONE }, |
||||
- { .current_types = SEG_RAID4, |
||||
- .possible_types = SEG_STRIPED_TARGET|SEG_RAID0|SEG_RAID0_META, |
||||
+ .possible_types = SEG_RAID1, |
||||
.current_areas = ~0U, |
||||
- .options = ALLOW_NONE }, |
||||
+ .options = ALLOW_NONE }, /* FIXME: ALLOW_REGION_SIZE */ |
||||
|
||||
/* END */ |
||||
{ .current_types = 0 } |
||||
@@ -2861,9 +2870,176 @@ static int _raid1_to_mirrored_wrapper(TAKEOVER_FN_ARGS) |
||||
allocate_pvs, 1, &removal_lvs); |
||||
} |
||||
|
||||
+/* |
||||
+ * HM Helper: (raid0_meta -> raid4) |
||||
+ * |
||||
+ * To convert raid0_meta to raid4, which involves shifting the |
||||
+ * parity device to lv segment area 0 and thus changing MD |
||||
+ * array roles, detach the MetaLVs and reload as raid0 in |
||||
+ * order to wipe them then reattach and set back to raid0_meta. |
||||
+ */ |
||||
+static int _clear_meta_lvs(struct logical_volume *lv) |
||||
+{ |
||||
+ uint32_t s; |
||||
+ struct lv_segment *seg = first_seg(lv); |
||||
+ struct lv_segment_area *tmp_areas; |
||||
+ const struct segment_type *tmp_segtype; |
||||
+ struct dm_list meta_lvs; |
||||
+ struct lv_list *lvl_array, *lvl; |
||||
+ |
||||
+ /* Reject non-raid0_meta segment types cautiously */ |
||||
+ if (!seg_is_raid0_meta(seg) || |
||||
+ !seg->meta_areas) |
||||
+ return_0; |
||||
+ |
||||
+ if (!(lvl_array = dm_pool_alloc(lv->vg->vgmem, seg->area_count * sizeof(*lvl_array)))) |
||||
+ return_0; |
||||
+ |
||||
+ dm_list_init(&meta_lvs); |
||||
+ tmp_areas = seg->meta_areas; |
||||
+ |
||||
+ /* Extract all MetaLVs listing them on @meta_lvs */ |
||||
+ log_debug_metadata("Extracting all MetaLVs of %s to activate as raid0", |
||||
+ display_lvname(lv)); |
||||
+ if (!_extract_image_component_sublist(seg, RAID_META, 0, seg->area_count, &meta_lvs, 0)) |
||||
+ return_0; |
||||
+ |
||||
+ /* Memorize meta areas and segtype to set again after initializing. */ |
||||
+ seg->meta_areas = NULL; |
||||
+ tmp_segtype = seg->segtype; |
||||
+ |
||||
+ if (!(seg->segtype = get_segtype_from_flag(lv->vg->cmd, SEG_RAID0)) || |
||||
+ !lv_update_and_reload(lv)) |
||||
+ return_0; |
||||
+ |
||||
+ /* |
||||
+ * Now deactivate the MetaLVs before clearing, so |
||||
+ * that _clear_lvs() will activate them visible. |
||||
+ */ |
||||
+ log_debug_metadata("Deactivating pulled out MetaLVs of %s before initializing.", |
||||
+ display_lvname(lv)); |
||||
+ dm_list_iterate_items(lvl, &meta_lvs) |
||||
+ if (!deactivate_lv(lv->vg->cmd, lvl->lv)) |
||||
+ return_0; |
||||
+ |
||||
+ log_debug_metadata("Clearing allocated raid0_meta metadata LVs for conversion to raid4"); |
||||
+ if (!_clear_lvs(&meta_lvs)) { |
||||
+ log_error("Failed to initialize metadata LVs"); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ /* Set memorized meta areas and raid0_meta segtype */ |
||||
+ seg->meta_areas = tmp_areas; |
||||
+ seg->segtype = tmp_segtype; |
||||
+ |
||||
+ log_debug_metadata("Adding metadata LVs back into %s", display_lvname(lv)); |
||||
+ s = 0; |
||||
+ dm_list_iterate_items(lvl, &meta_lvs) { |
||||
+ lv_set_hidden(lvl->lv); |
||||
+ if (!set_lv_segment_area_lv(seg, s++, lvl->lv, 0, RAID_META)) |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
+/* |
||||
+ * HM Helper: (raid0* <-> raid4) |
||||
+ * |
||||
+ * Rename SubLVs (pairs) allowing to shift names w/o collisions with active ones. |
||||
+ */ |
||||
+#define SLV_COUNT 2 |
||||
+static int _rename_area_lvs(struct logical_volume *lv, const char *suffix) |
||||
+{ |
||||
+ uint32_t s; |
||||
+ size_t sz = strlen("rimage") + (suffix ? strlen(suffix) : 0) + 1; |
||||
+ char *sfx[SLV_COUNT] = { NULL, NULL }; |
||||
+ struct lv_segment *seg = first_seg(lv); |
||||
+ |
||||
+ /* Create _generate_raid_name() suffixes w/ or w/o passed in @suffix */ |
||||
+ for (s = 0; s < SLV_COUNT; s++) |
||||
+ if (!(sfx[s] = dm_pool_alloc(lv->vg->cmd->mem, sz)) || |
||||
+ dm_snprintf(sfx[s], sz, suffix ? "%s%s" : "%s", s ? "rmeta" : "rimage", suffix) < 0) |
||||
+ return_0; |
||||
+ |
||||
+ /* Change names (temporarily) to be able to shift numerical name suffixes */ |
||||
+ for (s = 0; s < seg->area_count; s++) { |
||||
+ if (!(seg_lv(seg, s)->name = _generate_raid_name(lv, sfx[0], s))) |
||||
+ return_0; |
||||
+ if (seg->meta_areas && |
||||
+ !(seg_metalv(seg, s)->name = _generate_raid_name(lv, sfx[1], s))) |
||||
+ return_0; |
||||
+ } |
||||
+ |
||||
+ for (s = 0; s < SLV_COUNT; s++) |
||||
+ dm_pool_free(lv->vg->cmd->mem, sfx[s]); |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
+/* |
||||
+ * HM Helper: (raid0* <-> raid4) |
||||
+ * |
||||
+ * Switch area LVs in lv segment @seg indexed by @s1 and @s2 |
||||
+ */ |
||||
+static void _switch_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2) |
||||
+{ |
||||
+ struct logical_volume *lvt; |
||||
+ |
||||
+ lvt = seg_lv(seg, s1); |
||||
+ seg_lv(seg, s1) = seg_lv(seg, s2); |
||||
+ seg_lv(seg, s2) = lvt; |
||||
+ |
||||
+ /* Be cautious */ |
||||
+ if (seg->meta_areas) { |
||||
+ lvt = seg_metalv(seg, s1); |
||||
+ seg_metalv(seg, s1) = seg_metalv(seg, s2); |
||||
+ seg_metalv(seg, s2) = lvt; |
||||
+ } |
||||
+} |
||||
+ |
||||
+/* |
||||
+ * HM Helper: |
||||
+ * |
||||
+ * shift range of area LVs in @seg in range [ @s1, @s2 ] up if @s1 < @s2, |
||||
+ * else down bubbling the parity SubLVs up/down whilst shifting. |
||||
+ */ |
||||
+static void _shift_area_lvs(struct lv_segment *seg, uint32_t s1, uint32_t s2) |
||||
+{ |
||||
+ uint32_t s; |
||||
+ |
||||
+ if (s1 < s2) |
||||
+ /* Forward shift n+1 -> n */ |
||||
+ for (s = s1; s < s2; s++) |
||||
+ _switch_area_lvs(seg, s, s + 1); |
||||
+ else |
||||
+ /* Reverse shift n-1 -> n */ |
||||
+ for (s = s1; s > s2; s--) |
||||
+ _switch_area_lvs(seg, s, s - 1); |
||||
+} |
||||
+ |
||||
+/* |
||||
+ * Switch position of first and last area lv within |
||||
+ * @lv to move parity SubLVs from end to end. |
||||
+ * |
||||
+ * Direction depends on segment type raid4 / raid0_meta. |
||||
+ */ |
||||
+static int _shift_parity_dev(struct lv_segment *seg) |
||||
+{ |
||||
+ if (seg_is_raid0_meta(seg)) |
||||
+ _shift_area_lvs(seg, seg->area_count - 1, 0); |
||||
+ else if (seg_is_raid4(seg)) |
||||
+ _shift_area_lvs(seg, 0, seg->area_count - 1); |
||||
+ else |
||||
+ return 0; |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
/* raid45 -> raid0* / striped */ |
||||
static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS) |
||||
{ |
||||
+ int rename_sublvs = 0; |
||||
struct lv_segment *seg = first_seg(lv); |
||||
struct dm_list removal_lvs; |
||||
|
||||
@@ -2879,10 +3055,39 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS) |
||||
if (!_raid_in_sync(lv)) |
||||
return 0; |
||||
|
||||
+ if (!yes && yes_no_prompt("Are you sure you want to convert \"%s\" LV %s to \"%s\" " |
||||
+ "type using all resilience? [y/n]: ", |
||||
+ lvseg_name(seg), display_lvname(lv), new_segtype->name) == 'n') { |
||||
+ log_error("Logical volume %s NOT converted to \"%s\"", |
||||
+ display_lvname(lv), new_segtype->name); |
||||
+ return 0; |
||||
+ } |
||||
+ if (sigint_caught()) |
||||
+ return_0; |
||||
+ |
||||
/* Archive metadata */ |
||||
if (!archive(lv->vg)) |
||||
return_0; |
||||
|
||||
+ /* |
||||
+ * raid4 (which actually gets mapped to raid5/dedicated first parity disk) |
||||
+ * needs shifting of SubLVs to move the parity SubLV pair in the first area |
||||
+ * to the last one before conversion to raid0[_meta]/striped to allow for |
||||
+ * SubLV removal from the end of the areas arrays. |
||||
+ */ |
||||
+ if (seg_is_raid4(seg)) { |
||||
+ /* Shift parity SubLV pair "PDD..." -> "DD...P" to be able to remove it off the end */ |
||||
+ if (!_shift_parity_dev(seg)) |
||||
+ return 0; |
||||
+ |
||||
+ if (segtype_is_any_raid0(new_segtype) && |
||||
+ !(rename_sublvs = _rename_area_lvs(lv, "_"))) { |
||||
+ log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv)); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ } |
||||
+ |
||||
/* Remove meta and data LVs requested */ |
||||
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, &removal_lvs, 0, 0)) |
||||
return 0; |
||||
@@ -2902,7 +3107,19 @@ static int _raid456_to_raid0_or_striped_wrapper(TAKEOVER_FN_ARGS) |
||||
|
||||
seg->region_size = 0; |
||||
|
||||
- return _lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs); |
||||
+ if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, &removal_lvs)) |
||||
+ return_0; |
||||
+ |
||||
+ if (rename_sublvs) { |
||||
+ if (!_rename_area_lvs(lv, NULL)) { |
||||
+ log_error("Failed to rename %s LV %s MetaLVs", lvseg_name(seg), display_lvname(lv)); |
||||
+ return 0; |
||||
+ } |
||||
+ if (!lv_update_and_reload(lv)) |
||||
+ return_0; |
||||
+ } |
||||
+ |
||||
+ return 1; |
||||
} |
||||
|
||||
static int _striped_to_raid0_wrapper(struct logical_volume *lv, |
||||
@@ -2930,6 +3147,9 @@ static int _striped_to_raid0_wrapper(struct logical_volume *lv, |
||||
static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
||||
{ |
||||
struct lv_segment *seg = first_seg(lv); |
||||
+ struct dm_list removal_lvs; |
||||
+ |
||||
+ dm_list_init(&removal_lvs); |
||||
|
||||
if (seg_is_raid10(seg)) |
||||
return _takeover_unsupported_yet(lv, new_stripes, new_segtype); |
||||
@@ -2944,6 +3164,13 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
||||
return 0; |
||||
} |
||||
|
||||
+ /* FIXME: restricted to raid4 for the time being... */ |
||||
+ if (!segtype_is_raid4(new_segtype)) { |
||||
+ /* Can't convert striped/raid0* to e.g. raid10_offset */ |
||||
+ log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
/* Archive metadata */ |
||||
if (!archive(lv->vg)) |
||||
return_0; |
||||
@@ -2961,7 +3188,10 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
||||
log_debug_metadata("Adding metadata LVs to %s", display_lvname(lv)); |
||||
if (!_raid0_add_or_remove_metadata_lvs(lv, 1 /* update_and_reload */, allocate_pvs, NULL)) |
||||
return 0; |
||||
- } |
||||
+ /* raid0_meta -> raid4 needs clearing of MetaLVs in order to avoid raid disk role cahnge issues in the kernel */ |
||||
+ } else if (segtype_is_raid4(new_segtype) && |
||||
+ !_clear_meta_lvs(lv)) |
||||
+ return 0; |
||||
|
||||
/* Add the additional component LV pairs */ |
||||
log_debug_metadata("Adding %" PRIu32 " component LV pair(s) to %s", new_image_count - lv_raid_image_count(lv), |
||||
@@ -2969,8 +3199,9 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
||||
if (!_lv_raid_change_image_count(lv, new_image_count, allocate_pvs, NULL, 0, 1)) |
||||
return 0; |
||||
|
||||
- if (!segtype_is_raid4(new_segtype)) { |
||||
- /* Can't convert striped/raid0* to e.g. raid10_offset */ |
||||
+ if (segtype_is_raid4(new_segtype) && |
||||
+ (!_shift_parity_dev(seg) || |
||||
+ !_rename_area_lvs(lv, "_"))) { |
||||
log_error("Can't convert %s to %s", display_lvname(lv), new_segtype->name); |
||||
return 0; |
||||
} |
||||
@@ -2987,6 +3218,14 @@ static int _striped_or_raid0_to_raid45610_wrapper(TAKEOVER_FN_ARGS) |
||||
if (!_lv_update_reload_fns_reset_eliminate_lvs(lv, NULL)) |
||||
return_0; |
||||
|
||||
+ if (segtype_is_raid4(new_segtype)) { |
||||
+ /* We had to rename SubLVs because of collision free sgifting, rename back... */ |
||||
+ if (!_rename_area_lvs(lv, NULL)) |
||||
+ return 0; |
||||
+ if (!lv_update_and_reload(lv)) |
||||
+ return_0; |
||||
+ } |
||||
+ |
||||
return 1; |
||||
} |
||||
|
||||
diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh |
||||
index 19a65d3..0140e22 100644 |
||||
--- a/test/shell/lvconvert-raid-takeover.sh |
||||
+++ b/test/shell/lvconvert-raid-takeover.sh |
||||
@@ -78,22 +78,58 @@ aux wait_for_sync $vg $lv1 |
||||
# Clean up |
||||
lvremove --yes $vg/$lv1 |
||||
|
||||
-# Create 3-way raid0 |
||||
-lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv1 $vg |
||||
-check lv_field $vg/$lv1 segtype "raid0" |
||||
+# Create 3-way striped |
||||
+lvcreate -y -aey --type striped -i 3 -L 64M -n $lv1 $vg |
||||
+check lv_field $vg/$lv1 segtype "striped" |
||||
check lv_field $vg/$lv1 stripes 3 |
||||
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv1 |
||||
fsck -fn /dev/mapper/$vg-$lv1 |
||||
|
||||
-# Convert raid0 -> raid4 |
||||
+# Create 3-way raid0 |
||||
+lvcreate -y -aey --type raid0 -i 3 -L 64M -n $lv2 $vg |
||||
+check lv_field $vg/$lv2 segtype "raid0" |
||||
+check lv_field $vg/$lv2 stripes 3 |
||||
+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv2 |
||||
+fsck -fn /dev/mapper/$vg-$lv2 |
||||
+ |
||||
+# Create 3-way raid0_meta |
||||
+lvcreate -y -aey --type raid0_meta -i 3 -L 64M -n $lv3 $vg |
||||
+check lv_field $vg/$lv3 segtype "raid0_meta" |
||||
+check lv_field $vg/$lv3 stripes 3 |
||||
+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3 |
||||
+fsck -fn /dev/mapper/$vg-$lv3 |
||||
+ |
||||
+# Create 3-way raid4 |
||||
+lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg |
||||
+check lv_field $vg/$lv4 segtype "raid4" |
||||
+check lv_field $vg/$lv4 stripes 4 |
||||
+echo y | mkfs -t ext4 /dev/mapper/$vg-$lv4 |
||||
+fsck -fn /dev/mapper/$vg-$lv4 |
||||
+aux wait_for_sync $vg $lv4 |
||||
+fsck -fn /dev/mapper/$vg-$lv4 |
||||
+ |
||||
+# Convert raid4 -> striped (correct raid4 mapping test!) |
||||
+lvconvert -y --ty striped $vg/$lv4 |
||||
+check lv_field $vg/$lv4 segtype "striped" |
||||
+check lv_field $vg/$lv4 stripes 3 |
||||
+fsck -fn /dev/mapper/$vg-$lv4 |
||||
+ |
||||
+# Convert striped -> raid4 |
||||
lvconvert -y --ty raid4 $vg/$lv1 |
||||
-lvchange --refresh $vg/$lv1 |
||||
check lv_field $vg/$lv1 segtype "raid4" |
||||
check lv_field $vg/$lv1 stripes 4 |
||||
fsck -fn /dev/mapper/$vg-$lv1 |
||||
aux wait_for_sync $vg $lv1 |
||||
fsck -fn /dev/mapper/$vg-$lv1 |
||||
|
||||
+# Convert raid0 -> raid4 |
||||
+lvconvert -y --ty raid4 $vg/$lv2 |
||||
+check lv_field $vg/$lv2 segtype "raid4" |
||||
+check lv_field $vg/$lv2 stripes 4 |
||||
+fsck -fn /dev/mapper/$vg-$lv2 |
||||
+aux wait_for_sync $vg $lv2 |
||||
+fsck -fn /dev/mapper/$vg-$lv2 |
||||
+ |
||||
# Convert raid4 -> raid0_meta |
||||
lvconvert -y --ty raid0_meta $vg/$lv1 |
||||
check lv_field $vg/$lv1 segtype "raid0_meta" |
||||
@@ -116,11 +152,16 @@ fsck -fn /dev/mapper/$vg-$lv1 |
||||
|
||||
# Convert raid0 -> raid4 |
||||
lvconvert -y --ty raid4 $vg/$lv1 |
||||
-lvchange --refresh $vg/$lv1 |
||||
check lv_field $vg/$lv1 segtype "raid4" |
||||
check lv_field $vg/$lv1 stripes 4 |
||||
fsck -fn /dev/mapper/$vg-$lv1 |
||||
aux wait_for_sync $vg $lv1 |
||||
fsck -fn /dev/mapper/$vg-$lv1 |
||||
|
||||
+# Convert raid4 -> striped |
||||
+lvconvert -y --ty striped $vg/$lv1 |
||||
+check lv_field $vg/$lv1 segtype "striped" |
||||
+check lv_field $vg/$lv1 stripes 3 |
||||
+fsck -fn /dev/mapper/$vg-$lv1 |
||||
+ |
||||
vgremove -ff $vg |
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 0d2a4d1..541df72 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -1931,7 +1931,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
return 1; |
||||
} |
||||
goto try_new_takeover_or_reshape; |
||||
- } else if (!lp->repair && !lp->replace && (!*lp->type_str || seg->segtype == lp->segtype)) { |
||||
+ } else if (!lp->repair && !lp->replace && !*lp->type_str) { |
||||
log_error("Conversion operation not yet supported."); |
||||
return 0; |
||||
} |
||||
@@ -2017,28 +2017,18 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
return 1; |
||||
} |
||||
|
||||
- |
||||
try_new_takeover_or_reshape: |
||||
- |
||||
/* FIXME This needs changing globally. */ |
||||
if (!arg_is_set(cmd, stripes_long_ARG)) |
||||
lp->stripes = 0; |
||||
|
||||
- /* Only let raid4 through for now. */ |
||||
- if (lp->type_str && lp->type_str[0] && lp->segtype != seg->segtype && |
||||
- ((seg_is_raid4(seg) && seg_is_striped(lp) && lp->stripes > 1) || |
||||
- (seg_is_striped(seg) && seg->area_count > 1 && seg_is_raid4(lp)))) { |
||||
- if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size, |
||||
- lp->region_size, lp->pvh)) |
||||
- return_0; |
||||
- |
||||
- log_print_unless_silent("Logical volume %s successfully converted.", |
||||
- display_lvname(lv)); |
||||
- return 1; |
||||
- } |
||||
+ if (!lv_raid_convert(lv, lp->segtype, lp->yes, lp->force, lp->stripes, lp->stripe_size_supplied, lp->stripe_size, |
||||
+ lp->region_size, lp->pvh)) |
||||
+ return_0; |
||||
|
||||
- log_error("Conversion operation not yet supported."); |
||||
- return 0; |
||||
+ log_print_unless_silent("Logical volume %s successfully converted.", |
||||
+ display_lvname(lv)); |
||||
+ return 1; |
||||
} |
||||
|
||||
static int _lvconvert_splitsnapshot(struct cmd_context *cmd, struct logical_volume *cow, |
@ -0,0 +1,303 @@
@@ -0,0 +1,303 @@
|
||||
WHATS_NEW | 1 + |
||||
lib/activate/activate.c | 25 +++++++++++++++++++++++++ |
||||
lib/activate/activate.h | 3 ++- |
||||
lib/metadata/lv.c | 16 +++++++++++++++- |
||||
lib/metadata/segtype.h | 3 ++- |
||||
lib/raid/raid.c | 10 ++++++++-- |
||||
test/shell/lvconvert-raid-takeover.sh | 13 +++++++++++++ |
||||
tools/lvconvert.c | 26 ++++++++++++++++++++++++++ |
||||
tools/lvcreate.c | 6 ++++++ |
||||
9 files changed, 98 insertions(+), 5 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 6a0c311..519bbc9 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.167 - |
||||
====================================== |
||||
+ Prevent raid4 creation/conversion on non-supporting kernels |
||||
Add direct striped -> raid4 conversion |
||||
Fix raid4 parity image pair position on conversions from striped/raid0* |
||||
Disable lvconvert of thin pool to raid while active. |
||||
diff --git a/lib/activate/activate.c b/lib/activate/activate.c |
||||
index 5550955..571f2b2 100644 |
||||
--- a/lib/activate/activate.c |
||||
+++ b/lib/activate/activate.c |
||||
@@ -370,6 +370,11 @@ void activation_exit(void) |
||||
{ |
||||
} |
||||
|
||||
+int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype) |
||||
+{ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
int lv_is_active(const struct logical_volume *lv) |
||||
{ |
||||
return 0; |
||||
@@ -1489,6 +1494,26 @@ out: |
||||
return r || l; |
||||
} |
||||
|
||||
+/* |
||||
+ * Check if "raid4" @segtype is supported by kernel. |
||||
+ * |
||||
+ * if segment type is not raid4, return 1. |
||||
+ */ |
||||
+int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype) |
||||
+{ |
||||
+ unsigned attrs; |
||||
+ |
||||
+ if (segtype_is_raid4(segtype) && |
||||
+ (!segtype->ops->target_present || |
||||
+ !segtype->ops->target_present(cmd, NULL, &attrs) || |
||||
+ !(attrs & RAID_FEATURE_RAID4))) { |
||||
+ log_error("RAID module does not support RAID4."); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ return 1; |
||||
+} |
||||
+ |
||||
int lv_is_active(const struct logical_volume *lv) |
||||
{ |
||||
return _lv_is_active(lv, NULL, NULL, NULL); |
||||
diff --git a/lib/activate/activate.h b/lib/activate/activate.h |
||||
index 1e8d7a8..3922d78 100644 |
||||
--- a/lib/activate/activate.h |
||||
+++ b/lib/activate/activate.h |
||||
@@ -1,6 +1,6 @@ |
||||
/* |
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
||||
- * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved. |
||||
+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. |
||||
* |
||||
* This file is part of LVM2. |
||||
* |
||||
@@ -99,6 +99,7 @@ int target_present(struct cmd_context *cmd, const char *target_name, |
||||
int use_modprobe); |
||||
int target_version(const char *target_name, uint32_t *maj, |
||||
uint32_t *min, uint32_t *patchlevel); |
||||
+int raid4_is_supported(struct cmd_context *cmd, const struct segment_type *segtype); |
||||
int lvm_dm_prefix_check(int major, int minor, const char *prefix); |
||||
int list_segment_modules(struct dm_pool *mem, const struct lv_segment *seg, |
||||
struct dm_list *modules); |
||||
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c |
||||
index 53a1044..0f1b6e7 100644 |
||||
--- a/lib/metadata/lv.c |
||||
+++ b/lib/metadata/lv.c |
||||
@@ -1,6 +1,6 @@ |
||||
/* |
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
||||
- * Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved. |
||||
+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. |
||||
* |
||||
* This file is part of LVM2. |
||||
* |
||||
@@ -1425,6 +1425,7 @@ int lv_active_change(struct cmd_context *cmd, struct logical_volume *lv, |
||||
enum activation_change activate, int needs_exclusive) |
||||
{ |
||||
const char *ay_with_mode = NULL; |
||||
+ struct lv_segment *seg = first_seg(lv); |
||||
|
||||
if (activate == CHANGE_ASY) |
||||
ay_with_mode = "sh"; |
||||
@@ -1461,6 +1462,9 @@ deactivate: |
||||
break; |
||||
case CHANGE_ALY: |
||||
case CHANGE_AAY: |
||||
+ if (!raid4_is_supported(cmd, seg->segtype)) |
||||
+ goto no_raid4; |
||||
+ |
||||
if (needs_exclusive || _lv_is_exclusive(lv)) { |
||||
log_verbose("Activating logical volume %s exclusively locally.", |
||||
display_lvname(lv)); |
||||
@@ -1475,6 +1479,9 @@ deactivate: |
||||
break; |
||||
case CHANGE_AEY: |
||||
exclusive: |
||||
+ if (!raid4_is_supported(cmd, seg->segtype)) |
||||
+ goto no_raid4; |
||||
+ |
||||
log_verbose("Activating logical volume %s exclusively.", |
||||
display_lvname(lv)); |
||||
if (!activate_lv_excl(cmd, lv)) |
||||
@@ -1483,6 +1490,9 @@ exclusive: |
||||
case CHANGE_ASY: |
||||
case CHANGE_AY: |
||||
default: |
||||
+ if (!raid4_is_supported(cmd, seg->segtype)) |
||||
+ goto no_raid4; |
||||
+ |
||||
if (needs_exclusive || _lv_is_exclusive(lv)) |
||||
goto exclusive; |
||||
log_verbose("Activating logical volume %s.", display_lvname(lv)); |
||||
@@ -1495,6 +1505,10 @@ exclusive: |
||||
log_error("Failed to unlock logical volume %s.", display_lvname(lv)); |
||||
|
||||
return 1; |
||||
+ |
||||
+no_raid4: |
||||
+ log_error("Failed to activate %s LV %s", lvseg_name(seg), display_lvname(lv)); |
||||
+ return 0; |
||||
} |
||||
|
||||
char *lv_active_dup(struct dm_pool *mem, const struct logical_volume *lv) |
||||
diff --git a/lib/metadata/segtype.h b/lib/metadata/segtype.h |
||||
index 9ca740d..292b8b6 100644 |
||||
--- a/lib/metadata/segtype.h |
||||
+++ b/lib/metadata/segtype.h |
||||
@@ -1,6 +1,6 @@ |
||||
/* |
||||
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. |
||||
- * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. |
||||
+ * Copyright (C) 2004-2016 Red Hat, Inc. All rights reserved. |
||||
* |
||||
* This file is part of LVM2. |
||||
* |
||||
@@ -268,6 +268,7 @@ struct segment_type *init_unknown_segtype(struct cmd_context *cmd, |
||||
#define RAID_FEATURE_RAID10 (1U << 0) /* version 1.3 */ |
||||
#define RAID_FEATURE_RAID0 (1U << 1) /* version 1.7 */ |
||||
#define RAID_FEATURE_RESHAPING (1U << 2) /* version 1.8 */ |
||||
+#define RAID_FEATURE_RAID4 (1U << 3) /* ! version 1.8 or 1.9.0 */ |
||||
|
||||
#ifdef RAID_INTERNAL |
||||
int init_raid_segtypes(struct cmd_context *cmd, struct segtype_library *seglib); |
||||
diff --git a/lib/raid/raid.c b/lib/raid/raid.c |
||||
index 3bc3c75..92a96a3 100644 |
||||
--- a/lib/raid/raid.c |
||||
+++ b/lib/raid/raid.c |
||||
@@ -1,5 +1,5 @@ |
||||
/* |
||||
- * Copyright (C) 2011-2013 Red Hat, Inc. All rights reserved. |
||||
+ * Copyright (C) 2011-2016 Red Hat, Inc. All rights reserved. |
||||
* |
||||
* This file is part of LVM2. |
||||
* |
||||
@@ -366,7 +366,7 @@ static int _raid_target_present(struct cmd_context *cmd, |
||||
|
||||
static int _raid_checked = 0; |
||||
static int _raid_present = 0; |
||||
- static int _raid_attrs = 0; |
||||
+ static unsigned _raid_attrs = 0; |
||||
uint32_t maj, min, patchlevel; |
||||
unsigned i; |
||||
|
||||
@@ -389,6 +389,12 @@ static int _raid_target_present(struct cmd_context *cmd, |
||||
else |
||||
log_very_verbose("Target raid does not support %s.", |
||||
_features[i].feature); |
||||
+ |
||||
+ if (!(maj == 1 && (min == 8 || (min == 9 && patchlevel == 0)))) |
||||
+ _raid_attrs |= RAID_FEATURE_RAID4; |
||||
+ else |
||||
+ log_very_verbose("Target raid does not support %s.", |
||||
+ SEG_TYPE_NAME_RAID4); |
||||
} |
||||
|
||||
if (attributes) |
||||
diff --git a/test/shell/lvconvert-raid-takeover.sh b/test/shell/lvconvert-raid-takeover.sh |
||||
index 0140e22..332786d 100644 |
||||
--- a/test/shell/lvconvert-raid-takeover.sh |
||||
+++ b/test/shell/lvconvert-raid-takeover.sh |
||||
@@ -16,6 +16,8 @@ SKIP_WITH_LVMPOLLD=1 |
||||
|
||||
aux have_raid 1 9 0 || skip |
||||
|
||||
+[ `aux have_raid 1.9.1` ] && correct_raid4_layout=1 |
||||
+ |
||||
aux prepare_vg 9 288 |
||||
|
||||
# Delay 1st leg so that rebuilding status characters |
||||
@@ -99,6 +101,9 @@ check lv_field $vg/$lv3 stripes 3 |
||||
echo y | mkfs -t ext4 /dev/mapper/$vg-$lv3 |
||||
fsck -fn /dev/mapper/$vg-$lv3 |
||||
|
||||
+if [ $correct_raid4_layout -eq 1 ] |
||||
+then |
||||
+ |
||||
# Create 3-way raid4 |
||||
lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg |
||||
check lv_field $vg/$lv4 segtype "raid4" |
||||
@@ -164,4 +169,12 @@ check lv_field $vg/$lv1 segtype "striped" |
||||
check lv_field $vg/$lv1 stripes 3 |
||||
fsck -fn /dev/mapper/$vg-$lv1 |
||||
|
||||
+else |
||||
+ |
||||
+not lvcreate -y -aey --type raid4 -i 3 -L 64M -n $lv4 $vg |
||||
+not lvconvert -y --ty raid4 $vg/$lv1 |
||||
+not lvconvert -y --ty raid4 $vg/$lv2 |
||||
+ |
||||
+fi |
||||
+ |
||||
vgremove -ff $vg |
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 541df72..7a4215a 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -1821,6 +1821,25 @@ static void _lvconvert_raid_repair_ask(struct cmd_context *cmd, |
||||
} |
||||
} |
||||
|
||||
+/* Check for dm-raid target supporting raid4 conversion properly. */ |
||||
+static int _raid4_conversion_supported(struct logical_volume *lv, struct lvconvert_params *lp) |
||||
+{ |
||||
+ int ret = 1; |
||||
+ struct lv_segment *seg = first_seg(lv); |
||||
+ |
||||
+ if (seg_is_raid4(seg)) |
||||
+ ret = raid4_is_supported(lv->vg->cmd, seg->segtype); |
||||
+ else if (segtype_is_raid4(lp->segtype)) |
||||
+ ret = raid4_is_supported(lv->vg->cmd, lp->segtype); |
||||
+ |
||||
+ if (ret) |
||||
+ return 1; |
||||
+ |
||||
+ log_error("Cannot convert %s LV %s to %s.", |
||||
+ lvseg_name(seg), display_lvname(lv), lp->segtype->name); |
||||
+ return 0; |
||||
+} |
||||
+ |
||||
static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *lp) |
||||
{ |
||||
int replace = 0, image_count = 0; |
||||
@@ -1945,6 +1964,9 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
return 0; |
||||
} |
||||
|
||||
+ if (!_raid4_conversion_supported(lv, lp)) |
||||
+ return 0; |
||||
+ |
||||
if (!arg_is_set(cmd, stripes_long_ARG)) |
||||
lp->stripes = 0; |
||||
|
||||
@@ -2018,6 +2040,10 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
} |
||||
|
||||
try_new_takeover_or_reshape: |
||||
+ |
||||
+ if (!_raid4_conversion_supported(lv, lp)) |
||||
+ return 0; |
||||
+ |
||||
/* FIXME This needs changing globally. */ |
||||
if (!arg_is_set(cmd, stripes_long_ARG)) |
||||
lp->stripes = 0; |
||||
diff --git a/tools/lvcreate.c b/tools/lvcreate.c |
||||
index 387c8d4..dbc0708 100644 |
||||
--- a/tools/lvcreate.c |
||||
+++ b/tools/lvcreate.c |
||||
@@ -1054,6 +1054,12 @@ static int _lvcreate_params(struct cmd_context *cmd, |
||||
return 0; |
||||
} |
||||
|
||||
+ if (segtype_is_raid4(lp->segtype) && |
||||
+ !(lp->target_attr & RAID_FEATURE_RAID4)) { |
||||
+ log_error("RAID module does not support RAID4."); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
if (segtype_is_raid10(lp->segtype) && !(lp->target_attr & RAID_FEATURE_RAID10)) { |
||||
log_error("RAID module does not support RAID10."); |
||||
return 0; |
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
From dae4f53acb269219e876c229c8f034fcdaf3ff5a Mon Sep 17 00:00:00 2001 |
||||
From: Zdenek Kabelac <zkabelac@redhat.com> |
||||
Date: Sat, 4 Feb 2017 14:47:27 +0100 |
||||
Subject: [PATCH] clvmd: add mutex protection for cpg_ call |
||||
|
||||
The library for corosync multicasting is not supporting multithread |
||||
usage - add local mutex to avoid parallel call of cpg_mcast_joined(). |
||||
--- |
||||
WHATS_NEW | 1 + |
||||
daemons/clvmd/clvmd-corosync.c | 4 ++++ |
||||
2 files changed, 5 insertions(+) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 8ae2df8..0b571ae 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.169 - |
||||
===================================== |
||||
+ Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync. |
||||
Fix segfault in lvmetad from missing NULL in daemon_reply_simple. |
||||
|
||||
Version 2.02.167 - |
||||
diff --git a/daemons/clvmd/clvmd-corosync.c b/daemons/clvmd/clvmd-corosync.c |
||||
index 05c9882..2227cbf 100644 |
||||
--- a/daemons/clvmd/clvmd-corosync.c |
||||
+++ b/daemons/clvmd/clvmd-corosync.c |
||||
@@ -532,6 +532,7 @@ static int _cluster_fd_callback(struct local_client *fd, char *buf, int len, |
||||
static int _cluster_send_message(const void *buf, int msglen, const char *csid, |
||||
const char *errtext) |
||||
{ |
||||
+ static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER; |
||||
struct iovec iov[2]; |
||||
cs_error_t err; |
||||
int target_node; |
||||
@@ -546,7 +547,10 @@ static int _cluster_send_message(const void *buf, int msglen, const char *csid, |
||||
iov[1].iov_base = (char *)buf; |
||||
iov[1].iov_len = msglen; |
||||
|
||||
+ pthread_mutex_lock(&_mutex); |
||||
err = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2); |
||||
+ pthread_mutex_unlock(&_mutex); |
||||
+ |
||||
return cs_to_errno(err); |
||||
} |
||||
|
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
WHATS_NEW | 4 ++++ |
||||
daemons/lvmetad/lvmetad-core.c | 9 ++++++--- |
||||
2 files changed, 10 insertions(+), 3 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 519bbc9..8ae2df8 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,3 +1,7 @@ |
||||
+Version 2.02.169 - |
||||
+===================================== |
||||
+ Fix segfault in lvmetad from missing NULL in daemon_reply_simple. |
||||
+ |
||||
Version 2.02.167 - |
||||
====================================== |
||||
Prevent raid4 creation/conversion on non-supporting kernels |
||||
diff --git a/daemons/lvmetad/lvmetad-core.c b/daemons/lvmetad/lvmetad-core.c |
||||
index 36a5cec..c46c7ac 100644 |
||||
--- a/daemons/lvmetad/lvmetad-core.c |
||||
+++ b/daemons/lvmetad/lvmetad-core.c |
||||
@@ -2745,7 +2745,8 @@ static response handler(daemon_state s, client_handle h, request r) |
||||
"expected = %s", state->token, |
||||
"received = %s", token, |
||||
"update_pid = " FMTd64, (int64_t)state->update_pid, |
||||
- "reason = %s", "another command has populated the cache"); |
||||
+ "reason = %s", "another command has populated the cache", |
||||
+ NULL); |
||||
} |
||||
|
||||
DEBUGLOG(state, "token_update end len %d pid %d new token %s", |
||||
@@ -2778,7 +2779,8 @@ static response handler(daemon_state s, client_handle h, request r) |
||||
"expected = %s", state->token, |
||||
"received = %s", token, |
||||
"update_pid = " FMTd64, (int64_t)state->update_pid, |
||||
- "reason = %s", "another command has populated the cache"); |
||||
+ "reason = %s", "another command has populated the cache", |
||||
+ NULL); |
||||
} |
||||
|
||||
/* If a pid doing update was cancelled, ignore its update messages. */ |
||||
@@ -2793,7 +2795,8 @@ static response handler(daemon_state s, client_handle h, request r) |
||||
"expected = %s", state->token, |
||||
"received = %s", token, |
||||
"update_pid = " FMTd64, (int64_t)state->update_pid, |
||||
- "reason = %s", "another command has populated the lvmetad cache"); |
||||
+ "reason = %s", "another command has populated the lvmetad cache", |
||||
+ NULL); |
||||
} |
||||
|
||||
pthread_mutex_unlock(&state->token_lock); |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
WHATS_NEW | 1 + |
||||
tools/lvcreate.c | 4 +++- |
||||
2 files changed, 4 insertions(+), 1 deletion(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 0b571ae..26aa5b0 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -1,5 +1,6 @@ |
||||
Version 2.02.169 - |
||||
===================================== |
||||
+ Fix limit of stripes in lvcreate. |
||||
Avoid parallel usage of cpg_mcast_joined() in clvmd with corosync. |
||||
Fix segfault in lvmetad from missing NULL in daemon_reply_simple. |
||||
|
||||
diff --git a/tools/lvcreate.c b/tools/lvcreate.c |
||||
index dbc0708..dae9da6 100644 |
||||
--- a/tools/lvcreate.c |
||||
+++ b/tools/lvcreate.c |
||||
@@ -559,8 +559,10 @@ static int _read_mirror_and_raid_params(struct cmd_context *cmd, |
||||
else if (seg_is_any_raid6(lp)) |
||||
max_images -= 2; |
||||
} |
||||
- } else |
||||
+ } else if (seg_is_mirrored(lp)) |
||||
max_images = DEFAULT_MIRROR_MAX_IMAGES; |
||||
+ else |
||||
+ max_images = MAX_STRIPES; |
||||
|
||||
/* Common mirror and raid params */ |
||||
if (arg_is_set(cmd, mirrors_ARG)) { |
||||
-- |
||||
1.8.3.1 |
||||
|
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
conf/example.conf.in | 2 +- |
||||
lib/config/defaults.h | 2 +- |
||||
2 files changed, 2 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/conf/example.conf.in b/conf/example.conf.in |
||||
index b1a2a9c..8e68165 100644 |
||||
--- a/conf/example.conf.in |
||||
+++ b/conf/example.conf.in |
||||
@@ -311,7 +311,7 @@ devices { |
||||
# or activating LVs in it while a PV appears on multiple devices. |
||||
# Enabling this setting allows the VG to be used as usual even with |
||||
# uncertain devices. |
||||
- allow_changes_with_duplicate_pvs = 0 |
||||
+ allow_changes_with_duplicate_pvs = 1 |
||||
} |
||||
|
||||
# Configuration section allocation. |
||||
diff --git a/lib/config/defaults.h b/lib/config/defaults.h |
||||
index d988779..985c832 100644 |
||||
--- a/lib/config/defaults.h |
||||
+++ b/lib/config/defaults.h |
||||
@@ -45,7 +45,7 @@ |
||||
#define DEFAULT_DATA_ALIGNMENT_DETECTION 1 |
||||
#define DEFAULT_ISSUE_DISCARDS 0 |
||||
#define DEFAULT_PV_MIN_SIZE_KB 2048 |
||||
-#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 0 |
||||
+#define DEFAULT_ALLOW_CHANGES_WITH_DUPLICATE_PVS 1 |
||||
|
||||
#define DEFAULT_LOCKING_LIB "liblvm2clusterlock.so" |
||||
#define DEFAULT_ERROR_WHEN_FULL 0 |
@ -0,0 +1,104 @@
@@ -0,0 +1,104 @@
|
||||
configure | 20 ++++++++++---------- |
||||
configure.in | 4 ++-- |
||||
lib/device/dev-type.c | 3 +-- |
||||
3 files changed, 13 insertions(+), 14 deletions(-) |
||||
|
||||
diff --git a/configure b/configure |
||||
index 8253bfc..587b978 100755 |
||||
--- a/configure |
||||
+++ b/configure |
||||
@@ -11951,12 +11951,12 @@ if test -n "$BLKID_CFLAGS"; then |
||||
pkg_cv_BLKID_CFLAGS="$BLKID_CFLAGS" |
||||
elif test -n "$PKG_CONFIG"; then |
||||
if test -n "$PKG_CONFIG" && \ |
||||
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.24\""; } >&5 |
||||
- ($PKG_CONFIG --exists --print-errors "blkid >= 2.24") 2>&5 |
||||
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.23\""; } >&5 |
||||
+ ($PKG_CONFIG --exists --print-errors "blkid >= 2.23") 2>&5 |
||||
ac_status=$? |
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 |
||||
test $ac_status = 0; }; then |
||||
- pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.24" 2>/dev/null` |
||||
+ pkg_cv_BLKID_CFLAGS=`$PKG_CONFIG --cflags "blkid >= 2.23" 2>/dev/null` |
||||
test "x$?" != "x0" && pkg_failed=yes |
||||
else |
||||
pkg_failed=yes |
||||
@@ -11968,12 +11968,12 @@ if test -n "$BLKID_LIBS"; then |
||||
pkg_cv_BLKID_LIBS="$BLKID_LIBS" |
||||
elif test -n "$PKG_CONFIG"; then |
||||
if test -n "$PKG_CONFIG" && \ |
||||
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.24\""; } >&5 |
||||
- ($PKG_CONFIG --exists --print-errors "blkid >= 2.24") 2>&5 |
||||
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"blkid >= 2.23\""; } >&5 |
||||
+ ($PKG_CONFIG --exists --print-errors "blkid >= 2.23") 2>&5 |
||||
ac_status=$? |
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 |
||||
test $ac_status = 0; }; then |
||||
- pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.24" 2>/dev/null` |
||||
+ pkg_cv_BLKID_LIBS=`$PKG_CONFIG --libs "blkid >= 2.23" 2>/dev/null` |
||||
test "x$?" != "x0" && pkg_failed=yes |
||||
else |
||||
pkg_failed=yes |
||||
@@ -11994,9 +11994,9 @@ else |
||||
_pkg_short_errors_supported=no |
||||
fi |
||||
if test $_pkg_short_errors_supported = yes; then |
||||
- BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.24" 2>&1` |
||||
+ BLKID_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "blkid >= 2.23" 2>&1` |
||||
else |
||||
- BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.24" 2>&1` |
||||
+ BLKID_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "blkid >= 2.23" 2>&1` |
||||
fi |
||||
# Put the nasty error message in config.log where it belongs |
||||
echo "$BLKID_PKG_ERRORS" >&5 |
||||
@@ -12004,7 +12004,7 @@ fi |
||||
if test "$BLKID_WIPING" = maybe; then |
||||
BLKID_WIPING=no |
||||
else |
||||
- as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5 |
||||
+ as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5 |
||||
fi |
||||
elif test $pkg_failed = untried; then |
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 |
||||
@@ -12012,7 +12012,7 @@ $as_echo "no" >&6; } |
||||
if test "$BLKID_WIPING" = maybe; then |
||||
BLKID_WIPING=no |
||||
else |
||||
- as_fn_error $? "bailing out... blkid library >= 2.24 is required" "$LINENO" 5 |
||||
+ as_fn_error $? "bailing out... blkid library >= 2.23 is required" "$LINENO" 5 |
||||
fi |
||||
else |
||||
BLKID_CFLAGS=$pkg_cv_BLKID_CFLAGS |
||||
diff --git a/configure.in b/configure.in |
||||
index 33b5c76..9ed6226 100644 |
||||
--- a/configure.in |
||||
+++ b/configure.in |
||||
@@ -1302,12 +1302,12 @@ AC_MSG_RESULT($BLKID_WIPING) |
||||
|
||||
if test "$BLKID_WIPING" != no; then |
||||
pkg_config_init |
||||
- PKG_CHECK_MODULES(BLKID, blkid >= 2.24, |
||||
+ PKG_CHECK_MODULES(BLKID, blkid >= 2.23, |
||||
[test "$BLKID_WIPING" = maybe && BLKID_WIPING=yes], |
||||
[if test "$BLKID_WIPING" = maybe; then |
||||
BLKID_WIPING=no |
||||
else |
||||
- AC_MSG_ERROR([bailing out... blkid library >= 2.24 is required]) |
||||
+ AC_MSG_ERROR([bailing out... blkid library >= 2.23 is required]) |
||||
fi]) |
||||
if test "$BLKID_WIPING" = yes; then |
||||
BLKID_PC="blkid" |
||||
diff --git a/lib/device/dev-type.c b/lib/device/dev-type.c |
||||
index 0246c09..bae984a 100644 |
||||
--- a/lib/device/dev-type.c |
||||
+++ b/lib/device/dev-type.c |
||||
@@ -703,8 +703,7 @@ static int _wipe_known_signatures_with_blkid(struct device *dev, const char *nam |
||||
BLKID_SUBLKS_TYPE | |
||||
BLKID_SUBLKS_USAGE | |
||||
BLKID_SUBLKS_VERSION | |
||||
- BLKID_SUBLKS_MAGIC | |
||||
- BLKID_SUBLKS_BADCSUM); |
||||
+ BLKID_SUBLKS_MAGIC); |
||||
|
||||
while (!blkid_do_probe(probe)) { |
||||
if ((r_wipe = _blkid_wipe(probe, dev, name, types_to_exclude, types_no_prompt, yes, force)) == 1) { |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
libdm/.exported_symbols.DM_1_02_107 | 1 + |
||||
libdm/.exported_symbols.DM_1_02_110 | 1 - |
||||
2 files changed, 1 insertion(+), 1 deletion(-) |
||||
|
||||
diff --git a/libdm/.exported_symbols.DM_1_02_107 b/libdm/.exported_symbols.DM_1_02_107 |
||||
index 89d3464..0c7b7af 100644 |
||||
--- a/libdm/.exported_symbols.DM_1_02_107 |
||||
+++ b/libdm/.exported_symbols.DM_1_02_107 |
||||
@@ -13,3 +13,4 @@ dm_stats_create_region |
||||
dm_stats_driver_supports_histogram |
||||
dm_stats_get_histogram |
||||
dm_stats_get_region_nr_histogram_bins |
||||
+dm_tree_node_size_changed |
||||
diff --git a/libdm/.exported_symbols.DM_1_02_110 b/libdm/.exported_symbols.DM_1_02_110 |
||||
index eba5625..da742ee 100644 |
||||
--- a/libdm/.exported_symbols.DM_1_02_110 |
||||
+++ b/libdm/.exported_symbols.DM_1_02_110 |
||||
@@ -1,3 +1,2 @@ |
||||
dm_report_compact_given_fields |
||||
dm_hold_control_dev |
||||
-dm_tree_node_size_changed |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
commit dc1c96b8bebbd6bfe9b774fdb13f904f976f29bd |
||||
Author: David Teigland <teigland@redhat.com> |
||||
Date: Thu Jul 2 13:45:38 2015 -0500 |
||||
|
||||
lvmlockd: tech preview notice |
||||
--- |
||||
tools/toollib.c | 7 +++++++ |
||||
1 file changed, 7 insertions(+) |
||||
|
||||
diff --git a/tools/toollib.c b/tools/toollib.c |
||||
index 6b8ce22..b8edaea 100644 |
||||
--- a/tools/toollib.c |
||||
+++ b/tools/toollib.c |
||||
@@ -981,6 +981,13 @@ int vgcreate_params_set_from_args(struct cmd_context *cmd, |
||||
vp_new->clustered = 0; |
||||
|
||||
log_debug("Setting lock_type to %s", vp_new->lock_type); |
||||
+ |
||||
+ if (is_lockd_type(vp_new->lock_type)) { |
||||
+ log_print("WARNING: shared lock type \"%s\" and lvmlockd are Technology Preview.", vp_new->lock_type); |
||||
+ log_print("For more information on Technology Preview features, visit:"); |
||||
+ log_print("https://access.redhat.com/support/offerings/techpreview/"); |
||||
+ } |
||||
+ |
||||
return 1; |
||||
} |
||||
|
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
udev/10-dm.rules.in | 4 ---- |
||||
1 file changed, 4 deletions(-) |
||||
|
||||
diff --git a/udev/10-dm.rules.in b/udev/10-dm.rules.in |
||||
index 2755530..8d7a8ca 100644 |
||||
--- a/udev/10-dm.rules.in |
||||
+++ b/udev/10-dm.rules.in |
||||
@@ -120,10 +120,6 @@ ENV{DM_UDEV_RULES_VSN}="2" |
||||
|
||||
ENV{DM_UDEV_DISABLE_DM_RULES_FLAG}!="1", ENV{DM_NAME}=="?*", SYMLINK+="(DM_DIR)/$env{DM_NAME}" |
||||
|
||||
-# We have to ignore further rule application for inappropriate events |
||||
-# and devices. But still send the notification if cookie exists. |
||||
-ENV{DM_UUID}=="mpath-?*", ENV{DM_ACTION}=="PATH_FAILED", GOTO="dm_disable" |
||||
- |
||||
# Avoid processing and scanning a DM device in the other (foreign) |
||||
# rules if it is in suspended state. However, we still keep 'disk' |
||||
# and 'DM subsystem' related rules enabled in this case. |
@ -0,0 +1,323 @@
@@ -0,0 +1,323 @@
|
||||
WHATS_NEW | 1 - |
||||
daemons/dmeventd/plugins/raid/dmeventd_raid.c | 42 +++-------- |
||||
lib/metadata/lv.c | 7 ++ |
||||
lib/metadata/raid_manip.c | 2 +- |
||||
test/shell/lvconvert-repair-raid.sh | 104 ++------------------------ |
||||
tools/lvconvert.c | 19 +++++ |
||||
6 files changed, 41 insertions(+), 134 deletions(-) |
||||
|
||||
diff --git a/WHATS_NEW b/WHATS_NEW |
||||
index 25f6742..977e578 100644 |
||||
--- a/WHATS_NEW |
||||
+++ b/WHATS_NEW |
||||
@@ -3,7 +3,6 @@ Version 2.02.166 - 26th September 2016 |
||||
Fix lvm2-activation-generator to read all LVM2 config sources. (2.02.155) |
||||
Fix lvchange-rebuild-raid.sh to cope with older target versions. |
||||
Use dm_config_parse_without_dup_node_check() to speedup metadata reading. |
||||
- Fix lvconvert --repair regression |
||||
Fix reported origin lv field for cache volumes. (2.02.133) |
||||
Always specify snapshot cow LV for monitoring not internal LV. (2.02.165) |
||||
Fix lvchange --discard|--zero for active thin-pool. |
||||
diff --git a/daemons/dmeventd/plugins/raid/dmeventd_raid.c b/daemons/dmeventd/plugins/raid/dmeventd_raid.c |
||||
index bec594a..770fbc6 100644 |
||||
--- a/daemons/dmeventd/plugins/raid/dmeventd_raid.c |
||||
+++ b/daemons/dmeventd/plugins/raid/dmeventd_raid.c |
||||
@@ -1,5 +1,5 @@ |
||||
/* |
||||
- * Copyright (C) 2005-2016 Red Hat, Inc. All rights reserved. |
||||
+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved. |
||||
* |
||||
* This file is part of LVM2. |
||||
* |
||||
@@ -13,20 +13,14 @@ |
||||
*/ |
||||
|
||||
#include "lib.h" |
||||
-#include "defaults.h" |
||||
#include "dmeventd_lvm.h" |
||||
#include "libdevmapper-event.h" |
||||
|
||||
-/* Hold enough elements for the mximum number of RAID images */ |
||||
-#define RAID_DEVS_ELEMS ((DEFAULT_RAID_MAX_IMAGES + 63) / 64) |
||||
- |
||||
struct dso_state { |
||||
struct dm_pool *mem; |
||||
char cmd_lvscan[512]; |
||||
char cmd_lvconvert[512]; |
||||
- uint64_t raid_devs[RAID_DEVS_ELEMS]; |
||||
int failed; |
||||
- int warned; |
||||
}; |
||||
|
||||
DM_EVENT_LOG_FN("raid") |
||||
@@ -37,39 +31,20 @@ static int _process_raid_event(struct dso_state *state, char *params, const char |
||||
{ |
||||
struct dm_status_raid *status; |
||||
const char *d; |
||||
- int dead = 0, r = 1; |
||||
|
||||
if (!dm_get_status_raid(state->mem, params, &status)) { |
||||
log_error("Failed to process status line for %s.", device); |
||||
return 0; |
||||
} |
||||
|
||||
- d = status->dev_health; |
||||
- while ((d = strchr(d, 'D'))) { |
||||
- uint32_t dev = (uint32_t)(d - status->dev_health); |
||||
- |
||||
- if (!(state->raid_devs[dev / 64] & (1 << (dev % 64)))) |
||||
- log_error("Device #%u of %s array, %s, has failed.", |
||||
- dev, status->raid_type, device); |
||||
- |
||||
- state->raid_devs[dev / 64] |= (1 << (dev % 64)); |
||||
- d++; |
||||
- dead = 1; |
||||
- } |
||||
- |
||||
- if (dead) { |
||||
- if (status->insync_regions < status->total_regions) { |
||||
- if (!state->warned) |
||||
- log_warn("WARNING: waiting for resynchronization to finish " |
||||
- "before initiating repair on RAID device %s", device); |
||||
- |
||||
- state->warned = 1; |
||||
- goto out; /* Not yet done syncing with accessible devices */ |
||||
- } |
||||
- |
||||
+ if ((d = strchr(status->dev_health, 'D'))) { |
||||
if (state->failed) |
||||
goto out; /* already reported */ |
||||
|
||||
+ log_error("Device #%d of %s array, %s, has failed.", |
||||
+ (int)(d - status->dev_health), |
||||
+ status->raid_type, device); |
||||
+ |
||||
state->failed = 1; |
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvscan)) |
||||
log_warn("WARNING: Re-scan of RAID device %s failed.", device); |
||||
@@ -77,7 +52,8 @@ static int _process_raid_event(struct dso_state *state, char *params, const char |
||||
/* if repair goes OK, report success even if lvscan has failed */ |
||||
if (!dmeventd_lvm2_run_with_lock(state->cmd_lvconvert)) { |
||||
log_info("Repair of RAID device %s failed.", device); |
||||
- r = 0; |
||||
+ dm_pool_free(state->mem, status); |
||||
+ return 0; |
||||
} |
||||
} else { |
||||
state->failed = 0; |
||||
@@ -88,7 +64,7 @@ static int _process_raid_event(struct dso_state *state, char *params, const char |
||||
out: |
||||
dm_pool_free(state->mem, status); |
||||
|
||||
- return r; |
||||
+ return 1; |
||||
} |
||||
|
||||
void process_event(struct dm_task *dmt, |
||||
diff --git a/lib/metadata/lv.c b/lib/metadata/lv.c |
||||
index 70036f9..53a1044 100644 |
||||
--- a/lib/metadata/lv.c |
||||
+++ b/lib/metadata/lv.c |
||||
@@ -988,6 +988,7 @@ int lv_mirror_image_in_sync(const struct logical_volume *lv) |
||||
int lv_raid_image_in_sync(const struct logical_volume *lv) |
||||
{ |
||||
unsigned s; |
||||
+ dm_percent_t percent; |
||||
char *raid_health; |
||||
struct lv_segment *seg, *raid_seg = NULL; |
||||
|
||||
@@ -1017,6 +1018,12 @@ int lv_raid_image_in_sync(const struct logical_volume *lv) |
||||
return 0; |
||||
} |
||||
|
||||
+ if (!lv_raid_percent(raid_seg->lv, &percent)) |
||||
+ return_0; |
||||
+ |
||||
+ if (percent == DM_PERCENT_100) |
||||
+ return 1; |
||||
+ |
||||
/* Find out which sub-LV this is. */ |
||||
for (s = 0; s < raid_seg->area_count; s++) |
||||
if (seg_lv(raid_seg, s) == lv) |
||||
diff --git a/lib/metadata/raid_manip.c b/lib/metadata/raid_manip.c |
||||
index deb88a2..e5fdf4f 100644 |
||||
--- a/lib/metadata/raid_manip.c |
||||
+++ b/lib/metadata/raid_manip.c |
||||
@@ -3658,7 +3658,7 @@ static int _lv_raid_rebuild_or_replace(struct logical_volume *lv, |
||||
return 0; |
||||
} |
||||
|
||||
- if (!_raid_in_sync(lv)) { |
||||
+ if (!mirror_in_sync() && !_raid_in_sync(lv)) { |
||||
log_error("Unable to replace devices in %s/%s while it is" |
||||
" not in-sync.", lv->vg->name, lv->name); |
||||
return 0; |
||||
diff --git a/test/shell/lvconvert-repair-raid.sh b/test/shell/lvconvert-repair-raid.sh |
||||
index b51d8fe..1ef91c4 100644 |
||||
--- a/test/shell/lvconvert-repair-raid.sh |
||||
+++ b/test/shell/lvconvert-repair-raid.sh |
||||
@@ -22,52 +22,11 @@ aux lvmconf 'allocation/maximise_cling = 0' \ |
||||
|
||||
aux prepare_vg 8 |
||||
|
||||
-function delay |
||||
-{ |
||||
- for d in $(< DEVICES) |
||||
- do |
||||
- aux delay_dev "$d" 0 $1 $(get first_extent_sector "$d") |
||||
- done |
||||
-} |
||||
- |
||||
# It's possible small raid arrays do have problems with reporting in-sync. |
||||
# So try bigger size |
||||
-RAID_SIZE=32 |
||||
- |
||||
-# Fast sync and repair afterwards |
||||
-delay 0 |
||||
- |
||||
-# RAID1 dual-leg single replace after initial sync |
||||
-lvcreate --type raid1 -m 1 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" |
||||
-aux wait_for_sync $vg $lv1 |
||||
-aux disable_dev "$dev2" |
||||
-lvconvert -y --repair $vg/$lv1 |
||||
-vgreduce --removemissing $vg |
||||
-aux enable_dev "$dev2" |
||||
-vgextend $vg "$dev2" |
||||
-lvremove -ff $vg/$lv1 |
||||
- |
||||
-# Delayed sync to allow for repair during rebuild |
||||
-delay 50 |
||||
- |
||||
-# RAID1 triple-leg single replace during initial sync |
||||
-lvcreate --type raid1 -m 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" |
||||
-aux disable_dev "$dev2" "$dev3" |
||||
-not lvconvert -y --repair $vg/$lv1 |
||||
-aux wait_for_sync $vg $lv1 |
||||
-lvconvert -y --repair $vg/$lv1 |
||||
-vgreduce --removemissing $vg |
||||
-aux enable_dev "$dev2" "$dev3" |
||||
-vgextend $vg "$dev2" "$dev3" |
||||
-lvremove -ff $vg/$lv1 |
||||
- |
||||
- |
||||
-# Larger RAID size possible for striped RAID |
||||
RAID_SIZE=64 |
||||
|
||||
-# Fast sync and repair afterwards |
||||
-delay 0 |
||||
-# RAID5 single replace after initial sync |
||||
+# RAID5 single replace |
||||
lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" |
||||
aux wait_for_sync $vg $lv1 |
||||
aux disable_dev "$dev3" |
||||
@@ -75,69 +34,16 @@ lvconvert -y --repair $vg/$lv1 |
||||
vgreduce --removemissing $vg |
||||
aux enable_dev "$dev3" |
||||
vgextend $vg "$dev3" |
||||
-lvremove -ff $vg/$lv1 |
||||
+lvremove -ff $vg |
||||
|
||||
-# Delayed sync to allow for repair during rebuild |
||||
-delay 50 |
||||
- |
||||
-# RAID5 single replace during initial sync |
||||
-lvcreate --type raid5 -i 2 -L $RAID_SIZE -n $lv1 $vg "$dev1" "$dev2" "$dev3" |
||||
-aux disable_dev "$dev3" |
||||
-not lvconvert -y --repair $vg/$lv1 |
||||
-aux wait_for_sync $vg $lv1 |
||||
-lvconvert -y --repair $vg/$lv1 |
||||
-vgreduce --removemissing $vg |
||||
-aux enable_dev "$dev3" |
||||
-vgextend $vg "$dev3" |
||||
-lvremove -ff $vg/$lv1 |
||||
- |
||||
-# Fast sync and repair afterwards |
||||
-delay 0 |
||||
- |
||||
-# RAID6 double replace after initial sync |
||||
+# RAID6 double replace |
||||
lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \ |
||||
"$dev1" "$dev2" "$dev3" "$dev4" "$dev5" |
||||
aux wait_for_sync $vg $lv1 |
||||
aux disable_dev "$dev4" "$dev5" |
||||
lvconvert -y --repair $vg/$lv1 |
||||
vgreduce --removemissing $vg |
||||
-aux enable_dev "$dev4" "$dev5" |
||||
-vgextend $vg "$dev4" "$dev5" |
||||
-lvremove -ff $vg/$lv1 |
||||
- |
||||
-# Delayed sync to allow for repair during rebuild |
||||
-delay 50 |
||||
- |
||||
-# RAID6 single replace after initial sync |
||||
-lvcreate --type raid6 -i 3 -L $RAID_SIZE -n $lv1 $vg \ |
||||
- "$dev1" "$dev2" "$dev3" "$dev4" "$dev5" |
||||
-aux disable_dev "$dev4" |
||||
-not lvconvert -y --repair $vg/$lv1 |
||||
-delay 0 # Fast sync and repair afterwards |
||||
-aux disable_dev "$dev4" # Need to disable again after changing delay |
||||
-aux wait_for_sync $vg $lv1 |
||||
-lvconvert -y --repair $vg/$lv1 |
||||
-vgreduce --removemissing $vg |
||||
aux enable_dev "$dev4" |
||||
-vgextend $vg "$dev4" |
||||
-lvremove -ff $vg/$lv1 |
||||
- |
||||
-# Delayed sync to allow for repair during rebuild |
||||
-delay 50 |
||||
- |
||||
-# RAID10 single replace after initial sync |
||||
-lvcreate --type raid10 -m 1 -i 2 -L $RAID_SIZE -n $lv1 $vg \ |
||||
- "$dev1" "$dev2" "$dev3" "$dev4" |
||||
-aux disable_dev "$dev4" |
||||
-not lvconvert -y --repair $vg/$lv1 |
||||
-delay 0 # Fast sync and repair afterwards |
||||
-aux disable_dev "$dev4" # Need to disable again after changing delay |
||||
-aux disable_dev "$dev1" |
||||
-aux wait_for_sync $vg $lv1 |
||||
-lvconvert -y --repair $vg/$lv1 |
||||
-vgreduce --removemissing $vg |
||||
-aux enable_dev "$dev4" |
||||
-vgextend $vg "$dev4" |
||||
-lvremove -ff $vg/$lv1 |
||||
- |
||||
+aux enable_dev "$dev5" |
||||
+vgextend $vg "$dev4" "$dev5" |
||||
vgremove -ff $vg |
||||
diff --git a/tools/lvconvert.c b/tools/lvconvert.c |
||||
index 3607247..d1d21b6 100644 |
||||
--- a/tools/lvconvert.c |
||||
+++ b/tools/lvconvert.c |
||||
@@ -1826,6 +1826,7 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
struct dm_list *failed_pvs; |
||||
struct cmd_context *cmd = lv->vg->cmd; |
||||
struct lv_segment *seg = first_seg(lv); |
||||
+ dm_percent_t sync_percent; |
||||
|
||||
if (_linear_type_requested(lp->type_str)) { |
||||
if (arg_is_set(cmd, mirrors_ARG) && (arg_uint_value(cmd, mirrors_ARG, 0) != 0)) { |
||||
@@ -1973,6 +1974,24 @@ static int _lvconvert_raid(struct logical_volume *lv, struct lvconvert_params *l |
||||
return 0; |
||||
} |
||||
|
||||
+ if (!lv_raid_percent(lv, &sync_percent)) { |
||||
+ log_error("Unable to determine sync status of %s.", |
||||
+ display_lvname(lv)); |
||||
+ return 0; |
||||
+ } |
||||
+ |
||||
+ if (sync_percent != DM_PERCENT_100) { |
||||
+ log_warn("WARNING: %s is not in-sync.", display_lvname(lv)); |
||||
+ log_warn("WARNING: Portions of the array may be unrecoverable."); |
||||
+ |
||||
+ /* |
||||
+ * The kernel will not allow a device to be replaced |
||||
+ * in an array that is not in-sync unless we override |
||||
+ * by forcing the array to be considered "in-sync". |
||||
+ */ |
||||
+ init_mirror_in_sync(1); |
||||
+ } |
||||
+ |
||||
_lvconvert_raid_repair_ask(cmd, lp, &replace); |
||||
|
||||
if (replace) { |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
VERSION | 2 +- |
||||
VERSION_DM | 2 +- |
||||
2 files changed, 2 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/VERSION b/VERSION |
||||
index dd4e60e..39d6c15 100644 |
||||
--- a/VERSION |
||||
+++ b/VERSION |
||||
@@ -1 +1 @@ |
||||
-2.02.166(2) (2016-09-26) |
||||
+2.02.166(2)-RHEL7 (2016-11-16) |
||||
diff --git a/VERSION_DM b/VERSION_DM |
||||
index d53f47a..005fbd4 100644 |
||||
--- a/VERSION_DM |
||||
+++ b/VERSION_DM |
||||
@@ -1 +1 @@ |
||||
-1.02.135 (2016-09-26) |
||||
+1.02.135-RHEL7 (2016-11-16) |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
conf/example.conf.in | 2 +- |
||||
lib/config/config_settings.h | 2 +- |
||||
2 files changed, 2 insertions(+), 2 deletions(-) |
||||
|
||||
diff --git a/conf/example.conf.in b/conf/example.conf.in |
||||
index c0afcb7..ec12918 100644 |
||||
--- a/conf/example.conf.in |
||||
+++ b/conf/example.conf.in |
||||
@@ -106,7 +106,7 @@ devices { |
||||
# Example |
||||
# preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] |
||||
# |
||||
- # This configuration option does not have a default value defined. |
||||
+ preferred_names = [ "^/dev/mpath/", "^/dev/mapper/mpath", "^/dev/[hs]d" ] |
||||
|
||||
# Configuration option devices/filter. |
||||
# Limit the block devices that are used by LVM commands. |
||||
diff --git a/lib/config/config_settings.h b/lib/config/config_settings.h |
||||
index 9017043..c06b6f0 100644 |
||||
--- a/lib/config/config_settings.h |
||||
+++ b/lib/config/config_settings.h |
||||
@@ -205,7 +205,7 @@ cfg(devices_external_device_info_source_CFG, "external_device_info_source", devi |
||||
" compiled with udev support.\n" |
||||
"#\n") |
||||
|
||||
-cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY | CFG_DEFAULT_UNDEFINED , CFG_TYPE_STRING, NULL, vsn(1, 2, 19), NULL, 0, NULL, |
||||
+cfg_array(devices_preferred_names_CFG, "preferred_names", devices_CFG_SECTION, CFG_ALLOW_EMPTY, CFG_TYPE_STRING, "#S^/dev/mpath/#S^/dev/mapper/mpath#S^/dev/[hs]d", vsn(1, 2, 19), NULL, 0, NULL, |
||||
"Select which path name to display for a block device.\n" |
||||
"If multiple path names exist for a block device, and LVM needs to\n" |
||||
"display a name for the device, the path names are matched against\n" |
Loading…
Reference in new issue