diff options
author | David Teigland <teigland@redhat.com> | 2015-05-05 16:24:50 -0500 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2015-05-07 11:52:30 -0500 |
commit | ceb3afb5b21025c67f61693b3aa7fe33a120f182 (patch) | |
tree | a749e3f9798513f82039fb7dd0d0cad665c1d91a | |
parent | 6b7ec65c6cbb142338f1efbf083b40e1abe47b1d (diff) | |
download | lvm2-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.c | 31 | ||||
-rw-r--r-- | lib/cache/lvmcache.h | 3 | ||||
-rw-r--r-- | lib/cache/lvmetad.c | 51 | ||||
-rw-r--r-- | lib/cache/lvmetad.h | 7 | ||||
-rw-r--r-- | lib/metadata/metadata-exported.h | 6 | ||||
-rw-r--r-- | tools/toollib.c | 61 |
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; |