diff options
author | David Teigland <teigland@redhat.com> | 2016-03-01 15:59:33 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2016-03-03 15:14:25 -0600 |
commit | 219e00771b26717add28de982dbd3011ddca28aa (patch) | |
tree | 52d231038b9a3e97018879a690b1df592258701b | |
parent | ad9cbe271458741f87dca834c16078f181612d76 (diff) | |
download | lvm2-dev-dct-lvm-using-dev-2.tar.gz |
lvmcache: prefer duplicate device in use by lvmdev-dct-lvm-using-dev-2
-rw-r--r-- | lib/activate/activate.c | 9 | ||||
-rw-r--r-- | lib/activate/activate.h | 5 | ||||
-rw-r--r-- | lib/activate/dev_manager.c | 92 | ||||
-rw-r--r-- | lib/activate/dev_manager.h | 2 | ||||
-rw-r--r-- | lib/cache/lvmcache.c | 33 |
5 files changed, 138 insertions, 3 deletions
diff --git a/lib/activate/activate.c b/lib/activate/activate.c index 2eb24d49b..88a39fa9f 100644 --- a/lib/activate/activate.c +++ b/lib/activate/activate.c @@ -2389,6 +2389,15 @@ int pv_uses_vg(struct physical_volume *pv, return dev_manager_device_uses_vg(pv->dev, vg); } +/* + * Are there any active LVs using this device, + * i.e. is it in the dependency list of any LVM devices? + */ +int lvs_using_device(struct device *dev) +{ + return dev_manager_lvm_using_device(dev); +} + void activation_release(void) { if (critical_section()) diff --git a/lib/activate/activate.h b/lib/activate/activate.h index 74afb9525..8a37bd57a 100644 --- a/lib/activate/activate.h +++ b/lib/activate/activate.h @@ -220,6 +220,11 @@ int add_linear_area_to_dtree(struct dm_tree_node *node, uint64_t size, int pv_uses_vg(struct physical_volume *pv, struct volume_group *vg); +/* + * Returns 1 if device is in the dm dependency tree of any active LVs. + */ +int lvs_using_device(struct device *dev); + struct dev_usable_check_params { unsigned int check_empty:1; unsigned int check_blocked:1; diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 2d59cf480..78d9b622a 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -3160,3 +3160,95 @@ out: dm_tree_free(dtree); return r; } + +static int _is_lvm_uuid(char *dm_name) +{ + struct dm_info info; + struct dm_task *dmt; + const char *uuid; + int ret = 0; + + if (!(dmt = dm_task_create(DM_DEVICE_INFO))) + return 0; + + if (!dm_task_set_name(dmt, dm_name)) + goto out; + + if (!dm_task_run(dmt)) + goto out; + + if (!dm_task_get_info(dmt, &info)) + goto out; + + if (!info.exists) + goto out; + + if (!(uuid = dm_task_get_uuid(dmt))) + goto out; + + if (!strncmp(uuid, UUID_PREFIX, sizeof(UUID_PREFIX) - 1)) + ret = 1; + + /* Verify that a uuid follows the LVM prefix? */ +out: + dm_task_destroy(dmt); + return ret; +} + +int dev_manager_lvm_using_device(struct device *dev) +{ + struct dm_task *dmt; + struct dm_task *dmt2; + struct dm_deps *deps; + struct dm_names *names; + unsigned next = 0; + int is_used = 0; + int i; + + if (!(dmt = _setup_task(NULL, NULL, 0, DM_DEVICE_LIST, 0, 0, 0))) + return_0; + + if (!dm_task_run(dmt)) + goto_out; + + if (!(names = dm_task_get_names(dmt))) + goto_out; + + if (!names->dev) + goto_out; + + do { + names = (struct dm_names *)((char *) names + next); + dmt2 = NULL; + + if (!_is_lvm_uuid(names->name)) + goto next; + + if (!(dmt2 = _setup_task(names->name, NULL, 0, DM_DEVICE_DEPS, 0, 0, 0))) + goto next; + + if (!dm_task_run(dmt2)) + goto next; + + if (!(deps = dm_task_get_deps(dmt2))) + goto next; + + for (i = 0; i < deps->count; i++) { + if ((MAJOR(dev->dev) == (int) MAJOR(deps->device[i])) && + (MINOR(dev->dev) == (int) MINOR(deps->device[i]))) { + is_used = 1; + break; + } + } +next: + if (dmt2) + dm_task_destroy(dmt2); + next = names->next; + + } while (next && !is_used); + +out: + dm_task_destroy(dmt); + return is_used; +} + diff --git a/lib/activate/dev_manager.h b/lib/activate/dev_manager.h index bcfb2261c..fb042b6b3 100644 --- a/lib/activate/dev_manager.h +++ b/lib/activate/dev_manager.h @@ -97,4 +97,6 @@ int dev_manager_execute(struct dev_manager *dm); int dev_manager_device_uses_vg(struct device *dev, struct volume_group *vg); +int dev_manager_lvm_using_device(struct device *dev); + #endif diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c index b1e53e24d..c957bec85 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -25,6 +25,7 @@ #include "format_pool.h" #include "format1.h" #include "config.h" +#include "activate.h" #include "lvmetad.h" @@ -1823,6 +1824,8 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, int new_is_dm = 0; int old_has_holders = 0; int new_has_holders = 0; + int old_has_lvs = 0; + int new_has_lvs = 0; /* * Here are different devices with the same pvid: @@ -1861,12 +1864,15 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, old_has_holders = dm_device_has_holders(MAJOR(existing->dev->dev), MINOR(existing->dev->dev)); new_has_holders = dm_device_has_holders(MAJOR(dev->dev), MINOR(dev->dev)); - if (old_has_holders && new_has_holders) { + old_has_lvs = lvs_using_device(existing->dev); + new_has_lvs = lvs_using_device(dev); + + if (old_has_lvs && new_has_lvs) { /* * This is not a selection of old or new, but * just a warning to be aware of. */ - log_warn("WARNING: duplicate PV %s is being used from both devices %s and %s", + log_warn("WARNING: duplicate PV %s is being used by LVs on devices %s and %s", pvid_s, dev_name(existing->dev), dev_name(dev)); @@ -1884,7 +1890,28 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, return NULL; } - if (old_in_subsystem && !new_in_subsystem) { + if (old_has_lvs && !new_has_lvs) { + /* Use old, ignore new. */ + log_warn("Found duplicate PV %s: using %s not %s", + pvid_s, + dev_name(existing->dev), + dev_name(dev)); + log_warn("Using duplicate PV %s used by LVs, ignoring %s", + dev_name(existing->dev), + dev_name(dev)); + return NULL; + + } else if (!old_has_lvs && new_has_lvs) { + /* Use new, replace old. */ + log_warn("Found duplicate PV %s: using %s not %s", + pvid_s, + dev_name(dev), + dev_name(existing->dev)); + log_warn("Using duplicate PV %s used by LVs, replacing %s", + dev_name(dev), + dev_name(existing->dev)); + + } else if (old_in_subsystem && !new_in_subsystem) { /* Use old, ignore new. */ log_warn("Found duplicate PV %s: using %s not %s", pvid_s, |