1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

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.
This commit is contained in:
Alasdair G Kergon 2014-07-30 21:55:11 +01:00
parent c4484d9050
commit 7cff640d9a
6 changed files with 75 additions and 3 deletions

View File

@ -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
=================================

View File

@ -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
================================

View File

@ -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));

View File

@ -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

View File

@ -525,6 +525,11 @@ struct dm_tree_node;
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.
*/

View File

@ -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)