diff options
author | David Teigland <teigland@redhat.com> | 2015-01-09 14:55:16 -0600 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2015-01-13 13:19:09 -0600 |
commit | af3085fe9745d9123032ceb2e9c1522d855b68be (patch) | |
tree | 7bed3ec21f34e725a5313886578147b3c2ff6cb1 | |
parent | 1e4a4d48aeb1e56a8df19ba73425eb5f7632c9d2 (diff) | |
download | lvm2-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.c | 25 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 3 | ||||
-rw-r--r-- | lib/device/device.h | 6 | ||||
-rw-r--r-- | tools/toollib.c | 136 |
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; } |