summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2020-02-28 12:00:23 -0600
committerDavid Teigland <teigland@redhat.com>2020-03-03 13:47:07 -0600
commitc6746181a3c2c40447f5a33e15359b57567f8217 (patch)
treee7884b10b1a3be93b30f2f5eabe852cbef1414aa
parent1b79673845496402d9614784e8b08dbd284328ae (diff)
downloadlvm2-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.c199
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);
}