[lvm-devel] [PATCH 2/8] toollib: rework process_each_lv

David Teigland teigland at redhat.com
Tue Mar 26 21:09:22 UTC 2013


A new flag from commands makes explicit when
process_each_lv may query for "all vgs" and
run the command on each.  A command is run
against all vgs only when this flag is
provided and no vg/lv names or tags are provided.

When vg/lv names or tags are explicitly named
on the command line, the command is only run
against named vgs/lvs, or vgs/lvs with tags
matching one provided.

There should be no functional change.
---
 tools/lvdisplay.c |   4 +-
 tools/lvscan.c    |   4 +-
 tools/reporter.c  |   8 +-
 tools/toollib.c   | 459 ++++++++++++++++++++++++++++++------------------------
 tools/vgmknodes.c |   4 +-
 5 files changed, 267 insertions(+), 212 deletions(-)

diff --git a/tools/lvdisplay.c b/tools/lvdisplay.c
index f5531cb..a899b1e 100644
--- a/tools/lvdisplay.c
+++ b/tools/lvdisplay.c
@@ -54,6 +54,6 @@ int lvdisplay(struct cmd_context *cmd, int argc, char **argv)
 		return EINVALID_CMD_LINE;
 	}
 
-	return process_each_lv(cmd, argc, argv, 0, NULL,
-			       &_lvdisplay_single);
+	return process_each_lv(cmd, argc, argv, ENABLE_ALL_VGNAMES,
+			       NULL, &_lvdisplay_single);
 }
diff --git a/tools/lvscan.c b/tools/lvscan.c
index 636ac45..af82bbb 100644
--- a/tools/lvscan.c
+++ b/tools/lvscan.c
@@ -74,6 +74,6 @@ int lvscan(struct cmd_context *cmd, int argc, char **argv)
 		return EINVALID_CMD_LINE;
 	}
 
-	return process_each_lv(cmd, argc, argv, 0, NULL,
-			       &lvscan_single);
+	return process_each_lv(cmd, argc, argv, ENABLE_ALL_VGNAMES,
+			       NULL, &lvscan_single);
 }
diff --git a/tools/reporter.c b/tools/reporter.c
index ead401b..0e6cbe4 100644
--- a/tools/reporter.c
+++ b/tools/reporter.c
@@ -366,8 +366,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
 
 	switch (report_type) {
 	case LVS:
-		r = process_each_lv(cmd, argc, argv, 0, report_handle,
-				    &_lvs_single);
+		r = process_each_lv(cmd, argc, argv, ENABLE_ALL_VGNAMES,
+				    report_handle, &_lvs_single);
 		break;
 	case VGS:
 		r = process_each_vg(cmd, argc, argv, ENABLE_ALL_VGNAMES,
@@ -386,8 +386,8 @@ static int _report(struct cmd_context *cmd, int argc, char **argv,
 					    report_handle, &_pvs_in_vg);
 		break;
 	case SEGS:
-		r = process_each_lv(cmd, argc, argv, 0, report_handle,
-				    &_lvsegs_single);
+		r = process_each_lv(cmd, argc, argv, ENABLE_ALL_VGNAMES,
+				    report_handle, &_lvsegs_single);
 		break;
 	case PVSEGS:
 		if (args_are_pvs)
diff --git a/tools/toollib.c b/tools/toollib.c
index 247462b..e38e20c 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -194,208 +194,6 @@ int process_each_lv_in_vg(struct cmd_context *cmd,
 	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 = 0;
-
-	struct dm_list *tags_arg;
-	struct dm_list *vgnames;	/* VGs to process */
-	struct str_list *sll, *strl;
-	struct cmd_vg *cvl_vg;
-	struct dm_list cmd_vgs;
-	struct dm_list failed_lvnames;
-	struct dm_list tags, 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(&tags);
-	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, &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;
-				}
-			}
-		}
-		vgnames = &arg_vgnames;
-	}
-
-	if (!argc || !dm_list_empty(&tags)) {
-		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))) {
-			stack;
-			return ECMD_FAILED;
-		}
-
-		if (!cmd_vg_read(cmd, &cmd_vgs)) {
-			free_cmd_vgs(&cmd_vgs);
-			if (ret_max < ECMD_FAILED) {
-				log_error("Skipping volume group %s", vgname);
-				ret_max = ECMD_FAILED;
-			} else
-				stack;
-			continue;
-		}
-
-		tags_arg = &tags;
-		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;
-				}
-			}
-		}
-
-		while (!sigint_caught()) {
-			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);
-		/* FIXME: logic for breaking command is not consistent */
-		if (sigint_caught()) {
-			stack;
-			return ECMD_FAILED;
-		}
-	}
-
-	return ret_max;
-}
-
 int process_each_segment_in_pv(struct cmd_context *cmd,
 			       struct volume_group *vg,
 			       struct physical_volume *pv,
@@ -1792,3 +1590,260 @@ int process_each_vg(struct cmd_context *cmd,
 	return ret;
 }
 
+/*
+ * 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;
+
+	log_verbose("Using logical volume(s) on command line");
+
+	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, 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_vg_name_list(struct cmd_context *cmd, uint32_t flags,
+				   struct dm_list *vg_name_list,
+				   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 str_list *sl, *sll;
+	struct cmd_vg *cvl_vg;
+	struct dm_list *tags_arg;
+	struct dm_list cmd_vgs;
+	struct dm_list failed_lvnames;
+	struct dm_list lvnames;
+	const char *vgname;
+	int ret_max = ECMD_PROCESSED;
+	int ret = 0;
+
+	dm_list_init(&failed_lvnames);
+
+	dm_list_iterate_items(sl, vg_name_list) {
+		vgname = sl->str;
+
+		dm_list_init(&cmd_vgs);
+		if (!(cvl_vg = cmd_vg_add(cmd->mem, &cmd_vgs,
+					  vgname, NULL, flags))) {
+			stack;
+			return ECMD_FAILED;
+		}
+
+		if (!cmd_vg_read(cmd, &cmd_vgs)) {
+			free_cmd_vgs(&cmd_vgs);
+			if (ret_max < ECMD_FAILED) {
+				log_error("Skipping volume group %s", vgname);
+				ret_max = ECMD_FAILED;
+			} else
+				stack;
+			continue;
+		}
+
+		/*
+		 * 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(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;
+			}
+			
+			if (lv_name && !strncmp(vg_name, vgname, strlen(vgname)) &&
+			    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;
+				}
+			}
+		}
+
+		while (!sigint_caught()) {
+			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);
+		/* FIXME: logic for breaking command is not consistent */
+		if (sigint_caught()) {
+			stack;
+			return 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)
+{
+	struct dm_list all_vgnames;
+	struct dm_list arg_vgnames;
+	struct dm_list arg_lvnames;
+	struct dm_list arg_tags;
+	struct dm_list *vg_name_list;
+	int ret;
+
+	dm_list_init(&all_vgnames);
+	dm_list_init(&arg_vgnames);
+	dm_list_init(&arg_lvnames);
+	dm_list_init(&arg_tags);
+
+	ret = get_arg_lvnames(cmd, argc, argv,
+			      &arg_vgnames, &arg_lvnames, &arg_tags);
+	if (ret != ECMD_PROCESSED)
+		return ret;
+
+	if ((dm_list_empty(&arg_vgnames) && (flags & ENABLE_ALL_VGNAMES)) ||
+	    !dm_list_empty(&arg_tags)) {
+		ret = get_all_vgnames(cmd, &all_vgnames);
+		if (ret != ECMD_PROCESSED)
+			return ret;
+	}
+
+	if (dm_list_empty(&arg_vgnames) && dm_list_empty(&all_vgnames)) {
+		log_error("No volume groups found");
+		return ECMD_PROCESSED;
+	}
+
+	if (!dm_list_empty(&all_vgnames))
+		vg_name_list = &all_vgnames;
+	else
+		vg_name_list = &arg_vgnames;
+
+	ret = process_lv_vg_name_list(cmd, flags, vg_name_list,
+				      &arg_vgnames, &arg_lvnames, &arg_tags,
+				      handle, process_single_lv);
+	return ret;
+}
+
diff --git a/tools/vgmknodes.c b/tools/vgmknodes.c
index 0fd273f..a012230 100644
--- a/tools/vgmknodes.c
+++ b/tools/vgmknodes.c
@@ -39,6 +39,6 @@ int vgmknodes(struct cmd_context *cmd, int argc, char **argv)
 		return ECMD_FAILED;
 	}
 
-	return process_each_lv(cmd, argc, argv, LCK_VG_READ, NULL,
-			    &_vgmknodes_single);
+	return process_each_lv(cmd, argc, argv, LCK_VG_READ | ENABLE_ALL_VGNAMES,
+			       NULL, &_vgmknodes_single);
 }
-- 
1.8.1.rc1.5.g7e0651a




More information about the lvm-devel mailing list