1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

pvck: improve mda_offset mda_size choices

Attempt to calculate an offset or size if one only
value was specified in the settings.

Use header values when available.
This commit is contained in:
David Teigland 2020-02-28 12:00:23 -06:00
parent 1b79673845
commit c6746181a3

View File

@ -20,6 +20,8 @@
#include "lib/mm/xlate.h"
#include "lib/misc/crc.h"
#define ONE_MB_IN_BYTES 1048576
#define PRINT_CURRENT 1
#define PRINT_ALL 2
@ -297,6 +299,49 @@ static void _copy_line(char *in, char *out, int *len, int linesize)
*len = i+1;
}
static uint64_t mda2_offset_from_size(struct device *dev, uint64_t mda2_size)
{
uint64_t dev_sectors = 0;
uint64_t dev_bytes;
uint64_t extra_bytes;
uint64_t mda2_offset;
if (dev_get_size(dev, &dev_sectors))
stack;
dev_bytes = dev_sectors * 512;
extra_bytes = dev_bytes % ONE_MB_IN_BYTES;
if (dev_bytes < (2 * ONE_MB_IN_BYTES))
return_0;
mda2_offset = dev_bytes - extra_bytes - mda2_size;
return mda2_offset;
}
static uint64_t mda2_size_from_offset(struct device *dev, uint64_t mda2_offset)
{
uint64_t dev_sectors = 0;
uint64_t dev_bytes;
uint64_t extra_bytes;
uint64_t mda2_size;
if (dev_get_size(dev, &dev_sectors))
stack;
dev_bytes = dev_sectors * 512;
extra_bytes = dev_bytes % ONE_MB_IN_BYTES;
if (dev_bytes < (2 * ONE_MB_IN_BYTES))
return_0;
mda2_size = dev_bytes - extra_bytes - mda2_offset;
return mda2_size;
}
/* all sizes and offsets in bytes */
static int _dump_all_text(struct cmd_context *cmd, struct settings *set, const char *tofile, struct device *dev,
@ -1419,8 +1464,6 @@ static int _dump_found(struct cmd_context *cmd, struct settings *set, uint64_t l
return 1;
}
#define ONE_MB_IN_BYTES 1048576
/*
* all sizes and offsets in bytes (except dev_sectors from dev_get_size)
*
@ -1435,21 +1478,18 @@ static int _dump_search(struct cmd_context *cmd, const char *dump, struct settin
const char *tofile = NULL;
char *buf;
uint64_t mda1_offset = 0, mda1_size = 0, mda2_offset = 0, mda2_size = 0; /* bytes */
uint64_t mda_offset, mda_size; /* bytes */
uint64_t mda_offset = 0, mda_size = 0; /* bytes */
int mda_num = 0;
int found_label = 0;
int mda_count = 0;
int mda_num = 1;
int set_vals = 0;
if (arg_is_set(cmd, file_ARG)) {
if (!(tofile = arg_str_value(cmd, file_ARG, NULL)))
return_0;
}
if (set->mda_num)
mda_num = set->mda_num;
else if (arg_is_set(cmd, pvmetadatacopies_ARG))
mda_num = arg_int_value(cmd, pvmetadatacopies_ARG, 1);
_dump_label_and_pv_header(cmd, labelsector, dev, 0, NULL,
_dump_label_and_pv_header(cmd, labelsector, dev, 0, &found_label,
&mda1_offset, &mda1_size, &mda2_offset, &mda2_size, &mda_count);
/*
@ -1470,13 +1510,131 @@ static int _dump_search(struct cmd_context *cmd, const char *dump, struct settin
* at the end of device (mod 1MB extra) can make mda2 even
* larger.
*/
if (set->mda_offset_set && set->mda_size_set) {
/*
* When mda offset or size is set in command line settings,
* use what is set and calculate an unspecified value.
*/
if (set->mda_offset_set || set->mda_size_set) {
if (set->mda_offset_set) {
mda_offset = set->mda_offset;
set_vals++;
}
if (set->mda_size_set) {
mda_size = set->mda_size;
set_vals++;
}
if ((mda_num = set->mda_num))
set_vals++;
if (mda_offset && mda_size)
goto search;
if (set_vals < 2) {
log_error("Specify at least two values from: mda_num, mda_offset, mda_size.");
return 0;
}
if (!mda_size) {
if ((mda_num == 1) && mda1_size)
mda_size = mda1_size; /* from headers */
else if ((mda_num == 2) && mda2_size)
mda_size = mda2_size; /* from headers */
else if (mda_num == 1)
mda_size = ONE_MB_IN_BYTES - 4096;
else if (mda_num == 2)
mda_size = mda2_size_from_offset(dev, mda_offset);
}
if (!mda_offset) {
if (mda_num == 1)
mda_offset = 4096;
else if (mda_num == 2)
mda_offset = mda2_offset_from_size(dev, mda_size);
}
if (set->mda2_offset_set || set->mda2_size_set)
log_print("Ignoring mda2 values from settings.");
goto search;
}
if (set->mda2_offset_set || set->mda2_size_set) {
if (set->mda2_offset_set) {
mda_offset = set->mda2_offset;
set_vals++;
}
if (set->mda_size_set) {
mda_size = set->mda2_size;
set_vals++;
}
if ((mda_num = set->mda_num))
set_vals++;
if (mda_offset && mda_size)
goto search;
if (set_vals < 2) {
log_error("Specify at least two values from: mda_num, mda2_offset, mda2_size.");
return 0;
}
if (mda_num == 1) {
log_error("Invalid mda_num=1 and mda2 settings.");
return 0;
}
if (!mda_size) {
if (mda2_size)
mda_size = mda2_size; /* from headers */
else
mda_size = mda2_size_from_offset(dev, mda_offset);
}
if (!mda_offset) {
if (mda2_offset)
mda_offset = mda2_offset; /* from headers */
else
mda_offset = mda2_offset_from_size(dev, mda_size);
}
goto search;
}
/*
* When no mda offset or size is set in command line settings,
* the user can just set mda_num=1|2 to control if we pick defaults
* for mda1 or mda2. If unspecified, we search in the first mda.
*/
if (set->mda_num)
mda_num = set->mda_num;
else if (arg_is_set(cmd, pvmetadatacopies_ARG))
mda_num = arg_int_value(cmd, pvmetadatacopies_ARG, 1);
else
mda_num = 1;
/*
* No mda offset or size was set in command line settings,
* so we use what's in the headers or defaults.
*/
if ((mda_num == 1) && found_label && mda1_offset && mda1_size) {
/* use header values when available */
mda_offset = 4096;
mda_size = mda1_size;
} else if (mda_num == 1) {
/* use default values when header values are not available */
mda_offset = 4096;
mda_size = ONE_MB_IN_BYTES - 4096;
log_print("Using common defaults for first mda: offset %llu size %llu.",
(unsigned long long)mda_offset, (unsigned long long)mda_size);
log_print("Override defaults with --settings \"mda_offset=<bytes> mda_size=<bytes>\"");
} else if ((mda_num == 2) && found_label && mda2_offset && mda2_size) {
/* use header values when available */
mda_offset = mda2_offset;
mda_size = mda2_size;
} else if (mda_num == 2) {
/* use default values when header values are not available */
uint64_t dev_sectors = 0;
uint64_t dev_bytes;
uint64_t extra_bytes;
@ -1492,17 +1650,24 @@ static int _dump_search(struct cmd_context *cmd, const char *dump, struct settin
mda_offset = dev_bytes - extra_bytes - ONE_MB_IN_BYTES;
mda_size = dev_bytes - mda_offset;
} else
return_0;
if ((mda_num == 1) && (mda1_offset != mda_offset)) {
log_print("Using defaults for second mda: offset %llu size %llu.",
(unsigned long long)mda_offset, (unsigned long long)mda_size);
log_print("Override defaults with --settings \"mda_offset=<bytes> mda_size=<bytes>\"");
} else {
log_error("No mda location.");
return_0;
}
search:
if ((mda_num == 1) && ((mda1_offset && mda1_offset != mda_offset) || (mda1_size && mda1_size != mda_size))) {
log_print("Ignoring mda1_offset %llu mda1_size %llu from pv_header.",
(unsigned long long)mda1_offset,
(unsigned long long)mda1_size);
}
if ((mda_num == 2) && (mda2_offset != mda_offset)) {
log_print("Ignoring mda2_size %llu mda2_offset %llu from pv_header.",
if ((mda_num == 2) && ((mda2_offset && mda2_offset != mda_offset) || (mda2_size && mda2_size != mda_size))) {
log_print("Ignoring mda2_offset %llu mda2_size %llu from pv_header.",
(unsigned long long)mda2_offset,
(unsigned long long)mda2_size);
}