basebuilder_pel7ppc64bebuilder0
7 years ago
30 changed files with 8997 additions and 0 deletions
@ -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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
@@ -, +, @@ |
||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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 @@ |
|||||||
|
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