diff options
author | David Teigland <teigland@redhat.com> | 2020-02-28 12:00:23 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2020-03-03 13:47:07 -0600 |
commit | c6746181a3c2c40447f5a33e15359b57567f8217 (patch) | |
tree | e7884b10b1a3be93b30f2f5eabe852cbef1414aa | |
parent | 1b79673845496402d9614784e8b08dbd284328ae (diff) | |
download | lvm2-c6746181a3c2c40447f5a33e15359b57567f8217.tar.gz |
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.
-rw-r--r-- | tools/pvck.c | 199 |
1 files changed, 182 insertions, 17 deletions
diff --git a/tools/pvck.c b/tools/pvck.c index 745f0f945..ab8553796 100644 --- a/tools/pvck.c +++ b/tools/pvck.c @@ -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) { - mda_offset = set->mda_offset; - mda_size = set->mda_size; + + /* + * 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 + + 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; + } - if ((mda_num == 1) && (mda1_offset != mda_offset)) { + 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); } |