summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2016-03-01 15:59:33 -0600
committerDavid Teigland <teigland@redhat.com>2016-03-01 15:59:33 -0600
commit4fde9fcdc2d1dcc24565c0dc5423fb6f0be8b04f (patch)
tree46207a06807c112566faf8de032ec97fdf1bc5ef
parent3d610fabbdb5f63e6e46661f7080f74852b118b0 (diff)
downloadlvm2-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.c90
-rw-r--r--lib/activate/dev_manager.h2
-rw-r--r--lib/cache/lvmcache.c33
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,