Gitweb:
http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=7cff640d9ae20a...
Commit: 7cff640d9ae20a94647610e5adbb4151b7652fe5
Parent: c4484d90503c4e5c2bc945461da50a6b85c5d7e7
Author: Alasdair G Kergon <agk(a)redhat.com>
AuthorDate: Wed Jul 30 21:55:11 2014 +0100
Committer: Alasdair G Kergon <agk(a)redhat.com>
CommitterDate: Wed Jul 30 21:55:11 2014 +0100
activation: Fix upgrades using uuid suffixes.
2.02.106 added suffixes to some LV uuids in the kernel.
If any of these LVs is activated with 2.02.105 or earlier,
and then a later version is used, the LVs appear invisible and
activation commands fail.
The code now has to check the kernel for both old and new uuids.
---
WHATS_NEW | 1 +
WHATS_NEW_DM | 1 +
lib/activate/dev_manager.c | 29 ++++++++++++++++++++++++++++-
lib/misc/lvm-string.c | 1 +
libdm/libdevmapper.h | 5 +++++
libdm/libdm-deptree.c | 41 +++++++++++++++++++++++++++++++++++++++--
6 files changed, 75 insertions(+), 3 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index 64b174b..ace357b 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.109 -
=================================
+ Handle upgrade from 2.02.105 when an LV now gaining a uuid suffix is active.
Version 2.02.108 - 23rd July 2014
=================================
diff --git a/WHATS_NEW_DM b/WHATS_NEW_DM
index ad25215..b663bfc 100644
--- a/WHATS_NEW_DM
+++ b/WHATS_NEW_DM
@@ -1,5 +1,6 @@
Version 1.02.88 -
================================
+ Add dm_tree_set_optional_uuid_suffixes to handle upgrades.
Version 1.02.87 - 23rd July 2014
================================
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c
index d5fe620..2cf0b65 100644
--- a/lib/activate/dev_manager.c
+++ b/lib/activate/dev_manager.c
@@ -41,6 +41,9 @@ typedef enum {
CLEAN
} action_t;
+/* This list must match lib/misc/lvm-string.c:build_dm_uuid(). */
+const char *uuid_suffix_list[] = { "pool", "cdata",
"cmeta", "tdata", "tmeta", NULL};
+
struct dev_manager {
struct dm_pool *mem;
@@ -482,11 +485,31 @@ static int _info(const char *dlid, int with_open_count, int
with_read_ahead,
struct dm_info *info, uint32_t *read_ahead)
{
int r = 0;
+ char old_style_dlid[sizeof(UUID_PREFIX) + 2 * ID_LEN];
+ const char *suffix, *suffix_position;
+ unsigned i = 0;
+ /* Check for dlid */
if ((r = _info_run(NULL, dlid, info, read_ahead, 0, with_open_count,
with_read_ahead, 0, 0)) && info->exists)
return 1;
- else if ((r = _info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
+
+ /* Check for original version of dlid before the suffixes got added in 2.02.106 */
+ if ((suffix_position = rindex(dlid, '-'))) {
+ while ((suffix = uuid_suffix_list[i++])) {
+ if (strcmp(suffix_position + 1, suffix))
+ continue;
+
+ (void) strncpy(old_style_dlid, dlid, sizeof(old_style_dlid));
+ old_style_dlid[sizeof(old_style_dlid) - 1] = '\0';
+ if ((r = _info_run(NULL, old_style_dlid, info, read_ahead, 0, with_open_count,
+ with_read_ahead, 0, 0)) && info->exists)
+ return 1;
+ }
+ }
+
+ /* Check for dlid before UUID_PREFIX was added */
+ if ((r = _info_run(NULL, dlid + sizeof(UUID_PREFIX) - 1, info,
read_ahead, 0, with_open_count,
with_read_ahead, 0, 0)) && info->exists)
return 1;
@@ -2011,6 +2034,8 @@ static struct dm_tree *_create_partial_dtree(struct dev_manager *dm,
struct logi
return NULL;
}
+ dm_tree_set_optional_uuid_suffixes(dtree, &uuid_suffix_list[0]);
+
if (!_add_lv_to_dtree(dm, dtree, lv, (lv_is_origin(lv) || lv_is_thin_volume(lv)) ?
origin_only : 0))
goto_bad;
@@ -3001,6 +3026,8 @@ int dev_manager_device_uses_vg(struct device *dev,
return r;
}
+ dm_tree_set_optional_uuid_suffixes(dtree, &uuid_suffix_list[0]);
+
if (!dm_tree_add_dev(dtree, (uint32_t) MAJOR(dev->dev), (uint32_t)
MINOR(dev->dev))) {
log_error("Failed to add device %s (%" PRIu32 ":%" PRIu32") to
dtree",
dev_name(dev), (uint32_t) MAJOR(dev->dev), (uint32_t) MINOR(dev->dev));
diff --git a/lib/misc/lvm-string.c b/lib/misc/lvm-string.c
index 5858638..84c8708 100644
--- a/lib/misc/lvm-string.c
+++ b/lib/misc/lvm-string.c
@@ -185,6 +185,7 @@ char *build_dm_uuid(struct dm_pool *mem, const struct logical_volume
*lv,
* an internal LV they should not scan.
* Should also make internal detection simpler.
*/
+ /* Suffixes used here MUST match lib/activate/dev_manager.c */
layer = lv_is_cache_pool_data(lv) ? "cdata" :
lv_is_cache_pool_metadata(lv) ? "cmeta" :
// FIXME: dm-tree needs fixes for mirrors/raids
diff --git a/libdm/libdevmapper.h b/libdm/libdevmapper.h
index dc3da78..e37ee39 100644
--- a/libdm/libdevmapper.h
+++ b/libdm/libdevmapper.h
@@ -526,6 +526,11 @@ struct dm_tree *dm_tree_create(void);
void dm_tree_free(struct dm_tree *tree);
/*
+ * List of suffixes to be ignored when matching uuids against existing devices.
+ */
+void dm_tree_set_optional_uuid_suffixes(struct dm_tree *dtree, const char
**optional_uuid_suffixes);
+
+/*
* Add nodes to the tree for a given device and all the devices it uses.
*/
int dm_tree_add_dev(struct dm_tree *tree, uint32_t major, uint32_t minor);
diff --git a/libdm/libdm-deptree.c b/libdm/libdm-deptree.c
index f34c40f..55f061a 100644
--- a/libdm/libdm-deptree.c
+++ b/libdm/libdm-deptree.c
@@ -16,6 +16,7 @@
#include "libdm-targets.h"
#include "libdm-common.h"
#include "kdev_t.h"
+#include "dm-ioctl.h"
#include <stdarg.h>
#include <sys/param.h>
@@ -300,6 +301,7 @@ struct dm_tree {
int no_flush; /* 1 sets noflush (mirrors/multipath) */
int retry_remove; /* 1 retries remove if not successful */
uint32_t cookie;
+ const char **optional_uuid_suffixes; /* uuid suffixes ignored when matching */
};
/*
@@ -325,6 +327,7 @@ struct dm_tree *dm_tree_create(void)
dtree->skip_lockfs = 0;
dtree->no_flush = 0;
dtree->mem = dmem;
+ dtree->optional_uuid_suffixes = NULL;
if (!(dtree->devs = dm_hash_create(8))) {
log_error("dtree hash creation failed");
@@ -539,23 +542,57 @@ static struct dm_tree_node *_find_dm_tree_node(struct dm_tree
*dtree,
sizeof(dev));
}
+void dm_tree_set_optional_uuid_suffixes(struct dm_tree *dtree, const char
**optional_uuid_suffixes)
+{
+ dtree->optional_uuid_suffixes = optional_uuid_suffixes;
+}
+
static struct dm_tree_node *_find_dm_tree_node_by_uuid(struct dm_tree *dtree,
const char *uuid)
{
struct dm_tree_node *node;
const char *default_uuid_prefix;
size_t default_uuid_prefix_len;
+ const char *suffix, *suffix_position;
+ char uuid_without_suffix[DM_UUID_LEN];
+ unsigned i = 0;
+ const char **suffix_list = dtree->optional_uuid_suffixes;
- if ((node = dm_hash_lookup(dtree->uuids, uuid)))
+ if ((node = dm_hash_lookup(dtree->uuids, uuid))) {
+ log_debug("Matched uuid %s in deptree.", uuid);
return node;
+ }
default_uuid_prefix = dm_uuid_prefix();
default_uuid_prefix_len = strlen(default_uuid_prefix);
+ if (suffix_list && (suffix_position = rindex(uuid, '-'))) {
+ while ((suffix = suffix_list[i++])) {
+ if (strcmp(suffix_position + 1, suffix))
+ continue;
+
+ (void) strncpy(uuid_without_suffix, uuid, sizeof(uuid_without_suffix));
+ uuid_without_suffix[suffix_position - uuid] = '\0';
+
+ if ((node = dm_hash_lookup(dtree->uuids, uuid_without_suffix))) {
+ log_debug("Matched uuid %s (missing suffix -%s) in deptree.",
uuid_without_suffix, suffix);
+ return node;
+ }
+
+ break;
+ };
+ }
+
if (strncmp(uuid, default_uuid_prefix, default_uuid_prefix_len))
return NULL;
- return dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len);
+ if ((node = dm_hash_lookup(dtree->uuids, uuid + default_uuid_prefix_len))) {
+ log_debug("Matched uuid %s (missing prefix) in deptree.", uuid +
default_uuid_prefix_len);
+ return node;
+ }
+
+ log_debug("Not matched uuid %s in deptree.", uuid + default_uuid_prefix_len);
+ return NULL;
}
void dm_tree_node_set_udev_flags(struct dm_tree_node *dnode, uint16_t udev_flags)