master - cache: use _cpool for used cache-pools
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=dd7629ea090d4e55de0...
Commit: dd7629ea090d4e55de057b772e9eb9470a49e05b
Parent: 23f660cf98fd966525672309ee821348edebd014
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Oct 21 12:03:19 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Oct 21 15:31:33 2019 +0200
cache: use _cpool for used cache-pools
When LV gets cached and uses cache-pool - such cache-pool
will now get _cpool suffix automatically.
Thus 'Pool' column for cached LV will now show either _cvol
or _cpool LV.
---
WHATS_NEW | 1 +
lib/metadata/cache_manip.c | 12 ++++++++++++
tools/lvconvert.c | 12 ++++++------
3 files changed, 19 insertions(+), 6 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index d6e4c9a..001a12b 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.03.06 -
================================
+ Add _cpool suffix to cache-pool LV name when used by caching LV.
No longer store extra UUID for cmeta and cdata cachevol layer.
Enhance activation of cache devices with cachevols.
Add _cvol in list of protected suffixes and start use it with DM UUID.
diff --git a/lib/metadata/cache_manip.c b/lib/metadata/cache_manip.c
index 5275d24..c20cc49 100644
--- a/lib/metadata/cache_manip.c
+++ b/lib/metadata/cache_manip.c
@@ -430,6 +430,7 @@ int validate_cache_chunk_size(struct cmd_context *cmd, uint32_t chunk_size)
struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
struct logical_volume *origin_lv)
{
+ char cpool_name[NAME_LEN];
const struct segment_type *segtype;
struct cmd_context *cmd = pool_lv->vg->cmd;
struct logical_volume *cache_lv = origin_lv;
@@ -454,6 +455,17 @@ struct logical_volume *lv_cache_create(struct logical_volume *pool_lv,
if (!attach_pool_lv(seg, pool_lv, NULL, NULL, NULL))
return_NULL;
+ if (lv_is_cache_pool(pool_lv)) {
+ /* Used cache-pool gets _cpool suffix (easy to recognize from _cvol usage) */
+ if (dm_snprintf(cpool_name, sizeof(cpool_name), "%s_cpool", pool_lv->name) < 0) {
+ log_error("Can't prepare new cachepool name for %s.", display_lvname(pool_lv));
+ return NULL;
+ }
+
+ if (!lv_rename_update(cmd, pool_lv, cpool_name, 0))
+ return_NULL;
+ }
+
if (!seg->lv->profile) /* Inherit profile from cache-pool */
seg->lv->profile = seg->pool_lv->profile;
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 9159f57..e033e71 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -4287,6 +4287,7 @@ static int _lvconvert_cachepool_attach_single(struct cmd_context *cmd,
struct logical_volume *lv,
struct processing_handle *handle)
{
+ struct lv_segment *seg;
struct volume_group *vg = lv->vg;
struct logical_volume *cachepool_lv;
const char *cachepool_name;
@@ -4333,15 +4334,14 @@ static int _lvconvert_cachepool_attach_single(struct cmd_context *cmd,
goto out;
}
- if (!(cachepool_lv = find_lv(vg, cachepool_name))) {
- log_error("LV %s cannot be found.", display_lvname(cachepool_lv));
+ /* cachepool_lv is converted into cache-pool data LV */
+ if (!(seg = get_only_segment_using_this_lv(cachepool_lv))) {
+ log_error(INTERNAL_ERROR "LV %s is not a cache pool data volume.",
+ display_lvname(cachepool_lv));
goto out;
}
- if (!lv_is_cache_pool(cachepool_lv)) {
- log_error("LV %s is not a cache pool.", display_lvname(cachepool_lv));
- goto out;
- }
+ cachepool_lv = seg->lv;
} else {
if (!dm_list_empty(&cachepool_lv->segs_using_this_lv)) {
log_error("Cache pool %s is already in use.", cachepool_name);
4 years, 7 months
master - cache: drop _cpool suffix from unused cache-pool
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=23f660cf98fd9665256...
Commit: 23f660cf98fd966525672309ee821348edebd014
Parent: a5f8e7a96cd26afd14a8ddc6ab1a64a32dcf6fc6
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Oct 21 09:22:32 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Oct 21 12:14:15 2019 +0200
cache: drop _cpool suffix from unused cache-pool
Drop _cpool prefix if present and cache-pool is going to be unused.
---
tools/lvconvert.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index 8b5bf51..9159f57 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1913,6 +1913,8 @@ static int _lvconvert_split_and_keep_cachepool(struct cmd_context *cmd,
struct logical_volume *lv,
struct logical_volume *lv_fast)
{
+ char name[NAME_LEN];
+
if (!archive(lv->vg))
return_0;
@@ -1926,6 +1928,14 @@ static int _lvconvert_split_and_keep_cachepool(struct cmd_context *cmd,
if (!lv_cache_remove(lv))
return_0;
+ /* Cut off suffix _cpool */
+ if (!drop_lvname_suffix(name, lv_fast->name, "cpool")) {
+ /* likely older instance of metadata */
+ log_debug("LV %s has no suffix for cachepool (skipping rename).",
+ display_lvname(lv_fast));
+ } else if (!lv_uniq_rename_update(cmd, lv_fast, name, 0))
+ return_0;
+
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
return_0;
4 years, 7 months
master - lvconvert: use new functions
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=a5f8e7a96cd26afd14a...
Commit: a5f8e7a96cd26afd14a8ddc6ab1a64a32dcf6fc6
Parent: 766dedb62899f764ef75f21b17b86c0f17f9d009
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Oct 21 09:18:34 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Oct 21 12:14:15 2019 +0200
lvconvert: use new functions
---
tools/lvconvert.c | 18 +++---------------
1 files changed, 3 insertions(+), 15 deletions(-)
diff --git a/tools/lvconvert.c b/tools/lvconvert.c
index a21f965..8b5bf51 100644
--- a/tools/lvconvert.c
+++ b/tools/lvconvert.c
@@ -1841,7 +1841,6 @@ static int _lvconvert_split_and_keep_cachevol(struct cmd_context *cmd,
struct logical_volume *lv_fast)
{
char cvol_name[NAME_LEN];
- char *c;
struct lv_segment *cache_seg = first_seg(lv);
int cache_mode = cache_seg->cache_mode;
@@ -1882,23 +1881,12 @@ static int _lvconvert_split_and_keep_cachevol(struct cmd_context *cmd,
return_0;
/* Cut off suffix _cvol */
- if (!dm_strncpy(cvol_name, lv_fast->name, sizeof(cvol_name)) ||
- !(c = strstr(cvol_name, "_cvol"))) {
+ if (!drop_lvname_suffix(cvol_name, lv_fast->name, "cvol")) {
/* likely older instance of metadata */
log_debug("LV %s has no suffix for cachevol (skipping rename).",
display_lvname(lv_fast));
- } else {
- *c = 0;
- /* If the name is in use, generate new lvol%d */
- if (lv_name_is_used_in_vg(lv->vg, cvol_name, NULL) &&
- !generate_lv_name(lv->vg, "lvol%d", cvol_name, sizeof(cvol_name))) {
- log_error("Failed to generate unique name for unused logical volume.");
- return 0;
- }
-
- if (!lv_rename_update(cmd, lv_fast, cvol_name, 0))
- return_0;
- }
+ } else if (!lv_uniq_rename_update(cmd, lv_fast, cvol_name, 0))
+ return_0;
if (!vg_write(lv->vg) || !vg_commit(lv->vg))
return_0;
4 years, 7 months
master - lvm-string: add drop_lvname_suffix
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=766dedb62899f764ef7...
Commit: 766dedb62899f764ef75f21b17b86c0f17f9d009
Parent: 2266a1863f048899dc6f54c4d62ae05b33605349
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Oct 21 09:17:57 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Oct 21 12:14:15 2019 +0200
lvm-string: add drop_lvname_suffix
Internal function to drop suffix out of lvname.
---
lib/misc/lvm-string.c | 24 ++++++++++++++++++++++++
lib/misc/lvm-string.h | 1 +
2 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c
index 4034b40..d96d431 100644
--- a/lib/misc/lvm-string.c
+++ b/lib/misc/lvm-string.c
@@ -290,3 +290,27 @@ char *first_substring(const char *str, ...)
return r;
}
+
+/* Cut suffix (if present) and write the name into NAME_LEN sized new_name buffer
+ * When suffix is NULL, everythin past the last '_' is removed.
+ * Returns 1 when suffix was removed, 0 otherwise.
+ */
+int drop_lvname_suffix(char *new_name, const char *name, const char *suffix)
+{
+ char *c;
+
+ if (!dm_strncpy(new_name, name, NAME_LEN)) {
+ log_debug(INTERNAL_ERROR "Name is too long.");
+ return 0;
+ }
+
+ if (!(c = strrchr(new_name, '_')))
+ return 0;
+
+ if (suffix && strcmp(c + 1, suffix))
+ return 0;
+
+ *c = 0; /* remove suffix */
+
+ return 1;
+}
diff --git a/lib/misc/lvm-string.h b/lib/misc/lvm-string.h
index 4e7404a..5d2f95a 100644
--- a/lib/misc/lvm-string.h
+++ b/lib/misc/lvm-string.h
@@ -57,5 +57,6 @@ int is_reserved_lvname(const char *name);
* first match or else NULL.
*/
char *first_substring(const char *str, ...);
+int drop_lvname_suffix(char *new_name, const char *name, const char *suffix);
#endif
4 years, 7 months
master - lv_manip: add lv_uniq_rename_update
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=2266a1863f048899dc6...
Commit: 2266a1863f048899dc6f54c4d62ae05b33605349
Parent: 5714c8c9cc12d9442ad9ee85fb73a8ae49d6b548
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Mon Oct 21 09:16:45 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Mon Oct 21 12:14:15 2019 +0200
lv_manip: add lv_uniq_rename_update
Add function to rename LV to either passed name or if
the name is already in use, generate new lvol% name.
---
lib/metadata/lv_manip.c | 24 ++++++++++++++++++++++++
lib/metadata/metadata-exported.h | 2 ++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index 815ea99..ae103d3 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -4626,6 +4626,30 @@ int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
}
/*
+ * Rename LV to new name, if name is occupies, lvol% is generated.
+ * VG must be locked by caller.
+ */
+int lv_uniq_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
+ const char *new_name, int update_mda)
+{
+ char uniq_name[NAME_LEN];
+
+ /* If the name is in use, generate new lvol%d */
+ if (lv_name_is_used_in_vg(lv->vg, new_name, NULL)) {
+ if (!generate_lv_name(lv->vg, "lvol%d", uniq_name, sizeof(uniq_name))) {
+ log_error("Failed to generate unique name for unused logical volume.");
+ return 0;
+ }
+ new_name = uniq_name;
+ }
+
+ if (!lv_rename_update(cmd, lv, new_name, 0))
+ return_0;
+
+ return 1;
+}
+
+/*
* Core of LV renaming routine.
* VG must be locked by caller.
*/
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index f340093..c61c85c 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -845,6 +845,8 @@ int lv_rename(struct cmd_context *cmd, struct logical_volume *lv,
const char *new_name);
int lv_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
const char *new_name, int update_mda);
+int lv_uniq_rename_update(struct cmd_context *cmd, struct logical_volume *lv,
+ const char *new_name, int update_mda);
/* Updates and reloads metadata for given lv */
int lv_update_and_reload(struct logical_volume *lv);
4 years, 7 months
master - pvck: dump metadata search
by David Teigland
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=5714c8c9cc12d9442ad...
Commit: 5714c8c9cc12d9442ad9ee85fb73a8ae49d6b548
Parent: 4f860f79ff7c5bb35520776f5906ae51442d5920
Author: David Teigland <teigland(a)redhat.com>
AuthorDate: Thu Oct 17 17:24:22 2019 -0500
Committer: David Teigland <teigland(a)redhat.com>
CommitterDate: Fri Oct 18 12:26:29 2019 -0500
pvck: dump metadata search
Improve the implementation of extracting all text metadata
copies from the metadata area. Use this for the existing
metadata_all dump option.
Add a new metadata_search dump option which does not use
lvm headers to find metadata, but looks in standard
locations. This is useful if headers are damaged and
can't be used to locate metadata.
Adding '-v' to metadata_all or metadata_search will add
the description and creation_time to the printed list of
metadata instances that are found.
---
test/shell/pvck-dump.sh | 8 +-
tools/pvck.c | 845 +++++++++++++++++++++++++++++------------------
2 files changed, 534 insertions(+), 319 deletions(-)
diff --git a/test/shell/pvck-dump.sh b/test/shell/pvck-dump.sh
index 542fb49..17faa17 100644
--- a/test/shell/pvck-dump.sh
+++ b/test/shell/pvck-dump.sh
@@ -105,10 +105,10 @@ pvck --dump metadata_all --pvmetadatacopies 2 -f all3b "$dev3" > out3b
diff out1 out2
diff out1 out3
-grep "seqno 1 with" out1
-grep "seqno 1 with" out3b
-grep "seqno 2 with" out1
-grep "seqno 2 with" out3b
+grep "seqno 1" out1
+grep "seqno 1" out3b
+grep "seqno 2" out1
+grep "seqno 2" out3b
diff all1 all2
diff all1 all3
diff --git a/tools/pvck.c b/tools/pvck.c
index 2b5e63b..231faf9 100644
--- a/tools/pvck.c
+++ b/tools/pvck.c
@@ -20,6 +20,9 @@
#include "lib/mm/xlate.h"
#include "lib/misc/crc.h"
+#define PRINT_CURRENT 1
+#define PRINT_ALL 2
+
static char *_chars_to_str(void *in, void *out, int num, int max, const char *field)
{
char *i = in;
@@ -83,6 +86,374 @@ static char *_chars_to_hexstr(void *in, void *out, int num, int max, const char
return out;
}
+static int _check_vgname_start(char *buf, int *len)
+{
+ int chars = 0;
+ int space = 0;
+ int i;
+ char c;
+
+ /*
+ * Valid metadata begins: 'vgname {'
+ */
+ for (i = 0; i <= NAME_LEN + 2; i++) {
+ c = buf[i];
+
+ if (isalnum(c) || c == '.' || c == '_' || c == '-' || c == '+') {
+ if (space)
+ return 0;
+ chars++;
+ continue;
+ }
+
+ if (c == ' ') {
+ if (!chars || space)
+ return 0;
+ space++;
+ continue;
+ }
+
+ if (c == '{') {
+ if (chars && space) {
+ *len = chars;
+ return 1;
+ }
+ return 0;
+ }
+
+ return 0;
+ }
+ return 0;
+}
+
+static void _copy_out_metadata(char *buf, uint32_t start, uint32_t first_start, uint64_t mda_size, char **meta_buf, uint64_t *meta_size, int *bad_end)
+{
+ char *new_buf;
+ uint64_t i;
+ uint64_t new_len;
+ uint64_t len_a = 0, len_b = 0;
+ uint32_t stop;
+ int found_end;
+
+ /*
+ * If we wrap around the buffer searching for the
+ * end of some metadata, either stop when we reach
+ * where we began (start), or stop where we found
+ * the first copy of metadata (first_start).
+ */
+ if (!first_start)
+ stop = start;
+ else
+ stop = first_start;
+
+ found_end = 0;
+ for (i = start; i < mda_size; i++) {
+ if (buf[i] == '\0') {
+ found_end = 1;
+ break;
+ }
+ }
+
+ if (found_end) {
+ new_len = i - start;
+ } else {
+ len_a = i - start;
+
+ found_end = 0;
+ for (i = 512; i < stop; i++) {
+ if (buf[i] == '\0') {
+ found_end = 1;
+ break;
+ }
+ }
+
+ if (!found_end)
+ return;
+
+ len_b = i - 512;
+ new_len = len_a + len_b;
+ }
+
+ if (new_len < 256) {
+ log_print("skip invalid metadata with len %llu at %llu",
+ (unsigned long long)new_len, (unsigned long long)start);
+ return;
+ }
+
+ /* terminating 0 byte */
+ new_len++;
+
+ if (!(new_buf = malloc(new_len)))
+ return;
+
+ memset(new_buf, 0, new_len);
+
+ if (len_a) {
+ memcpy(new_buf, buf+start, len_a);
+ memcpy(new_buf+len_a, buf+512, len_b);
+ } else {
+ memcpy(new_buf, buf+start, new_len);
+ }
+
+ /* \0 should be preceded by \n\n (0x0a0a) */
+ if (new_buf[new_len-1] != 0 || new_buf[new_len-2] != 0x0a || new_buf[new_len-3] != 0x0a)
+ *bad_end = 1;
+
+ *meta_buf = new_buf;
+ *meta_size = new_len;
+}
+
+static int _text_buf_parsable(char *text_buf, uint64_t text_size)
+{
+ struct dm_config_tree *cft;
+
+ if (!(cft = config_open(CONFIG_FILE_SPECIAL, NULL, 0))) {
+ return 0;
+ }
+
+ if (!dm_config_parse(cft, text_buf, text_buf + text_size)) {
+ config_destroy(cft);
+ return 0;
+ }
+
+ config_destroy(cft);
+ return 1;
+}
+
+#define MAX_LINE_CHECK 128
+#define ID_STR_SIZE 48
+
+static void _copy_line(char *in, char *out, int *len)
+{
+ int i;
+
+ *len = 0;
+
+ for (i = 0; i < MAX_LINE_CHECK; i++) {
+ if ((in[i] == '\n') || (in[i] == '\0'))
+ break;
+ out[i] = in[i];
+ }
+ *len = i+1;
+}
+
+static int _dump_all_text(struct cmd_context *cmd, const char *tofile, struct device *dev,
+ int mda_num, uint64_t mda_offset, uint64_t mda_size, char *buf)
+{
+ FILE *fp = NULL;
+ char line[MAX_LINE_CHECK];
+ char vgname[NAME_LEN+1];
+ char id_str[ID_STR_SIZE];
+ char id_first[ID_STR_SIZE];
+ char *text_buf;
+ char *p;
+ uint32_t buf_off; /* offset with buf which begins with mda_header */
+ uint32_t buf_off_first = 0;
+ uint32_t seqno;
+ uint32_t crc;
+ uint64_t text_size;
+ uint64_t meta_size;
+ int multiple_vgs = 0;
+ int bad_end;
+ int vgnamelen;
+ int count;
+ int len;
+
+ if (tofile) {
+ if (!(fp = fopen(tofile, "wx"))) {
+ log_error("Failed to create file %s", tofile);
+ return 0;
+ }
+ }
+
+ /*
+ * If metadata has not wrapped, and the metadata area beginning
+ * has not been damaged, the text area will begin with vgname {.
+ * Wrapping or damage would mean we find no metadata starting at
+ * the start of the area.
+ *
+ * Try looking at each 512 byte offset within the area for the start
+ * of another copy of metadata. Metadata copies have begun at 512
+ * aligned offsets since very early lvm2 code in 2002.
+ *
+ * (We could also search for something definitive like
+ * "# Generated by LVM2" in the area, and then work backward to find
+ * a likely beginning.)
+ *
+ * N.B. This relies on VG metadata first having the id = "..." field
+ * followed by the "seqno = N" field.
+ */
+
+ memset(id_first, 0, sizeof(id_str));
+
+ /*
+ * A count of 512 byte chunks within the metadata area.
+ */
+ count = 0;
+
+ meta_size = mda_size - 512;
+
+ /*
+ * Search 512 byte boundaries for the start of new metadata copies.
+ */
+ while (count < (meta_size / 512)) {
+ memset(vgname, 0, sizeof(vgname));
+ memset(id_str, 0, sizeof(id_str));
+ seqno = 0;
+ vgnamelen = 0;
+ text_size = 0;
+ bad_end = 0;
+
+ /*
+ * Check for a new metadata copy at each 512 offset
+ * (after skipping 512 bytes for mda_header at the
+ * start of the buf).
+ *
+ * If a line looks like it begins with a vgname
+ * it could be a new copy of metadata, but it could
+ * also be a random bit of metadata that looks like
+ * a vgname, so confirm it's the start of metadata
+ * by looking for id and seqno lines following the
+ * possible vgname.
+ */
+ buf_off = 512 + (count * 512);
+ p = buf + buf_off;
+
+ /*
+ * copy line of possible metadata to check for vgname
+ */
+ memset(line, 0, sizeof(line));
+ _copy_line(p, line, &len);
+ p += len;
+
+ if (!_check_vgname_start(line, &vgnamelen)) {
+ count++;
+ continue;
+ }
+
+ memcpy(vgname, line, vgnamelen);
+
+ /*
+ * copy next line of metadata, which should contain id
+ */
+ memset(line, 0, sizeof(line));
+ _copy_line(p, line, &len);
+ p += len;
+
+ if (strncmp(line, "id = ", 5)) {
+ count++;
+ continue;
+ }
+
+ memcpy(id_str, line + 6, 38);
+
+ /*
+ * copy next line of metadata, which should contain seqno
+ */
+ memset(line, 0, sizeof(line));
+ _copy_line(p, line, &len);
+ p += len;
+
+ if (strncmp(line, "seqno = ", 8)) {
+ count++;
+ continue;
+ }
+
+ sscanf(line, "seqno = %u", &seqno);
+
+ /*
+ * The first three lines look like metadata with
+ * vgname/id/seqno, so copy out the full metadata.
+ *
+ * If this reaches the end of buf without reaching the
+ * end marker of metadata, it will wrap around to the
+ * start of buf and continue copying until it reaches
+ * a NL or until it reaches buf_off_first (which is
+ * where we've already taken text from.)
+ */
+ _copy_out_metadata(buf, buf_off, buf_off_first, mda_size, &text_buf, &text_size, &bad_end);
+
+ if (!text_buf) {
+ log_warn("Failed to extract full metadata text at %llu, skipping.",
+ (unsigned long long)(mda_offset + buf_off));
+ count++;
+ continue;
+ }
+
+ /*
+ * check if it's finding metadata from different vgs
+ */
+ if (!id_first[0])
+ memcpy(id_first, id_str, sizeof(id_first));
+ else if (memcmp(id_first, id_str, sizeof(id_first)))
+ multiple_vgs = 1;
+
+ crc = calc_crc(INITIAL_CRC, (uint8_t *)text_buf, text_size);
+
+ log_print("metadata at %llu length %llu crc %08x vg %s seqno %u id %s",
+ (unsigned long long)(mda_offset + buf_off),
+ (unsigned long long)text_size,
+ crc, vgname, seqno, id_str);
+
+ /*
+ * save the location of the first metadata we've found so
+ * we know where to stop after wrapping buf.
+ */
+ if (!buf_off_first)
+ buf_off_first = buf_off;
+
+ /*
+ * check if the full metadata is parsable
+ */
+
+ if (!_text_buf_parsable(text_buf, text_size))
+ log_warn("WARNING: parse error for metadata at %llu", (unsigned long long)(mda_offset + buf_off));
+ if (bad_end)
+ log_warn("WARNING: bad terminating bytes for metadata at %llu", (unsigned long long)(mda_offset + buf_off));
+
+ if (arg_is_set(cmd, verbose_ARG)) {
+ char *str1, *str2;
+ if ((str1 = strstr(text_buf, "description = "))) {
+ memset(line, 0, sizeof(line));
+ _copy_line(str1, line, &len);
+ log_print("%s", line);
+ }
+ if ((str2 = strstr(str1, "creation_time = "))) {
+ memset(line, 0, sizeof(line));
+ _copy_line(str2, line, &len);
+ log_print("%s\n", line);
+ }
+ }
+
+ if (fp) {
+ fprintf(fp, "%s", text_buf);
+ fprintf(fp, "\n--\n");
+ }
+
+ free(text_buf);
+ text_buf = NULL;
+
+ if (text_size < 512)
+ count++;
+ else if (!(text_size % 512))
+ count += (text_size / 512);
+ else
+ count += ((text_size / 512) + 1);
+ }
+
+ if (multiple_vgs)
+ log_warn("WARNING: metadata from multiple VGs was found.");
+
+ if (fp) {
+ if (fflush(fp))
+ stack;
+ if (fclose(fp))
+ stack;
+ }
+
+ return 1;
+}
+
static int _check_label_header(struct label_header *lh, uint64_t labelsector,
int *found_label)
{
@@ -317,311 +688,13 @@ static int _dump_meta_area(struct device *dev, const char *tofile,
* 1\23456789012345678901234567890123456789012345678
* 10 20 30 40
*/
-#define ID_STR_SIZE 48
-
-#define SEARCH_VGNAME_LEN 512
-
-static int _dump_meta_all(struct device *dev, const char *tofile,
- uint64_t mda_offset, uint64_t mda_size,
- uint64_t meta_offset, uint64_t meta_size,
- char *meta_buf)
-{
- FILE *fp = NULL;
- struct dm_config_tree *cft;
- char vgname[SEARCH_VGNAME_LEN];
- char id_str[ID_STR_SIZE];
- char *text_buf, *new_buf;
- char *p, *brace, *start, *buf_begin, *buf_end;
- uint64_t search_offset, start_offset;
- uint32_t brace_dist, new_len, len_a, len_b;
- uint32_t left_count, right_count;
- uint32_t seqno;
- int search_wrapped = 0;
- int p_wrapped;
- int save_bad;
- int i;
-
- /*
- * metadata begins:
- *
- * <vgname> {
- * id = "<uuid>"
- *
- * Search the metadata buffer for each instance
- * of the string:
- *
- * {
- * id = "<uuid>"
- *
- * Then reverse by the length of the <vgname> +1
- * to get to the start of the metadata. The
- * vgname must come from the original/current copy
- * of metadata found through the mda_header pointer.
- *
- * From the start of the metadata, find the end of
- * the metadata by searching foward until \0 is found.
- * Metadata ends with the three bytes:
- * \n\n\0 (0x0a0a00)
- */
-
- memset(vgname, 0, sizeof(vgname));
- memset(id_str, 0, sizeof(id_str));
- for (i = 0; i < SEARCH_VGNAME_LEN; i++) {
- if (meta_buf[i] == ' ')
- break;
- vgname[i] = meta_buf[i];
- }
-
- if (!(p = strchr(meta_buf, '{')))
- return_0;
-
- for (i = 0; i < ID_STR_SIZE; i++) {
- id_str[i] = *p;
- p++;
- }
-
- if (!(text_buf = malloc(mda_size)))
- return_0;
- memset(text_buf, 0, mda_size);
-
- if (!dev_read_bytes(dev, mda_offset, mda_size, text_buf)) {
- log_print("CHECK: failed to read metadata area at offset %llu size %llu",
- (unsigned long long)mda_offset, (unsigned long long)mda_size);
- free(text_buf);
- return 0;
- }
-
- search_offset = meta_offset + meta_size;
-
- search_next:
- if (search_wrapped && (search_offset >= meta_offset + meta_size))
- goto done;
-
- if (search_offset > mda_size) {
- if (search_wrapped)
- goto done;
- search_offset = 512;
- search_wrapped = 1;
- }
-
- /*
- * Search between buf_begin and buf_end for next open brace.
- */
- buf_begin = text_buf + search_offset;
- buf_end = text_buf + mda_size;
- brace = NULL;
-
- for (p = buf_begin; p < buf_end; p++) {
- if (*p != '{')
- continue;
- brace = p;
- break;
- }
-
- if (!brace && search_wrapped)
- goto done;
- if (!brace) {
- search_offset = 512;
- search_wrapped = 1;
- goto search_next;
- }
-
- /*
- * brace_dist is the distance from the last place we
- * began searching to the brace we are testing for
- * metadata. If this brace is not the start of valid
- * metadata, then advance brace_dist and search for
- * the next brace to check.
- */
- brace_dist = (uint32_t)(brace - buf_begin);
-
- /*
- * Found an open brace, check if it's the start of new metadata
- * by checking if brace is followed by id = "<uuid>".
- */
-
- if (memcmp(brace, id_str, ID_STR_SIZE)) {
- /* It's not, look for next open brace. */
- search_offset += (brace_dist + 1);
- goto search_next;
- }
-
- /*
- * This looks like a new instance of metadata, check if it's complete.
- * The start of the metadata is the vgname preceding the open brace,
- * so step backward through the text_buf to find the start of vgname.
- * There is no delimiter preceding the vgname, there can be any
- * text or data in the byte immediately before vgname (this means
- * we cannot handle extracting metadata prior to a vgrename.)
- *
- * <vgname> {
- * id = "..."
- */
- start = brace - (strlen(vgname) + 1);
-
- /* Offset from the begininng of device to the start of this metadata. */
- start_offset = (uint64_t)(start - text_buf) + mda_offset;
-
- /*
- * The end of the metadata is found by searching forward in text_buf
- * until \0, at which point open and close braces should match.
- * This forward search may wrap around to the start of text_buf.
- *
- * Metadata ends with the three bytes \n\n\0: 0a 0a 00
- */
- p = start;
- p_wrapped = 0;
- len_a = 0;
- len_b = 0;
- new_len = 0;
- new_buf = NULL;
- left_count = 0;
- right_count = 0;
- save_bad = 0;
- seqno = 0;
-
- while (1) {
- p++;
-
- if (p == (buf_end)) {
- p = text_buf + 512;
- p_wrapped = 1;
- }
-
- if (*p == '{')
- left_count++;
- else if (*p == '}')
- right_count++;
- else if (*p == '\0')
- break;
- }
-
- /* \0 should be preceded by \n\n (0x0a0a) */
- if ((*(p - 2) != 0x0a) || (*(p - 1) != 0x0a))
- log_print("Unexpected metadata end bytes.");
-
- if (p_wrapped) {
- len_a = (uint32_t)(buf_end - start);
- len_b = (uint32_t)(p - (text_buf + 512));
- new_len = len_a + len_b;
- search_wrapped = 1;
- } else {
- new_len = (uint32_t)(p - start);
- }
-
- /*
- * A couple simple tests indicate if this could be valid metadata
- * before attempting to parse it. (min length is probably greater
- * than 256, so this could be increased.)
- *
- * If this is complete but corrupt, we should save it.
- * TODO: If this is a fragment we should skip it.
- */
- if ((left_count != right_count) || (new_len < 256)) {
- /*
- * To skip this:
- * search_offset += (brace_dist + 1);
- * goto search_next;
- */
- log_print("Found incorrect metadata at %llu length %u with braces %u %u",
- (unsigned long long)start_offset, new_len, left_count, right_count);
- save_bad = 1;
- }
-
- /*
- * Copy the potential metadata into a new buffer to parse.
- */
- if (!(new_buf = malloc(new_len + 1))) {
- search_offset += (brace_dist + 1);
- log_print("No memory for metadata at %llu length %u with %u sections",
- (unsigned long long)start_offset, new_len, right_count);
- goto search_next;
- }
- memset(new_buf, 0, new_len + 1);
-
- if (p_wrapped) {
- memcpy(new_buf, start, len_a);
- memcpy(new_buf + len_a, text_buf + 512, len_b);
- } else {
- memcpy(new_buf, start, new_len);
- }
-
- if (save_bad)
- goto save;
-
- /*
- * Check the metadata is parsable.
- * If this is complete but corrupt, we should save it.
- * TODO: If this is a fragment we should skip it.
- */
- if ((cft = config_open(CONFIG_FILE_SPECIAL, NULL, 0))) {
- if (!dm_config_parse(cft, new_buf, new_buf + new_len)) {
- /*
- * To skip this:
- * search_offset += (brace_dist + 1);
- * goto search_next;
- */
- log_print("Found unparsable metadata at %llu length %u with %u sections",
- (unsigned long long)start_offset, new_len, right_count);
- config_destroy(cft);
- goto save;
- }
-
- if (cft->root && cft->root->child)
- dm_config_get_uint32(cft->root->child, "seqno", &seqno);
- config_destroy(cft);
- }
-
- log_print("Found metadata at %llu length %u seqno %u with %u sections",
- (unsigned long long)start_offset, new_len, seqno, right_count);
-
- save:
- if (!fp && tofile) {
- if (!(fp = fopen(tofile, "a"))) {
- log_error("Failed to open file %s", tofile);
- goto out;
- }
- }
-
- if (fp) {
- fprintf(fp, "%s", new_buf);
- fprintf(fp, "\n--\n");
- }
-
- out:
- free(new_buf);
-
- /*
- * Look for another id_str instance after the metadata
- * that was just finished.
- */
-
- if (p_wrapped)
- search_offset = len_b;
- else
- search_offset += new_len;
- goto search_next;
-
- done:
- if (fp) {
- if (fflush(fp))
- stack;
- if (fclose(fp))
- stack;
- }
-
- free(text_buf);
- return 1;
-}
-
-static int _dump_meta_text(struct device *dev,
- int print_fields, int print_metadata, const char *tofile,
- int mda_num, int rlocn_index,
- uint64_t mda_offset, uint64_t mda_size,
- uint64_t meta_offset, uint64_t meta_size,
- uint32_t meta_checksum,
- char **meta_buf_out)
+static int _dump_current_text(struct device *dev,
+ int print_fields, int print_metadata, const char *tofile,
+ int mda_num, int rlocn_index,
+ uint64_t mda_offset, uint64_t mda_size,
+ uint64_t meta_offset, uint64_t meta_size,
+ uint32_t meta_checksum)
{
char *meta_buf;
struct dm_config_tree *cft;
@@ -729,8 +802,6 @@ static int _dump_meta_text(struct device *dev,
}
out:
- *meta_buf_out = meta_buf;
-
if (bad)
return 0;
return 1;
@@ -999,7 +1070,6 @@ static int _dump_mda_header(struct cmd_context *cmd,
{
char str[256];
char *buf;
- char *meta_buf = NULL;
struct mda_header *mh;
struct raw_locn *rlocn0, *rlocn1;
uint64_t rlocn0_offset, rlocn1_offset;
@@ -1090,24 +1160,35 @@ static int _dump_mda_header(struct cmd_context *cmd,
/*
* looking at the current copy of metadata referenced by raw_locn
*/
- if (print_metadata < 2) {
- if (!_dump_meta_text(dev, print_fields, print_metadata, tofile, mda_num, 0, mda_offset, mda_size, meta_offset, meta_size, meta_checksum, &meta_buf))
+ if (print_metadata <= PRINT_CURRENT) {
+ if (!_dump_current_text(dev, print_fields, print_metadata, tofile, mda_num, 0, mda_offset, mda_size, meta_offset, meta_size, meta_checksum))
bad++;
}
/*
* looking at all copies of the metadata in the area
*/
- if (print_metadata == 2) {
- if (!_dump_meta_text(dev, 0, 0, NULL, mda_num, 0, mda_offset, mda_size, meta_offset, meta_size, meta_checksum, &meta_buf))
- bad++;
+ if (print_metadata == PRINT_ALL) {
+ free(buf);
+
+ if (!(buf = malloc(mda_size)))
+ goto_out;
+ memset(buf, 0, mda_size);
- if (!_dump_meta_all(dev, tofile, mda_offset, mda_size, meta_offset, meta_size, meta_buf))
+ if (!dev_read_bytes(dev, mda_offset, mda_size, buf)) {
+ log_print("CHECK: failed to read metadata area at offset %llu size %llu",
+ (unsigned long long)mda_offset, (unsigned long long)mda_size);
bad++;
+ goto out;
+ }
+
+ _dump_all_text(cmd, tofile, dev, mda_num, mda_offset, mda_size, buf);
}
/* Should we also check text metadata if it exists in rlocn1? */
out:
+ if (buf)
+ free(buf);
if (bad)
return 0;
return 1;
@@ -1303,6 +1384,137 @@ static int _dump_found(struct cmd_context *cmd, struct device *dev,
return 1;
}
+#define ONE_MB_IN_BYTES 1048576
+
+/*
+ * Look for metadata text in common locations, without using any headers
+ * (pv_header/mda_header) to find the location, since the headers may be
+ * zeroed/damaged.
+ */
+
+static int _dump_search(struct cmd_context *cmd,
+ int argc, char **argv)
+{
+ char str[256];
+ struct device *dev;
+ const char *pv_name;
+ const char *tofile = NULL;
+ char *buf;
+ struct mda_header *mh;
+ uint64_t mda1_offset = 0, mda1_size = 0, mda2_offset = 0, mda2_size = 0;
+ uint64_t mda_offset, mda_size;
+ int found_header = 0;
+ int mda_count = 0;
+ int mda_num = 1;
+
+ if (arg_is_set(cmd, file_ARG)) {
+ if (!(tofile = arg_str_value(cmd, file_ARG, NULL)))
+ return ECMD_FAILED;
+ }
+
+ /* 1: dump metadata from first mda, 2: dump metadata from second mda */
+ if (arg_is_set(cmd, pvmetadatacopies_ARG))
+ mda_num = arg_int_value(cmd, pvmetadatacopies_ARG, 1);
+
+ pv_name = argv[0];
+
+ if (!(dev = dev_cache_get(cmd, pv_name, cmd->filter))) {
+ log_error("No device found for %s %s.", pv_name, dev_cache_filtered_reason(pv_name));
+ return ECMD_FAILED;
+ }
+
+ label_scan_setup_bcache();
+
+ _dump_label_and_pv_header(cmd, 0, dev, NULL,
+ &mda1_offset, &mda1_size, &mda2_offset, &mda2_size, &mda_count);
+
+ /*
+ * TODO: allow mda_offset and mda_size to be specified on the
+ * command line.
+ *
+ * For mda1, mda_offset is always 4096 bytes from the start of
+ * device, and mda_size is the space between mda_offset and
+ * the first PE which is usually at 1MB.
+ *
+ * For mda2, take the dev_size, reduce that to be a 1MB
+ * multiple. The mda_offset is then 1MB prior to that,
+ * and mda_size is the amount of space between that offset
+ * and the end of the device.
+ *
+ * The second mda is generally 4K larger (at least) than the
+ * first mda because the first mda begins at a 4K offset from
+ * the start of the device and ends on a 1MB boundary.
+ * The second mda begins on a 1MB boundary (no 4K offset like
+ * mda1), then goes to the end of the device. Extra space
+ * at the end of device (mod 1MB extra) can make mda2 even
+ * larger.
+ */
+ if (mda_num == 1) {
+ mda_offset = 4096;
+ mda_size = ONE_MB_IN_BYTES - 4096;
+ } else if (mda_num == 2) {
+ uint64_t dev_sectors = 0;
+ uint64_t dev_bytes;
+ uint64_t extra_bytes;
+
+ dev_get_size(dev, &dev_sectors);
+
+ dev_bytes = dev_sectors * 512;
+ extra_bytes = dev_bytes % ONE_MB_IN_BYTES;
+
+ if (dev_bytes < (2 * ONE_MB_IN_BYTES))
+ return ECMD_FAILED;
+
+ mda_offset = dev_bytes - extra_bytes - ONE_MB_IN_BYTES;
+ mda_size = dev_bytes - mda_offset;
+ }
+
+ if ((mda_num == 1) && (mda1_offset != mda_offset)) {
+ 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.",
+ (unsigned long long)mda2_offset,
+ (unsigned long long)mda2_size);
+ }
+
+ log_print("Searching for metadata in mda%d at offset %llu size %llu", mda_num,
+ (unsigned long long)mda_offset, (unsigned long long)mda_size);
+
+ if (!(buf = malloc(mda_size)))
+ return ECMD_FAILED;
+ memset(buf, 0, mda_size);
+
+ if (!dev_read_bytes(dev, mda_offset, mda_size, buf)) {
+ log_print("CHECK: failed to read metadata area at offset %llu size %llu",
+ (unsigned long long)mda_offset, (unsigned long long)mda_size);
+ free(buf);
+ return ECMD_FAILED;
+ }
+
+ mh = (struct mda_header *)buf;
+
+ /* Can be useful to know if there's a valid mda_header at this location. */
+ log_print("mda_header_%d at %llu # metadata area", mda_num, (unsigned long long)mda_offset);
+ log_print("mda_header_%d.checksum 0x%x", mda_num, xlate32(mh->checksum_xl));
+ log_print("mda_header_%d.magic 0x%s", mda_num, _chars_to_hexstr(mh->magic, str, 16, 256, "mda_header.magic"));
+ log_print("mda_header_%d.version %u", mda_num, xlate32(mh->version));
+ log_print("mda_header_%d.start %llu", mda_num, (unsigned long long)xlate64(mh->start));
+ log_print("mda_header_%d.size %llu", mda_num, (unsigned long long)xlate64(mh->size));
+
+ _check_mda_header(mh, mda_num, mda_offset, mda_size, &found_header);
+
+ log_print("searching for metadata text");
+
+ _dump_all_text(cmd, tofile, dev, mda_num, mda_offset, mda_size, buf);
+
+ free(buf);
+ return ECMD_PROCESSED;
+}
+
int pvck(struct cmd_context *cmd, int argc, char **argv)
{
struct device *dev;
@@ -1316,14 +1528,17 @@ int pvck(struct cmd_context *cmd, int argc, char **argv)
dump = arg_str_value(cmd, dump_ARG, NULL);
if (!strcmp(dump, "metadata"))
- return _dump_metadata(cmd, argc, argv, 1, 0);
+ return _dump_metadata(cmd, argc, argv, PRINT_CURRENT, 0);
if (!strcmp(dump, "metadata_all"))
- return _dump_metadata(cmd, argc, argv, 2, 0);
+ return _dump_metadata(cmd, argc, argv, PRINT_ALL, 0);
if (!strcmp(dump, "metadata_area"))
return _dump_metadata(cmd, argc, argv, 0, 1);
+ if (!strcmp(dump, "metadata_search"))
+ return _dump_search(cmd, argc, argv);
+
if (!strcmp(dump, "headers"))
return _dump_headers(cmd, argc, argv);
4 years, 7 months
master - tests: cachevol needs FORMAT2
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=4f860f79ff7c5bb3552...
Commit: 4f860f79ff7c5bb35520776f5906ae51442d5920
Parent: f07e5c1fe43524ec6f9da6afaf95c5b328972703
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Oct 16 21:58:57 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Oct 17 13:03:50 2019 +0200
tests: cachevol needs FORMAT2
FORMAT2 is mandatory with cachevols...
---
test/shell/cache-single-thin.sh | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/test/shell/cache-single-thin.sh b/test/shell/cache-single-thin.sh
index 2547502..6b478fb 100644
--- a/test/shell/cache-single-thin.sh
+++ b/test/shell/cache-single-thin.sh
@@ -16,7 +16,7 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
-aux have_cache 1 3 0 || skip
+aux have_cache 1 10 0 || skip
aux have_thin 1 0 0 || skip
aux prepare_devs 5 80
4 years, 7 months
master - tests: skip when raid is not present
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=f07e5c1fe43524ec6f9...
Commit: f07e5c1fe43524ec6f9da6afaf95c5b328972703
Parent: ec85dfe0f8096ee486c39c22b740f3938932707e
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Wed Oct 16 21:58:39 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Oct 17 13:03:50 2019 +0200
tests: skip when raid is not present
---
test/shell/lvextend-raid.sh | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/test/shell/lvextend-raid.sh b/test/shell/lvextend-raid.sh
index 8988411..1c0e9c6 100644
--- a/test/shell/lvextend-raid.sh
+++ b/test/shell/lvextend-raid.sh
@@ -15,6 +15,7 @@ SKIP_WITH_LVMPOLLD=1
. lib/inittest
+aux have_raid 1 3 0 || skip
v1_15_0=0
aux have_raid 1 15 0 && v1_15_0=1
4 years, 7 months
master - cachevol: support removal of cachevol
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=ec85dfe0f8096ee486c...
Commit: ec85dfe0f8096ee486c39c22b740f3938932707e
Parent: 5938cde11bb7298104871acf47d60b0fd5835b71
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Oct 17 12:48:56 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Oct 17 13:03:50 2019 +0200
cachevol: support removal of cachevol
Removal of cachevol is equivalent of lvconvert --uncache
and works the same way as with cachepool.
---
lib/metadata/lv_manip.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index b5b9a4a..815ea99 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -6278,7 +6278,8 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
/* FIXME Ensure not referred to by another existing LVs */
ask_discard = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL);
- if (lv_is_active(lv)) {
+ if (!lv_is_cache_vol(lv) &&
+ lv_is_active(lv)) {
if (!lv_check_not_in_use(lv, 1))
return_0;
@@ -6355,6 +6356,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
/* Used cache pool, COW or historical LV cannot be activated */
if (!lv_is_used_cache_pool(lv) &&
+ !lv_is_cache_vol(lv) &&
!lv_is_cow(lv) && !lv_is_historical(lv) &&
!deactivate_lv_with_sub_lv(lv))
/* FIXME Review and fix the snapshot error paths! */
@@ -6404,7 +6406,7 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
}
}
- if (lv_is_used_cache_pool(lv)) {
+ if (lv_is_used_cache_pool(lv) || lv_is_cache_vol(lv)) {
/* Cache pool removal drops cache layer
* If the cache pool is not linked, we can simply remove it. */
if (!(cache_seg = get_only_segment_using_this_lv(lv)))
4 years, 7 months
master - cache: single code for removal of cached volume
by Zdenek Kabelac
Gitweb: https://sourceware.org/git/?p=lvm2.git;a=commitdiff;h=5938cde11bb72981048...
Commit: 5938cde11bb7298104871acf47d60b0fd5835b71
Parent: 9969361b51d0b69fa04a6a7cd87ca74208b2437a
Author: Zdenek Kabelac <zkabelac(a)redhat.com>
AuthorDate: Thu Oct 17 12:53:54 2019 +0200
Committer: Zdenek Kabelac <zkabelac(a)redhat.com>
CommitterDate: Thu Oct 17 13:03:50 2019 +0200
cache: single code for removal of cached volume
Use same routine for dropping cached LV for cachevol and cachepool.
---
lib/metadata/lv_manip.c | 31 ++++++++++++++++---------------
1 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/lib/metadata/lv_manip.c b/lib/metadata/lv_manip.c
index b3a749d..b5b9a4a 100644
--- a/lib/metadata/lv_manip.c
+++ b/lib/metadata/lv_manip.c
@@ -6275,19 +6275,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
if (!lockd_lv(cmd, lock_lv, "ex", LDLV_PERSISTENT))
return_0;
- if (lv_is_cache(lv) && lv_is_cache_vol(first_seg(lv)->pool_lv)) {
- struct logical_volume *cachevol_lv = first_seg(lv)->pool_lv;
-
- if (!lv_cache_remove(lv)) {
- log_error("Failed to detach cache from %s", display_lvname(lv));
- return 0;
- }
- if (!lv_remove_single(cmd, cachevol_lv, force, suppress_remove_message)) {
- log_error("Failed to remove cachevol %s.", display_lvname(cachevol_lv));
- return 0;
- }
- }
-
/* FIXME Ensure not referred to by another existing LVs */
ask_discard = find_config_tree_bool(cmd, devices_issue_discards_CFG, NULL);
@@ -6339,7 +6326,22 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
}
if (lv_is_cache(lv) && !lv_is_pending_delete(lv)) {
- if (!lv_remove_single(cmd, first_seg(lv)->pool_lv, force,
+ /* Handles both cachepool & cachevol based cached LVs.
+ * It's placed before deactivation, so it can try to uncache
+ * 'active' LV if possible
+ */
+ struct logical_volume *cachevol_lv = first_seg(lv)->pool_lv;
+
+ if (lv_is_cache_pool(cachevol_lv))
+ is_last_pool = 1;
+
+ if (!archive(vg))
+ return_0;
+
+ if (!lv_cache_remove(lv))
+ return_0;
+
+ if (!lv_remove_single(cmd, cachevol_lv, force,
suppress_remove_message)) {
if (force < DONT_PROMPT_OVERRIDE) {
log_error("Failed to uncache %s.", display_lvname(lv));
@@ -6349,7 +6351,6 @@ int lv_remove_single(struct cmd_context *cmd, struct logical_volume *lv,
log_print_unless_silent("Ignoring uncache failure of %s.",
display_lvname(lv));
}
- is_last_pool = 1;
}
/* Used cache pool, COW or historical LV cannot be activated */
4 years, 7 months