summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-01-09 14:55:16 -0600
committerDavid Teigland <teigland@redhat.com>2015-01-13 13:19:09 -0600
commitaf3085fe9745d9123032ceb2e9c1522d855b68be (patch)
tree7bed3ec21f34e725a5313886578147b3c2ff6cb1
parent1e4a4d48aeb1e56a8df19ba73425eb5f7632c9d2 (diff)
downloadlvm2-dev-dct-pvdup4.tar.gz
toollib: handle duplicate pvs in process_in_pvdev-dct-pvdup4
Without lvmetad. With two duplicate devices, loop0 and loop3: # pvs Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0 PV VG Fmt Attr PSize PFree /dev/loop3 loopa lvm2 a-- 12.00m 12.00m # pvs /dev/loop3 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0 PV VG Fmt Attr PSize PFree /dev/loop3 loopa lvm2 a-- 12.00m 12.00m # pvs /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0 PV /dev/loop3 selected by duplicate device /dev/loop0. PV VG Fmt Attr PSize PFree /dev/loop3 loopa lvm2 a-- 12.00m 12.00m # pvs /dev/loop0 /dev/loop3 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0 PV /dev/loop3 repeated for duplicate device /dev/loop0. PV VG Fmt Attr PSize PFree /dev/loop0 loopa lvm2 a-- 12.00m 12.00m /dev/loop3 loopa lvm2 a-- 12.00m 12.00m # pvs -o+dev_size /dev/loop0 /dev/loop3 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop0 PV /dev/loop3 repeated for duplicate device /dev/loop0. PV VG Fmt Attr PSize PFree DevSize /dev/loop0 loopa lvm2 a-- 12.00m 12.00m 16.00m /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m With three duplicate devices, loop0, loop1, loop3: # pvs -o+dev_size Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV VG Fmt Attr PSize PFree DevSize /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop3 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV VG Fmt Attr PSize PFree DevSize /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV /dev/loop3 selected by duplicate device /dev/loop0. PV VG Fmt Attr PSize PFree DevSize /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop1 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV /dev/loop3 selected by duplicate device /dev/loop1. PV VG Fmt Attr PSize PFree DevSize /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop3 /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV /dev/loop3 repeated for duplicate device /dev/loop0. PV VG Fmt Attr PSize PFree DevSize /dev/loop0 loopa lvm2 a-- 12.00m 12.00m 16.00m /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop3 /dev/loop1 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV /dev/loop3 repeated for duplicate device /dev/loop1. PV VG Fmt Attr PSize PFree DevSize /dev/loop1 loopa lvm2 a-- 12.00m 12.00m 32.00m /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop0 /dev/loop1 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV /dev/loop3 selected by duplicate device /dev/loop0. PV /dev/loop3 repeated for duplicate device /dev/loop1. PV VG Fmt Attr PSize PFree DevSize /dev/loop1 loopa lvm2 a-- 12.00m 12.00m 32.00m /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m # pvs -o+dev_size /dev/loop0 /dev/loop1 /dev/loop3 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop1 not /dev/loop0 Found duplicate PV XhLbpVo0hmuwrMQLjfxuAvPFUFZqD4vr: using /dev/loop3 not /dev/loop1 PV /dev/loop3 repeated for duplicate device /dev/loop0. PV /dev/loop3 repeated for duplicate device /dev/loop1. PV VG Fmt Attr PSize PFree DevSize /dev/loop0 loopa lvm2 a-- 12.00m 12.00m 16.00m /dev/loop1 loopa lvm2 a-- 12.00m 12.00m 32.00m /dev/loop3 loopa lvm2 a-- 12.00m 12.00m 32.00m
-rw-r--r--lib/cache/lvmcache.c25
-rw-r--r--lib/cache/lvmcache.h3
-rw-r--r--lib/device/device.h6
-rw-r--r--tools/toollib.c136
4 files changed, 132 insertions, 38 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 416907e99..eb88c9305 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -1467,6 +1467,29 @@ int lvmcache_update_vg(struct volume_group *vg, unsigned precommitted)
return 1;
}
+/*
+ * Replace pv->dev with dev so that dev will appear for reporting.
+ */
+
+void lvmcache_replace_dev(struct cmd_context *cmd, struct physical_volume *pv,
+ struct device *dev)
+{
+ struct lvmcache_info *info;
+ char pvid_s[ID_LEN + 1] __attribute__((aligned(8)));
+
+ strncpy(pvid_s, (char *) &pv->id, sizeof(pvid_s) - 1);
+ pvid_s[sizeof(pvid_s) - 1] = '\0';
+
+ if (!(info = lvmcache_info_from_pvid(pvid_s, 0)))
+ return;
+
+ /* pv_dev->pvid[0] = '\0'; */
+ strncpy(dev->pvid, pvid_s, sizeof(pvid_s) - 1);
+ info->dev = dev;
+ info->label->dev = dev;
+ pv->dev = dev;
+}
+
struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
struct device *dev,
const char *vgname, const char *vgid,
@@ -1539,7 +1562,7 @@ struct lvmcache_info *lvmcache_add(struct labeller *labeller, const char *pvid,
//else if (dm_is_dm_major(MAJOR(existing->dev->dev)) &&
//dm_is_dm_major(MAJOR(dev->dev)))
//
- else if (!strcmp(pvid_s, existing->dev->pvid))
+ else if (!strcmp(pvid_s, existing->dev->pvid))
log_error("Found duplicate PV %s: using %s not "
"%s", pvid, dev_name(dev),
dev_name(existing->dev));
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index d43866dca..7a049175b 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -157,4 +157,7 @@ unsigned lvmcache_mda_count(struct lvmcache_info *info);
int lvmcache_vgid_is_cached(const char *vgid);
uint64_t lvmcache_smallest_mda_size(struct lvmcache_info *info);
+void lvmcache_replace_dev(struct cmd_context *cmd, struct physical_volume *pv,
+ struct device *dev);
+
#endif
diff --git a/lib/device/device.h b/lib/device/device.h
index c916a4bdb..097800cb2 100644
--- a/lib/device/device.h
+++ b/lib/device/device.h
@@ -57,6 +57,12 @@ struct device_list {
struct device *dev;
};
+struct device_id_list {
+ struct dm_list list;
+ struct device *dev;
+ char pvid[ID_LEN + 1];
+};
+
struct device_area {
struct device *dev;
uint64_t start; /* Bytes */
diff --git a/tools/toollib.c b/tools/toollib.c
index 1b3883e7f..d90e5aec5 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -2079,20 +2079,21 @@ static int _get_arg_devices(struct cmd_context *cmd,
struct dm_list *arg_devices)
{
struct dm_str_list *sl;
- struct device_list *devl;
+ struct device_id_list *dil;
int ret_max = ECMD_PROCESSED;
dm_list_iterate_items(sl, arg_pvnames) {
- if (!(devl = dm_pool_alloc(cmd->mem, sizeof(*devl)))) {
- log_error("device_list alloc failed.");
+ if (!(dil = dm_pool_alloc(cmd->mem, sizeof(*dil)))) {
+ log_error("device_id_list alloc failed.");
return ECMD_FAILED;
}
- if (!(devl->dev = dev_cache_get(sl->str, cmd->filter))) {
- log_error("Failed to find physical volume \"%s\".", sl->str);
+ if (!(dil->dev = dev_cache_get(sl->str, cmd->filter))) {
+ log_error("Failed to find device for physical volume \"%s\".", sl->str);
ret_max = ECMD_FAILED;
} else {
- dm_list_add(arg_devices, &devl->list);
+ strncpy(dil->pvid, dil->dev->pvid, ID_LEN);
+ dm_list_add(arg_devices, &dil->list);
}
}
@@ -2103,7 +2104,7 @@ static int _get_all_devices(struct cmd_context *cmd, struct dm_list *all_devices
{
struct dev_iter *iter;
struct device *dev;
- struct device_list *devl;
+ struct device_id_list *dil;
int r = ECMD_FAILED;
lvmcache_seed_infos_from_lvmetad(cmd);
@@ -2114,13 +2115,13 @@ static int _get_all_devices(struct cmd_context *cmd, struct dm_list *all_devices
}
while ((dev = dev_iter_get(iter))) {
- if (!(devl = dm_pool_alloc(cmd->mem, sizeof(*devl)))) {
- log_error("device_list alloc failed.");
+ if (!(dil = dm_pool_alloc(cmd->mem, sizeof(*dil)))) {
+ log_error("device_id_list alloc failed.");
goto out;
}
- devl->dev = dev;
- dm_list_add(all_devices, &devl->list);
+ dil->dev = dev;
+ dm_list_add(all_devices, &dil->list);
}
r = ECMD_PROCESSED;
@@ -2129,13 +2130,13 @@ out:
return r;
}
-static int _device_list_remove(struct dm_list *all_devices, struct device *dev)
+static int _device_list_remove(struct dm_list *devices, struct device *dev)
{
- struct device_list *devl;
+ struct device_id_list *dil;
- dm_list_iterate_items(devl, all_devices) {
- if (devl->dev == dev) {
- dm_list_del(&devl->list);
+ dm_list_iterate_items(dil, devices) {
+ if (dil->dev == dev) {
+ dm_list_del(&dil->list);
return 1;
}
}
@@ -2143,16 +2144,28 @@ static int _device_list_remove(struct dm_list *all_devices, struct device *dev)
return 0;
}
-static int _device_list_match(struct dm_list *devices, struct device *dev)
+static struct device_id_list *_device_list_find_dev(struct dm_list *devices, struct device *dev)
{
- struct device_list *devl;
+ struct device_id_list *dil;
- dm_list_iterate_items(devl, devices) {
- if (devl->dev == dev)
- return 1;
+ dm_list_iterate_items(dil, devices) {
+ if (dil->dev == dev)
+ return dil;
}
- return 0;
+ return NULL;
+}
+
+static struct device_id_list *_device_list_find_pvid(struct dm_list *devices, struct physical_volume *pv)
+{
+ struct device_id_list *dil;
+
+ dm_list_iterate_items(dil, devices) {
+ if (id_equal((struct id *) dil->pvid, &pv->id))
+ return dil;
+ }
+
+ return NULL;
}
static int _process_device_list(struct cmd_context *cmd, struct dm_list *all_devices,
@@ -2160,7 +2173,7 @@ static int _process_device_list(struct cmd_context *cmd, struct dm_list *all_dev
{
struct physical_volume pv_dummy;
struct physical_volume *pv;
- struct device_list *devl;
+ struct device_id_list *dil;
int ret_max = ECMD_PROCESSED;
int ret = 0;
@@ -2168,17 +2181,17 @@ static int _process_device_list(struct cmd_context *cmd, struct dm_list *all_dev
* Pretend that each device is a PV with dummy values.
* FIXME Formalise this extension or find an alternative.
*/
- dm_list_iterate_items(devl, all_devices) {
+ dm_list_iterate_items(dil, all_devices) {
if (sigint_caught())
return_ECMD_FAILED;
memset(&pv_dummy, 0, sizeof(pv_dummy));
dm_list_init(&pv_dummy.tags);
dm_list_init(&pv_dummy.segments);
- pv_dummy.dev = devl->dev;
+ pv_dummy.dev = dil->dev;
pv = &pv_dummy;
- log_very_verbose("Processing device %s.", dev_name(devl->dev));
+ log_very_verbose("Processing device %s.", dev_name(dil->dev));
ret = process_single_pv(cmd, NULL, pv, handle);
@@ -2201,6 +2214,8 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
{
struct physical_volume *pv;
struct pv_list *pvl;
+ struct device_id_list *dil;
+ struct device *dev_orig;
const char *pv_name;
int process_pv;
int dev_found;
@@ -2219,9 +2234,19 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
/* Remove each arg_devices entry as it is processed. */
if (!process_pv && !dm_list_empty(arg_devices) &&
- _device_list_match(arg_devices, pv->dev)) {
+ (dil = _device_list_find_dev(arg_devices, pv->dev))) {
process_pv = 1;
- _device_list_remove(arg_devices, pv->dev);
+ _device_list_remove(arg_devices, dil->dev);
+ }
+
+ /* Select the PV if the device arg has the same pvid. */
+
+ if (!process_pv && !dm_list_empty(arg_devices) &&
+ (dil = _device_list_find_pvid(arg_devices, pv))) {
+ log_warn("PV %s selected by duplicate device %s.",
+ pv_name, dev_name(dil->dev));
+ process_pv = 1;
+ _device_list_remove(arg_devices, dil->dev);
}
if (!process_pv && !dm_list_empty(arg_tags) &&
@@ -2257,6 +2282,39 @@ static int _process_pvs_in_vg(struct cmd_context *cmd,
if (ret > ret_max)
ret_max = ret;
}
+
+ /*
+ * This is a very rare and obscure case where multiple
+ * duplicate devices are specified on the command line
+ * referring to this PV. In this case we want to
+ * process this PV once for each specified device.
+ */
+
+ if (!skip && !dm_list_empty(arg_devices)) {
+ while ((dil = _device_list_find_pvid(arg_devices, pv))) {
+ log_warn("PV %s repeated for duplicate device %s.",
+ pv_name, dev_name(dil->dev));
+
+ _device_list_remove(arg_devices, dil->dev);
+
+ /*
+ * Replace pv->dev with this dil->dev
+ * in lvmcache so the duplicate dev
+ * info will be reported.
+ */
+ dev_orig = pv->dev;
+ lvmcache_replace_dev(cmd, pv, dil->dev);
+
+ ret = process_single_pv(cmd, vg, pv, handle);
+ if (ret != ECMD_PROCESSED)
+ stack;
+ if (ret > ret_max)
+ ret_max = ret;
+
+ /* Put the cache state back as it was. */
+ lvmcache_replace_dev(cmd, pv, dev_orig);
+ }
+ }
}
/*
@@ -2347,10 +2405,10 @@ int process_each_pv(struct cmd_context *cmd,
{
struct dm_list arg_tags; /* str_list */
struct dm_list arg_pvnames; /* str_list */
- struct dm_list arg_devices; /* device_list */
+ struct dm_list arg_devices; /* device_id_list */
struct dm_list all_vgnameids; /* vgnameid_list */
struct dm_list all_devices; /* device_list */
- struct device_list *devl;
+ struct device_id_list *dil;
int process_all_pvs;
int process_all_devices;
int ret_max = ECMD_PROCESSED;
@@ -2363,6 +2421,15 @@ int process_each_pv(struct cmd_context *cmd,
dm_list_init(&all_devices);
/*
+ * We need to read all the vgs first because this has the effect
+ * of initializing other device/lvmcache info that we need.
+ */
+ if ((ret = _get_vgnameids_on_system(cmd, &all_vgnameids, only_this_vgname, 1) != ECMD_PROCESSED)) {
+ stack;
+ return ret;
+ }
+
+ /*
* Create two lists from argv:
* arg_pvnames: pvs explicitly named in argv
* arg_tags: tags explicitly named in argv
@@ -2396,11 +2463,6 @@ int process_each_pv(struct cmd_context *cmd,
return ret;
}
- if ((ret = _get_vgnameids_on_system(cmd, &all_vgnameids, only_this_vgname, 1) != ECMD_PROCESSED)) {
- stack;
- return ret;
- }
-
ret = _process_pvs_in_vgs(cmd, flags, &all_vgnameids, &all_devices,
&arg_devices, &arg_tags, process_all_pvs,
handle, process_single_pv);
@@ -2409,8 +2471,8 @@ int process_each_pv(struct cmd_context *cmd,
if (ret > ret_max)
ret_max = ret;
- dm_list_iterate_items(devl, &arg_devices) {
- log_error("Failed to find physical volume \"%s\".", dev_name(devl->dev));
+ dm_list_iterate_items(dil, &arg_devices) {
+ log_error("Failed to find physical volume \"%s\".", dev_name(dil->dev));
ret_max = ECMD_FAILED;
}