summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-11-30 12:11:01 -0600
committerDavid Teigland <teigland@redhat.com>2015-11-30 13:18:31 -0600
commit3c2737c8a522f2f492d99893f1eb08479d73090d (patch)
tree3c756a4264e1235b8da2c7c70ebba1c2a97f6df9
parent2160cdc1a16a4fc7b6626f865ddd29fa49cdefef (diff)
downloadlvm2-dev-dct-dupvgnames-B.tar.gz
process_each: resolve duplicate VG namesdev-dct-dupvgnames-B
If two different VGs with the same name exist on the system, a command that just specifies that ambiguous name will fail with a new error: $ vgs -o name,uuid ... foo qyUS65-vn32-TuKs-a8yF-wfeQ-7DkF-Fds0uf foo vfhKCP-mpc7-KLLL-Uh08-4xPG-zLNR-4cnxJX $ lvs foo Multiple VGs found with the same name: foo Use the --select option with VG UUID (vg_uuid). $ vgremove foo Multiple VGs found with the same name: foo Use the --select option with VG UUID (vg_uuid). $ lvs -S vg_uuid=qyUS65-vn32-TuKs-a8yF-wfeQ-7DkF-Fds0uf lv1 foo ... This is implemented for process_each_vg/lv, and works with or without lvmetad. It does not work for commands that do not use process_each. This change includes one exception to the behavior shown above. If one of the VGs is foreign, and the other is not, then the command assumes that the intended VG is the local one and uses it.
-rw-r--r--tools/toollib.c93
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.");