diff options
author | David Teigland <teigland@redhat.com> | 2016-03-01 15:59:33 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2016-03-01 15:59:33 -0600 |
commit | 4fde9fcdc2d1dcc24565c0dc5423fb6f0be8b04f (patch) | |
tree | 46207a06807c112566faf8de032ec97fdf1bc5ef | |
parent | 3d610fabbdb5f63e6e46661f7080f74852b118b0 (diff) | |
download | lvm2-dev-dct-lvm-using-dev.tar.gz |
lvmcache: prefer duplicate device in use by lvmdev-dct-lvm-using-dev
-rw-r--r-- | lib/activate/dev_manager.c | 90 | ||||
-rw-r--r-- | lib/activate/dev_manager.h | 2 | ||||
-rw-r--r-- | lib/cache/lvmcache.c | 33 |
3 files changed, 123 insertions, 2 deletions
diff --git a/lib/activate/dev_manager.c b/lib/activate/dev_manager.c index 2d59cf480..6b9f0fe06 100644 --- a/lib/activate/dev_manager.c +++ b/lib/activate/dev_manager.c @@ -3160,3 +3160,93 @@ 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; +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..cb6dd2268 100644 --- a/lib/cache/lvmcache.c +++ b/lib/cache/lvmcache.c @@ -26,6 +26,9 @@ #include "format1.h" #include "config.h" +/* FIXME */ +int dev_manager_lvm_using_device(struct device *dev); + #include "lvmetad.h" #define CACHE_INVALID 0x00000001 @@ -1823,6 +1826,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_is_used = 0; + int new_is_used = 0; /* * Here are different devices with the same pvid: @@ -1861,7 +1866,10 @@ 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_is_used = dev_manager_lvm_using_device(existing->dev); + new_is_used = dev_manager_lvm_using_device(dev); + + if (old_is_used && new_is_used) { /* * This is not a selection of old or new, but * just a warning to be aware of. @@ -1884,7 +1892,28 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid, return NULL; } - if (old_in_subsystem && !new_in_subsystem) { + if (old_is_used && !new_is_used) { + /* 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 lvm, ignoring %s", + dev_name(existing->dev), + dev_name(dev)); + return NULL; + + } else if (!old_is_used && new_is_used) { + /* 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 lvm, 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, |