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:
parent
68e2ea11a3
commit
4ff2583dc5
219
tools/toollib.c
219
tools/toollib.c
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user