summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2015-05-05 16:24:50 -0500
committerDavid Teigland <teigland@redhat.com>2015-05-07 11:52:30 -0500
commitceb3afb5b21025c67f61693b3aa7fe33a120f182 (patch)
treea749e3f9798513f82039fb7dd0d0cad665c1d91a
parent6b7ec65c6cbb142338f1efbf083b40e1abe47b1d (diff)
downloadlvm2-dev-dct-vgnameids.tar.gz
toollib: avoid repeated lvmetad vg_lookupdev-dct-vgnameids
In process_each_vg and process_each_lv when no vgname args are given, the first step is to get a list of all vgid/vgname on the system. This is exactly what lvmetad returns from a vg_list request. The current code is doing a vg_lookup on each VG after the vg_list and populating lvmcache with the info for each VG. These preliminary vg_lookup's are unnecessary, because they will be done again when the processing functions call vg_read. This patch eliminates the initial round of vg_lookup's, which can roughly cut in half the number of lvmetad requests and save a lot of extra work.
-rw-r--r--lib/cache/lvmcache.c31
-rw-r--r--lib/cache/lvmcache.h3
-rw-r--r--lib/cache/lvmetad.c51
-rw-r--r--lib/cache/lvmetad.h7
-rw-r--r--lib/metadata/metadata-exported.h6
-rw-r--r--tools/toollib.c61
6 files changed, 123 insertions, 36 deletions
diff --git a/lib/cache/lvmcache.c b/lib/cache/lvmcache.c
index 5c5a9ab2d..5ee7a9c6c 100644
--- a/lib/cache/lvmcache.c
+++ b/lib/cache/lvmcache.c
@@ -885,6 +885,37 @@ int lvmcache_vginfo_holders_dec_and_test_for_zero(struct lvmcache_vginfo *vginfo
}
// #endif
+int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
+ struct dm_list *vgnameids)
+{
+ struct vgnameid_list *vgnl;
+ struct lvmcache_vginfo *vginfo;
+
+ lvmcache_label_scan(cmd, 0);
+
+ dm_list_iterate_items(vginfo, &_vginfos) {
+ if (!include_internal && is_orphan_vg(vginfo->vgname))
+ continue;
+
+ if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl)))) {
+ log_error("vgnameid_list allocation failed.");
+ return 0;
+ }
+
+ vgnl->vgid = dm_pool_strdup(cmd->mem, vginfo->vgid);
+ vgnl->vg_name = dm_pool_strdup(cmd->mem, vginfo->vgname);
+
+ if (!vgnl->vgid || !vgnl->vg_name) {
+ log_error("vgnameid_list member allocation failed.");
+ return 0;
+ }
+
+ dm_list_add(vgnameids, &vgnl->list);
+ }
+
+ return 1;
+}
+
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
int include_internal)
{
diff --git a/lib/cache/lvmcache.h b/lib/cache/lvmcache.h
index 015f650a7..aea56cc32 100644
--- a/lib/cache/lvmcache.h
+++ b/lib/cache/lvmcache.h
@@ -107,6 +107,9 @@ struct dm_list *lvmcache_get_vgnames(struct cmd_context *cmd,
struct dm_list *lvmcache_get_vgids(struct cmd_context *cmd,
int include_internal);
+int lvmcache_get_vgnameids(struct cmd_context *cmd, int include_internal,
+ struct dm_list *vgnameids);
+
/* Returns list of struct dm_str_list containing pool-allocated copy of pvids */
struct dm_list *lvmcache_get_pvids(struct cmd_context *cmd, const char *vgname,
const char *vgid);
diff --git a/lib/cache/lvmetad.c b/lib/cache/lvmetad.c
index 0894c791c..cd9fe8890 100644
--- a/lib/cache/lvmetad.c
+++ b/lib/cache/lvmetad.c
@@ -673,6 +673,57 @@ int lvmetad_pv_list_to_lvmcache(struct cmd_context *cmd)
return 1;
}
+int lvmetad_get_vgnameids(struct cmd_context *cmd, int include_internal,
+ struct dm_list *vgnameids)
+{
+ struct vgnameid_list *vgnl;
+ struct id vgid;
+ const char *vgid_txt;
+ const char *vg_name;
+ daemon_reply reply;
+ struct dm_config_node *cn;
+
+ log_debug_lvmetad("Asking lvmetad for complete list of known VG ids/names");
+ reply = _lvmetad_send("vg_list", NULL);
+ if (!_lvmetad_handle_reply(reply, "list VGs", "", NULL)) {
+ daemon_reply_destroy(reply);
+ return_0;
+ }
+
+ if ((cn = dm_config_find_node(reply.cft->root, "volume_groups"))) {
+ for (cn = cn->child; cn; cn = cn->sib) {
+ vgid_txt = cn->key;
+ if (!id_read_format(&vgid, vgid_txt)) {
+ stack;
+ continue;
+ }
+
+ if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl)))) {
+ log_error("vgnameid_list allocation failed.");
+ return 0;
+ }
+
+ if (!(vg_name = dm_config_find_str(cn->child, "name", NULL))) {
+ log_error("vg_list no name found.");
+ return 0;
+ }
+
+ vgnl->vgid = dm_pool_strdup(cmd->mem, (char *)&vgid);
+ vgnl->vg_name = dm_pool_strdup(cmd->mem, vg_name);
+
+ if (!vgnl->vgid || !vgnl->vg_name) {
+ log_error("vgnameid_list member allocation failed.");
+ return 0;
+ }
+
+ dm_list_add(vgnameids, &vgnl->list);
+ }
+ }
+
+ daemon_reply_destroy(reply);
+ return 1;
+}
+
int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd)
{
struct volume_group *tmp;
diff --git a/lib/cache/lvmetad.h b/lib/cache/lvmetad.h
index b5bac69e4..dcbd8d94d 100644
--- a/lib/cache/lvmetad.h
+++ b/lib/cache/lvmetad.h
@@ -143,6 +143,13 @@ int lvmetad_pv_lookup_by_dev(struct cmd_context *cmd, struct device *dev, int *f
int lvmetad_vg_list_to_lvmcache(struct cmd_context *cmd);
/*
+ * Request a list of vgid/vgname pairs for all VGs known to lvmetad.
+ * Does not do vg_lookup's on each VG, and does not populate lvmcache.
+ */
+int lvmetad_get_vgnameids(struct cmd_context *cmd, int include_internal,
+ struct dm_list *vgnameids);
+
+/*
* Find a VG by its ID or its name in the lvmetad cache. Gives NULL if the VG is
* not found.
*/
diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h
index 47fb9ae56..d8f92f6a7 100644
--- a/lib/metadata/metadata-exported.h
+++ b/lib/metadata/metadata-exported.h
@@ -494,6 +494,12 @@ struct vg_list {
struct volume_group *vg;
};
+struct vgnameid_list {
+ struct dm_list list;
+ const char *vg_name;
+ const char *vgid;
+};
+
#define PV_PE_START_CALC ((uint64_t) -1) /* Calculate pe_start value */
struct pvcreate_restorable_params {
diff --git a/tools/toollib.c b/tools/toollib.c
index e6c3cdb5e..cda8051be 100644
--- a/tools/toollib.c
+++ b/tools/toollib.c
@@ -1515,12 +1515,6 @@ int validate_restricted_lvname_param(struct cmd_context *cmd, const char **vg_na
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.
*/
@@ -1594,9 +1588,6 @@ static int _get_vgnameids_on_system(struct cmd_context *cmd,
const char *only_this_vgname, int include_internal)
{
struct vgnameid_list *vgnl;
- struct dm_list *vgids;
- struct dm_str_list *sl;
- const char *vgid;
if (only_this_vgname) {
vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl));
@@ -1614,32 +1605,30 @@ static int _get_vgnameids_on_system(struct cmd_context *cmd,
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, include_internal);
- 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;
- }
+ if (lvmetad_active() && include_internal) {
+ /*
+ * Used by process_each_pv which needs to initially read all
+ * vgs to populate device/lvmcache so that pvids are available
+ * and duplicates identified while processing the pvs, and
+ * so that process_each_pv can process the orphan vg, which
+ * is available through lvmcache, but not from lvmetad.
+ */
+ lvmetad_vg_list_to_lvmcache(cmd);
+ lvmcache_get_vgnameids(cmd, include_internal, vgnameids_on_system);
- vgnl->vgid = dm_pool_strdup(cmd->mem, vgid);
- vgnl->vg_name = lvmcache_vgname_from_vgid(cmd->mem, vgid);
+ } else if (lvmetad_active() && !include_internal) {
+ /*
+ * We can avoid reading all vgs from lvmetad to populate
+ * lvmcache, and just get the vg ids/names from lvmetad.
+ */
+ lvmetad_get_vgnameids(cmd, include_internal, vgnameids_on_system);
- dm_list_add(vgnameids_on_system, &vgnl->list);
+ } else {
+ /*
+ * In the non-lvmetad case, this function begins by calling
+ * lvmcache_label_scan() to populate lvmcache.
+ */
+ lvmcache_get_vgnameids(cmd, include_internal, vgnameids_on_system);
}
return ECMD_PROCESSED;
@@ -2821,10 +2810,10 @@ int process_each_pv(struct cmd_context *cmd,
process_all_devices = process_all_pvs && (cmd->command->flags & ENABLE_ALL_DEVS) &&
arg_count(cmd, all_ARG);
+
/*
- * Read all the vgs here because this has the effect of initializing
- * device/lvmcache info so that dev->pvid is available when creating
- * a list of devices.
+ * Read all the vgs here to populate the device/lvmcache info,
+ * so that dev->pvid is available when creating a list of devices.
*/
if ((ret = _get_vgnameids_on_system(cmd, &all_vgnameids, only_this_vgname, 1) != ECMD_PROCESSED)) {
stack;