[lvm-devel] master - toollib: Rewrite process_each_lv.

Alasdair Kergon agk at fedoraproject.org
Fri Oct 3 22:39:20 UTC 2014


Gitweb:        http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=91615603cdc7974047103c4c6f6af7e56f97437b
Commit:        91615603cdc7974047103c4c6f6af7e56f97437b
Parent:        bfb6a4ecc6ad7bb06649ffd026d9c997443dd684
Author:        David Teigland <teigland at redhat.com>
AuthorDate:    Fri Oct 3 23:37:49 2014 +0100
Committer:     Alasdair G Kergon <agk at redhat.com>
CommitterDate: Fri Oct 3 23:37:49 2014 +0100

toollib: Rewrite process_each_lv.

Copy the same form as the new process_each_vg.
Replace unused struct cmd_vg and cmd_vg_read() replicator
code with struct vg and vg_read() directly.
The failed_lvnames arg is no longer used since the
cmd_vg replicator wrapper was removed.

[Committed by agk with cosmetic changes and tweaks.]
---
 tools/toollib.c   |  643 ++++++++++++++++++++++++++++-------------------------
 tools/toollib.h   |    3 +-
 tools/vgdisplay.c |    2 +-
 3 files changed, 340 insertions(+), 308 deletions(-)

diff --git a/tools/toollib.c b/tools/toollib.c
index 8049b1f..721c727 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -184,308 +184,6 @@ int ignore_vg(struct volume_group *vg, const char *vg_name, int allow_inconsiste
 /*
  * Metadata iteration functions
  */
-int process_each_lv_in_vg(struct cmd_context *cmd,
-			  struct volume_group *vg,
-			  const struct dm_list *arg_lvnames,
-			  const struct dm_list *tagsl,
-			  struct dm_list *failed_lvnames,
-			  void *handle,
-			  process_single_lv_fn_t process_single_lv)
-{
-	int ret_max = ECMD_PROCESSED;
-	int ret;
-	unsigned process_all = 0;
-	unsigned tags_supplied = 0;
-	unsigned lvargs_supplied = 0;
-	unsigned lvargs_matched = 0;
-	char *lv_name;
-	struct lv_list *lvl;
-
-	if (!vg_check_status(vg, EXPORTED_VG))
-		return ECMD_FAILED;
-
-	if (tagsl && !dm_list_empty(tagsl))
-		tags_supplied = 1;
-
-	if (arg_lvnames && !dm_list_empty(arg_lvnames))
-		lvargs_supplied = 1;
-
-	/* Process all LVs in this VG if no restrictions given */
-	if (!tags_supplied && !lvargs_supplied)
-		process_all = 1;
-	/* Or if VG tags match */
-	else if (tags_supplied &&
-		 str_list_match_list(tagsl, &vg->tags, NULL))
-		process_all = 1;
-
-	/*
-	 * FIXME: In case of remove it goes through deleted entries,
-	 * but it works since entries are allocated from vg mem pool.
-	 */
-	dm_list_iterate_items(lvl, &vg->lvs) {
-		if (lvl->lv->status & SNAPSHOT)
-			continue;
-
-		/* Skip availability change for non-virt snaps when processing all LVs */
-		/* FIXME: pass process_all to process_single_lv() */
-		if (process_all && arg_count(cmd, activate_ARG) &&
-		    lv_is_cow(lvl->lv) && !lv_is_virtual_origin(origin_from_cow(lvl->lv)))
-			continue;
-
-		if (lv_is_virtual_origin(lvl->lv) && !arg_count(cmd, all_ARG)) {
-			if (lvargs_supplied &&
-			    str_list_match_item(arg_lvnames, lvl->lv->name))
-				log_print_unless_silent("Ignoring virtual origin logical volume %s.",
-							display_lvname(lvl->lv));
-			continue;
-		}
-
-		/*
-		 * Only let hidden LVs through it --all was used or the LVs 
-		 * were specifically named on the command line.
-		 */
-		if (!lvargs_supplied && !lv_is_visible(lvl->lv) && !arg_count(cmd, all_ARG))
-			continue;
-
-		/* LV name match? */
-		if (lvargs_supplied &&
-		    str_list_match_item(arg_lvnames, lvl->lv->name))
-			/* Check even when process_all for counter */
-			lvargs_matched++;
-		/* LV tag match?   skip test, when process_all */
-		else if (!process_all &&
-			 (!tags_supplied ||
-			  !str_list_match_list(tagsl, &lvl->lv->tags, NULL)))
-			continue;
-
-		if (sigint_caught())
-			return_ECMD_FAILED;
-
-		lvl->lv->vg->cmd_missing_vgs = 0;
-		ret = process_single_lv(cmd, lvl->lv, handle);
-		if (ret != ECMD_PROCESSED && failed_lvnames) {
-			lv_name = dm_pool_strdup(cmd->mem, lvl->lv->name);
-			if (!lv_name ||
-			    !str_list_add(cmd->mem, failed_lvnames, lv_name)) {
-				log_error("Allocation failed for str_list.");
-				return ECMD_FAILED;
-			}
-			if (lvl->lv->vg->cmd_missing_vgs)
-				ret = ECMD_PROCESSED;
-		}
-		if (ret > ret_max)
-			ret_max = ret;
-	}
-
-	if (lvargs_supplied && lvargs_matched != dm_list_size(arg_lvnames)) {
-		/*
-		 * FIXME: lvm supports removal of LV with all its dependencies
-		 * this leads to miscalculation that depends on the order of args.
-		 */
-		log_error("One or more specified logical volume(s) not found.");
-		if (ret_max < ECMD_FAILED)
-			ret_max = ECMD_FAILED;
-	}
-
-	return ret_max;
-}
-
-int process_each_lv(struct cmd_context *cmd, int argc, char **argv,
-		    uint32_t flags, void *handle,
-		    process_single_lv_fn_t process_single_lv)
-{
-	int opt = 0;
-	int ret_max = ECMD_PROCESSED;
-	int ret;
-
-	struct dm_list *tags_arg;
-	struct dm_list *vgnames;	/* VGs to process */
-	struct dm_str_list *sll, *strl;
-	struct cmd_vg *cvl_vg;
-	struct dm_list cmd_vgs;
-	struct dm_list failed_lvnames;
-	struct dm_list tagsl, lvnames;
-	struct dm_list arg_lvnames;	/* Cmdline vgname or vgname/lvname */
-	struct dm_list arg_vgnames;
-	char *vglv;
-	size_t vglv_sz;
-
-	const char *vgname;
-
-	dm_list_init(&tagsl);
-	dm_list_init(&arg_lvnames);
-	dm_list_init(&failed_lvnames);
-
-	if (argc) {
-		log_verbose("Using logical volume(s) on command line");
-		dm_list_init(&arg_vgnames);
-
-		for (; opt < argc; opt++) {
-			const char *lv_name = argv[opt];
-			const char *tmp_lv_name;
-			char *vgname_def;
-			unsigned dev_dir_found = 0;
-
-			/* Do we have a tag or vgname or lvname? */
-			vgname = lv_name;
-
-			if (*vgname == '@') {
-				if (!validate_tag(vgname + 1)) {
-					log_error("Skipping invalid tag %s",
-						  vgname);
-					continue;
-				}
-				if (!str_list_add(cmd->mem, &tagsl,
-						  dm_pool_strdup(cmd->mem,
-							      vgname + 1))) {
-					log_error("strlist allocation failed");
-					return ECMD_FAILED;
-				}
-				continue;
-			}
-
-			/* FIXME Jumbled parsing */
-			vgname = skip_dev_dir(cmd, vgname, &dev_dir_found);
-
-			if (*vgname == '/') {
-				log_error("\"%s\": Invalid path for Logical "
-					  "Volume", argv[opt]);
-				if (ret_max < ECMD_FAILED)
-					ret_max = ECMD_FAILED;
-				continue;
-			}
-			lv_name = vgname;
-			if ((tmp_lv_name = strchr(vgname, '/'))) {
-				/* Must be an LV */
-				lv_name = tmp_lv_name;
-				while (*lv_name == '/')
-					lv_name++;
-				if (!(vgname = extract_vgname(cmd, vgname))) {
-					if (ret_max < ECMD_FAILED) {
-						stack;
-						ret_max = ECMD_FAILED;
-					}
-					continue;
-				}
-			} else if (!dev_dir_found &&
-				   (vgname_def = default_vgname(cmd))) {
-				vgname = vgname_def;
-			} else
-				lv_name = NULL;
-
-			if (!str_list_add(cmd->mem, &arg_vgnames,
-					  dm_pool_strdup(cmd->mem, vgname))) {
-				log_error("strlist allocation failed");
-				return ECMD_FAILED;
-			}
-
-			if (!lv_name) {
-				if (!str_list_add(cmd->mem, &arg_lvnames,
-						  dm_pool_strdup(cmd->mem,
-							      vgname))) {
-					log_error("strlist allocation failed");
-					return ECMD_FAILED;
-				}
-			} else {
-				vglv_sz = strlen(vgname) + strlen(lv_name) + 2;
-				if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
-				    dm_snprintf(vglv, vglv_sz, "%s/%s", vgname,
-						 lv_name) < 0) {
-					log_error("vg/lv string alloc failed");
-					return ECMD_FAILED;
-				}
-				if (!str_list_add(cmd->mem, &arg_lvnames, vglv)) {
-					log_error("strlist allocation failed");
-					return ECMD_FAILED;
-				}
-			}
-		}
-		vgnames = &arg_vgnames;
-	}
-
-	if (!argc || !dm_list_empty(&tagsl)) {
-		log_verbose("Finding all logical volumes");
-		if (!lvmetad_vg_list_to_lvmcache(cmd))
-			stack;
-		if (!(vgnames = get_vgnames(cmd, 0)) || dm_list_empty(vgnames)) {
-			log_error("No volume groups found");
-			return ret_max;
-		}
-	}
-
-	dm_list_iterate_items(strl, vgnames) {
-		vgname = strl->str;
-		dm_list_init(&cmd_vgs);
-		if (!(cvl_vg = cmd_vg_add(cmd->mem, &cmd_vgs,
-					  vgname, NULL, flags)))
-			return_ECMD_FAILED;
-
-		if (!cmd_vg_read(cmd, &cmd_vgs)) {
-			if (ignore_vg(cvl_vg->vg, vgname, 0, &ret_max))
-				stack;
-
-			free_cmd_vgs(&cmd_vgs);
-			continue;
-		}
-
-		tags_arg = &tagsl;
-		dm_list_init(&lvnames);	/* LVs to be processed in this VG */
-		dm_list_iterate_items(sll, &arg_lvnames) {
-			const char *vg_name = sll->str;
-			const char *lv_name = strchr(vg_name, '/');
-
-			if ((!lv_name && !strcmp(vg_name, vgname))) {
-				/* Process all LVs in this VG */
-				tags_arg = NULL;
-				dm_list_init(&lvnames);
-				break;
-			} else if (!strncmp(vg_name, vgname, strlen(vgname)) && lv_name &&
-				   strlen(vgname) == (size_t) (lv_name - vg_name)) {
-				if (!str_list_add(cmd->mem, &lvnames,
-						  dm_pool_strdup(cmd->mem,
-								 lv_name + 1))) {
-					log_error("strlist allocation failed");
-					free_cmd_vgs(&cmd_vgs);
-					return ECMD_FAILED;
-				}
-			}
-		}
-
-		for (;;) {
-			if (sigint_caught())
-				return_ECMD_FAILED;
-
-			ret = process_each_lv_in_vg(cmd, cvl_vg->vg, &lvnames,
-						    tags_arg, &failed_lvnames,
-						    handle, process_single_lv);
-			if (ret != ECMD_PROCESSED) {
-				stack;
-				break;
-			}
-
-			if (dm_list_empty(&failed_lvnames))
-				break;
-
-			/* Try again with failed LVs in this VG */
-			dm_list_init(&lvnames);
-			dm_list_splice(&lvnames, &failed_lvnames);
-
-			free_cmd_vgs(&cmd_vgs);
-			if (!cmd_vg_read(cmd, &cmd_vgs)) {
-				stack;
-				ret = ECMD_FAILED; /* break */
-				break;
-			}
-		}
-		if (ret > ret_max)
-			ret_max = ret;
-
-		free_cmd_vgs(&cmd_vgs);
-	}
-
-	return ret_max;
-}
-
 int process_each_segment_in_pv(struct cmd_context *cmd,
 			       struct volume_group *vg,
 			       struct physical_volume *pv,
@@ -2002,8 +1700,8 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
  * Copy the contents of a str_list of VG names to a name list, filling
  * in the vgid with NULL (unknown).
  */
-static int _copy_str_to_name_list(struct cmd_context *cmd, struct dm_list *sll,
-				  struct dm_list *vgnll)
+static int _copy_str_to_vgnameid_list(struct cmd_context *cmd, struct dm_list *sll,
+				      struct dm_list *vgnll)
 {
 	const char *vgname;
 	struct dm_str_list *sl;
@@ -2067,6 +1765,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
 	}
 
 	if (dm_list_empty(&arg_vgnames) && dm_list_empty(&vgnameids_on_system)) {
+		/* FIXME Should be log_print, but suppressed for reporting cmds */
 		log_error("No volume groups found");
 		return ECMD_PROCESSED;
 	}
@@ -2077,7 +1776,7 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
 	 */
 	if (!dm_list_empty(&vgnameids_on_system))
 		dm_list_splice(&vgnameids_to_process, &vgnameids_on_system);
-	else if ((ret = _copy_str_to_name_list(cmd, &arg_vgnames, &vgnameids_to_process)) != ECMD_PROCESSED) {
+	else if ((ret = _copy_str_to_vgnameid_list(cmd, &arg_vgnames, &vgnameids_to_process)) != ECMD_PROCESSED) {
 		stack;
 		return ret;
 	}
@@ -2085,3 +1784,337 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
 	return _process_vgnameid_list(cmd, flags, &vgnameids_to_process,
 				      &arg_vgnames, &arg_tags, handle, process_single_vg);
 }
+
+int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
+			  struct dm_list *arg_lvnames, const struct dm_list *tags_in,
+			  void *handle, process_single_lv_fn_t process_single_lv)
+{
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+	unsigned process_all = 0;
+	unsigned tags_supplied = 0;
+	unsigned lvargs_supplied = 0;
+	struct lv_list *lvl;
+	struct dm_str_list *sl;
+
+	if (!vg_check_status(vg, EXPORTED_VG))
+		return_ECMD_FAILED;
+
+	if (tags_in && !dm_list_empty(tags_in))
+		tags_supplied = 1;
+
+	if (arg_lvnames && !dm_list_empty(arg_lvnames))
+		lvargs_supplied = 1;
+
+	/* Process all LVs in this VG if no restrictions given 
+	 * or if VG tags match. */
+	if ((!tags_supplied && !lvargs_supplied) ||
+	    (tags_supplied && str_list_match_list(tags_in, &vg->tags, NULL)))
+		process_all = 1;
+
+	/*
+	 * FIXME: In case of remove it goes through deleted entries,
+	 * but it works since entries are allocated from vg mem pool.
+	 */
+	dm_list_iterate_items(lvl, &vg->lvs) {
+		if (lvl->lv->status & SNAPSHOT)
+			continue;
+
+		/* Skip availability change for non-virt snaps when processing all LVs */
+		/* FIXME: pass process_all to process_single_lv() */
+		if (process_all && arg_count(cmd, activate_ARG) &&
+		    lv_is_cow(lvl->lv) && !lv_is_virtual_origin(origin_from_cow(lvl->lv)))
+			continue;
+
+		if (lv_is_virtual_origin(lvl->lv) && !arg_count(cmd, all_ARG)) {
+			if (lvargs_supplied &&
+			    str_list_match_item(arg_lvnames, lvl->lv->name))
+				log_print_unless_silent("Ignoring virtual origin logical volume %s.",
+							display_lvname(lvl->lv));
+			continue;
+		}
+
+		/*
+		 * Only let hidden LVs through it --all was used or the LVs 
+		 * were specifically named on the command line.
+		 */
+		if (!lvargs_supplied && !lv_is_visible(lvl->lv) && !arg_count(cmd, all_ARG))
+			continue;
+
+		/* Only process the LV if the name matches or process_all is set or if an LV tag matches */
+		if (lvargs_supplied && str_list_match_item(arg_lvnames, lvl->lv->name))
+			/* Remove LV from list of unprocessed LV names */
+			str_list_del(arg_lvnames, lvl->lv->name);
+		else if (!process_all &&
+			 (!tags_supplied || !str_list_match_list(tags_in, &lvl->lv->tags, NULL)))
+			continue;
+
+		if (sigint_caught())
+			return_ECMD_FAILED;
+
+		log_very_verbose("Processing LV %s in VG %s", lvl->lv->name, vg->name);
+
+		ret = process_single_lv(cmd, lvl->lv, handle);
+
+		if (ret > ret_max)
+			ret_max = ret;
+	}
+
+	if (lvargs_supplied) {
+		/*
+		 * FIXME: lvm supports removal of LV with all its dependencies
+		 * this leads to miscalculation that depends on the order of args.
+		 */
+		dm_list_iterate_items(sl, arg_lvnames) {
+			log_error("Failed to find logical volume \"%s/%s\"",
+				  vg->name, sl->str);
+			if (ret_max < ECMD_FAILED)
+				ret_max = ECMD_FAILED;
+		}
+	}
+
+	return ret_max;
+}
+
+/*
+ * If arg is tag, add it to arg_tags
+ * else the arg is either vgname or vgname/lvname:
+ * - add the vgname of each arg to arg_vgnames
+ * - if arg has no lvname, add just vgname arg_lvnames,
+ *   it represents all lvs in the vg
+ * - if arg has lvname, add vgname/lvname to arg_lvnames
+ */
+static int _get_arg_lvnames(struct cmd_context *cmd,
+			    int argc, char **argv,
+			    struct dm_list *arg_vgnames,
+			    struct dm_list *arg_lvnames,
+			    struct dm_list *arg_tags)
+{
+	int opt = 0;
+	int ret_max = ECMD_PROCESSED;
+	char *vglv;
+	size_t vglv_sz;
+	const char *vgname;
+	const char *lv_name;
+	const char *tmp_lv_name;
+	char *vgname_def;
+	unsigned dev_dir_found;
+
+	log_verbose("Using logical volume(s) on command line");
+
+	for (; opt < argc; opt++) {
+		lv_name = argv[opt];
+		dev_dir_found = 0;
+
+		/* Do we have a tag or vgname or lvname? */
+		vgname = lv_name;
+
+		if (*vgname == '@') {
+			if (!validate_tag(vgname + 1)) {
+				log_error("Skipping invalid tag %s", vgname);
+				continue;
+			}
+			if (!str_list_add(cmd->mem, arg_tags,
+					  dm_pool_strdup(cmd->mem, vgname + 1))) {
+				log_error("strlist allocation failed");
+				return ECMD_FAILED;
+			}
+			continue;
+		}
+
+		/* FIXME Jumbled parsing */
+		vgname = skip_dev_dir(cmd, vgname, &dev_dir_found);
+
+		if (*vgname == '/') {
+			log_error("\"%s\": Invalid path for Logical Volume",
+				  argv[opt]);
+			if (ret_max < ECMD_FAILED)
+				ret_max = ECMD_FAILED;
+			continue;
+		}
+		lv_name = vgname;
+		if ((tmp_lv_name = strchr(vgname, '/'))) {
+			/* Must be an LV */
+			lv_name = tmp_lv_name;
+			while (*lv_name == '/')
+				lv_name++;
+			if (!(vgname = extract_vgname(cmd, vgname))) {
+				if (ret_max < ECMD_FAILED) {
+					stack;
+					ret_max = ECMD_FAILED;
+				}
+				continue;
+			}
+		} else if (!dev_dir_found &&
+			   (vgname_def = default_vgname(cmd)))
+			vgname = vgname_def;
+		else
+			lv_name = NULL;
+
+		if (!str_list_add(cmd->mem, arg_vgnames,
+				  dm_pool_strdup(cmd->mem, vgname))) {
+			log_error("strlist allocation failed");
+			return ECMD_FAILED;
+		}
+
+		if (!lv_name) {
+			if (!str_list_add(cmd->mem, arg_lvnames,
+					  dm_pool_strdup(cmd->mem, vgname))) {
+				log_error("strlist allocation failed");
+				return ECMD_FAILED;
+			}
+		} else {
+			vglv_sz = strlen(vgname) + strlen(lv_name) + 2;
+			if (!(vglv = dm_pool_alloc(cmd->mem, vglv_sz)) ||
+			    dm_snprintf(vglv, vglv_sz, "%s/%s", vgname, lv_name) < 0) {
+				log_error("vg/lv string alloc failed");
+				return ECMD_FAILED;
+			}
+			if (!str_list_add(cmd->mem, arg_lvnames, vglv)) {
+				log_error("strlist allocation failed");
+				return ECMD_FAILED;
+			}
+		}
+	}
+
+	return ret_max;
+}
+
+static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
+				     struct dm_list *vgnameids_to_process,
+				     struct dm_list *arg_vgnames,
+				     struct dm_list *arg_lvnames,
+				     struct dm_list *arg_tags,
+				     void *handle,
+				     process_single_lv_fn_t process_single_lv)
+{
+	struct volume_group *vg;
+	struct vgnameid_list *nl;
+	struct dm_str_list *sl;
+	struct dm_list *tags_arg;
+	struct dm_list lvnames;
+	const char *vg_name;
+	const char *vg_uuid;
+	const char *vgn;
+	const char *lvn;
+	int ret_max = ECMD_PROCESSED;
+	int ret;
+
+	dm_list_iterate_items(nl, vgnameids_to_process) {
+		vg_name = nl->vg_name;
+		vg_uuid = nl->vgid;
+		ret = 0;
+
+		/*
+		 * arg_lvnames contains some elements that are just "vgname"
+		 * which means process all lvs in the vg.  Other elements
+		 * are "vgname/lvname" which means process only the select
+		 * lvs in the vg.
+		 */
+		tags_arg = arg_tags;
+		dm_list_init(&lvnames);	/* LVs to be processed in this VG */
+
+		dm_list_iterate_items(sl, arg_lvnames) {
+			vgn = sl->str;
+			lvn = strchr(vgn, '/');
+
+			if (!lvn && !strcmp(vgn, vg_name)) {
+				/* Process all LVs in this VG */
+				tags_arg = NULL;
+				dm_list_init(&lvnames);
+				break;
+			}
+			
+			if (lvn && !strncmp(vgn, vg_name, strlen(vg_name)) &&
+			    strlen(vg_name) == (size_t) (lvn - vgn)) {
+				if (!str_list_add(cmd->mem, &lvnames,
+						  dm_pool_strdup(cmd->mem, lvn + 1))) {
+					log_error("strlist allocation failed");
+					return ECMD_FAILED;
+				}
+			}
+		}
+
+		vg = vg_read(cmd, vg_name, vg_uuid, flags);
+		if (ignore_vg(vg, vg_name, flags & READ_ALLOW_INCONSISTENT, &ret)) {
+			if (ret > ret_max)
+				ret_max = ret;
+			release_vg(vg);
+			stack;
+			continue;
+		}
+
+		ret = process_each_lv_in_vg(cmd, vg, &lvnames, tags_arg,
+					    handle, process_single_lv);
+		unlock_and_release_vg(cmd, vg, vg_name);
+
+		if (ret > ret_max)
+			ret_max = ret;
+
+		if (sigint_caught())
+			break;
+	}
+
+	return ret_max;
+}
+
+/*
+ * Call process_single_lv() for each LV selected by the command line arguments.
+ */
+int process_each_lv(struct cmd_context *cmd, int argc, char **argv, uint32_t flags,
+		    void *handle, process_single_lv_fn_t process_single_lv)
+{
+	struct dm_list arg_tags;		/* str_list */
+	struct dm_list arg_vgnames;		/* str_list */
+	struct dm_list arg_lvnames;		/* str_list */
+	struct dm_list vgnameids_on_system;	/* vgnameid_list */
+	struct dm_list vgnameids_to_process;	/* vgnameid_list */
+
+	int enable_all_vgs = (cmd->command->flags & ALL_VGS_IS_DEFAULT);
+	int ret;
+
+	dm_list_init(&arg_tags);
+	dm_list_init(&arg_vgnames);
+	dm_list_init(&arg_lvnames);
+	dm_list_init(&vgnameids_on_system);
+	dm_list_init(&vgnameids_to_process);
+
+	/*
+	 * Find any LVs, VGs or tags explicitly provided on the command line.
+	 */
+	if ((ret = _get_arg_lvnames(cmd, argc, argv, &arg_vgnames, &arg_lvnames, &arg_tags) != ECMD_PROCESSED)) {
+		stack;
+		return ret;
+	}
+
+	/*
+	 * Obtain the complete list of VGs present on the system if it is needed because:
+	 *   any tags were supplied and need resolving; or
+	 *   no VG names were given and the command defaults to processing all VGs.
+	*/
+	if (((dm_list_empty(&arg_vgnames) && enable_all_vgs) || !dm_list_empty(&arg_tags)) &&
+	    (ret = _get_vgnameids_on_system(cmd, &vgnameids_on_system) != ECMD_PROCESSED)) {
+		stack;
+		return ret;
+	}
+
+	if (dm_list_empty(&arg_vgnames) && dm_list_empty(&vgnameids_on_system)) {
+		/* FIXME Should be log_print, but suppressed for reporting cmds */
+		log_error("No volume groups found");
+		return ECMD_PROCESSED;
+	}
+
+	/*
+	 * If we obtained a full list of VGs on the system, we need to work through them all;
+	 * otherwise we can merely work through the VG names provided.
+	 */
+	if (!dm_list_empty(&vgnameids_on_system))
+		dm_list_splice(&vgnameids_to_process, &vgnameids_on_system);
+	else if ((ret = _copy_str_to_vgnameid_list(cmd, &arg_vgnames, &vgnameids_to_process)) != ECMD_PROCESSED) {
+		stack;
+		return ret;
+	}
+
+	return _process_lv_vgnameid_list(cmd, flags, &vgnameids_to_process, &arg_vgnames, &arg_lvnames,
+					 &arg_tags, handle, process_single_lv);
+}
diff --git a/tools/toollib.h b/tools/toollib.h
index 8aa82e0..1a14d60 100644
--- a/tools/toollib.h
+++ b/tools/toollib.h
@@ -86,9 +86,8 @@ int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
 
 int process_each_lv_in_vg(struct cmd_context *cmd,
 			  struct volume_group *vg,
-			  const struct dm_list *arg_lvnames,
+			  struct dm_list *arg_lvnames,
 			  const struct dm_list *tagsl,
-			  struct dm_list *failed_lvnames,
 			  void *handle,
 			  process_single_lv_fn_t process_single_lv);
 
diff --git a/tools/vgdisplay.c b/tools/vgdisplay.c
index a739d11..39cdaf3 100644
--- a/tools/vgdisplay.c
+++ b/tools/vgdisplay.c
@@ -39,7 +39,7 @@ static int vgdisplay_single(struct cmd_context *cmd, const char *vg_name,
 	if (arg_count(cmd, verbose_ARG)) {
 		vgdisplay_extents(vg);
 
-		process_each_lv_in_vg(cmd, vg, NULL, NULL, NULL, NULL,
+		process_each_lv_in_vg(cmd, vg, NULL, NULL, NULL,
 				      (process_single_lv_fn_t)lvdisplay_full);
 
 		log_print("--- Physical volumes ---");




More information about the lvm-devel mailing list