1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-03-10 16:58:47 +03:00

process_each: always use list of vgnames on system

This makes process_each_vg/lv always use the list of
vgnames on the system.  When specific VGs are named on
the command line, the corresponding entries from
vgnameids_on_system are moved to vgnameids_to_process.

Previously, when specific VGs were named on the command
line, the vgnameids_on_system list was not created, and
vgnameids_to_process was created from the arg_vgnames
list (which is only names, without vgids).

Now, vgnameids_on_system is always created, and entries
are moved from that list to vgnameids_to_process -- either
some (when arg_vgnames specifies only some), or all (when
the command is processing all VGs, or needs to look at
all VGs for checking tags/selection).

This change adds one new lvmetad lookup (vg_list) to a
command that specifies VG names.  It adds no new work
for other commands, e.g. non-lvmetad commands, or
commands that look at all VGs.

When using lvmetad, 'lvs foo' previously sent one
request to lvmetad: 'vg_lookup foo'.
Now, 'lvs foo' sends two requests to lvmetad:
'vg_list' and 'vg_lookup foo <uuid>'.

(The lookup can now always include the uuid in the request
because the initial vg_list contains name/vgid pairs.)
This commit is contained in:
David Teigland 2015-11-30 12:51:44 -06:00
parent 68e2ea11a3
commit 4ff2583dc5

View File

@ -1916,6 +1916,7 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
struct processing_handle *handle,
process_single_vg_fn_t process_single_vg)
{
char uuid[64] __attribute__((aligned(8)));
struct volume_group *vg;
struct vgnameid_list *vgnl;
const char *vg_name;
@ -1947,6 +1948,11 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
skip = 0;
notfound = 0;
if (vg_uuid)
id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid));
log_very_verbose("Processing VG %s %s", vg_name, vg_uuid ? uuid : "");
if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
ret_max = ECMD_FAILED;
continue;
@ -1966,6 +1972,9 @@ static int _process_vgnameid_list(struct cmd_context *cmd, uint32_t read_flags,
(!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))) &&
select_match_vg(cmd, handle, vg, &selected) && selected) {
log_very_verbose("Process single VG %s", vg_name);
ret = process_single_vg(cmd, vg_name, vg, handle);
_update_selection_result(handle, &whole_selected);
if (ret != ECMD_PROCESSED)
@ -2016,6 +2025,57 @@ static int _copy_str_to_vgnameid_list(struct cmd_context *cmd, struct dm_list *s
return ECMD_PROCESSED;
}
/*
* For each arg_vgname, move the corresponding entry from
* vgnameids_on_system to vgnameids_to_process. If an
* item in arg_vgnames doesn't exist in vgnameids_on_system,
* then add a new entry for it to vgnameids_to_process.
*/
static void _choose_vgs_to_process(struct cmd_context *cmd,
struct dm_list *arg_vgnames,
struct dm_list *vgnameids_on_system,
struct dm_list *vgnameids_to_process)
{
struct dm_str_list *sl, *sl2;
struct vgnameid_list *vgnl, *vgnl2;
int found;
dm_list_iterate_items_safe(sl, sl2, arg_vgnames) {
found = 0;
dm_list_iterate_items_safe(vgnl, vgnl2, vgnameids_on_system) {
if (strcmp(sl->str, vgnl->vg_name))
continue;
dm_list_del(&vgnl->list);
dm_list_add(vgnameids_to_process, &vgnl->list);
found = 1;
break;
}
/*
* If the name arg was not found in the list of all VGs, then
* it probably doesn't exist, but we want the "VG not found"
* failure to be handled by the existing vg_read() code for
* that error. So, create an entry with just the VG name so
* that the processing loop will attempt to process it and use
* the vg_read() error path.
*/
if (!found) {
log_verbose("VG name on command line not found in list of VGs: %s", sl->str);
if (!(vgnl = dm_pool_alloc(cmd->mem, sizeof(*vgnl))))
continue;
vgnl->vgid = NULL;
if (!(vgnl->vg_name = dm_pool_strdup(cmd->mem, sl->str)))
continue;
dm_list_add(vgnameids_to_process, &vgnl->list);
}
}
}
/*
* Call process_single_vg() for each VG selected by the command line arguments.
*/
@ -2028,9 +2088,10 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
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 one_vgname_arg = (cmd->command->flags & ONE_VGNAME_ARG);
int process_all_vgs_on_system = 0;
int ret_max = ECMD_PROCESSED;
int ret;
/* Disable error in vg_read so we can print it from ignore_vg. */
@ -2044,29 +2105,46 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
/*
* Find any VGs or tags explicitly provided on the command line.
*/
if ((ret = _get_arg_vgnames(cmd, argc, argv, one_vgname_arg, &arg_vgnames, &arg_tags)) != ECMD_PROCESSED)
if ((ret = _get_arg_vgnames(cmd, argc, argv, one_vgname_arg, &arg_vgnames, &arg_tags)) != ECMD_PROCESSED) {
ret_max = ret;
goto_out;
}
/*
* 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.
* Process all VGs on the system when:
* . tags are specified and all VGs need to be read to
* look for matching tags.
* . no VG names are specified and the command defaults
* to processing all VGs when none are specified.
*/
if ((dm_list_empty(&arg_vgnames) && enable_all_vgs) || !dm_list_empty(&arg_tags)) {
/* Needed for a current listing of the global VG namespace. */
if (!lockd_gl(cmd, "sh", 0)) {
ret = ECMD_FAILED;
goto_out;
}
if ((dm_list_empty(&arg_vgnames) && enable_all_vgs) || !dm_list_empty(&arg_tags))
process_all_vgs_on_system = 1;
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0))
goto_out;
/*
* Needed for a current listing of the global VG namespace.
*/
if (process_all_vgs_on_system && !lockd_gl(cmd, "sh", 0)) {
ret_max = ECMD_FAILED;
goto_out;
}
/*
* A list of all VGs on the system is needed when:
* . processing all VGs on the system
* . A VG name is specified which may refer to one
* of multiple VGs on the system with that name.
*/
log_very_verbose("Get list of VGs on system");
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0)) {
ret_max = ECMD_FAILED;
goto_out;
}
if (dm_list_empty(&arg_vgnames) && dm_list_empty(&vgnameids_on_system)) {
/* FIXME Should be log_print, but suppressed for reporting cmds */
log_verbose("No volume groups found.");
ret = ECMD_PROCESSED;
ret_max = ECMD_PROCESSED;
goto out;
}
@ -2074,28 +2152,37 @@ int process_each_vg(struct cmd_context *cmd, int argc, char **argv,
read_flags |= READ_OK_NOTFOUND;
/*
* 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.
* When processing all VGs, vgnameids_on_system simply becomes
* vgnameids_to_process.
* When processing only specified VGs, then for each item in
* arg_vgnames, move the corresponding entry from
* vgnameids_on_system to vgnameids_to_process.
*/
if (!dm_list_empty(&vgnameids_on_system))
if (process_all_vgs_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)
goto_out;
else
_choose_vgs_to_process(cmd, &arg_vgnames, &vgnameids_on_system, &vgnameids_to_process);
if (!handle && !(handle = init_processing_handle(cmd)))
if (!handle && !(handle = init_processing_handle(cmd))) {
ret_max = ECMD_FAILED;
goto_out;
}
if (handle->internal_report_for_select && !handle->selection_handle &&
!init_selection_handle(cmd, handle, VGS))
!init_selection_handle(cmd, handle, VGS)) {
ret_max = ECMD_FAILED;
goto_out;
}
ret = _process_vgnameid_list(cmd, read_flags, &vgnameids_to_process,
&arg_vgnames, &arg_tags, handle, process_single_vg);
if (ret > ret_max)
ret_max = ret;
out:
if (!handle_supplied)
destroy_processing_handle(cmd, handle);
return ret;
return ret_max;
}
int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
@ -2386,6 +2473,7 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag
struct processing_handle *handle,
process_single_lv_fn_t process_single_lv)
{
char uuid[64] __attribute__((aligned(8)));
struct volume_group *vg;
struct vgnameid_list *vgnl;
struct dm_str_list *sl;
@ -2440,6 +2528,11 @@ static int _process_lv_vgnameid_list(struct cmd_context *cmd, uint32_t read_flag
}
}
if (vg_uuid)
id_write_format((const struct id*)vg_uuid, uuid, sizeof(uuid));
log_very_verbose("Processing VG %s %s", vg_name, vg_uuid ? uuid : "");
if (!lockd_vg(cmd, vg_name, NULL, 0, &lockd_state)) {
ret_max = ECMD_FAILED;
continue;
@ -2483,9 +2576,9 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, uint32_t rea
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 need_vgnameids = 0;
int process_all_vgs_on_system = 0;
int ret_max = ECMD_PROCESSED;
int ret;
/* Disable error in vg_read so we can print it from ignore_vg. */
@ -2500,44 +2593,63 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, uint32_t rea
/*
* 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))
if ((ret = _get_arg_lvnames(cmd, argc, argv, &arg_vgnames, &arg_lvnames, &arg_tags) != ECMD_PROCESSED)) {
ret_max = ret;
goto_out;
}
if (!handle && !(handle = init_processing_handle(cmd)))
if (!handle && !(handle = init_processing_handle(cmd))) {
ret_max = ECMD_FAILED;
goto_out;
}
if (handle->internal_report_for_select && !handle->selection_handle &&
!init_selection_handle(cmd, handle, LVS))
!init_selection_handle(cmd, handle, LVS)) {
ret_max = ECMD_FAILED;
goto_out;
}
/*
* 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 select option needs resolving; or
* no VG names were given and the command defaults to processing all VGs.
*/
* Process all VGs on the system when:
* . tags are specified and all VGs need to be read to
* look for matching tags.
* . no VG names are specified and the command defaults
* to processing all VGs when none are specified.
* . no VG names are specified and the select option needs
* resolving.
*/
if (!dm_list_empty(&arg_tags))
need_vgnameids = 1;
process_all_vgs_on_system = 1;
else if (dm_list_empty(&arg_vgnames) && enable_all_vgs)
need_vgnameids = 1;
process_all_vgs_on_system = 1;
else if (dm_list_empty(&arg_vgnames) && handle->internal_report_for_select)
need_vgnameids = 1;
process_all_vgs_on_system = 1;
if (need_vgnameids) {
/* Needed for a current listing of the global VG namespace. */
if (!lockd_gl(cmd, "sh", 0)) {
ret = ECMD_FAILED;
goto_out;
}
/*
* Needed for a current listing of the global VG namespace.
*/
if (process_all_vgs_on_system && !lockd_gl(cmd, "sh", 0)) {
ret_max = ECMD_FAILED;
goto_out;
}
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0))
goto_out;
/*
* A list of all VGs on the system is needed when:
* . processing all VGs on the system
* . A VG name is specified which may refer to one
* of multiple VGs on the system with that name.
*/
log_very_verbose("Get list of VGs on system");
if (!get_vgnameids(cmd, &vgnameids_on_system, NULL, 0)) {
ret_max = ECMD_FAILED;
goto_out;
}
if (dm_list_empty(&arg_vgnames) && dm_list_empty(&vgnameids_on_system)) {
/* FIXME Should be log_print, but suppressed for reporting cmds */
log_verbose("No volume groups found.");
ret = ECMD_PROCESSED;
ret_max = ECMD_PROCESSED;
goto out;
}
@ -2545,20 +2657,27 @@ int process_each_lv(struct cmd_context *cmd, int argc, char **argv, uint32_t rea
read_flags |= READ_OK_NOTFOUND;
/*
* 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.
* When processing all VGs, vgnameids_on_system simply becomes
* vgnameids_to_process.
* When processing only specified VGs, then for each item in
* arg_vgnames, move the corresponding entry from
* vgnameids_on_system to vgnameids_to_process.
*/
if (!dm_list_empty(&vgnameids_on_system))
if (process_all_vgs_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)
goto_out;
else
_choose_vgs_to_process(cmd, &arg_vgnames, &vgnameids_on_system, &vgnameids_to_process);
ret = _process_lv_vgnameid_list(cmd, read_flags, &vgnameids_to_process, &arg_vgnames, &arg_lvnames,
&arg_tags, handle, process_single_lv);
if (ret > ret_max)
ret_max = ret;
out:
if (!handle_supplied)
destroy_processing_handle(cmd, handle);
return ret;
return ret_max;
}
static int _get_arg_pvnames(struct cmd_context *cmd,