[lvm-devel] master - toollib: Rewrite process_each_vg.
Alasdair Kergon
agk at fedoraproject.org
Fri Oct 3 19:51:22 UTC 2014
Gitweb: http://git.fedorahosted.org/git/?p=lvm2.git;a=commitdiff;h=bfb6a4ecc6ad7bb06649ffd026d9c997443dd684
Commit: bfb6a4ecc6ad7bb06649ffd026d9c997443dd684
Parent: 91198ac13e61c66b65884660410311ffc8b8c24e
Author: David Teigland <teigland at redhat.com>
AuthorDate: Fri Oct 3 20:47:19 2014 +0100
Committer: Alasdair G Kergon <agk at redhat.com>
CommitterDate: Fri Oct 3 20:47:19 2014 +0100
toollib: Rewrite process_each_vg.
Split VG argument collection from processing.
This allows the two different loops through VGs to
be replaced by a single loop.
Replace unused struct cmd_vg and cmd_vg_read() replicator
code with struct vg and vg_read() directly.
[Committed by agk with cosmetic changes and tweaks.]
---
WHATS_NEW | 1 +
tools/toollib.c | 391 ++++++++++++++++++++++++++++++++++---------------------
2 files changed, 246 insertions(+), 146 deletions(-)
diff --git a/WHATS_NEW b/WHATS_NEW
index a94edc6..ad7bafb 100644
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
Version 2.02.112 -
=====================================
+ Refactor process_each_vg in toollib.
Pools cannot be used as external origin.
Use lv_update_and_reload() for snapshot reload.
Don't print message in adjusted_mirror_region_size() in activation.
diff --git a/tools/toollib.c b/tools/toollib.c
index c5395ba..8049b1f 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -169,7 +169,9 @@ int ignore_vg(struct volume_group *vg, const char *vg_name, int allow_inconsiste
if ((read_error == FAILED_INCONSISTENT) && allow_inconsistent)
return 0;
- if (read_error == FAILED_CLUSTERED && vg->cmd->ignore_clustered_vgs)
+ if (read_error == FAILED_NOTFOUND)
+ *ret = ECMD_FAILED;
+ else if (read_error == FAILED_CLUSTERED && vg->cmd->ignore_clustered_vgs)
log_verbose("Skipping volume group %s", vg_name);
else {
log_error("Skipping volume group %s", vg_name);
@@ -566,151 +568,6 @@ int process_each_segment_in_lv(struct cmd_context *cmd,
return ret_max;
}
-static int _process_one_vg(struct cmd_context *cmd, const char *vg_name,
- const char *vgid,
- struct dm_list *tagsl, struct dm_list *arg_vgnames,
- uint32_t flags, void *handle, int ret_max,
- process_single_vg_fn_t process_single_vg)
-{
- struct dm_list cmd_vgs;
- struct cmd_vg *cvl_vg;
- int ret = ECMD_PROCESSED;
-
- log_verbose("Finding volume group \"%s\"", vg_name);
-
- dm_list_init(&cmd_vgs);
- if (!(cvl_vg = cmd_vg_add(cmd->mem, &cmd_vgs, vg_name, vgid, flags)))
- return_ECMD_FAILED;
-
- for (;;) {
- if (sigint_caught()) {
- ret = ECMD_FAILED;
- stack;
- break;
- }
-
- if (!cmd_vg_read(cmd, &cmd_vgs)) {
- /* Allow FAILED_INCONSISTENT through only for vgcfgrestore */
- if (ignore_vg(cvl_vg->vg, vg_name, flags & READ_ALLOW_INCONSISTENT, &ret)) {
- stack;
- break;
- }
- }
-
- if (!dm_list_empty(tagsl) &&
- /* Only process if a tag matches or it's on arg_vgnames */
- !str_list_match_item(arg_vgnames, vg_name) &&
- !str_list_match_list(tagsl, &cvl_vg->vg->tags, NULL))
- break;
-
- ret = process_single_vg(cmd, vg_name, cvl_vg->vg, handle);
-
- if (vg_read_error(cvl_vg->vg)) /* FAILED_INCONSISTENT */
- break;
-
- if (!cvl_vg->vg->cmd_missing_vgs)
- break;
-
- free_cmd_vgs(&cmd_vgs);
- }
-
- free_cmd_vgs(&cmd_vgs);
-
- return (ret > ret_max) ? ret : ret_max;
-}
-
-int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
- uint32_t flags, void *handle,
- process_single_vg_fn_t process_single_vg)
-{
- int opt = 0;
- int ret_max = ECMD_PROCESSED;
-
- struct dm_str_list *sl;
- struct dm_list *vgnames, *vgids;
- struct dm_list arg_vgnames, tagsl;
-
- const char *vg_name, *vgid;
-
- dm_list_init(&tagsl);
- dm_list_init(&arg_vgnames);
-
- if (argc) {
- log_verbose("Using volume group(s) on command line");
-
- for (; opt < argc; opt++) {
- vg_name = argv[opt];
- if (*vg_name == '@') {
- if (!validate_tag(vg_name + 1)) {
- log_error("Skipping invalid tag %s",
- vg_name);
- if (ret_max < EINVALID_CMD_LINE)
- ret_max = EINVALID_CMD_LINE;
- continue;
- }
- if (!str_list_add(cmd->mem, &tagsl,
- dm_pool_strdup(cmd->mem,
- vg_name + 1))) {
- log_error("strlist allocation failed");
- return ECMD_FAILED;
- }
- continue;
- }
-
- vg_name = skip_dev_dir(cmd, vg_name, NULL);
- if (strchr(vg_name, '/')) {
- log_error("Invalid volume group name: %s",
- vg_name);
- if (ret_max < EINVALID_CMD_LINE)
- ret_max = EINVALID_CMD_LINE;
- continue;
- }
- if (!str_list_add(cmd->mem, &arg_vgnames,
- dm_pool_strdup(cmd->mem, vg_name))) {
- log_error("strlist allocation failed");
- return ECMD_FAILED;
- }
- }
-
- vgnames = &arg_vgnames;
- }
-
- if (!argc || !dm_list_empty(&tagsl)) {
- log_verbose("Finding all volume groups");
- if (!lvmetad_vg_list_to_lvmcache(cmd))
- stack;
- if (!(vgids = get_vgids(cmd, 0)) || dm_list_empty(vgids)) {
- log_error("No volume groups found");
- return ret_max;
- }
- dm_list_iterate_items(sl, vgids) {
- if (sigint_caught())
- return_ECMD_FAILED;
- vgid = sl->str;
- if (!vgid || !(vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid)))
- continue;
- ret_max = _process_one_vg(cmd, vg_name, vgid, &tagsl,
- &arg_vgnames,
- flags, handle,
- ret_max, process_single_vg);
- }
- } else {
- dm_list_iterate_items(sl, vgnames) {
- if (sigint_caught())
- return_ECMD_FAILED;
- vg_name = sl->str;
- if (is_orphan_vg(vg_name))
- continue; /* FIXME Unnecessary? */
- ret_max = _process_one_vg(cmd, vg_name, NULL, &tagsl,
- &arg_vgnames,
- flags, handle,
- ret_max, process_single_vg);
- }
- }
-
- return ret_max;
-}
-
int process_each_pv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
const struct dm_list *tagsl, void *handle,
process_single_pv_fn_t process_single_pv)
@@ -1986,3 +1843,245 @@ int validate_lvname_param(struct cmd_context *cmd, const char **vg_name,
return 1;
}
+
+struct vgnameid_list {
+ struct dm_list list;
+ const char *vg_name;
+ const char *vgid;
+};
+
+/*
+ * Extract list of VG names and list of tags from command line arguments.
+ */
+static int _get_arg_vgnames(struct cmd_context *cmd,
+ int argc, char **argv,
+ struct dm_list *arg_vgnames,
+ struct dm_list *arg_tags)
+{
+ int opt = 0;
+ int ret_max = ECMD_PROCESSED;
+ const char *vg_name;
+
+ log_verbose("Using volume group(s) on command line");
+
+ for (; opt < argc; opt++) {
+ vg_name = argv[opt];
+ if (*vg_name == '@') {
+ if (!validate_tag(vg_name + 1)) {
+ log_error("Skipping invalid tag: %s", vg_name);
+ if (ret_max < EINVALID_CMD_LINE)
+ ret_max = EINVALID_CMD_LINE;
+ continue;
+ }
+ if (!str_list_add(cmd->mem, arg_tags,
+ dm_pool_strdup(cmd->mem, vg_name + 1))) {
+ log_error("strlist allocation failed");
+ return ECMD_FAILED;
+ }
+ continue;
+ }
+
+ vg_name = skip_dev_dir(cmd, vg_name, NULL);
+ if (strchr(vg_name, '/')) {
+ log_error("Invalid volume group name: %s", vg_name);
+ if (ret_max < EINVALID_CMD_LINE)
+ ret_max = EINVALID_CMD_LINE;
+ continue;
+ }
+ if (!str_list_add(cmd->mem, arg_vgnames,
+ dm_pool_strdup(cmd->mem, vg_name))) {
+ log_error("strlist allocation failed");
+ return ECMD_FAILED;
+ }
+ }
+
+ return ret_max;
+}
+
+/*
+ * FIXME Add arg to include (or not) entries with duplicate vg names?
+ *
+ * Obtain complete list of VG name/vgid pairs known on the system.
+ */
+static int _get_vgnameids_on_system(struct cmd_context *cmd,
+ struct dm_list *vgnameids_on_system)
+{
+ struct vgnameid_list *vgnl;
+ struct dm_list *vgids;
+ struct dm_str_list *sl;
+ const char *vgid;
+
+ log_verbose("Finding all volume groups");
+
+ if (!lvmetad_vg_list_to_lvmcache(cmd))
+ stack;
+
+ /*
+ * Start with complete vgid list because multiple VGs might have same name.
+ */
+ vgids = get_vgids(cmd, 0);
+ if (!vgids || dm_list_empty(vgids)) {
+ stack;
+ return ECMD_PROCESSED;
+ }
+
+ /* FIXME get_vgids() should provide these pairings directly */
+ dm_list_iterate_items(sl, vgids) {
+ if (!(vgid = sl->str))
+ continue;
+
+ if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl)))) {
+ log_error("vgnameid_list allocation failed");
+ return ECMD_FAILED;
+ }
+
+ vgnl->vgid = dm_pool_strdup(cmd->mem, vgid);
+ vgnl->vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid);
+
+ dm_list_add(vgnameids_on_system, &vgnl->list);
+ }
+
+ return ECMD_PROCESSED;
+}
+
+static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t flags,
+ struct dm_list *vgnameids_to_process,
+ struct dm_list *arg_vgnames,
+ struct dm_list *arg_tags, void *handle,
+ process_single_vg_fn_t process_single_vg)
+{
+ struct volume_group *vg;
+ struct vgnameid_list *vgnl;
+ const char *vg_name;
+ const char *vg_uuid;
+ int ret_max = ECMD_PROCESSED;
+ int ret;
+ int process_all = 0;
+
+ /*
+ * If no VG names or tags were supplied, then process all VGs.
+ */
+ if (dm_list_empty(arg_vgnames) && dm_list_empty(arg_tags))
+ process_all = 1;
+
+ dm_list_iterate_items(vgnl, vgnameids_to_process) {
+ vg_name = vgnl->vg_name;
+ vg_uuid = vgnl->vgid;
+ ret = 0;
+
+ 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;
+ }
+
+ /* Process this VG? */
+ if (process_all ||
+ (!dm_list_empty(arg_vgnames) && str_list_match_item(arg_vgnames, vg_name)) ||
+ (!dm_list_empty(arg_tags) && str_list_match_list(arg_tags, &vg->tags, NULL)))
+ ret = process_single_vg(cmd, vg_name, vg, handle);
+
+ if (vg_read_error(vg))
+ release_vg(vg);
+ else
+ unlock_and_release_vg(cmd, vg, vg_name);
+
+ if (ret > ret_max)
+ ret_max = ret;
+ if (sigint_caught())
+ break;
+ }
+
+ return ret_max;
+}
+
+/*
+ * 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)
+{
+ const char *vgname;
+ struct dm_str_list *sl;
+ struct vgnameid_list *vgnl;
+
+ dm_list_iterate_items(sl, sll) {
+ vgname = sl->str;
+
+ vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl));
+ if (!vgnl) {
+ log_error("vgnameid_list allocation failed");
+ return ECMD_FAILED;
+ }
+
+ vgnl->vgid = NULL;
+ vgnl->vg_name = dm_pool_strdup(cmd->mem, vgname);
+
+ dm_list_add(vgnll, &vgnl->list);
+ }
+
+ return ECMD_PROCESSED;
+}
+
+/*
+ * Call process_single_vg() for each VG selected by the command line arguments.
+ */
+int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
+ uint32_t flags, void *handle,
+ process_single_vg_fn_t process_single_vg)
+{
+ struct dm_list arg_tags; /* str_list */
+ struct dm_list arg_vgnames; /* 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(&vgnameids_on_system);
+ dm_list_init(&vgnameids_to_process);
+
+ /*
+ * Find any VGs or tags explicitly provided on the command line.
+ */
+ if ((ret = _get_arg_vgnames(cmd, argc, argv, &arg_vgnames, &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)) {
+ 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_name_list(cmd, &arg_vgnames, &vgnameids_to_process)) != ECMD_PROCESSED) {
+ stack;
+ return ret;
+ }
+
+ return _process_vgnameid_list(cmd, flags, &vgnameids_to_process,
+ &arg_vgnames, &arg_tags, handle, process_single_vg);
+}
More information about the lvm-devel
mailing list