mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
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.]
This commit is contained in:
parent
91198ac13e
commit
bfb6a4ecc6
@ -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.
|
||||
|
391
tools/toollib.c
391
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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user