diff options
Diffstat (limited to 'tools/toollib.c')
-rw-r--r-- | tools/toollib.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/tools/toollib.c b/tools/toollib.c index 18ccd4f19..700089191 100644 --- a/tools/toollib.c +++ b/tools/toollib.c @@ -2022,6 +2022,77 @@ static int _copy_str_to_vgnameid_list(struct cmd_context *cmd, struct dm_list *s } /* + * Check if a command line VG name is ambiguous, i.e. there are multiple VGs on + * the system that have the given name. If *one* VG with the given name is + * local and the rest are foreign, then use the local VG (removing foreign VGs + * with the same name from the vgnameids_on_system list). If multiple VGs with + * the given name are local, we don't know which VG is intended, so remove the + * ambiguous name from the list of args. + */ +static int _resolve_duplicate_vgnames(struct cmd_context *cmd, + struct dm_list *arg_vgnames, + struct dm_list *vgnameids_on_system) +{ + struct dm_str_list *sl, *sl2; + struct vgnameid_list *vgnl, *vgnl2; + char uuid[64] __attribute__((aligned(8))); + int found; + int ret = ECMD_PROCESSED; + + dm_list_iterate_items_safe(sl, sl2, arg_vgnames) { + found = 0; + dm_list_iterate_items(vgnl, vgnameids_on_system) { + if (strcmp(sl->str, vgnl->vg_name)) + continue; + found++; + } + + if (found < 2) + continue; + + /* + * More than one VG match the given name. + * If only one is local, use that one. + */ + + found = 0; + dm_list_iterate_items_safe(vgnl, vgnl2, vgnameids_on_system) { + if (strcmp(sl->str, vgnl->vg_name)) + continue; + + /* + * Without lvmetad, a label scan has already populated + * lvmcache vginfo with this information. + * With lvmetad, this function does vg_lookup on this + * name/vgid and checks system_id in the metadata. + */ + if (lvmcache_vg_is_foreign(cmd, vgnl->vg_name, vgnl->vgid)) { + id_write_format((const struct id*)vgnl->vgid, uuid, sizeof(uuid)); + log_warn("WARNING: Ignoring foreign VG with matching name %s UUID %s.", + vgnl->vg_name, uuid); + dm_list_del(&vgnl->list); + } else { + found++; + } + } + + if (found < 2) + continue; + + /* + * More than one VG with this name is local so the intended VG + * is unknown. + */ + log_error("Multiple VGs found with the same name: %s", sl->str); + log_error("Use the --select option with VG UUID (vg_uuid)."); + dm_list_del(&sl->list); + ret = ECMD_FAILED; + } + + return ret; +} + +/* * For each arg_vgname, move the corresponding entry from * vgnameids_on_system to vgnameids_to_process. If an * item in arg_vgnames doesn't exist in vgnameids_on_system, @@ -2137,6 +2208,17 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv, goto_out; } + if (!dm_list_empty(&arg_vgnames)) { + /* This may remove entries from arg_vgnames or vgnameids_on_system. */ + ret = _resolve_duplicate_vgnames(cmd, &arg_vgnames, &vgnameids_on_system); + if (ret > ret_max) + ret_max = ret; + if (dm_list_empty(&arg_vgnames) && dm_list_empty(&arg_tags)) { + ret_max = ECMD_FAILED; + goto out; + } + } + if (dm_list_empty(&arg_vgnames) && dm_list_empty(&vgnameids_on_system)) { /* FIXME Should be log_print, but suppressed for reporting cmds */ log_verbose("No volume groups found."); @@ -2638,6 +2720,17 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, uint32_t rea goto_out; } + if (!dm_list_empty(&arg_vgnames)) { + /* This may remove entries from arg_vgnames or vgnameids_on_system. */ + ret = _resolve_duplicate_vgnames(cmd, &arg_vgnames, &vgnameids_on_system); + if (ret > ret_max) + ret_max = ret; + if (dm_list_empty(&arg_vgnames) && dm_list_empty(&arg_tags)) { + ret_max = ECMD_FAILED; + goto out; + } + } + if (dm_list_empty(&arg_vgnames) && dm_list_empty(&vgnameids_on_system)) { /* FIXME Should be log_print, but suppressed for reporting cmds */ log_verbose("No volume groups found."); |